Audacity 3.2.0
Uuid.cpp
Go to the documentation of this file.
1/*!********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 @file Uuid.cpp
6 @brief Define a class to generate and parse UUIDs
7
8 Dmitry Vedenko
9 **********************************************************************/
10
11/*!********************************************************************
12
13 @class Uuid
14 @brief Platform independent class for generating and parsing UUIDs.
15
16 **********************************************************************/
17
18#include "Uuid.h"
19
20#include <algorithm>
21#include <cstring>
22#include <cassert>
23#include "CFResources.h"
24
25#if defined(USE_UUID_CREATE)
26# include <rpc.h>
27#elif defined(USE_CFUUID)
28# include <CoreFoundation/CFUUID.h>
29#elif defined(USE_LIBUUID)
30# include <uuid/uuid.h>
31#endif
32
33#include "HexHelpers.h"
34
35namespace audacity
36{
37
38constexpr int BRACED_UUID_LENGTH = 38;
39constexpr int UUID_LENGTH = 36;
40constexpr int HEX_UUID_LENGTH = 32;
41
42namespace
43{
44bool readByte(Uuid::Bytes::iterator& outputIt,
45 std::string::const_iterator& inputIt,
46 const std::string::const_iterator& inputEnd)
47{
48 if (inputIt == inputEnd)
49 return false;
50
51 const char c1 = *inputIt++;
52
53 if (!std::isxdigit(c1))
54 return false;
55
56 if (inputIt == inputEnd)
57 return false;
58
59 const char c2 = *inputIt++;
60
61 if (!std::isxdigit(c2))
62 return false;
63
64 *outputIt = static_cast<uint8_t>((HexCharToNum(c1) << 4) | HexCharToNum(c2));
65
66 ++outputIt;
67
68 return true;
69}
70} // namespace
71
73 : Uuid(Bytes {})
74{
75}
76
77Uuid::Uuid(const Bytes& data) noexcept
78 : mData(data)
79{
80}
81
83{
84#if defined(USE_UUID_CREATE)
85 UUID winUid;
86
87 if (RPC_S_OK != ::UuidCreate(&winUid))
88 return {};
89
90 Uuid uuid;
91
92 std::memcpy(uuid.mData.data(), &winUid, sizeof(winUid));
93
94 return uuid;
95#elif defined(USE_CFUUID)
96 CFUUIDBytes bytes = CFUUIDGetUUIDBytes(
97 CF_ptr<CFUUIDRef>{ CFUUIDCreate(NULL) }.get());
98
99 Uuid uuid;
100
101 std::memcpy(uuid.mData.data(), &bytes, sizeof(bytes));
102
103 return uuid;
104#elif defined(USE_LIBUUID)
105 uuid_t newId;
106
107 uuid_generate(newId);
108
109 Uuid uuid;
110
111 std::memcpy(uuid.mData.data(), newId, sizeof(newId));
112
113 return uuid;
114#else
115# error "UUID generator is not defined"
116#endif
117}
118
119Uuid Uuid::FromString(const std::string& str)
120{
121 const size_t length = str.length();
122
123 if (length == 0)
124 return {};
125
126 const bool hasBraces = str[0] == '{';
127
128 if (hasBraces && (length != BRACED_UUID_LENGTH || str.back() != '}'))
129 return {};
130 else if (!hasBraces && length != UUID_LENGTH)
131 return {};
132
133 const unsigned int iteratorOffset = hasBraces ? 1 : 0;
134
135 std::string::const_iterator currentSymbol = str.begin() + iteratorOffset;
136 std::string::const_iterator inputEnd = str.end() - iteratorOffset;
137
138 Uuid uuid;
139 Bytes::iterator currentByte = uuid.mData.begin();
140
141 for (int i = 0; i < 16; ++i)
142 {
143 if (!readByte(currentByte, currentSymbol, inputEnd))
144 return {};
145
146 if (currentSymbol != inputEnd && *currentSymbol == '-')
147 ++currentSymbol;
148 }
149
150 return uuid;
151}
152
153bool Uuid::IsNil() const noexcept
154{
155 return std::all_of(mData.begin(), mData.end(),
156 [](uint8_t c) { return c == 0; });
157}
158
159Uuid::operator bool() const noexcept
160{
161 return !IsNil();
162}
163
164bool Uuid::operator==(const Uuid& rhs) const noexcept
165{
166 return mData == rhs.mData;
167}
168
169bool Uuid::operator!=(const Uuid& rhs) const noexcept
170{
171 return mData != rhs.mData;
172}
173
174bool Uuid::operator>(const Uuid& rhs) const noexcept
175{
176 return mData > rhs.mData;
177}
178
179bool Uuid::operator>=(const Uuid& rhs) const noexcept
180{
181 return mData >= rhs.mData;
182}
183
184bool Uuid::operator<(const Uuid& rhs) const noexcept
185{
186 return mData < rhs.mData;
187}
188
189bool Uuid::operator<=(const Uuid& rhs) const noexcept
190{
191 return mData <= rhs.mData;
192}
193
194const Uuid::Bytes& Uuid::ToBytes() const noexcept
195{
196 return mData;
197}
198
199std::string Uuid::ToString() const
200{
201 char buffer[UUID_LENGTH + 1] = {};
202
203 const int bytesWritten = snprintf(
204 buffer, sizeof(buffer),
205 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
206 mData[0], mData[1], mData[2], mData[3], mData[4], mData[5], mData[6],
207 mData[7], mData[8], mData[9], mData[10], mData[11], mData[12], mData[13],
208 mData[14], mData[15]);
209
210 assert(bytesWritten == UUID_LENGTH);
211
212 return buffer;
213}
214
215std::string Uuid::ToHexString() const
216{
217 char buffer[HEX_UUID_LENGTH + 1] = {};
218
219 const int bytesWritten = snprintf(
220 buffer, sizeof(buffer),
221 "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
222 mData[0], mData[1], mData[2], mData[3], mData[4], mData[5], mData[6],
223 mData[7], mData[8], mData[9], mData[10], mData[11], mData[12], mData[13],
224 mData[14], mData[15]);
225
226 assert(bytesWritten == HEX_UUID_LENGTH);
227
228 return buffer;
229}
230
231// GoldenRatio is a constant, that has 0 and ones uniformly distributed.
232// (It is a binary representation of golden ration number)
233// We need to have different constants for 32 and 64 bit architectures.
234template <int S> struct GoldenRatio;
235
236template <> struct GoldenRatio<4>
237{
238 enum : unsigned
239 {
240 Value = 0x9e3779b9U
241 };
242};
243
244template <> struct GoldenRatio<8>
245{
246 enum : unsigned long long
247 {
248 Value = 0x9e3779b97f4a7c15ULL
249 };
250};
251
252std::size_t Uuid::GetHash() const noexcept
253{
254 const std::hash<uint8_t> hasher;
255
256 constexpr std::size_t goldenRatio = GoldenRatio<sizeof(std::size_t)>::Value;
257
258 std::size_t seed = ~0;
259
260 for (uint8_t byte : mData)
261 {
262 seed ^= hasher(seed) + goldenRatio + (seed << 6) + (seed >> 2);
263 }
264
265 return seed;
266}
267
268} // namespace audacity
Wrap resource pointers from Apple Core SDK for RAII.
#define str(a)
Define helper functions for hex-to-num conversion.
Declare a class to generate and parse UUIDs.
Utility class that generates and parses UUIDs.
Definition: Uuid.h:28
static Uuid Generate()
Generate a new UUID.
Definition: Uuid.cpp:82
bool operator!=(const Uuid &other) const noexcept
Definition: Uuid.cpp:169
bool operator<=(const Uuid &other) const noexcept
Definition: Uuid.cpp:189
std::size_t GetHash() const noexcept
Definition: Uuid.cpp:252
bool operator>=(const Uuid &other) const noexcept
Definition: Uuid.cpp:179
bool operator>(const Uuid &other) const noexcept
Definition: Uuid.cpp:174
bool IsNil() const noexcept
Checks, if the UUID is nil.
Definition: Uuid.cpp:153
Uuid()
Creates a nil UUID.
Definition: Uuid.cpp:72
std::string ToString() const
Get a string in the xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format.
Definition: Uuid.cpp:199
bool operator==(const Uuid &other) const noexcept
Definition: Uuid.cpp:164
bool operator<(const Uuid &other) const noexcept
Definition: Uuid.cpp:184
std::string ToHexString() const
Get a string in the xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx format.
Definition: Uuid.cpp:215
const Bytes & ToBytes() const noexcept
Get the 16 bytes long array with the raw UUID data.
Definition: Uuid.cpp:194
static Uuid FromString(const std::string &str)
Definition: Uuid.cpp:119
std::array< uint8_t, 16 > Bytes
Definition: Uuid.h:30
Bytes mData
Definition: Uuid.h:78
bool readByte(Uuid::Bytes::iterator &outputIt, std::string::const_iterator &inputIt, const std::string::const_iterator &inputEnd)
Definition: Uuid.cpp:44
constexpr int BRACED_UUID_LENGTH
Definition: Uuid.cpp:38
constexpr int HEX_UUID_LENGTH
Definition: Uuid.cpp:40
constexpr int UUID_LENGTH
Definition: Uuid.cpp:39
uint8_t HexCharToNum(char c) noexcept
Definition: HexHelpers.h:20