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());
202SCORE_CLANG_NO_SANITIZE_INTEGER
203constexpr inline std::size_t hash_value(uuid const& u) noexcept
204{
205 std::size_t seed = 0;
206 for(uuid::const_iterator i = u.begin(), e = u.end(); i != e; ++i)
207 {
208 seed ^= static_cast<std::size_t>(*i) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
209 }
210
211 return seed;
212}
213
215{
216 typedef uuid result_type;
217
218 template <int N>
219 static constexpr uuid compute(const char (&s)[N])
220 {
221 static_assert(N == 37, "Invalid uuid");
222 return compute(s, s + N);
223 }
224
225 template <typename CharIterator>
226 static constexpr uuid compute(CharIterator begin, CharIterator end)
227 {
228 // check open brace
229 auto c = *begin++;
230
231 bool has_dashes = false;
232
233 uint8_t u[16]{};
234 int i = 0;
235 for(auto it_byte = u; it_byte != u + 16; ++it_byte, ++i)
236 {
237 if(it_byte != u)
238 {
239 c = *begin++;
240 }
241
242 if(i == 4)
243 {
244 has_dashes = is_dash(c);
245 if(has_dashes)
246 {
247 c = *begin++;
248 }
249 }
250
251 if(has_dashes)
252 {
253 if(i == 6 || i == 8 || i == 10)
254 {
255 if(is_dash(c))
256 {
257 c = *begin++;
258 }
259 else
260 {
261 throw std::runtime_error{"Invalid uuid"};
262 }
263 }
264 }
265 auto res = get_value(c);
266 c = *begin++;
267 res <<= 4;
268 res |= get_value(c);
269 *it_byte = res;
270 }
271
272 return u;
273 }
274
275private:
276 static constexpr unsigned char get_value(char c)
277 {
278 switch(c)
279 {
280 case '0':
281 return 0;
282 case '1':
283 return 1;
284 case '2':
285 return 2;
286 case '3':
287 return 3;
288 case '4':
289 return 4;
290 case '5':
291 return 5;
292 case '6':
293 return 6;
294 case '7':
295 return 7;
296 case '8':
297 return 8;
298 case '9':
299 return 9;
300 case 'a':
301 case 'A':
302 return 10;
303 case 'b':
304 case 'B':
305 return 11;
306 case 'c':
307 case 'C':
308 return 12;
309 case 'd':
310 case 'D':
311 return 13;
312 case 'e':
313 case 'E':
314 return 14;
315 case 'f':
316 case 'F':
317 return 15;
318 default:
319 throw std::runtime_error{"Invalid uuid"};
320 }
321 }
322
323 static constexpr unsigned char get_value(QChar c) { return get_value(c.toLatin1()); }
324
325 static constexpr bool is_dash(char c) { return c == '-'; }
326 static constexpr bool is_dash(QChar c) { return c.toLatin1() == '-'; }
327};
328
329SCORE_LIB_BASE_EXPORT QByteArray toByteArray(score::uuids::uuid const& u);
330
331}
332using uuid_t = uuids::uuid;
333}
334
335#define return_uuid(text) \
336 do \
337 { \
338 constexpr const auto t = score::uuids::string_generator::compute((text)); \
339 return t; \
340 } while(0)
341
342template <typename Tag>
344{
345 using this_type = UuidKey<Tag>;
346
347 friend struct std::hash<this_type>;
348 // friend struct boost::hash<this_type>;
349 // friend struct boost::hash<const this_type>;
350 friend constexpr bool operator==(const this_type& lhs, const this_type& rhs)
351 {
352 return static_cast<const score::uuid_t&>(lhs)
353 == static_cast<const score::uuid_t&>(rhs);
354 }
355 friend constexpr bool operator!=(const this_type& lhs, const this_type& rhs)
356 {
357 return static_cast<const score::uuid_t&>(lhs)
358 != static_cast<const score::uuid_t&>(rhs);
359 }
360 friend constexpr bool operator<(const this_type& lhs, const this_type& rhs)
361 {
362 return static_cast<const score::uuid_t&>(lhs)
363 < static_cast<const score::uuid_t&>(rhs);
364 }
365
366public:
367 constexpr UuidKey() noexcept = default;
368 constexpr UuidKey(const UuidKey& other) noexcept = default;
369 constexpr UuidKey(UuidKey&& other) noexcept = default;
370 constexpr UuidKey& operator=(const UuidKey& other) noexcept = default;
371 constexpr UuidKey& operator=(UuidKey&& other) noexcept = default;
372
373 constexpr UuidKey(score::uuid_t other) noexcept
374 : score::uuid_t(other)
375 {
376 }
377
378 template <int N>
379 explicit constexpr UuidKey(const char (&txt)[N])
380 : score::uuid_t(score::uuids::string_generator::compute<N>(txt))
381 {
382 }
383
384 template <typename Iterator>
385 constexpr UuidKey(Iterator beg_it, Iterator end_it)
386 : score::uuid_t(score::uuids::string_generator::compute(beg_it, end_it))
387 {
388 }
389
390 constexpr static UuidKey fromString(const std::string& str)
391 {
392 return UuidKey{str.begin(), str.end()};
393 }
394
395 constexpr static UuidKey fromString(const QString& str)
396 {
397 return UuidKey{str.begin(), str.end()};
398 }
399
400 constexpr const score::uuid_t& impl() const { return *this; }
401 constexpr score::uuid_t& impl() { return *this; }
402};
403
404namespace std
405{
406template <typename T>
407struct hash<UuidKey<T>>
408{
409 constexpr std::size_t operator()(const UuidKey<T>& kagi) const noexcept
410 {
411 return score::uuids::hash_value(kagi.impl());
412 }
413};
414}
415
416#include <score/serialization/VisitorInterface.hpp>
417template <>
418struct is_custom_serialized<score::uuid_t> : std::true_type
419{
420};
421
422template <>
423struct SCORE_LIB_BASE_EXPORT TSerializer<JSONObject, score::uuid_t>
424{
425 using type = score::uuid_t;
426 static void readFrom(JSONObject::Serializer& s, const type& obj);
427 static void writeTo(JSONObject::Deserializer& s, type& obj);
428};
429
430template <typename U>
432{
433 static void readFrom(JSONObject::Serializer& s, const UuidKey<U>& uid)
434 {
436 }
437
438 static void writeTo(JSONObject::Deserializer& s, UuidKey<U>& uid)
439 {
441 }
442};
443
444template <>
445struct SCORE_LIB_BASE_EXPORT TSerializer<DataStream, score::uuid_t>
446{
447 static void readFrom(DataStream::Serializer& s, const score::uuid_t& obj);
448 static void writeTo(DataStream::Deserializer& s, score::uuid_t& obj);
449};
450
451template <typename U>
453{
454 static void readFrom(DataStream::Serializer& s, const UuidKey<U>& uid)
455 {
457 }
458
459 static void writeTo(DataStream::Deserializer& s, UuidKey<U>& uid)
460 {
462 }
463};
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:344
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:215
Definition UuidKey.hpp:24