-
-
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?