-
-
Save kennykerr/6c948882de395c25b3218ad8d4daf362 to your computer and use it in GitHub Desktop.
| #include <string_view> | |
| #include <exception> | |
| #include <assert.h> | |
| using namespace std::literals; | |
| struct guid | |
| { | |
| uint32_t Data1; | |
| uint16_t Data2; | |
| uint16_t Data3; | |
| uint8_t Data4[8]; | |
| }; | |
| constexpr bool operator==(guid const& left, guid const& right) noexcept | |
| { | |
| return left.Data1 == right.Data1 && | |
| left.Data2 == right.Data2 && | |
| left.Data3 == right.Data3 && | |
| left.Data4[0] == right.Data4[0] && | |
| left.Data4[1] == right.Data4[1] && | |
| left.Data4[2] == right.Data4[2] && | |
| left.Data4[3] == right.Data4[3] && | |
| left.Data4[4] == right.Data4[4] && | |
| left.Data4[5] == right.Data4[5] && | |
| left.Data4[6] == right.Data4[6] && | |
| left.Data4[7] == right.Data4[7]; | |
| } | |
| constexpr uint32_t to_uint(char const value) noexcept | |
| { | |
| if (value >= '0' && value <= '9') | |
| { | |
| return value - '0'; | |
| } | |
| if (value >= 'A' && value <= 'F') | |
| { | |
| return 10 + value - 'A'; | |
| } | |
| if (value >= 'a' && value <= 'f') | |
| { | |
| return 10 + value - 'a'; | |
| } | |
| std::terminate(); | |
| } | |
| constexpr guid make_guid(std::string_view const& value) noexcept | |
| { | |
| if (value.size() != 36 || value[8] != '-' || value[13] != '-' || value[18] != '-' || value[23] != '-') | |
| { | |
| std::terminate(); | |
| } | |
| return | |
| { | |
| ((to_uint(value[0]) * 16 + to_uint(value[1])) << 24) + | |
| ((to_uint(value[2]) * 16 + to_uint(value[3])) << 16) + | |
| ((to_uint(value[4]) * 16 + to_uint(value[5])) << 8) + | |
| (to_uint(value[6]) * 16 + to_uint(value[7])), | |
| static_cast<uint16_t>(((to_uint(value[9]) * 16 + to_uint(value[10])) << 8) + | |
| (to_uint(value[11]) * 16 + to_uint(value[12]))), | |
| static_cast<uint16_t>(((to_uint(value[14]) * 16 + to_uint(value[15])) << 8) + | |
| (to_uint(value[16]) * 16 + to_uint(value[17]))), | |
| { | |
| static_cast<uint8_t>(to_uint(value[19]) * 16 + to_uint(value[20])), | |
| static_cast<uint8_t>(to_uint(value[21]) * 16 + to_uint(value[22])), | |
| static_cast<uint8_t>(to_uint(value[24]) * 16 + to_uint(value[25])), | |
| static_cast<uint8_t>(to_uint(value[26]) * 16 + to_uint(value[27])), | |
| static_cast<uint8_t>(to_uint(value[28]) * 16 + to_uint(value[29])), | |
| static_cast<uint8_t>(to_uint(value[30]) * 16 + to_uint(value[31])), | |
| static_cast<uint8_t>(to_uint(value[32]) * 16 + to_uint(value[33])), | |
| static_cast<uint8_t>(to_uint(value[34]) * 16 + to_uint(value[35])), | |
| } | |
| }; | |
| } | |
| static constexpr guid a | |
| { 0x8aa90cad, 0xfed1, 0x4c54, { 0x89, 0xdb, 0x9b, 0x75, 0x22, 0xd8, 0xaa, 0x92 } }; | |
| static constexpr guid b | |
| { make_guid("8AA90CAD-fed1-4c54-89db-9B7522D8AA92"sv) }; | |
| static_assert(a == b); | |
| int main() | |
| { | |
| assert(a == b); | |
| } |
Hi Howard, if you have a need for this please create an issue and I'll try to knock it off when I get a moment. https://github.com/microsoft/cppwinrt/issues
Ask and ye shall receive :-)
microsoft/cppwinrt#797
Question: Based on the Wikipedia description here:
https://en.wikipedia.org/wiki/Universally_unique_identifier
in the test case above, the first 2 bits of 0x89 (10001001) identify this as "variant 1", which means that the integers should be stored in big-endian order, yes? The MSVC compiler on Intel will assemble the integers in little-endian order. The endianness doesn't matter if the UUIDs are all generated, stored, compared, etc., within a homogeneous MSVC environment, but might matter in some kind of heterogeneous environment -- maybe sending and receiving UUIDs generated on various platforms across the network. If I understand the Wikipedia article correctly, and if the article is correct, either:
- that 0x89 should start with 0xc_ or 0xd_ (1100hhhh or 1101hhhh) to mark this is "variant 2", or
- the integers should be swapped to big-endian order.
Yes? No?
The binary encoding of UUIDs varies between systems. Variant 1 UUIDs, nowadays the most common variant, are encoded in a big-endian format. For example, 00112233-4455-6677-8899-aabbccddeeff is encoded as the bytes 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff
Variant 2 UUIDs, historically used in Microsoft's COM/OLE libraries, use a mixed-endian format, whereby the first three components of the UUID are little-endian, and the last two are big-endian. For example, 00112233-4455-6677-8899-aabbccddeeff is encoded as the bytes 33 22 11 00 55 44 77 66 88 99 aa bb cc dd ee ff
Any plans to add this to C++/WinRT?
And add wchar_t/wstring flavors?