ATLAS Offline Software
Loading...
Searching...
No Matches
Guid.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#ifndef PERSISTENTDATAMODEL_GUID_H
6#define PERSISTENTDATAMODEL_GUID_H
7
12
13#include <iosfwd> // for std::ostream
14#include <string>
15#include <array>
16#include <stdexcept>
17#include <type_traits>
18#include <span>
19#include <algorithm>
20#include <format>
21
25class Guid {
26public:
27 static constexpr size_t StrLen = 36;
31 class string : public std::array<char, StrLen> {
32 public:
33 constexpr operator std::string_view() const {
34 return std::string_view(data(), size());
35 }
36 constexpr std::string_view sv() const {return std::string_view(data(), size());}
37 static constexpr int stringSize() { return StrLen; }
38 };
39
40 //Remove FallBack code if there is no need for it is discovered
41 struct FallBack{};
43 constexpr Guid() : m_data1(0U), m_data2(0U), m_data3(0U), m_data4() {}
45 explicit Guid(bool assign) : Guid() { if (assign) create(*this); }
46
47 //Use this constructor if you find an old malformed Guid and can't correct it
48 Guid(const std::string& s, FallBack) { fromStringFallBack(s); }
50 constexpr Guid(std::string_view s) { fromString(s); }
51 //Constructor for const char* -- prevents trying to call bool version
52 constexpr Guid(const char *s) { fromString(s); }
54 Guid(const Guid& c) = default;
55 Guid& operator=(const Guid& c) = default;
57 auto operator<=>(const Guid&) const = default;
58 bool operator==(const Guid&) const = default;
59 bool operator==(std::string_view str) const;
60
61 constexpr static int stringSize() { return StrLen; }
62
64 constexpr void toString(std::span<char, StrLen> buf, bool uppercase = true) const noexcept;
65 constexpr std::string toString(bool uppercase = true) const{
66 std::string buf(Guid::string::stringSize(), ' ');
67 toString(std::span<char, stringSize()>(buf.data(), stringSize()), uppercase);
68 return buf;
69 }
70 constexpr Guid::string to_fixed_string(bool uppercase = true) const{
71 Guid::string buffer;
72 toString(buffer, uppercase);
73 return buffer;
74 }
75 static bool isGuid(std::string_view) noexcept;
77 constexpr void fromString(std::string_view s);
78
79 void fromStringFallBack(const std::string&);
80
82 static const Guid& null() noexcept;
83
88
91 static void create(Guid& guid, GuidGenMethod method = GuidGenDefault);
92
94 unsigned int data1() const { return m_data1; }
95 unsigned short data2() const { return m_data2; }
96 unsigned short data3() const { return m_data3; }
97 unsigned char data4(unsigned int i) const { if (i < 8) return m_data4[i]; return 0; }
98
100 void setData1(unsigned int data) { m_data1 = data; }
101 void setData2(unsigned short data) { m_data2 = data; }
102 void setData3(unsigned short data) { m_data3 = data; }
103 void setData4(unsigned char data, unsigned int i) { if (i < 8) m_data4[i] = data; }
104
106 friend bool operator==( std::string_view str, const Guid& rhs) { return (rhs.operator==(str)); }
108 friend bool operator!=( std::string_view str, const Guid& rhs) { return !(rhs.operator==(str)); }
110 friend std::ostream& operator<<(std::ostream& os, const Guid& rhs);
111
112private:
113 constexpr void setToNull() noexcept;
114 unsigned int m_data1{};
115 unsigned short m_data2{};
116 unsigned short m_data3{};
117 std::array<unsigned char,8> m_data4{};
118};
119
120//This piece of code allows std::format to deal with Guid::string without additional boilerplate
121template <>
122struct std::formatter<Guid::string> : std::formatter<std::string_view> {
123 constexpr auto format(const Guid::string& guid, auto& ctx) const {
124 return std::formatter<std::string_view>::format(static_cast<std::string_view>(guid), ctx);
125 }
126};
127
128//This piece of code allows it to be piped into std::ostream without additional boilerplate
129inline std::ostream& operator<<(std::ostream& os, const Guid::string& guid) {
130 return os << static_cast<std::string_view>(guid);
131}
132
133constexpr void Guid::setToNull() noexcept {
134 m_data1 = 0U;
135 m_data2 = 0U;
136 m_data3 = 0U;
137 m_data4.fill('\0');
138}
139
140//This is an unrolled method provided by AI, it should work to ~20ns
141constexpr void Guid::fromString(std::string_view sv) {
142 // Trim any whitespace
143 if(std::is_constant_evaluated() && std::min(sv.find_first_not_of(' '), sv.size()) > 0){
144 throw std::runtime_error("Remove spaces from GUID");
145 }
146 sv.remove_prefix(std::min(sv.find_first_not_of(' '), sv.size()));
147 auto last_non_space = sv.find_last_not_of(' ');
148 if (last_non_space == std::string_view::npos) {
149 sv = {}; // String is empty or all spaces
150 } else {
151 if(std::is_constant_evaluated() && (sv.size() - last_non_space - 1)!=0){
152 throw std::runtime_error("Remove spaces from GUID");
153 }
154 sv.remove_suffix(sv.size() - last_non_space - 1);
155 }
156
157 // Validate format
158 if (sv.size() != 36 ||
159 sv[8] != '-' || sv[13] != '-' || sv[18] != '-' || sv[23] != '-') {
160 setToNull();
161 if(std::is_constant_evaluated()){
162 throw std::runtime_error("failed to compile time parse GUID");
163 }
164 return;
165 }
166 bool success = true;
167 // Custom constexpr hex parser
168 auto parse_hex = [&success](std::string_view part) -> unsigned long long {
169 unsigned long long val = 0;
170 for (char c : part) {
171 val <<= 4; // Multiply by 16
172 if (c >= '0' && c <= '9') {
173 val += static_cast<unsigned long long>(c - '0');
174 } else if (c >= 'a' && c <= 'f') {
175 val += static_cast<unsigned long long>(10 + c - 'a');
176 } else if (c >= 'A' && c <= 'F') {
177 val += static_cast<unsigned long long>(10 + c - 'A');
178 } else {
179 success = false;
180 return 0;
181 }
182 }
183 return val;
184 };
185
186 // Parse m_data1 (positions 0-7)
187 m_data1 = static_cast<unsigned int>(parse_hex(sv.substr(0, 8)));
188
189 // Parse m_data2 (positions 9-12)
190 m_data2 = static_cast<unsigned short>(parse_hex(sv.substr(9, 4)));
191
192 // Parse m_data3 (positions 14-17)
193 m_data3 = static_cast<unsigned short>(parse_hex(sv.substr(14, 4)));
194
195
196 // Parse m_data4 bytes
197 int pos = 19;
198 for(int i =0; i< 2; i++){
199 auto val = parse_hex(sv.substr(pos, 2));
200 m_data4[i] = static_cast<unsigned char>(val);
201 pos+=2;
202 }
203 //Skip the dash at pos 23
204 pos = 24;
205 for(int i =2; i< 8; i++){
206 auto val = parse_hex(sv.substr(pos, 2));
207 m_data4[i] = static_cast<unsigned char>(val);
208 pos+=2;
209 }
210
211 if (!success) {
212 setToNull();
213 if(std::is_constant_evaluated()){
214 throw std::runtime_error("failed to compile time parse GUID");
215 }
216 }
217 return;
218}
219
220//This is an unrolled method provided by ai, is should work to ~20ns
221constexpr void Guid::toString(std::span<char, 36> buf, bool uppercase) const noexcept {
222
223 constexpr char lowhex[] = "0123456789abcdef";
224 constexpr char uphex[] = "0123456789ABCDEF";
225 const char *hex = uppercase ? uphex : lowhex;
226
227 // Unrolled for m_data1 (8 hex digits)
228 unsigned int v1 = m_data1;
229 buf[0] = hex[(v1 >> 28) & 0xF];
230 buf[1] = hex[(v1 >> 24) & 0xF];
231 buf[2] = hex[(v1 >> 20) & 0xF];
232 buf[3] = hex[(v1 >> 16) & 0xF];
233 buf[4] = hex[(v1 >> 12) & 0xF];
234 buf[5] = hex[(v1 >> 8) & 0xF];
235 buf[6] = hex[(v1 >> 4) & 0xF];
236 buf[7] = hex[v1 & 0xF];
237 buf[8] = '-';
238
239 // Unrolled for m_data2 (4 hex digits)
240 unsigned short v2 = m_data2;
241 buf[9] = hex[(v2 >> 12) & 0xF];
242 buf[10] = hex[(v2 >> 8) & 0xF];
243 buf[11] = hex[(v2 >> 4) & 0xF];
244 buf[12] = hex[v2 & 0xF];
245 buf[13] = '-';
246
247 // Unrolled for m_data3 (4 hex digits)
248 unsigned short v3 = m_data3;
249 buf[14] = hex[(v3 >> 12) & 0xF];
250 buf[15] = hex[(v3 >> 8) & 0xF];
251 buf[16] = hex[(v3 >> 4) & 0xF];
252 buf[17] = hex[v3 & 0xF];
253 buf[18] = '-';
254
255 // Unrolled for m_data4[0] and [1] (2+2 hex digits)
256 int pos = 19;
257 for(int i =0; i<2;i++){
258 unsigned char c = m_data4[i];
259 buf[pos] = hex[c >> 4];
260 buf[pos+1] = hex[c & 0xF];
261 pos +=2;
262 }
263 buf[23] = '-';
264 pos = 24;
265 // Unrolled for remaining m_data4[2..7] (6 pairs of hex digits)
266 for(int i =2; i<8;i++){
267 unsigned char c = m_data4[i];
268 buf[pos] = hex[c >> 4];
269 buf[pos+1] = hex[c & 0xF];
270 pos +=2;
271 }
272
273}
274
275
276namespace std {
277 template<>
278 struct hash<Guid> {
279 size_t operator()(const Guid& g) const noexcept {
280 // Treat the Guid as a 16-byte array for hashing.
281 // Checking the memory layout is contiguous and test for padding at compile time.
282 static_assert(sizeof(Guid) == (sizeof(unsigned int) + sizeof(unsigned short)
283 + sizeof(unsigned short) + sizeof(std::array<unsigned char,8>)));
284 const unsigned char* bytes = reinterpret_cast<const unsigned char*>(&g);
285 size_t hash_value = 0;
286 // Simple hash combiner: FNV-1a inspired for 128-bit data
287 constexpr size_t fnv_prime = sizeof(size_t) == 8 ? 0x100000001b3ULL : 0x01000193U;
288 constexpr size_t fnv_offset = sizeof(size_t) == 8 ? 0xcbf29ce484222325ULL : 0x811c9dc5U;
289 hash_value = fnv_offset;
290 for (size_t i = 0; i < sizeof(Guid); ++i) {
291 hash_value ^= static_cast<size_t>(bytes[i]);
292 hash_value *= fnv_prime;
293 }
294 return hash_value;
295 }
296 };
297}
298
299
300#endif
std::ostream & operator<<(std::ostream &os, const Guid::string &guid)
Definition Guid.h:129
size_t size() const
Number of registered mappings.
A class designed to facilitate exchange of Guid::string objects without additional allocations.
Definition Guid.h:31
static constexpr int stringSize()
Definition Guid.h:37
constexpr std::string_view sv() const
Definition Guid.h:36
This class provides a encapsulation of a GUID/UUID/CLSID/IID data structure (128 bit number).
Definition Guid.h:25
constexpr void fromString(std::string_view s)
Automatic conversion from string representation.
Definition Guid.h:141
static const Guid & null() noexcept
NULL-Guid: static class method.
Definition Guid.cxx:14
void setData3(unsigned short data)
Definition Guid.h:102
bool operator==(const Guid &) const =default
static void create(Guid &guid, GuidGenMethod method=GuidGenDefault)
Create a new Guid default method is currently Random, can be changed by param, API or environment.
Definition Guid.cxx:29
constexpr Guid::string to_fixed_string(bool uppercase=true) const
Definition Guid.h:70
static constexpr size_t StrLen
Definition Guid.h:27
friend bool operator==(std::string_view str, const Guid &rhs)
Equality operator.
Definition Guid.h:106
unsigned short m_data2
Definition Guid.h:115
std::array< unsigned char, 8 > m_data4
Definition Guid.h:117
unsigned short data2() const
Definition Guid.h:95
void setData4(unsigned char data, unsigned int i)
Definition Guid.h:103
unsigned int data1() const
Allow accessors to member data.
Definition Guid.h:94
Guid(bool assign)
Standard constructor (With possible initialization).
Definition Guid.h:45
constexpr Guid()
Standard constructor.
Definition Guid.h:43
void setData2(unsigned short data)
Definition Guid.h:101
unsigned char data4(unsigned int i) const
Definition Guid.h:97
Guid(const Guid &c)=default
Copy constructor.
constexpr void setToNull() noexcept
Definition Guid.h:133
unsigned int m_data1
Definition Guid.h:114
Guid(const std::string &s, FallBack)
Definition Guid.h:48
friend bool operator!=(std::string_view str, const Guid &rhs)
Non-equality operator.
Definition Guid.h:108
static GuidGenMethod initGuidGenMethod()
Checks for POOL_GUID_TIME or POOL_GUID_RANDOM env variables.
Definition Guid.cxx:20
constexpr void toString(std::span< char, StrLen > buf, bool uppercase=true) const noexcept
Automatic conversion to string representation.
auto operator<=>(const Guid &) const =default
Magic spaceship operator.
static constexpr int stringSize()
Definition Guid.h:61
Guid & operator=(const Guid &c)=default
static const GuidGenMethod m_guidGenMethod
Definition Guid.h:85
friend std::ostream & operator<<(std::ostream &os, const Guid &rhs)
Extraction operators.
Definition Guid.cxx:106
constexpr Guid(const char *s)
Definition Guid.h:52
GuidGenMethod
Definition Guid.h:84
@ GuidGenDefault
Definition Guid.h:84
@ GuidGenByTime
Definition Guid.h:84
@ GuidGenRandom
Definition Guid.h:84
void setData1(unsigned int data)
Allow modifiers for member data.
Definition Guid.h:100
constexpr Guid(std::string_view s)
Constructor for Guid from string_view.
Definition Guid.h:50
void fromStringFallBack(const std::string &)
Definition Guid.cxx:86
static bool isGuid(std::string_view) noexcept
Definition Guid.cxx:54
unsigned short data3() const
Definition Guid.h:96
unsigned short m_data3
Definition Guid.h:116
STL namespace.
constexpr auto format(const Guid::string &guid, auto &ctx) const
Definition Guid.h:123
size_t operator()(const Guid &g) const noexcept
Definition Guid.h:279