#include "uuid.h" #ifdef _WIN32 #include #elif defined(__linux__) || defined(__unix__) #include #elif defined(__APPLE__) #include #endif namespace { template constexpr inline unsigned char hex2char(TChar const ch) { if (ch >= static_cast('0') && ch <= static_cast('9')) return ch - static_cast('0'); if (ch >= static_cast('a') && ch <= static_cast('f')) return 10 + ch - static_cast('a'); if (ch >= static_cast('A') && ch <= static_cast('F')) return 10 + ch - static_cast('A'); return 0; } template constexpr inline bool is_hex(TChar const ch) { return (ch >= static_cast('0') && ch <= static_cast('9')) || (ch >= static_cast('a') && ch <= static_cast('f')) || (ch >= static_cast('A') && ch <= static_cast('F')); } template constexpr inline unsigned char hexpair2char(TChar const a, TChar const b) { return (hex2char(a) << 4) | hex2char(b); } } namespace uuids { uuid::uuid(std::string_view str) { create(str.data(), str.size()); } uuid::uuid(std::wstring_view str) { create(str.data(), str.size()); } template void uuid::create(TChar const * const str, size_t const size) { TChar digit = 0; bool firstdigit = true; size_t index = 0; for (size_t i = 0; i < size; ++i) { if (str[i] == static_cast('-')) continue; if (index >= 16 || !is_hex(str[i])) { std::fill(std::begin(data), std::end(data), std::byte{ 0 }); return; } if (firstdigit) { digit = str[i]; firstdigit = false; } else { data[index++] = std::byte{ hexpair2char(digit, str[i]) }; firstdigit = true; } } if (index < 16) { std::fill(std::begin(data), std::end(data), std::byte{ 0 }); } } uuid make_uuid() { #ifdef _WIN32 GUID newId; ::CoCreateGuid(&newId); std::array bytes = {{ std::byte{ (unsigned char)((newId.Data1 >> 24) & 0xFF) }, std::byte{ (unsigned char)((newId.Data1 >> 16) & 0xFF) }, std::byte{ (unsigned char)((newId.Data1 >> 8) & 0xFF) }, std::byte{ (unsigned char)((newId.Data1) & 0xFF) }, std::byte{ (unsigned char)((newId.Data2 >> 8) & 0xFF) }, std::byte{ (unsigned char)((newId.Data2) & 0xFF) }, std::byte{ (unsigned char)((newId.Data3 >> 8) & 0xFF) }, std::byte{ (unsigned char)((newId.Data3) & 0xFF) }, std::byte{ newId.Data4[0] }, std::byte{ newId.Data4[1] }, std::byte{ newId.Data4[2] }, std::byte{ newId.Data4[3] }, std::byte{ newId.Data4[4] }, std::byte{ newId.Data4[5] }, std::byte{ newId.Data4[6] }, std::byte{ newId.Data4[7] } }}; return uuid{ std::begin(bytes), std::end(bytes) }; #elif defined(__linux__) || defined(__unix__) uuid_t id; uuid_generate(id); std::array bytes = { { std::byte{ id[0] }, std::byte{ id[1] }, std::byte{ id[2] }, std::byte{ id[3] }, std::byte{ id[4] }, std::byte{ id[5] }, std::byte{ id[6] }, std::byte{ id[7] }, std::byte{ id[8] }, std::byte{ id[9] }, std::byte{ id[10] }, std::byte{ id[11] }, std::byte{ id[12] }, std::byte{ id[13] }, std::byte{ id[14] }, std::byte{ id[15] } }}; return uuid { std::begin(bytes), std::end(bytes) }; #elif defined(__APPLE__) auto newId = CFUUIDCreate(NULL); auto bytes = CFUUIDGetUUIDBytes(newId); CFRelease(newId); std::array bytes = {{ std::byte{ bytes.byte0 }, std::byte{ bytes.byte1 }, std::byte{ bytes.byte2 }, std::byte{ bytes.byte3 }, std::byte{ bytes.byte4 }, std::byte{ bytes.byte5 }, std::byte{ bytes.byte6 }, std::byte{ bytes.byte7 }, std::byte{ bytes.byte8 }, std::byte{ bytes.byte9 }, std::byte{ bytes.byte10 }, std::byte{ bytes.byte11 }, std::byte{ bytes.byte12 }, std::byte{ bytes.byte13 }, std::byte{ bytes.byte14 }, std::byte{ bytes.byte15 } }}; return uuid{ std::begin(bytes), std::end(bytes) }; #elif return uuid{}; #endif } } namespace std { template <> void swap(uuids::uuid & lhs, uuids::uuid & rhs) { lhs.swap(rhs); } }