ATLAS Offline Software
Loading...
Searching...
No Matches
Guid.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 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
121//This may be able to be removed in C++23
122template <>
123struct std::formatter<Guid::string> : std::formatter<std::string_view> {
124 constexpr auto format(const Guid::string& guid, auto& ctx) const {
125 return std::formatter<std::string_view>::format(static_cast<std::string_view>(guid), ctx);
126 }
127};
128
129//This piece of code allows it to be piped into std::ostream without additional boilerplate
130//This may be able to be removed in C++23
131inline std::ostream& operator<<(std::ostream& os, const Guid::string& guid) {
132 return os << static_cast<std::string_view>(guid);
133}
134
135constexpr void Guid::setToNull() noexcept {
136 m_data1 = 0U;
137 m_data2 = 0U;
138 m_data3 = 0U;
139 m_data4.fill('\0');
140}
141
142//This is an unrolled method provided by AI, it should work to ~20ns
143constexpr void Guid::fromString(std::string_view sv) {
144 // Trim any whitespace
145 if(std::is_constant_evaluated() && std::min(sv.find_first_not_of(' '), sv.size()) > 0){
146 throw std::runtime_error("Remove spaces from GUID");
147 }
148 sv.remove_prefix(std::min(sv.find_first_not_of(' '), sv.size()));
149 auto last_non_space = sv.find_last_not_of(' ');
150 if (last_non_space == std::string_view::npos) {
151 sv = {}; // String is empty or all spaces
152 } else {
153 if(std::is_constant_evaluated() && (sv.size() - last_non_space - 1)!=0){
154 throw std::runtime_error("Remove spaces from GUID");
155 }
156 sv.remove_suffix(sv.size() - last_non_space - 1);
157 }
158
159 // Validate format
160 if (sv.size() != 36 ||
161 sv[8] != '-' || sv[13] != '-' || sv[18] != '-' || sv[23] != '-') {
162 setToNull();
163 if(std::is_constant_evaluated()){
164 throw std::runtime_error("failed to compile time parse GUID");
165 }
166 return;
167 }
168 bool success = true;
169 // Custom constexpr hex parser
170 auto parse_hex = [&success](std::string_view part) -> unsigned long long {
171 unsigned long long val = 0;
172 for (char c : part) {
173 val <<= 4; // Multiply by 16
174 if (c >= '0' && c <= '9') {
175 val += static_cast<unsigned long long>(c - '0');
176 } else if (c >= 'a' && c <= 'f') {
177 val += static_cast<unsigned long long>(10 + c - 'a');
178 } else if (c >= 'A' && c <= 'F') {
179 val += static_cast<unsigned long long>(10 + c - 'A');
180 } else {
181 success = false;
182 return 0;
183 }
184 }
185 return val;
186 };
187
188 // Parse m_data1 (positions 0-7)
189 m_data1 = static_cast<unsigned int>(parse_hex(sv.substr(0, 8)));
190
191 // Parse m_data2 (positions 9-12)
192 m_data2 = static_cast<unsigned short>(parse_hex(sv.substr(9, 4)));
193
194 // Parse m_data3 (positions 14-17)
195 m_data3 = static_cast<unsigned short>(parse_hex(sv.substr(14, 4)));
196
197
198 // Parse m_data4 bytes
199 int pos = 19;
200 for(int i =0; i< 2; i++){
201 auto val = parse_hex(sv.substr(pos, 2));
202 m_data4[i] = static_cast<unsigned char>(val);
203 pos+=2;
204 }
205 //Skip the dash at pos 23
206 pos = 24;
207 for(int i =2; i< 8; i++){
208 auto val = parse_hex(sv.substr(pos, 2));
209 m_data4[i] = static_cast<unsigned char>(val);
210 pos+=2;
211 }
212
213 if (!success) {
214 setToNull();
215 if(std::is_constant_evaluated()){
216 throw std::runtime_error("failed to compile time parse GUID");
217 }
218 }
219 return;
220}
221
222//This is an unrolled method provided by ai, is should work to ~20ns
223constexpr void Guid::toString(std::span<char, 36> buf, bool uppercase) const noexcept {
224
225 constexpr char lowhex[] = "0123456789abcdef";
226 constexpr char uphex[] = "0123456789ABCDEF";
227 const char *hex = uppercase ? uphex : lowhex;
228
229 // Unrolled for m_data1 (8 hex digits)
230 unsigned int v1 = m_data1;
231 buf[0] = hex[(v1 >> 28) & 0xF];
232 buf[1] = hex[(v1 >> 24) & 0xF];
233 buf[2] = hex[(v1 >> 20) & 0xF];
234 buf[3] = hex[(v1 >> 16) & 0xF];
235 buf[4] = hex[(v1 >> 12) & 0xF];
236 buf[5] = hex[(v1 >> 8) & 0xF];
237 buf[6] = hex[(v1 >> 4) & 0xF];
238 buf[7] = hex[v1 & 0xF];
239 buf[8] = '-';
240
241 // Unrolled for m_data2 (4 hex digits)
242 unsigned short v2 = m_data2;
243 buf[9] = hex[(v2 >> 12) & 0xF];
244 buf[10] = hex[(v2 >> 8) & 0xF];
245 buf[11] = hex[(v2 >> 4) & 0xF];
246 buf[12] = hex[v2 & 0xF];
247 buf[13] = '-';
248
249 // Unrolled for m_data3 (4 hex digits)
250 unsigned short v3 = m_data3;
251 buf[14] = hex[(v3 >> 12) & 0xF];
252 buf[15] = hex[(v3 >> 8) & 0xF];
253 buf[16] = hex[(v3 >> 4) & 0xF];
254 buf[17] = hex[v3 & 0xF];
255 buf[18] = '-';
256
257 // Unrolled for m_data4[0] and [1] (2+2 hex digits)
258 int pos = 19;
259 for(int i =0; i<2;i++){
260 unsigned char c = m_data4[i];
261 buf[pos] = hex[c >> 4];
262 buf[pos+1] = hex[c & 0xF];
263 pos +=2;
264 }
265 buf[23] = '-';
266 pos = 24;
267 // Unrolled for remaining m_data4[2..7] (6 pairs of hex digits)
268 for(int i =2; i<8;i++){
269 unsigned char c = m_data4[i];
270 buf[pos] = hex[c >> 4];
271 buf[pos+1] = hex[c & 0xF];
272 pos +=2;
273 }
274
275}
276
277
278namespace std {
279 template<>
280 struct hash<Guid> {
281 size_t operator()(const Guid& g) const noexcept {
282 // Treat the Guid as a 16-byte array for hashing.
283 // Checking the memory layout is contiguous and test for padding at compile time.
284 static_assert(sizeof(Guid) == (sizeof(unsigned int) + sizeof(unsigned short)
285 + sizeof(unsigned short) + sizeof(std::array<unsigned char,8>)));
286 const unsigned char* bytes = reinterpret_cast<const unsigned char*>(&g);
287 size_t hash_value = 0;
288 // Simple hash combiner: FNV-1a inspired for 128-bit data
289 constexpr size_t fnv_prime = sizeof(size_t) == 8 ? 0x100000001b3ULL : 0x01000193U;
290 constexpr size_t fnv_offset = sizeof(size_t) == 8 ? 0xcbf29ce484222325ULL : 0x811c9dc5U;
291 hash_value = fnv_offset;
292 for (size_t i = 0; i < sizeof(Guid); ++i) {
293 hash_value ^= static_cast<size_t>(bytes[i]);
294 hash_value *= fnv_prime;
295 }
296 return hash_value;
297 }
298 };
299}
300
301
302#endif
std::ostream & operator<<(std::ostream &os, const Guid::string &guid)
Definition Guid.h:131
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
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:143
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:135
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:124
size_t operator()(const Guid &g) const noexcept
Definition Guid.h:281