Skip to content

Commit 9947eb8

Browse files
added uuid
1 parent d8ec48e commit 9947eb8

1 file changed

Lines changed: 236 additions & 0 deletions

File tree

taskflow/utility/uuid.hpp

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
#pragma once
2+
3+
#include <iostream>
4+
#include <cstdio>
5+
#include <cstdlib>
6+
#include <cstring>
7+
#include <cstddef>
8+
#include <random>
9+
#include <chrono>
10+
11+
namespace tf {
12+
13+
// Class: UUID
14+
//
15+
// A universally unique identifier (UUID) is an identifier standard used in software
16+
// construction. A UUID is simply a 128-bit value. The meaning of each bit is defined
17+
// by any of several variants.
18+
// For human-readable display, many systems use a canonical format using hexadecimal
19+
// text with inserted hyphen characters.
20+
//
21+
// For example: 123e4567-e89b-12d3-a456-426655440000
22+
//
23+
// The intent of UUIDs is to enable distributed systems to uniquely identify information
24+
// without significant central coordination.
25+
//
26+
// Copyright 2006 Andy Tompkins.
27+
// Distributed under the Boost Software License, Version 1.0. (See
28+
// accompanying file LICENSE_1_0.txt or copy at
29+
// http://www.boost.org/LICENSE_1_0.txt)
30+
//
31+
struct UUID {
32+
33+
using value_type = uint8_t;
34+
using reference = uint8_t&;
35+
using const_reference = const uint8_t&;
36+
using iterator = uint8_t*;
37+
using const_iterator = const uint8_t*;
38+
using size_type = size_t;
39+
using difference_type = ptrdiff_t;
40+
41+
inline UUID();
42+
43+
UUID(const UUID&) = default;
44+
UUID(UUID&&) = default;
45+
46+
UUID& operator = (const UUID&) = default;
47+
UUID& operator = (UUID&&) = default;
48+
49+
inline static size_type size();
50+
inline iterator begin();
51+
inline const_iterator begin() const;
52+
inline iterator end();
53+
inline const_iterator end() const;
54+
55+
inline bool is_nil() const;
56+
inline void swap(UUID& rhs);
57+
inline size_t hash_value() const;
58+
59+
inline bool operator == (const UUID&) const;
60+
inline bool operator < (const UUID&) const;
61+
inline bool operator > (const UUID&) const;
62+
inline bool operator != (const UUID&) const;
63+
inline bool operator >= (const UUID&) const;
64+
inline bool operator <= (const UUID&) const;
65+
66+
uint8_t data[16] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
67+
68+
inline std::string to_string() const;
69+
};
70+
71+
// Constructor
72+
inline UUID::UUID() {
73+
74+
static thread_local std::random_device rd;
75+
static thread_local std::mt19937 engine {rd()};
76+
77+
std::uniform_int_distribution<unsigned long> distribution(
78+
std::numeric_limits<unsigned long>::min(),
79+
std::numeric_limits<unsigned long>::max()
80+
);
81+
82+
int i = 0;
83+
auto random_value = distribution(engine);
84+
for (auto it=begin(); it!=end(); ++it, ++i) {
85+
if (i == sizeof(unsigned long)) {
86+
random_value = distribution(engine);
87+
i = 0;
88+
}
89+
*it = static_cast<UUID::value_type>((random_value >> (i*8)) & 0xFF);
90+
}
91+
92+
// set variant: must be 0b10xxxxxx
93+
*(begin()+8) &= 0xBF;
94+
*(begin()+8) |= 0x80;
95+
96+
// set version: must be 0b0100xxxx
97+
*(begin()+6) &= 0x4F; //0b01001111
98+
*(begin()+6) |= 0x40; //0b01000000
99+
}
100+
101+
// Function: size
102+
inline typename UUID::size_type UUID::size() {
103+
return 16;
104+
}
105+
106+
// Function: begin
107+
inline typename UUID::iterator UUID::begin() {
108+
return data;
109+
}
110+
111+
// Function: begin
112+
inline typename UUID::const_iterator UUID::begin() const {
113+
return data;
114+
}
115+
116+
// Function: end
117+
inline typename UUID::iterator UUID::end() {
118+
return data+size();
119+
}
120+
121+
// Function: end
122+
inline typename UUID::const_iterator UUID::end() const {
123+
return data+size();
124+
}
125+
126+
// Function: is_nil
127+
inline bool UUID::is_nil() const {
128+
for (std::size_t i = 0; i < sizeof(this->data); ++i) {
129+
if (this->data[i] != 0U) {
130+
return false;
131+
}
132+
}
133+
return true;
134+
}
135+
136+
// Procedure: swap
137+
inline void UUID::swap(UUID& rhs) {
138+
UUID tmp = *this;
139+
*this = rhs;
140+
rhs = tmp;
141+
}
142+
143+
// Function: hash_value
144+
inline size_t UUID::hash_value() const {
145+
size_t seed = 0;
146+
for(auto i=begin(); i != end(); ++i) {
147+
seed ^= static_cast<size_t>(*i) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
148+
}
149+
return seed;
150+
}
151+
152+
// Operator: ==
153+
inline bool UUID::operator == (const UUID& rhs) const {
154+
return std::memcmp(data, rhs.data, sizeof(data)) == 0;
155+
}
156+
157+
// Operator: !=
158+
inline bool UUID::operator != (const UUID& rhs) const {
159+
return std::memcmp(data, rhs.data, sizeof(data)) != 0;
160+
}
161+
162+
// Operator: <
163+
inline bool UUID::operator < (const UUID& rhs) const {
164+
return std::memcmp(data, rhs.data, sizeof(data)) < 0;
165+
}
166+
167+
// Operator: >
168+
inline bool UUID::operator > (const UUID& rhs) const {
169+
return std::memcmp(data, rhs.data, sizeof(data)) > 0;
170+
}
171+
172+
// Operator: <=
173+
inline bool UUID::operator <= (const UUID& rhs) const {
174+
return std::memcmp(data, rhs.data, sizeof(data)) <= 0;
175+
}
176+
177+
// Operator: >=
178+
inline bool UUID::operator >= (const UUID& rhs) const {
179+
return std::memcmp(data, rhs.data, sizeof(data)) >= 0;
180+
}
181+
182+
// Function: to_string
183+
inline std::string UUID::to_string() const {
184+
185+
auto to_char = [](size_t i) {
186+
if (i <= 9) return static_cast<char>('0' + i);
187+
return static_cast<char>('a' + (i-10));
188+
};
189+
190+
std::string result;
191+
result.reserve(36);
192+
193+
std::size_t i=0;
194+
for (auto it = begin(); it!=end(); ++it, ++i) {
195+
196+
const size_t hi = ((*it) >> 4) & 0x0F;
197+
result += to_char(hi);
198+
199+
const size_t lo = (*it) & 0x0F;
200+
result += to_char(lo);
201+
202+
if (i == 3 || i == 5 || i == 7 || i == 9) {
203+
result += '-';
204+
}
205+
}
206+
return result;
207+
}
208+
209+
// Procedure: swap
210+
inline void swap(UUID& lhs, UUID& rhs) {
211+
lhs.swap(rhs);
212+
}
213+
214+
// ostream
215+
inline std::ostream& operator << (std::ostream& os, const UUID& rhs) {
216+
os << rhs.to_string();
217+
return os;
218+
}
219+
220+
}; // End of namespace tf. ---------------------------------------------------
221+
222+
//-----------------------------------------------------------------------------
223+
224+
225+
namespace std {
226+
227+
// Partial specialization: hash<tf::UUID>
228+
template <>
229+
struct hash<tf::UUID> {
230+
size_t operator()(const tf::UUID& rhs) const { return rhs.hash_value(); }
231+
};
232+
233+
234+
} // End of namespace std. ---------------------------------------------------
235+
236+

0 commit comments

Comments
 (0)