EtcPal  HEAD (unstable)
ETC Platform Abstraction Layer (EtcPal)
View other versions:
uuid.h
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2022 ETC Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *******************************************************************************
16  * This file is a part of EtcPal. For more information, go to:
17  * https://github.com/ETCLabs/EtcPal
18  ******************************************************************************/
19 
22 
23 #ifndef ETCPAL_CPP_UUID_H_
24 #define ETCPAL_CPP_UUID_H_
25 
26 #include <cstdint>
27 #include <cstring>
28 #include <array>
29 #include <string>
30 #include "etcpal/pack.h"
31 #include "etcpal/uuid.h"
32 #include "etcpal/cpp/hash.h"
33 
34 namespace etcpal
35 {
36 // clang-format off
69 // clang-format on
70 
72 enum class UuidVersion
73 {
74  kV1 = 1,
75  kV2 = 2,
76  kV3 = 3,
77  kV4 = 4,
78  kV5 = 5,
79  kUnknown
80 };
81 
87 class Uuid
88 {
89 public:
91  Uuid() = default;
92 
93  Uuid(const uint8_t* data) noexcept;
94 
95  // Note: this constructor is not explicit by design, to allow implicit conversions e.g.
96  // etcpal::Uuid uuid = etcpal_c_function_that_returns_uuid();
97  constexpr Uuid(const EtcPalUuid& c_uuid) noexcept;
98  Uuid& operator=(const EtcPalUuid& c_uuid) noexcept;
99 
100  constexpr const EtcPalUuid& get() const noexcept;
101  const uint8_t* data() const noexcept;
102  std::string ToString() const;
103  bool IsNull() const noexcept;
104  UuidVersion version() const noexcept;
105 
108  uint32_t time_low() const noexcept;
109  uint16_t time_mid() const noexcept;
110  uint16_t time_hi_and_version() const noexcept;
111  std::array<uint8_t, 8> clock_seq_and_node() const noexcept;
113 
114  static Uuid FromString(const char* uuid_str) noexcept;
115  static Uuid FromString(const std::string& uuid_str) noexcept;
116  static Uuid V1() noexcept;
117  static Uuid V3(const Uuid& ns, const void* name, size_t name_len) noexcept;
118  static Uuid V3(const Uuid& ns, const char* name) noexcept;
119  static Uuid V3(const Uuid& ns, const std::string& name) noexcept;
120  static Uuid V4() noexcept;
121  static Uuid V5(const Uuid& ns, const void* name, size_t name_len) noexcept;
122  static Uuid V5(const Uuid& ns, const char* name) noexcept;
123  static Uuid V5(const Uuid& ns, const std::string& name) noexcept;
124  static Uuid OsPreferred() noexcept;
125  static Uuid Device(const std::string& device_str, const uint8_t* mac_addr, uint32_t uuid_num) noexcept;
126  static Uuid Device(const std::string& device_str, const std::array<uint8_t, 6>& mac_addr, uint32_t uuid_num) noexcept;
127 
128 private:
130 };
131 
133 constexpr Uuid::Uuid(const EtcPalUuid& c_uuid) noexcept : uuid_(c_uuid)
134 {
135 }
136 
139 inline Uuid::Uuid(const uint8_t* data) noexcept
140 {
141  std::memcpy(uuid_.data, data, ETCPAL_UUID_BYTES);
142 }
143 
145 inline Uuid& Uuid::operator=(const EtcPalUuid& c_uuid) noexcept
146 {
147  uuid_ = c_uuid;
148  return *this;
149 }
150 
152 constexpr const EtcPalUuid& Uuid::get() const noexcept
153 {
154  return uuid_;
155 }
156 
159 inline const uint8_t* Uuid::data() const noexcept
160 {
161  return uuid_.data;
162 }
163 
165 inline std::string Uuid::ToString() const
166 {
167  std::array<char, ETCPAL_UUID_STRING_BYTES> str_buf{};
168  if (etcpal_uuid_to_string(&uuid_, str_buf.data()))
169  return {str_buf.data()};
170  return {};
171 }
172 
174 inline bool Uuid::IsNull() const noexcept
175 {
176  return ETCPAL_UUID_IS_NULL(&uuid_);
177 }
178 
181 inline UuidVersion Uuid::version() const noexcept
182 {
183  uint8_t vers_val = uuid_.data[6] >> 4;
184  return (vers_val >= 1 && vers_val <= 5) ? static_cast<UuidVersion>(vers_val) : UuidVersion::kUnknown;
185 }
186 
188 inline uint32_t Uuid::time_low() const noexcept
189 {
190  return etcpal_unpack_u32b(&uuid_.data[0]);
191 }
192 
194 inline uint16_t Uuid::time_mid() const noexcept
195 {
196  return etcpal_unpack_u16b(&uuid_.data[4]);
197 }
198 
200 inline uint16_t Uuid::time_hi_and_version() const noexcept
201 {
202  return etcpal_unpack_u16b(&uuid_.data[6]);
203 }
204 
207 inline std::array<uint8_t, 8> Uuid::clock_seq_and_node() const noexcept
208 {
209  std::array<uint8_t, 8> res{};
210  std::memcpy(res.data(), &uuid_.data[8], 8);
211  return res;
212 }
213 
216 inline Uuid Uuid::FromString(const char* uuid_str) noexcept
217 {
218  Uuid uuid;
219  etcpal_string_to_uuid(uuid_str, &uuid.uuid_);
220  return uuid;
221 }
222 
225 inline Uuid Uuid::FromString(const std::string& uuid_str) noexcept
226 {
227  return FromString(uuid_str.c_str());
228 }
229 
233 inline Uuid Uuid::V1() noexcept
234 {
235  Uuid uuid;
236  etcpal_generate_v1_uuid(&uuid.uuid_);
237  return uuid;
238 }
239 
243 inline Uuid Uuid::V3(const Uuid& ns, const void* name, size_t name_len) noexcept
244 {
245  Uuid uuid;
246  etcpal_generate_v3_uuid(&ns.get(), name, name_len, &uuid.uuid_);
247  return uuid;
248 }
249 
255 inline Uuid Uuid::V3(const Uuid& ns, const char* name) noexcept
256 {
257  return V3(ns, name, std::strlen(name));
258 }
259 
265 inline Uuid Uuid::V3(const Uuid& ns, const std::string& name) noexcept
266 {
267  return V3(ns, name.c_str(), name.length());
268 }
269 
273 inline Uuid Uuid::V4() noexcept
274 {
275  Uuid uuid;
276  etcpal_generate_v4_uuid(&uuid.uuid_);
277  return uuid;
278 }
279 
283 inline Uuid Uuid::V5(const Uuid& ns, const void* name, size_t name_len) noexcept
284 {
285  Uuid uuid;
286  etcpal_generate_v5_uuid(&ns.get(), name, name_len, &uuid.uuid_);
287  return uuid;
288 }
289 
295 inline Uuid Uuid::V5(const Uuid& ns, const char* name) noexcept
296 {
297  return V5(ns, name, std::strlen(name));
298 }
299 
305 inline Uuid Uuid::V5(const Uuid& ns, const std::string& name) noexcept
306 {
307  return V5(ns, name.c_str(), name.length());
308 }
309 
314 inline Uuid Uuid::OsPreferred() noexcept
315 {
316  Uuid uuid;
318  return uuid;
319 }
320 
324 inline Uuid Uuid::Device(const std::string& device_str, const uint8_t* mac_addr, uint32_t uuid_num) noexcept
325 {
326  Uuid uuid;
327  etcpal_generate_device_uuid(device_str.c_str(), mac_addr, uuid_num, &uuid.uuid_);
328  return uuid;
329 }
330 
334 inline Uuid Uuid::Device(const std::string& device_str,
335  const std::array<uint8_t, 6>& mac_addr,
336  uint32_t uuid_num) noexcept
337 {
338  Uuid uuid;
339  etcpal_generate_device_uuid(device_str.c_str(), mac_addr.data(), uuid_num, &uuid.uuid_);
340  return uuid;
341 }
342 
345 
348 
349 // Special operators for comparing with EtcPalUuids
350 
351 inline bool operator==(const EtcPalUuid& c_uuid, const Uuid& uuid) noexcept
352 {
353  return c_uuid == uuid.get();
354 }
355 
356 inline bool operator!=(const EtcPalUuid& c_uuid, const Uuid& uuid) noexcept
357 {
358  return !(c_uuid == uuid);
359 }
360 
361 inline bool operator==(const Uuid& uuid, const EtcPalUuid& c_uuid) noexcept
362 {
363  return uuid.get() == c_uuid;
364 }
365 
366 inline bool operator!=(const Uuid& uuid, const EtcPalUuid& c_uuid) noexcept
367 {
368  return !(uuid == c_uuid);
369 }
370 
371 // Standard operators
372 
373 inline bool operator==(const Uuid& a, const Uuid& b) noexcept
374 {
375  return a.get() == b.get();
376 }
377 
378 inline bool operator!=(const Uuid& a, const Uuid& b) noexcept
379 {
380  return !(a == b);
381 }
382 
383 inline bool operator<(const Uuid& a, const Uuid& b) noexcept
384 {
385  return a.get() < b.get();
386 }
387 
388 inline bool operator>(const Uuid& a, const Uuid& b) noexcept
389 {
390  return b < a;
391 }
392 
393 inline bool operator<=(const Uuid& a, const Uuid& b) noexcept
394 {
395  return !(b < a);
396 }
397 
398 inline bool operator>=(const Uuid& a, const Uuid& b) noexcept
399 {
400  return !(a < b);
401 }
402 
405 
406 }; // namespace etcpal
407 
409 
410 namespace std
411 {
412 // Inject a new std::hash specialization for etcpal::Uuid, so that UUIDs can be used in hash-based containers (e.g.
413 // unordered_map and unordered_set) without a user needing to create a hash specialization.
414 //
415 // The std::hash specialization combines hashes of each byte of the underlying data.
416 template <>
417 struct hash<::etcpal::Uuid>
418 {
419  std::size_t operator()(const ::etcpal::Uuid& uuid) const noexcept
420  {
421  size_t seed = 0u;
422  for (size_t i = 0; i < ETCPAL_UUID_BYTES; ++i)
423  ::etcpal::HashCombine(seed, uuid.data()[i]);
424 
425  return seed;
426  }
427 };
428 }; // namespace std
429 
431 
432 #endif // ETCPAL_CPP_UUID_H_
A wrapper class for the EtcPal UUID type.
Definition: uuid.h:88
static Uuid V1() noexcept
Generate and return a Version 1 UUID.
Definition: uuid.h:233
uint16_t time_hi_and_version() const noexcept
Get the time_hi_and_version portion of a UUID.
Definition: uuid.h:200
uint32_t time_low() const noexcept
Get the time_low portion of a UUID.
Definition: uuid.h:188
std::string ToString() const
Convert the UUID to a string representation formatted per RFC 4122.
Definition: uuid.h:165
const uint8_t * data() const noexcept
Get the raw data of a UUID.
Definition: uuid.h:159
bool IsNull() const noexcept
Check if a UUID is null (all 0's).
Definition: uuid.h:174
static Uuid Device(const std::string &device_str, const uint8_t *mac_addr, uint32_t uuid_num) noexcept
Generate and return a Device UUID.
Definition: uuid.h:324
static Uuid V4() noexcept
Generate and return a Version 4 UUID.
Definition: uuid.h:273
uint16_t time_mid() const noexcept
Get the time_mid portion of a UUID.
Definition: uuid.h:194
constexpr const EtcPalUuid & get() const noexcept
Get a reference to the underlying C type.
Definition: uuid.h:152
static Uuid FromString(const char *uuid_str) noexcept
Create a UUID from a string representation.
Definition: uuid.h:216
Uuid()=default
Constructs a null UUID by default.
static Uuid V3(const Uuid &ns, const void *name, size_t name_len) noexcept
Generate and return a Version 3 UUID.
Definition: uuid.h:243
std::array< uint8_t, 8 > clock_seq_and_node() const noexcept
Get the remaining portion of a UUID, including clock_seq_hi_and_res, clock_seq_low,...
Definition: uuid.h:207
UuidVersion version() const noexcept
Get the version type of a UUID.
Definition: uuid.h:181
Uuid & operator=(const EtcPalUuid &c_uuid) noexcept
Assign an instance of the C EtcPalUuid type to an instance of this class.
Definition: uuid.h:145
static Uuid OsPreferred() noexcept
Generate and return a UUID of the version preferred by the underlying OS.
Definition: uuid.h:314
static Uuid V5(const Uuid &ns, const void *name, size_t name_len) noexcept
Generate and return a Version 5 UUID.
Definition: uuid.h:283
UuidVersion
Represents a UUID version as defined in RFC 4122.
Definition: uuid.h:73
@ kUnknown
Unknown UUID version.
@ kV3
Version 3 UUID: Namespace-based, MD5.
@ kV1
Version 1 UUID: Date-time and MAC address.
@ kV2
Version 2 UUID: DCE Security version (rarely used)
@ kV5
Version 5 UUID: Namespace-based, SHA-1.
void HashCombine(size_t &seed, const T &val)
A function that combines the hash of a new value into an existing seed, based on boost::hash_combine.
Definition: hash.h:52
uint32_t etcpal_unpack_u32b(const uint8_t *buf)
Unpack a uint32_t from a known big-endian buffer.
Definition: pack.c:174
uint16_t etcpal_unpack_u16b(const uint8_t *buf)
Unpack a uint16_t from a known big-endian buffer.
Definition: pack.c:74
etcpal_error_t etcpal_generate_device_uuid(const char *dev_str, const uint8_t *mac_addr, uint32_t uuid_num, EtcPalUuid *uuid)
Generate a UUID from a combination of a custom string and MAC address.
Definition: uuid.c:309
etcpal_error_t etcpal_generate_v4_uuid(EtcPalUuid *uuid)
Generate a Version 4 UUID.
Definition: uuid.c:216
#define ETCPAL_UUID_IS_NULL(uuidptr)
Determine if a UUID is null.
Definition: uuid.h:119
bool etcpal_uuid_to_string(const EtcPalUuid *uuid, char *buf)
Create a string representation of a UUID.
Definition: uuid.c:61
etcpal_error_t etcpal_generate_v1_uuid(EtcPalUuid *uuid)
Generate a Version 1 UUID.
Definition: uuid.c:152
bool etcpal_string_to_uuid(const char *str, EtcPalUuid *uuid)
Create a UUID from a string representation.
Definition: uuid.c:85
etcpal_error_t etcpal_generate_os_preferred_uuid(EtcPalUuid *uuid)
Generate the preferred UUID version of the underlying OS.
Definition: uuid.c:282
etcpal_error_t etcpal_generate_v5_uuid(const EtcPalUuid *ns, const void *name, size_t name_len, EtcPalUuid *uuid)
Generate a Version 5 UUID.
Definition: uuid.c:243
etcpal_error_t etcpal_generate_v3_uuid(const EtcPalUuid *ns, const void *name, size_t name_len, EtcPalUuid *uuid)
Generate a Version 3 UUID.
Definition: uuid.c:178
#define ETCPAL_UUID_BYTES
The number of bytes that make up a UUID.
Definition: uuid.h:90
const EtcPalUuid kEtcPalNullUuid
A null (all 0's) UUID, used by ETCPAL_UUID_IS_NULL() for comparison.
Definition: uuid.c:46
The UUID type.
Definition: uuid.h:94
uint8_t data[ETCPAL_UUID_BYTES]
The 16-byte UUID data.
Definition: uuid.h:95