| 1 | // Copyright (c) Microsoft Corporation. All rights reserved. |
| 2 | // Licensed under the MIT license. |
| 3 | |
| 4 | #pragma once |
| 5 | |
| 6 | #include <cassert> |
| 7 | #include <cstdint> |
| 8 | #include <cstring> |
| 9 | #include <functional> |
| 10 | #include <string> |
| 11 | |
| 12 | #ifdef _WIN32 |
| 13 | #define NOMINMAX |
| 14 | #define _WINSOCKAPI_ |
| 15 | #include <Windows.h> |
| 16 | #else |
| 17 | #include <uuid/uuid.h> |
| 18 | #endif |
| 19 | |
| 20 | namespace FASTER { |
| 21 | namespace core { |
| 22 | |
| 23 | /// Wrapper for GUIDs, for Windows and Linux. |
| 24 | class Guid { |
| 25 | public: |
| 26 | #ifdef _WIN32 |
| 27 | Guid() { |
| 28 | guid_.Data1 = 0; |
| 29 | guid_.Data2 = 0; |
| 30 | guid_.Data3 = 0; |
| 31 | std::memset(guid_.Data4, 0, 8); |
| 32 | } |
| 33 | #else |
| 34 | Guid() { |
| 35 | uuid_clear(uuid_); |
| 36 | } |
| 37 | #endif |
| 38 | |
| 39 | private: |
| 40 | #ifdef _WIN32 |
| 41 | Guid(const GUID& guid) |
| 42 | : guid_{ guid } { |
| 43 | } |
| 44 | #else |
| 45 | Guid(const uuid_t uuid) { |
| 46 | uuid_copy(uuid_, uuid); |
| 47 | } |
| 48 | #endif |
| 49 | |
| 50 | public: |
| 51 | static Guid Create() { |
| 52 | #ifdef _WIN32 |
| 53 | GUID guid; |
| 54 | HRESULT result = ::CoCreateGuid(&guid); |
| 55 | assert(result == S_OK); |
| 56 | return guid; |
| 57 | #else |
| 58 | uuid_t uuid; |
| 59 | uuid_generate(uuid); |
| 60 | return uuid; |
| 61 | #endif |
| 62 | } |
| 63 | |
| 64 | static Guid Parse(const std::string str) { |
| 65 | #ifdef _WIN32 |
| 66 | GUID guid; |
| 67 | auto result = ::UuidFromString(reinterpret_cast<uint8_t*>(const_cast<char*>(str.c_str())), |
| 68 | &guid); |
| 69 | assert(result = RPC_S_OK); |
| 70 | return guid; |
| 71 | #else |
| 72 | uuid_t uuid; |
| 73 | int result = uuid_parse(const_cast<char*>(str.c_str()), uuid); |
| 74 | assert(result == 0); |
| 75 | return uuid; |
| 76 | #endif |
| 77 | } |
| 78 | |
| 79 | std::string ToString() const { |
| 80 | char buffer[37]; |
| 81 | #ifdef _WIN32 |
| 82 | size_t offset = sprintf(buffer, "%.8lX-%.4hX-%.4hX-" , guid_.Data1, guid_.Data2, guid_.Data3); |
| 83 | for(size_t idx = 0; idx < 2; ++idx) { |
| 84 | offset += sprintf(buffer + offset, "%.2hhX" , guid_.Data4[idx]); |
| 85 | } |
| 86 | offset += sprintf(buffer + offset, "-" ); |
| 87 | for(size_t idx = 2; idx < sizeof(guid_.Data4); ++idx) { |
| 88 | offset += sprintf(buffer + offset, "%.2hhX" , guid_.Data4[idx]); |
| 89 | } |
| 90 | buffer[36] = '\0'; |
| 91 | #else |
| 92 | uuid_unparse(uuid_, buffer); |
| 93 | #endif |
| 94 | return std::string { buffer }; |
| 95 | } |
| 96 | |
| 97 | bool operator==(const Guid& other) const { |
| 98 | #ifdef _WIN32 |
| 99 | return guid_.Data1 == other.guid_.Data1 && |
| 100 | guid_.Data2 == other.guid_.Data2 && |
| 101 | guid_.Data3 == other.guid_.Data3 && |
| 102 | std::memcmp(guid_.Data4, other.guid_.Data4, 8) == 0; |
| 103 | #else |
| 104 | return uuid_compare(uuid_, other.uuid_) == 0; |
| 105 | #endif |
| 106 | } |
| 107 | |
| 108 | uint32_t GetHashCode() const { |
| 109 | #ifdef _WIN32 |
| 110 | // From C#, .NET Reference Framework. |
| 111 | return guid_.Data1 ^ ((static_cast<uint32_t>(guid_.Data2) << 16) | |
| 112 | static_cast<uint32_t>(guid_.Data3)) ^ |
| 113 | ((static_cast<uint32_t>(guid_.Data4[2]) << 24) | guid_.Data4[7]); |
| 114 | #else |
| 115 | uint32_t Data1; |
| 116 | uint16_t Data2; |
| 117 | uint16_t Data3; |
| 118 | std::memcpy(&Data1, uuid_, sizeof(Data1)); |
| 119 | std::memcpy(&Data2, uuid_ + 4, sizeof(Data2)); |
| 120 | std::memcpy(&Data3, uuid_ + 6, sizeof(Data3)); |
| 121 | // From C#, .NET Reference Framework. |
| 122 | return Data1 ^ ((static_cast<uint32_t>(Data2) << 16) | |
| 123 | static_cast<uint32_t>(Data3)) ^ |
| 124 | ((static_cast<uint32_t>(uuid_[10]) << 24) | uuid_[15]); |
| 125 | #endif |
| 126 | } |
| 127 | |
| 128 | private: |
| 129 | #ifdef _WIN32 |
| 130 | GUID guid_; |
| 131 | #else |
| 132 | uuid_t uuid_; |
| 133 | #endif |
| 134 | }; |
| 135 | |
| 136 | } |
| 137 | } // namespace FASTER::core |
| 138 | |
| 139 | /// Implement std::hash<> for GUIDs. |
| 140 | namespace std { |
| 141 | template<> |
| 142 | struct hash<FASTER::core::Guid> { |
| 143 | size_t operator()(const FASTER::core::Guid& val) const { |
| 144 | return val.GetHashCode(); |
| 145 | } |
| 146 | }; |
| 147 | } |
| 148 | |