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