70 template <
class ElementType, std::
size_t Extent>
71 using span = std::span<ElementType, Extent>;
73 template <
class ElementType, std::ptrdiff_t Extent>
74 using span = gsl::span<ElementType, Extent>;
79 template <
typename TChar>
80 [[nodiscard]]
constexpr inline unsigned char hex2char(TChar
const ch)
noexcept
82 if (ch >=
static_cast<TChar
>(
'0') && ch <=
static_cast<TChar
>(
'9'))
83 return static_cast<unsigned char>(ch -
static_cast<TChar
>(
'0'));
84 if (ch >=
static_cast<TChar
>(
'a') && ch <= static_cast<TChar>(
'f'))
85 return static_cast<unsigned char>(10 + ch -
static_cast<TChar
>(
'a'));
86 if (ch >=
static_cast<TChar
>(
'A') && ch <= static_cast<TChar>(
'F'))
87 return static_cast<unsigned char>(10 + ch -
static_cast<TChar
>(
'A'));
91 template <
typename TChar>
92 [[nodiscard]]
constexpr inline bool is_hex(TChar
const ch)
noexcept
95 (ch >=
static_cast<TChar
>(
'0') && ch <=
static_cast<TChar
>(
'9')) ||
96 (ch >=
static_cast<TChar
>(
'a') && ch <=
static_cast<TChar
>(
'f')) ||
97 (ch >=
static_cast<TChar
>(
'A') && ch <= static_cast<TChar>(
'F'));
100 template <
typename TChar>
101 [[nodiscard]]
constexpr std::basic_string_view<TChar>
to_string_view(TChar
const* str)
noexcept
107 template <
typename StringType>
109 constexpr std::basic_string_view<
110 typename StringType::value_type,
111 typename StringType::traits_type>
156 const uint8_t* begin =
static_cast<const uint8_t*
>(start);
157 const uint8_t* finish =
static_cast<const uint8_t*
>(end);
158 while (begin != finish)
167 const uint8_t* block =
static_cast<const uint8_t*
>(
data);
192 process_byte(
static_cast<unsigned char>((bitCount >> 24) & 0xFF));
193 process_byte(
static_cast<unsigned char>((bitCount >> 16) & 0xFF));
194 process_byte(
static_cast<unsigned char>((bitCount >> 8) & 0xFF));
195 process_byte(
static_cast<unsigned char>((bitCount) & 0xFF));
197 memcpy(digest,
m_digest, 5 *
sizeof(uint32_t));
206 digest[di++] =
static_cast<uint8_t
>(d32[0] >> 24);
207 digest[di++] =
static_cast<uint8_t
>(d32[0] >> 16);
208 digest[di++] =
static_cast<uint8_t
>(d32[0] >> 8);
209 digest[di++] =
static_cast<uint8_t
>(d32[0] >> 0);
211 digest[di++] =
static_cast<uint8_t
>(d32[1] >> 24);
212 digest[di++] =
static_cast<uint8_t
>(d32[1] >> 16);
213 digest[di++] =
static_cast<uint8_t
>(d32[1] >> 8);
214 digest[di++] =
static_cast<uint8_t
>(d32[1] >> 0);
216 digest[di++] =
static_cast<uint8_t
>(d32[2] >> 24);
217 digest[di++] =
static_cast<uint8_t
>(d32[2] >> 16);
218 digest[di++] =
static_cast<uint8_t
>(d32[2] >> 8);
219 digest[di++] =
static_cast<uint8_t
>(d32[2] >> 0);
221 digest[di++] =
static_cast<uint8_t
>(d32[3] >> 24);
222 digest[di++] =
static_cast<uint8_t
>(d32[3] >> 16);
223 digest[di++] =
static_cast<uint8_t
>(d32[3] >> 8);
224 digest[di++] =
static_cast<uint8_t
>(d32[3] >> 0);
226 digest[di++] =
static_cast<uint8_t
>(d32[4] >> 24);
227 digest[di++] =
static_cast<uint8_t
>(d32[4] >> 16);
228 digest[di++] =
static_cast<uint8_t
>(d32[4] >> 8);
229 digest[di++] =
static_cast<uint8_t
>(d32[4] >> 0);
238 for (
size_t i = 0;
i < 16;
i++) {
239 w[
i] =
static_cast<uint32_t
>(
m_block[
i * 4 + 0] << 24);
240 w[
i] |=
static_cast<uint32_t
>(
m_block[
i * 4 + 1] << 16);
241 w[
i] |=
static_cast<uint32_t
>(
m_block[
i * 4 + 2] << 8);
242 w[
i] |=
static_cast<uint32_t
>(
m_block[
i * 4 + 3]);
244 for (
size_t i = 16;
i < 80;
i++) {
254 for (std::size_t
i = 0;
i < 80; ++
i)
260 f = (
b & c) | (~
b & d);
268 f = (
b & c) | (
b & d) | (c & d);
297 template <
typename CharT>
298 inline constexpr CharT
empty_guid[37] =
"00000000-0000-0000-0000-000000000000";
303 template <
typename CharT>
380 template <
class CharT = char,
381 class Traits = std::char_traits<CharT>,
382 class Allocator = std::allocator<CharT>>
383 std::basic_string<CharT, Traits, Allocator>
to_string(uuid
const&
id);
393 constexpr uuid() noexcept = default;
397 std::copy(std::cbegin(arr), std::cend(arr), std::begin(
data));
400 constexpr uuid(std::array<value_type, 16>
const& arr) noexcept :
data{ arr } {}
404 std::copy(std::cbegin(
bytes), std::cend(
bytes), std::begin(
data));
407 template<
typename ForwardIterator>
408 explicit uuid(ForwardIterator first, ForwardIterator last)
410 if (std::distance(first, last) == 16)
411 std::copy(first, last, std::begin(
data));
416 if ((
data[8] & 0x80) == 0x00)
418 else if ((
data[8] & 0xC0) == 0x80)
420 else if ((
data[8] & 0xE0) == 0xC0)
428 if ((
data[6] & 0xF0) == 0x10)
430 else if ((
data[6] & 0xF0) == 0x20)
432 else if ((
data[6] & 0xF0) == 0x30)
434 else if ((
data[6] & 0xF0) == 0x40)
436 else if ((
data[6] & 0xF0) == 0x50)
442 [[nodiscard]]
constexpr bool is_nil() const noexcept
444 for (
size_t i = 0;
i <
data.size(); ++
i)
if (
data[
i] != 0)
return false;
450 data.swap(other.data);
458 template <
typename StringType>
459 [[nodiscard]]
constexpr static bool is_valid_uuid(StringType
const& in_str)
noexcept
462 bool firstDigit =
true;
463 size_t hasBraces = 0;
469 if (str.front() ==
'{')
471 if (hasBraces && str.back() !=
'}')
474 for (
size_t i = hasBraces;
i < str.size() - hasBraces; ++
i)
476 if (str[
i] ==
'-')
continue;
502 template <
typename StringType>
503 [[nodiscard]]
constexpr static std::optional<uuid>
from_string(StringType
const& in_str)
noexcept
506 bool firstDigit =
true;
507 size_t hasBraces = 0;
510 std::array<uint8_t, 16>
data{ { 0 } };
512 if (str.empty())
return {};
514 if (str.front() ==
'{')
516 if (hasBraces && str.back() !=
'}')
519 for (
size_t i = hasBraces;
i < str.size() - hasBraces; ++
i)
521 if (str[
i] ==
'-')
continue;
550 std::array<value_type, 16>
data{ { 0 } };
555 template <
class Elem,
class Traits>
556 friend std::basic_ostream<Elem, Traits>&
operator<<(std::basic_ostream<Elem, Traits>&
s,
uuid const&
id);
558 template<
class CharT,
class Traits,
class Allocator>
559 friend std::basic_string<CharT, Traits, Allocator>
to_string(
uuid const&
id);
561 friend std::hash<uuid>;
570 return lhs.data == rhs.data;
575 return !(lhs == rhs);
580 return lhs.data < rhs.data;
583 template <
class CharT,
586 [[nodiscard]]
inline std::basic_string<CharT, Traits, Allocator>
to_string(
uuid const&
id)
588 std::basic_string<CharT, Traits, Allocator> uustr{ detail::empty_guid<CharT> };
590 for (
size_t i = 0,
index = 0;
i < 36; ++
i)
592 if (
i == 8 ||
i == 13 ||
i == 18 ||
i == 23)
596 uustr[
i] = detail::guid_encoder<CharT>[
id.data[
index] >> 4 & 0x0f];
597 uustr[++
i] = detail::guid_encoder<CharT>[
id.data[
index] & 0x0f];
604 template <
class Elem,
class Traits>
605 std::basic_ostream<Elem, Traits>&
operator<<(std::basic_ostream<Elem, Traits>&
s,
uuid const&
id)
621 static uuid uuid_namespace_dns{ {0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} };
624 static uuid uuid_namespace_url{ {0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} };
627 static uuid uuid_namespace_oid{ {0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} };
630 static uuid uuid_namespace_x500{ {0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} };
636#ifdef UUID_SYSTEM_GENERATOR
637 class uuid_system_generator
640 using result_type = uuid;
647 HRESULT
hr = ::CoCreateGuid(&newId);
651 throw std::system_error(
hr, std::system_category(),
"CoCreateGuid failed");
654 std::array<uint8_t, 16>
bytes =
656 static_cast<unsigned char>((newId.Data1 >> 24) & 0xFF),
657 static_cast<unsigned char>((newId.Data1 >> 16) & 0xFF),
658 static_cast<unsigned char>((newId.Data1 >> 8) & 0xFF),
659 static_cast<unsigned char>((newId.Data1) & 0xFF),
661 (
unsigned char)((newId.Data2 >> 8) & 0xFF),
662 (
unsigned char)((newId.Data2) & 0xFF),
664 (
unsigned char)((newId.Data3 >> 8) & 0xFF),
665 (
unsigned char)((newId.Data3) & 0xFF),
677 return uuid{ std::begin(
bytes), std::end(
bytes) };
679#elif defined(__linux__) || defined(__unix__)
684 std::array<uint8_t, 16>
bytes =
704 return uuid{ std::begin(
bytes), std::end(
bytes) };
706#elif defined(__APPLE__)
707 auto newId = CFUUIDCreate(
NULL);
708 auto bytes = CFUUIDGetUUIDBytes(newId);
711 std::array<uint8_t, 16> arrbytes =
730 return uuid{ std::begin(arrbytes), std::end(arrbytes) };
738 template <
typename UniformRandomNumberGenerator>
751 alignas(uint32_t) uint8_t
bytes[16];
752 for (
int i = 0;
i < 16;
i += 4)
768 std::shared_ptr<UniformRandomNumberGenerator>
generator;
780 template <
typename StringType>
794 std::copy(std::cbegin(nsbytes), std::cend(nsbytes),
bytes);
798 template <
typename CharT,
typename Traits>
801 for (uint32_t c : str)
804 if constexpr (!std::is_same_v<CharT, char>)
826 return uuid{ digest, digest + 16 };
834#ifdef UUID_TIME_GENERATOR
837 class uuid_time_generator
839 using mac_address = std::array<unsigned char, 6>;
841 std::optional<mac_address> device_address;
843 [[nodiscard]]
bool get_mac_address()
845 if (device_address.has_value())
852 auto ret = GetAdaptersInfo(
nullptr, &len);
853 if (ret != ERROR_BUFFER_OVERFLOW)
return false;
854 std::vector<unsigned char> buf(len);
855 auto pips =
reinterpret_cast<PIP_ADAPTER_INFO
>(&buf.front());
856 ret = GetAdaptersInfo(pips, &len);
857 if (ret != ERROR_SUCCESS)
return false;
859 std::copy(pips->Address, pips->Address + 6, std::begin(addr));
860 device_address = addr;
863 return device_address.has_value();
866 [[nodiscard]]
long long get_time_intervals()
868 auto start = std::chrono::system_clock::from_time_t(time_t(-12219292800));
869 auto diff = std::chrono::system_clock::now() - start;
870 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(diff).count();
874 [[nodiscard]]
static unsigned short get_clock_sequence()
876 static std::mt19937 clock_gen(std::random_device{}());
877 static std::uniform_int_distribution<unsigned short> clock_dis;
878 static std::atomic_ushort clock_sequence = clock_dis(clock_gen);
879 return clock_sequence++;
883 [[nodiscard]] uuid operator()()
885 if (get_mac_address())
887 std::array<uuids::uuid::value_type, 16>
data;
889 auto tm = get_time_intervals();
891 auto clock_seq = get_clock_sequence();
895 memcpy(&
data[0], ptm + 4, 4);
896 memcpy(&
data[4], ptm + 2, 2);
897 memcpy(&
data[6], ptm, 2);
899 memcpy(&
data[8], &clock_seq, 2);
909 memcpy(&
data[10], &device_address.value()[0], 6);