Stroika Library 3.0d25
 
Loading...
Searching...
No Matches
GUID.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4
6
7 /*
8 ********************************************************************************
9 ********************************* Common::GUID *********************************
10 ********************************************************************************
11 */
12#if qStroika_Platform_MacOS
13 inline GUID::GUID (const uuid_t& src) noexcept
14 : GUID{FromRFC9562Bytes (as_bytes (span<const unsigned char, 16>{src}))}
15 {
16 }
17#elif qStroika_Platform_Windows
18 constexpr GUID::GUID (const ::GUID& src) noexcept
19 : Data1{src.Data1}
20 , Data2{src.Data2}
21 , Data3{src.Data3}
22 {
23 for (size_t i = 0; i < std::size (Data4); ++i) {
24 Data4[i] = src.Data4[i];
25 }
26 }
27#endif
28 constexpr GUID GUID::FromRFC9562Bytes (span<const byte, 16> bytes) noexcept
29 {
30 // by shifting, not copying - so whatever this machine's byte order
31 auto b = [&] (size_t i) { return static_cast<uint32_t> (bytes[i]); };
32 GUID r;
33 r.Data1 = (b (0) << 24) | (b (1) << 16) | (b (2) << 8) | b (3);
34 r.Data2 = static_cast<uint16_t> ((b (4) << 8) | b (5));
35 r.Data3 = static_cast<uint16_t> ((b (6) << 8) | b (7));
36 for (size_t i = 0; i < std::size (r.Data4); ++i) {
37 r.Data4[i] = static_cast<uint8_t> (bytes[8 + i]);
38 }
39 return r;
40 }
41 constexpr array<byte, 16> GUID::AsRFC9562Bytes () const noexcept
42 {
43 array<byte, 16> r{};
44 r[0] = static_cast<byte> (Data1 >> 24);
45 r[1] = static_cast<byte> (Data1 >> 16);
46 r[2] = static_cast<byte> (Data1 >> 8);
47 r[3] = static_cast<byte> (Data1);
48 r[4] = static_cast<byte> (Data2 >> 8);
49 r[5] = static_cast<byte> (Data2);
50 r[6] = static_cast<byte> (Data3 >> 8);
51 r[7] = static_cast<byte> (Data3);
52 for (size_t i = 0; i < std::size (Data4); ++i) {
53 r[8 + i] = static_cast<byte> (Data4[i]);
54 }
55 return r;
56 }
57 namespace Private_ {
58 template <Characters::IConvertibleToString STRISH_TYPE>
59 inline string AsAscii (STRISH_TYPE&& src)
60 {
61 // @todo could be more efficient either using spans and passed in buffer arg for if needed (like with String Peek) but
62 // also could just do additional template specializations in CPP file for cases like string_view or const char*
63 if constexpr (same_as<STRISH_TYPE, Characters::String>) {
64 return src.AsASCII ();
65 }
66 if constexpr (IAnyOf<STRISH_TYPE, const char*, string_view, string>) {
67 return forward<STRISH_TYPE> (src);
68 }
69 return Characters::String{src}.AsASCII ();
70 }
71 }
72 template <Characters::IConvertibleToString STRISH_TYPE>
73 inline GUID::GUID (STRISH_TYPE&& src)
74 : GUID{mk_ (Private_::AsAscii (src))}
75 {
76 }
77 inline Common::GUID::GUID (const array<uint8_t, 16>& src) noexcept
78 {
79 ::memcpy (this, src.data (), 16);
80 }
81 inline const byte* GUID::begin () const noexcept
82 {
83 return reinterpret_cast<const byte*> (this);
84 }
85 inline const byte* GUID::end () const noexcept
86 {
87 return reinterpret_cast<const byte*> (this) + 16;
88 }
89 constexpr size_t GUID::size () const noexcept
90 {
91 return 16;
92 }
93 inline const uint8_t* GUID::data () const noexcept
94 {
95 return reinterpret_cast<const uint8_t*> (this);
96 }
97 template <IAnyOf<Characters::String, std::string, Memory::BLOB, array<byte, 16>, array<uint8_t, 16>> T>
98 inline T Common::GUID::As () const
99 {
100 if constexpr (same_as<T, Characters::String>) {
101 char buf[1024];
102 Verify (::snprintf (buf, std::size (buf), "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", Data1, Data2, Data3, Data4[0],
103 Data4[1], Data4[2], Data4[3], Data4[4], Data4[5], Data4[6], Data4[7]) > 0);
104 return Characters::String{buf};
105 }
106 else if constexpr (same_as<T, std::string>) {
107 char buf[1024];
108 Verify (::snprintf (buf, std::size (buf), "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", Data1, Data2, Data3, Data4[0],
109 Data4[1], Data4[2], Data4[3], Data4[4], Data4[5], Data4[6], Data4[7]) > 0);
110 return buf;
111 }
112 else if constexpr (same_as<T, array<byte, 16>> or same_as<T, array<uint8_t, 16>>) {
113 return *reinterpret_cast<const T*> (this);
114 }
115 else if constexpr (same_as<T, Memory::BLOB>) {
116 return T{begin (), end ()}; // tricky case cuz BLOB forward declared, not defined when this procedure definition first seen
117 }
118 }
119
120}
121
122/*
123 ********************************************************************************
124 ********* formatter<Stroika::Foundation::Common::GUID, char/wchar_t> ***********
125 ********************************************************************************
126 */
127template <class FmtContext>
128inline typename FmtContext::iterator qStroika_Foundation_Characters_FMT_PREFIX_::formatter<Stroika::Foundation::Common::GUID, wchar_t>::format (
129 const Stroika::Foundation::Common::GUID& s, FmtContext& ctx) const
130{
131 return inherited::format (s.As<Stroika::Foundation::Characters::String> ().As<std::wstring> (), ctx);
132}
133template <class FmtContext>
134inline typename FmtContext::iterator
135qStroika_Foundation_Characters_FMT_PREFIX_::formatter<Stroika::Foundation::Common::GUID, char>::format (const Stroika::Foundation::Common::GUID& s,
136 FmtContext& ctx) const
137{
138 return inherited::format (s.As<std::string> (), ctx);
139}
#define Verify(c)
Definition Assertions.h:422
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
constexpr array< byte, 16 > AsRFC9562Bytes() const noexcept
Its 16 bytes in RFC 9562's order - the order its text is written in (.
Definition GUID.inl:41
constexpr GUID() noexcept=default
static constexpr GUID FromRFC9562Bytes(span< const byte, 16 > bytes) noexcept
From its 16 bytes in RFC 9562's order: network byte order, the order its text is written in - as a uu...
Definition GUID.inl:28
nonvirtual const byte * end() const noexcept
Definition GUID.inl:85
nonvirtual const byte * begin() const noexcept
Definition GUID.inl:81
nonvirtual const uint8_t * data() const noexcept
Definition GUID.inl:93