Loading...
Searching...
No Matches
UuidKey.hpp
1#pragma once
2#include <score/serialization/VisitorInterface.hpp>
3
4#include <QString>
5
6#include <score_lib_base_export.h>
7
8#include <cstdint>
9#include <stdexcept>
10#include <string>
11
12// Yay for windows defining uuid_t macro
13#if defined(uuid_t)
14#undef uuid_t
15#endif
16
17class JSONObject;
18namespace score
19{
20namespace uuids
21{
22// Taken from boost.uuid
23struct uuid
24{
25public:
26 typedef uint8_t value_type;
27 typedef uint8_t& reference;
28 typedef uint8_t const& const_reference;
29 typedef uint8_t* iterator;
30 typedef uint8_t const* const_iterator;
31 typedef std::size_t size_type;
32 typedef std::ptrdiff_t difference_type;
33
34 static constexpr size_type static_size() noexcept { return 16; }
35
36public:
37 constexpr uuid() noexcept
38 : data{{}}
39 {
40 }
41
42 constexpr uuid(const uuid& other) noexcept
43 : data{other.data[0], other.data[1], other.data[2], other.data[3],
44 other.data[4], other.data[5], other.data[6], other.data[7],
45 other.data[8], other.data[9], other.data[10], other.data[11],
46 other.data[12], other.data[13], other.data[14], other.data[15]}
47 {
48 }
49
50 constexpr uuid& operator=(const uuid& other) noexcept
51 {
52 for(int i = 0; i < 16; i++)
53 data[i] = other.data[i];
54 return *this;
55 }
56
57 constexpr uuid(const uint8_t (&other)[16]) noexcept
58 : data{other[0], other[1], other[2], other[3], other[4], other[5],
59 other[6], other[7], other[8], other[9], other[10], other[11],
60 other[12], other[13], other[14], other[15]}
61 {
62 }
63
64 constexpr auto begin() noexcept { return &data[0]; }
65 constexpr auto end() noexcept { return &data[0] + 16; }
66
67 constexpr auto begin() const noexcept { return &data[0]; }
68 constexpr auto end() const noexcept { return &data[0] + 16; }
69
70 constexpr size_type size() const noexcept { return static_size(); }
71
72 constexpr bool is_nil() const noexcept
73 {
74 for(std::size_t i = 0; i < sizeof(data); ++i)
75 {
76 if(data[i] != 0U)
77 return false;
78 }
79 return true;
80 }
81
82 enum variant_type
83 {
84 variant_ncs, // NCS backward compatibility
85 variant_rfc_4122, // defined in RFC 4122 document
86 variant_microsoft, // Microsoft Corporation backward compatibility
87 variant_future // future definition
88 };
89 variant_type variant() const noexcept
90 {
91 // variant is stored in octet 7
92 // which is index 8, since indexes count backwards
93 unsigned char octet7 = data[8]; // octet 7 is array index 8
94 if((octet7 & 0x80) == 0x00)
95 { // 0b0xxxxxxx
96 return variant_ncs;
97 }
98 else if((octet7 & 0xC0) == 0x80)
99 { // 0b10xxxxxx
100 return variant_rfc_4122;
101 }
102 else if((octet7 & 0xE0) == 0xC0)
103 { // 0b110xxxxx
104 return variant_microsoft;
105 }
106 else
107 {
108 // assert( (octet7 & 0xE0) == 0xE0 ) // 0b111xxxx
109 return variant_future;
110 }
111 }
112
113 enum version_type
114 {
115 version_unknown = -1,
116 version_time_based = 1,
117 version_dce_security = 2,
118 version_name_based_md5 = 3,
119 version_random_number_based = 4,
120 version_name_based_sha1 = 5
121 };
122 version_type version() const noexcept
123 {
124 // version is stored in octet 9
125 // which is index 6, since indexes count backwards
126 uint8_t octet9 = data[6];
127 if((octet9 & 0xF0) == 0x10)
128 {
129 return version_time_based;
130 }
131 else if((octet9 & 0xF0) == 0x20)
132 {
133 return version_dce_security;
134 }
135 else if((octet9 & 0xF0) == 0x30)
136 {
137 return version_name_based_md5;
138 }
139 else if((octet9 & 0xF0) == 0x40)
140 {
141 return version_random_number_based;
142 }
143 else if((octet9 & 0xF0) == 0x50)
144 {
145 return version_name_based_sha1;
146 }
147 else
148 {
149 return version_unknown;
150 }
151 }
152
153public:
154 // or should it be array<uint8_t, 16>
155 uint8_t data[16];
156};
157
158constexpr inline bool operator==(uuid const& lhs, uuid const& rhs) noexcept
159{
160 for(std::size_t i = 0; i < uuid::static_size(); ++i)
161 {
162 if(lhs.data[i] != rhs.data[i])
163 return false;
164 }
165 return true;
166}
167
168constexpr inline bool operator!=(uuid const& lhs, uuid const& rhs) noexcept
169{
170 return !(lhs == rhs);
171}
172
173#if __cpp_lib_constexpr_algorithms >= 201806L
174#define constexpr_algorithm constexpr
175#else
176#define constexpr_algorithm
177#endif
178
179constexpr_algorithm inline bool operator<(uuid const& lhs, uuid const& rhs) noexcept
180{
181 return std::lexicographical_compare(
182 lhs.data, lhs.data + uuid::static_size(), rhs.data,
183 rhs.data + uuid::static_size());
184}
185
186constexpr_algorithm inline bool operator>(uuid const& lhs, uuid const& rhs) noexcept
187{
188 return rhs < lhs;
189}
190
191constexpr_algorithm inline bool operator<=(uuid const& lhs, uuid const& rhs) noexcept
192{
193 return !(rhs < lhs);
194}
195
196constexpr_algorithm inline bool operator>=(uuid const& lhs, uuid const& rhs) noexcept
197{
198 return !(lhs < rhs);
199}
200
201// This is equivalent to boost::hash_range(u.begin(), u.end());
202constexpr inline std::size_t hash_value(uuid const& u) noexcept
203{
204 std::size_t seed = 0;
205 for(uuid::const_iterator i = u.begin(), e = u.end(); i != e; ++i)
206 {
207 seed ^= static_cast<std::size_t>(*i) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
208 }
209
210 return seed;
211}
212
214{
215 typedef uuid result_type;
216
217 template <int N>
218 static constexpr uuid compute(const char (&s)[N])
219 {
220 static_assert(N == 37, "Invalid uuid");
221 return compute(s, s + N);
222 }
223
224 template <typename CharIterator>
225 static constexpr uuid compute(CharIterator begin, CharIterator end)
226 {
227 // check open brace
228 auto c = *begin++;
229
230 bool has_dashes = false;
231
232 uint8_t u[16]{};
233 int i = 0;
234 for(auto it_byte = u; it_byte != u + 16; ++it_byte, ++i)
235 {
236 if(it_byte != u)
237 {
238 c = *begin++;
239 }
240
241 if(i == 4)
242 {
243 has_dashes = is_dash(c);
244 if(has_dashes)
245 {
246 c = *begin++;
247 }
248 }
249
250 if(has_dashes)
251 {
252 if(i == 6 || i == 8 || i == 10)
253 {
254 if(is_dash(c))
255 {
256 c = *begin++;
257 }
258 else
259 {
260 throw std::runtime_error{"Invalid uuid"};
261 }
262 }
263 }
264 auto res = get_value(c);
265 c = *begin++;
266 res <<= 4;
267 res |= get_value(c);
268 *it_byte = res;
269 }
270
271 return u;
272 }
273
274private:
275 static constexpr unsigned char get_value(char c)
276 {
277 switch(c)
278 {
279 case '0':
280 return 0;
281 case '1':
282 return 1;
283 case '2':
284 return 2;
285 case '3':
286 return 3;
287 case '4':
288 return 4;
289 case '5':
290 return 5;
291 case '6':
292 return 6;
293 case '7':
294 return 7;
295 case '8':
296 return 8;
297 case '9':
298 return 9;
299 case 'a':
300 case 'A':
301 return 10;
302 case 'b':
303 case 'B':
304 return 11;
305 case 'c':
306 case 'C':
307 return 12;
308 case 'd':
309 case 'D':
310 return 13;
311 case 'e':
312 case 'E':
313 return 14;
314 case 'f':
315 case 'F':
316 return 15;
317 default:
318 throw std::runtime_error{"Invalid uuid"};
319 }
320 }
321
322 static constexpr unsigned char get_value(QChar c) { return get_value(c.toLatin1()); }
323
324 static constexpr bool is_dash(char c) { return c == '-'; }
325 static constexpr bool is_dash(QChar c) { return c.toLatin1() == '-'; }
326};
327
328SCORE_LIB_BASE_EXPORT QByteArray toByteArray(score::uuids::uuid const& u);
329
330}
331using uuid_t = uuids::uuid;
332}
333
334#define return_uuid(text) \
335 do \
336 { \
337 constexpr const auto t = score::uuids::string_generator::compute((text)); \
338 return t; \
339 } while(0)
340
341template <typename Tag>
343{
344 using this_type = UuidKey<Tag>;
345
346 friend struct std::hash<this_type>;
347 // friend struct boost::hash<this_type>;
348 // friend struct boost::hash<const this_type>;
349 friend constexpr bool operator==(const this_type& lhs, const this_type& rhs)
350 {
351 return static_cast<const score::uuid_t&>(lhs)
352 == static_cast<const score::uuid_t&>(rhs);
353 }
354 friend constexpr bool operator!=(const this_type& lhs, const this_type& rhs)
355 {
356 return static_cast<const score::uuid_t&>(lhs)
357 != static_cast<const score::uuid_t&>(rhs);
358 }
359 friend constexpr bool operator<(const this_type& lhs, const this_type& rhs)
360 {
361 return static_cast<const score::uuid_t&>(lhs)
362 < static_cast<const score::uuid_t&>(rhs);
363 }
364
365public:
366 constexpr UuidKey() noexcept = default;
367 constexpr UuidKey(const UuidKey& other) noexcept = default;
368 constexpr UuidKey(UuidKey&& other) noexcept = default;
369 constexpr UuidKey& operator=(const UuidKey& other) noexcept = default;
370 constexpr UuidKey& operator=(UuidKey&& other) noexcept = default;
371
372 constexpr UuidKey(score::uuid_t other) noexcept
373 : score::uuid_t(other)
374 {
375 }
376
377 template <int N>
378 explicit constexpr UuidKey(const char (&txt)[N])
379 : score::uuid_t(score::uuids::string_generator::compute<N>(txt))
380 {
381 }
382
383 template <typename Iterator>
384 constexpr UuidKey(Iterator beg_it, Iterator end_it)
385 : score::uuid_t(score::uuids::string_generator::compute(beg_it, end_it))
386 {
387 }
388
389 constexpr static UuidKey fromString(const std::string& str)
390 {
391 return UuidKey{str.begin(), str.end()};
392 }
393
394 constexpr static UuidKey fromString(const QString& str)
395 {
396 return UuidKey{str.begin(), str.end()};
397 }
398
399 constexpr const score::uuid_t& impl() const { return *this; }
400 constexpr score::uuid_t& impl() { return *this; }
401};
402
403namespace std
404{
405template <typename T>
406struct hash<UuidKey<T>>
407{
408 constexpr std::size_t operator()(const UuidKey<T>& kagi) const noexcept
409 {
410 return score::uuids::hash_value(kagi.impl());
411 }
412};
413}
414
415#include <score/serialization/VisitorInterface.hpp>
416template <>
417struct is_custom_serialized<score::uuid_t> : std::true_type
418{
419};
420
421template <>
422struct SCORE_LIB_BASE_EXPORT TSerializer<JSONObject, score::uuid_t>
423{
424 using type = score::uuid_t;
425 static void readFrom(JSONObject::Serializer& s, const type& obj);
426 static void writeTo(JSONObject::Deserializer& s, type& obj);
427};
428
429template <typename U>
431{
432 static void readFrom(JSONObject::Serializer& s, const UuidKey<U>& uid)
433 {
435 }
436
437 static void writeTo(JSONObject::Deserializer& s, UuidKey<U>& uid)
438 {
440 }
441};
442
443template <>
444struct SCORE_LIB_BASE_EXPORT TSerializer<DataStream, score::uuid_t>
445{
446 static void readFrom(DataStream::Serializer& s, const score::uuid_t& obj);
447 static void writeTo(DataStream::Deserializer& s, score::uuid_t& obj);
448};
449
450template <typename U>
452{
453 static void readFrom(DataStream::Serializer& s, const UuidKey<U>& uid)
454 {
456 }
457
458 static void writeTo(DataStream::Deserializer& s, UuidKey<U>& uid)
459 {
461 }
462};
Definition VisitorInterface.hpp:53
Definition DataStreamVisitor.hpp:27
Definition DataStreamVisitor.hpp:202
Definition VisitorInterface.hpp:61
Definition JSONVisitor.hpp:52
Definition JSONVisitor.hpp:423
Definition UuidKey.hpp:343
Base toolkit upon which the software is built.
Definition Application.cpp:90
STL namespace.
Definition lv2_atom_helpers.hpp:99
Definition VisitorInterface.hpp:13
Definition UuidKey.hpp:214
Definition UuidKey.hpp:24