#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 const & str) { create(str.c_str(), str.size()); } uuid::uuid(std::wstring const & str) { create(str.c_str(), 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), 0); return; } if (firstdigit) { digit = str[i]; firstdigit = false; } else { data[index++] = hexpair2char(digit, str[i]); firstdigit = true; } } if (index < 16) { std::fill(std::begin(data), std::end(data), 0); } } uuid make_uuid() { #ifdef _WIN32 GUID newId; ::CoCreateGuid(&newId); std::array bytes = { (unsigned char)((newId.Data1 >> 24) & 0xFF), (unsigned char)((newId.Data1 >> 16) & 0xFF), (unsigned char)((newId.Data1 >> 8) & 0xFF), (unsigned char)((newId.Data1) & 0xff), (unsigned char)((newId.Data2 >> 8) & 0xFF), (unsigned char)((newId.Data2) & 0xff), (unsigned char)((newId.Data3 >> 8) & 0xFF), (unsigned char)((newId.Data3) & 0xFF), (unsigned char)newId.Data4[0], (unsigned char)newId.Data4[1], (unsigned char)newId.Data4[2], (unsigned char)newId.Data4[3], (unsigned char)newId.Data4[4], (unsigned char)newId.Data4[5], (unsigned char)newId.Data4[6], (unsigned char)newId.Data4[7] }; return uuid{ bytes }; #elif defined(__linux__) || defined(__unix__) uuid_t id; uuid_generate(id); return uuid{ id }; #elif defined(__APPLE__) auto newId = CFUUIDCreate(NULL); auto bytes = CFUUIDGetUUIDBytes(newId); CFRelease(newId); std::array byteArray = { bytes.byte0, bytes.byte1, bytes.byte2, bytes.byte3, bytes.byte4, bytes.byte5, bytes.byte6, bytes.byte7, bytes.byte8, bytes.byte9, bytes.byte10, bytes.byte11, bytes.byte12, bytes.byte13, bytes.byte14, bytes.byte15 }; return uuid{ byteArray }; #elif return uuid{}; #endif } } namespace std { template <> void swap(uuids::uuid & lhs, uuids::uuid & rhs) { lhs.swap(rhs); } }