diff options
Diffstat (limited to 'nihil.uuid')
| -rw-r--r-- | nihil.uuid/test.cc | 28 | ||||
| -rw-r--r-- | nihil.uuid/uuid.ccm | 458 |
2 files changed, 286 insertions, 200 deletions
diff --git a/nihil.uuid/test.cc b/nihil.uuid/test.cc index 04a6ab5..0f21298 100644 --- a/nihil.uuid/test.cc +++ b/nihil.uuid/test.cc @@ -29,6 +29,8 @@ #include <catch2/catch_test_macros.hpp> +//NOLINTBEGIN(bugprone-unchecked-optional-access) + namespace { @@ -69,7 +71,7 @@ TEST_CASE("uuid: Test multiple default generators", "[uuid]") { std::random_device rd; auto seed_data = std::array<int, std::mt19937::state_size> {}; - std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); + std::ranges::generate(seed_data, std::ref(rd)); std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); std::mt19937 generator(seq); @@ -82,7 +84,7 @@ TEST_CASE("uuid: Test multiple default generators", "[uuid]") { std::random_device rd; auto seed_data = std::array<int, std::mt19937::state_size> {}; - std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); + std::ranges::generate(seed_data, std::ref(rd)); std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); std::mt19937 generator(seq); @@ -99,7 +101,7 @@ TEST_CASE("uuid: Test default generator", "[uuid]") { std::random_device rd; auto seed_data = std::array<int, std::mt19937::state_size> {}; - std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); + std::ranges::generate(seed_data, std::ref(rd)); std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); std::mt19937 generator(seq); @@ -114,7 +116,7 @@ TEST_CASE("uuid: Test random generator (conversion ctor w/ smart ptr)", { std::random_device rd; auto seed_data = std::array<int, std::mt19937::state_size> {}; - std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); + std::ranges::generate(seed_data, std::ref(rd)); std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); std::mt19937 generator(seq); @@ -136,7 +138,7 @@ TEST_CASE("uuid: Test random generator (conversion ctor w/ ptr)", "[uuid]") { std::random_device rd; auto seed_data = std::array<int, std::mt19937::state_size> {}; - std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); + std::ranges::generate(seed_data, std::ref(rd)); std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); auto generator = std::make_unique<std::mt19937>(seq); @@ -158,7 +160,7 @@ TEST_CASE("uuid: Test random generator (conversion ctor w/ ref)", "[uuid]") { std::random_device rd; auto seed_data = std::array<int, std::mt19937::state_size> {}; - std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); + std::ranges::generate(seed_data, std::ref(rd)); std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); std::mt19937 generator(seq); @@ -181,7 +183,7 @@ TEST_CASE("uuid: Test basic random generator (conversion ctor w/ ptr) " { std::random_device rd; auto seed_data = std::array<int, 6> {}; - std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); + std::ranges::generate(seed_data, std::ref(rd)); std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); std::ranlux48_base generator(seq); @@ -204,7 +206,7 @@ TEST_CASE("uuid: Test basic random generator (conversion ctor w/ smart ptr) " { std::random_device rd; auto seed_data = std::array<int, 6> {}; - std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); + std::ranges::generate(seed_data, std::ref(rd)); std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); auto generator = std::make_unique<std::ranlux48_base>(seq); @@ -227,7 +229,7 @@ TEST_CASE("uuid: Test basic random generator (conversion ctor w/ ref) " { std::random_device rd; auto seed_data = std::array<int, 6> {}; - std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); + std::ranges::generate(seed_data, std::ref(rd)); std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); std::ranlux48_base generator(seq); @@ -347,7 +349,8 @@ TEST_CASE("uuid: Test name generator equality (char const*, std::string, " { using namespace std::literals; - uuid_name_generator dgen(uuid::from_string("47183823-2574-4bfd-b411-99ed177d3e43").value()); + auto dgen = uuid_name_generator(uuid::from_string( + "47183823-2574-4bfd-b411-99ed177d3e43").value()); auto id1 = dgen("john"); auto id2 = dgen("john"s); auto id3 = dgen("john"sv); @@ -791,7 +794,7 @@ TEST_CASE("uuid: Test iterators constructor", "[uuid]") } { - uuid::value_type arr[16] = { + uuid::value_type arr[16] = { // NOLINT 0x47, 0x18, 0x38, 0x23, 0x25, 0x74, 0x4b, 0xfd, @@ -837,7 +840,7 @@ TEST_CASE("uuid: Test array constructors", "[uuid]") } { - uuid::value_type arr[16] { + uuid::value_type arr[16] { //NOLINT 0x47, 0x18, 0x38, 0x23, 0x25, 0x74, 0x4b, 0xfd, @@ -995,3 +998,4 @@ TEST_CASE("uuid: Test as_bytes", "[uuid]") } } +//NOLINTEND(bugprone-unchecked-optional-access) diff --git a/nihil.uuid/uuid.ccm b/nihil.uuid/uuid.ccm index 0c46b60..4aa424e 100644 --- a/nihil.uuid/uuid.ccm +++ b/nihil.uuid/uuid.ccm @@ -48,28 +48,37 @@ export module nihil.uuid; namespace nihil { template <typename TChar> -[[nodiscard]] constexpr unsigned char hex2char(TChar const ch) noexcept +[[nodiscard]] constexpr auto hex2char(TChar const ch) noexcept -> unsigned char { if (ch >= static_cast<TChar>('0') && ch <= static_cast<TChar>('9')) - return static_cast<unsigned char>(ch - static_cast<TChar>('0')); + return static_cast<unsigned char>( + ch - static_cast<TChar>('0')); + if (ch >= static_cast<TChar>('a') && ch <= static_cast<TChar>('f')) - return static_cast<unsigned char>(10 + ch - static_cast<TChar>('a')); + return static_cast<unsigned char>( + 10 + ch - static_cast<TChar>('a')); + if (ch >= static_cast<TChar>('A') && ch <= static_cast<TChar>('F')) - return static_cast<unsigned char>(10 + ch - static_cast<TChar>('A')); + return static_cast<unsigned char>( + 10 + ch - static_cast<TChar>('A')); + return 0; } template <typename TChar> -[[nodiscard]] constexpr bool is_hex(TChar const ch) noexcept +[[nodiscard]] constexpr auto is_hex(TChar const ch) noexcept -> bool { - return - (ch >= static_cast<TChar>('0') && ch <= static_cast<TChar>('9')) || - (ch >= static_cast<TChar>('a') && ch <= static_cast<TChar>('f')) || - (ch >= static_cast<TChar>('A') && ch <= static_cast<TChar>('F')); + return (ch >= static_cast<TChar>('0') && + ch <= static_cast<TChar>('9')) || + (ch >= static_cast<TChar>('a') && + ch <= static_cast<TChar>('f')) || + (ch >= static_cast<TChar>('A') && + ch <= static_cast<TChar>('F')); } template <typename TChar> -[[nodiscard]] constexpr std::basic_string_view<TChar> to_string_view(TChar const * str) noexcept +[[nodiscard]] constexpr auto to_string_view(TChar const *str) noexcept + -> std::basic_string_view<TChar> { if (str) return str; @@ -77,101 +86,117 @@ template <typename TChar> } template <typename StringType> -[[nodiscard]] -constexpr std::basic_string_view< - typename StringType::value_type, - typename StringType::traits_type> -to_string_view(StringType const & str) noexcept +[[nodiscard]] constexpr auto to_string_view(StringType const &str) noexcept + -> std::basic_string_view< + typename StringType::value_type, + typename StringType::traits_type> { return str; } struct sha1 { - using digest32_t = uint32_t[5]; - using digest8_t = uint8_t[20]; + using digest32_t = std::array<std::uint32_t, 5>; + using digest8_t = std::array<std::uint8_t, 20>; static constexpr unsigned int block_bytes = 64; - [[nodiscard]] inline static uint32_t left_rotate(uint32_t value, size_t const count) noexcept + sha1() { - return (value << count) ^ (value >> (32 - count)); + reset(); } - sha1() + [[nodiscard]] inline static auto + left_rotate(std::uint32_t value, std::size_t const count) noexcept + -> std::uint32_t { - reset(); + return (value << count) ^ (value >> (32 - count)); } - void reset() noexcept + auto reset(this sha1 &self) noexcept -> void { - m_digest[0] = 0x67452301; - m_digest[1] = 0xEFCDAB89; - m_digest[2] = 0x98BADCFE; - m_digest[3] = 0x10325476; - m_digest[4] = 0xC3D2E1F0; - m_blockByteIndex = 0; - m_byteCount = 0; + self.m_digest[0] = 0x67452301; + self.m_digest[1] = 0xEFCDAB89; + self.m_digest[2] = 0x98BADCFE; + self.m_digest[3] = 0x10325476; + self.m_digest[4] = 0xC3D2E1F0; + self.m_blockByteIndex = 0; + self.m_byteCount = 0; } - void process_byte(uint8_t octet) + auto process_byte(this sha1 &self, std::uint8_t octet) -> void { - this->m_block[this->m_blockByteIndex++] = octet; - ++this->m_byteCount; - if (m_blockByteIndex == block_bytes) { - this->m_blockByteIndex = 0; - process_block(); + self.m_block[self.m_blockByteIndex++] = octet; + ++self.m_byteCount; + + if (self.m_blockByteIndex == block_bytes) { + self.m_blockByteIndex = 0; + self.process_block(); } } - void process_block(void const * const start, void const * const end) + auto process_block(this sha1 &self, + void const *const start, + void const *const end) + -> void { - auto *begin = static_cast<const uint8_t*>(start); - auto *finish = static_cast<const uint8_t*>(end); - while (begin != finish) { - process_byte(*begin); - begin++; + auto *first = static_cast<uint8_t const *>(start); + auto *last = static_cast<uint8_t const *>(end); + + while (first != last) { + self.process_byte(*first); + first++; } } - void process_bytes(void const * const data, size_t const len) + auto process_bytes(this sha1 &self, + void const *const data, + size_t const len) + -> void { - auto *block = static_cast<const uint8_t*>(data); - process_block(block, block + len); + auto *block = static_cast<uint8_t const *>(data); + self.process_block(block, block + len); } - uint32_t const * get_digest(digest32_t digest) + auto get_digest(this sha1 &self) -> digest32_t { - size_t const bitCount = this->m_byteCount * 8; - process_byte(0x80); - if (this->m_blockByteIndex > 56) { - while (m_blockByteIndex != 0) - process_byte(0); - while (m_blockByteIndex < 56) - process_byte(0); + auto const bit_count = self.m_byteCount * 8; + + self.process_byte(0x80); + if (self.m_blockByteIndex > 56) { + while (self.m_blockByteIndex != 0) + self.process_byte(0); + + while (self.m_blockByteIndex < 56) + self.process_byte(0); } else { - while (m_blockByteIndex < 56) - process_byte(0); + while (self.m_blockByteIndex < 56) + self.process_byte(0); } - process_byte(0); - process_byte(0); - process_byte(0); - process_byte(0); - process_byte(static_cast<unsigned char>((bitCount >> 24) & 0xFF)); - process_byte(static_cast<unsigned char>((bitCount >> 16) & 0xFF)); - process_byte(static_cast<unsigned char>((bitCount >> 8) & 0xFF)); - process_byte(static_cast<unsigned char>((bitCount) & 0xFF)); - - std::memcpy(digest, m_digest, 5 * sizeof(uint32_t)); - return digest; + self.process_byte(0); + self.process_byte(0); + self.process_byte(0); + self.process_byte(0); + self.process_byte(static_cast<unsigned char>( + (bit_count >> 24) & 0xFF)); + self.process_byte(static_cast<unsigned char>( + (bit_count >> 16) & 0xFF)); + self.process_byte(static_cast<unsigned char>( + (bit_count >> 8) & 0xFF)); + self.process_byte(static_cast<unsigned char>( + (bit_count) & 0xFF)); + + return self.m_digest; } - uint8_t const * get_digest_bytes(digest8_t digest) + auto get_digest_bytes(this sha1 &self) -> digest8_t { - digest32_t d32; - get_digest(d32); - size_t di = 0; + auto d32 = self.get_digest(); + auto digest = digest8_t{}; + + auto di = std::size_t{0}; + digest[di++] = static_cast<uint8_t>(d32[0] >> 24); digest[di++] = static_cast<uint8_t>(d32[0] >> 16); digest[di++] = static_cast<uint8_t>(d32[0] >> 8); @@ -201,28 +226,35 @@ struct sha1 } private: - void process_block() + auto process_block(this sha1 &self) -> void { - uint32_t w[80]; - for (size_t i = 0; i < 16; i++) { - w[i] = static_cast<uint32_t>(m_block[i * 4 + 0] << 24); - w[i] |= static_cast<uint32_t>(m_block[i * 4 + 1] << 16); - w[i] |= static_cast<uint32_t>(m_block[i * 4 + 2] << 8); - w[i] |= static_cast<uint32_t>(m_block[i * 4 + 3]); + auto w = std::array<std::uint32_t, 80>(); + + for (std::size_t i = 0; i < 16; i++) { + w[i] = static_cast<std::uint32_t>( + self.m_block[i * 4 + 0]) << 24; + w[i] |= static_cast<std::uint32_t>( + self.m_block[i * 4 + 1]) << 16; + w[i] |= static_cast<std::uint32_t>( + self.m_block[i * 4 + 2]) << 8; + w[i] |= static_cast<std::uint32_t>( + self.m_block[i * 4 + 3]); } - for (size_t i = 16; i < 80; i++) { - w[i] = left_rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1); + + for (std::size_t i = 16; i < 80; i++) { + w[i] = left_rotate((w[i - 3] ^ w[i - 8] ^ + w[i - 14] ^ w[i - 16]), 1); } - uint32_t a = m_digest[0]; - uint32_t b = m_digest[1]; - uint32_t c = m_digest[2]; - uint32_t d = m_digest[3]; - uint32_t e = m_digest[4]; + auto a = self.m_digest[0]; + auto b = self.m_digest[1]; + auto c = self.m_digest[2]; + auto d = self.m_digest[3]; + auto e = self.m_digest[4]; for (std::size_t i = 0; i < 80; ++i) { - uint32_t f = 0; - uint32_t k = 0; + auto f = std::uint32_t{0}; + auto k = std::uint32_t{0}; if (i < 20) { f = (b & c) | (~b & d); @@ -238,7 +270,8 @@ private: k = 0xCA62C1D6; } - uint32_t temp = left_rotate(a, 5) + f + e + k + w[i]; + auto temp = std::uint32_t{left_rotate(a, 5) + + f + e + k + w[i]}; e = d; d = c; c = left_rotate(b, 30); @@ -246,45 +279,54 @@ private: a = temp; } - m_digest[0] += a; - m_digest[1] += b; - m_digest[2] += c; - m_digest[3] += d; - m_digest[4] += e; + self.m_digest[0] += a; + self.m_digest[1] += b; + self.m_digest[2] += c; + self.m_digest[3] += d; + self.m_digest[4] += e; } - digest32_t m_digest; - uint8_t m_block[64]; - size_t m_blockByteIndex; - size_t m_byteCount; + digest32_t m_digest; + std::array<std::uint8_t, 64> m_block; + std::size_t m_blockByteIndex; + std::size_t m_byteCount; }; template <typename CharT> -inline constexpr CharT empty_guid[37] = "00000000-0000-0000-0000-000000000000"; +inline constexpr std::string_view empty_guid = + "00000000-0000-0000-0000-000000000000"; template <> -inline constexpr wchar_t empty_guid<wchar_t>[37] = L"00000000-0000-0000-0000-000000000000"; +inline constexpr std::wstring_view empty_guid<wchar_t> + = L"00000000-0000-0000-0000-000000000000"; template <typename CharT> -inline constexpr CharT guid_encoder[17] = "0123456789abcdef"; +inline constexpr std::string_view guid_encoder = "0123456789abcdef"; template <> -inline constexpr wchar_t guid_encoder<wchar_t>[17] = L"0123456789abcdef"; +inline constexpr std::wstring_view guid_encoder<wchar_t> = L"0123456789abcdef"; -// -------------------------------------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------- // UUID format https://tools.ietf.org/html/rfc4122 -// -------------------------------------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------- -// -------------------------------------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------- // Field NDR Data Type Octet # Note -// -------------------------------------------------------------------------------------------------------------------------- -// time_low unsigned long 0 - 3 The low field of the timestamp. -// time_mid unsigned short 4 - 5 The middle field of the timestamp. -// time_hi_and_version unsigned short 6 - 7 The high field of the timestamp multiplexed with the version number. -// clock_seq_hi_and_reserved unsigned small 8 The high field of the clock sequence multiplexed with the variant. -// clock_seq_low unsigned small 9 The low field of the clock sequence. -// node character 10 - 15 The spatially unique node identifier. -// -------------------------------------------------------------------------------------------------------------------------- +// Note +// --------------------------------------------------------------------- +// time_low unsigned long 0 - 3 +// The low field of the timestamp. +// time_mid unsigned short 4 - 5 +// The middle field of the timestamp. +// time_hi_and_version unsigned short 6 - 7 +// The high field of the timestamp multiplexed with the version number. +// clock_seq_hi_and_reserved unsigned small 8 +// The high field of the clock sequence multiplexed with the variant. +// clock_seq_low unsigned small 9 +// The low field of the clock sequence. +// node character 10 - 15 +// The spatially unique node identifier. +// --------------------------------------------------------------------- // 0 1 2 3 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -297,18 +339,22 @@ inline constexpr wchar_t guid_encoder<wchar_t>[17] = L"0123456789abcdef"; // | node (2-5) | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// -------------------------------------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------- // enumerations -// -------------------------------------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------- -// indicated by a bit pattern in octet 8, marked with N in xxxxxxxx-xxxx-xxxx-Nxxx-xxxxxxxxxxxx +// indicated by a bit pattern in octet 8, marked with N in +// xxxxxxxx-xxxx-xxxx-Nxxx-xxxxxxxxxxxx export enum struct uuid_variant { - // NCS backward compatibility (with the obsolete Apollo Network Computing System 1.5 UUID format) + // NCS backward compatibility (with the obsolete Apollo Network + // Computing System 1.5 UUID format). // N bit pattern: 0xxx - // > the first 6 octets of the UUID are a 48-bit timestamp (the number of 4 microsecond units of time since 1 Jan 1980 UTC); + // > the first 6 octets of the UUID are a 48-bit timestamp (the number + // of 4 microsecond units of time since 1 Jan 1980 UTC); // > the next 2 octets are reserved; // > the next octet is the "address family"; - // > the final 7 octets are a 56-bit host ID in the form specified by the address family + // > the final 7 octets are a 56-bit host ID in the form specified by + // the address family ncs, // RFC 4122/DCE 1.1 @@ -327,37 +373,45 @@ export enum struct uuid_variant { reserved }; -// indicated by a bit pattern in octet 6, marked with M in xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx +// indicated by a bit pattern in octet 6, marked with M in +// xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx export enum struct uuid_version { - none = 0, // only possible for nil or invalid uuids - time_based = 1, // The time-based version specified in RFC 4122 - dce_security = 2, // DCE Security version, with embedded POSIX UIDs. - name_based_md5 = 3, // The name-based version specified in RFS 4122 with MD5 hashing - random_number_based = 4, // The randomly or pseudo-randomly generated version specified in RFS 4122 - name_based_sha1 = 5 // The name-based version specified in RFS 4122 with SHA1 hashing + // only possible for nil or invalid uuids + none = 0, + // The time-based version specified in RFC 4122 + time_based = 1, + // DCE Security version, with embedded POSIX UIDs. + dce_security = 2, + // The name-based version specified in RFS 4122 with MD5 hashing + name_based_md5 = 3, + // The randomly or pseudo-randomly generated version specified in RFS 4122 + random_number_based = 4, + // The name-based version specified in RFS 4122 with SHA1 hashing + name_based_sha1 = 5 }; -// Forward declare uuid & to_string so that we can declare to_string as a friend later. +// Forward declare uuid and to_string so that we can declare to_string as a +// friend later. export struct uuid; export template <typename CharT = char, typename Traits = std::char_traits<CharT>, typename Allocator = std::allocator<CharT>> -std::basic_string<CharT, Traits, Allocator> to_string(uuid const &id); +auto to_string(uuid const &id) -> std::basic_string<CharT, Traits, Allocator>; // -------------------------------------------------------------------------------------------------------------------------- // uuid class // -------------------------------------------------------------------------------------------------------------------------- export struct uuid { - using value_type = uint8_t; + using value_type = std::uint8_t; constexpr uuid() noexcept = default; - uuid(value_type(&arr)[16]) noexcept + uuid(value_type(&arr)[16]) noexcept // NOLINT { std::ranges::copy(arr, std::ranges::begin(data)); } - constexpr uuid(std::array<value_type, 16> const & arr) noexcept + constexpr uuid(std::array<value_type, 16> const &arr) noexcept : data{arr} { } @@ -367,14 +421,23 @@ export struct uuid { std::ranges::copy(bytes, std::ranges::begin(data)); } + explicit uuid(std::span<value_type> bytes) + { + if (bytes.size() != 16) + throw std::logic_error("wrong size for uuid"); + std::ranges::copy(bytes, std::ranges::begin(data)); + } + template<typename ForwardIterator> explicit uuid(ForwardIterator first, ForwardIterator last) { - if (std::distance(first, last) == 16) - std::copy(first, last, std::begin(data)); + if (std::distance(first, last) != 16) + throw std::logic_error("wrong size for uuid"); + + std::copy(first, last, std::begin(data)); } - [[nodiscard]] constexpr uuid_variant variant() const noexcept + [[nodiscard]] constexpr auto variant() const noexcept -> uuid_variant { if ((data[8] & 0x80) == 0x00) return uuid_variant::ncs; @@ -386,7 +449,7 @@ export struct uuid { return uuid_variant::reserved; } - [[nodiscard]] constexpr uuid_version version() const noexcept + [[nodiscard]] constexpr auto version() const noexcept -> uuid_version { if ((data[6] & 0xF0) == 0x10) return uuid_version::time_based; @@ -402,37 +465,43 @@ export struct uuid { return uuid_version::none; } - [[nodiscard]] constexpr bool is_nil() const noexcept + [[nodiscard]] constexpr auto is_nil() const noexcept -> bool { - for (size_t i = 0; i < data.size(); ++i) - if (data[i] != 0) + for (auto i : data) + if (i != 0) return false; return true; } - void swap(uuid &other) noexcept + auto swap(uuid &other) noexcept -> void { data.swap(other.data); } - [[nodiscard]] inline std::span<std::byte const, 16> as_bytes() const + [[nodiscard]] inline auto as_bytes() const + -> std::span<std::byte const, 16> { - return std::span<std::byte const, 16>(reinterpret_cast<std::byte const*>(data.data()), 16); + return std::span<std::byte const, 16>( + reinterpret_cast<std::byte const*>(data.data()), + 16); } template <typename StringType> - [[nodiscard]] constexpr static bool is_valid_uuid(StringType const & in_str) noexcept + [[nodiscard]] constexpr static auto + is_valid_uuid(StringType const &in_str) noexcept + -> bool { auto str = to_string_view(in_str); - bool firstDigit = true; - size_t hasBraces = 0; - size_t index = 0; + auto firstDigit = true; + auto hasBraces = std::size_t{0}; + auto index = std::size_t{0}; if (str.empty()) return false; if (str.front() == '{') hasBraces = 1; + if (hasBraces && str.back() != '}') return false; @@ -458,7 +527,9 @@ export struct uuid { } template <typename StringType> - [[nodiscard]] constexpr static std::optional<uuid> from_string(StringType const & in_str) noexcept + [[nodiscard]] constexpr static auto + from_string(StringType const & in_str) noexcept + -> std::optional<uuid> { auto str = to_string_view(in_str); bool firstDigit = true; @@ -503,14 +574,17 @@ export struct uuid { private: std::array<value_type, 16> data{ { 0 } }; - friend bool operator==(uuid const & lhs, uuid const & rhs) noexcept; - friend bool operator<(uuid const & lhs, uuid const & rhs) noexcept; + friend auto operator==(uuid const &, uuid const &) noexcept -> bool; + friend auto operator<(uuid const &, uuid const &) noexcept -> bool; template <class Elem, class Traits> - friend std::basic_ostream<Elem, Traits> & operator<<(std::basic_ostream<Elem, Traits> &s, uuid const & id); + friend auto operator<<(std::basic_ostream<Elem, Traits> &s, + uuid const &id) + -> std::basic_ostream<Elem, Traits> &; template<class CharT, class Traits, class Allocator> - friend std::basic_string<CharT, Traits, Allocator> to_string(uuid const& id); + friend auto to_string(uuid const &id) + -> std::basic_string<CharT, Traits, Allocator>; friend std::hash<uuid>; }; @@ -520,19 +594,19 @@ private: // -------------------------------------------------------------------------------------------------------------------------- export [[nodiscard]] -auto operator== (uuid const& lhs, uuid const& rhs) noexcept -> bool +auto operator== (uuid const &lhs, uuid const &rhs) noexcept -> bool { return lhs.data == rhs.data; } export [[nodiscard]] -auto operator!= (uuid const& lhs, uuid const& rhs) noexcept -> bool +auto operator!= (uuid const &lhs, uuid const &rhs) noexcept -> bool { return !(lhs == rhs); } export [[nodiscard]] -auto operator< (uuid const& lhs, uuid const& rhs) noexcept -> bool +auto operator< (uuid const &lhs, uuid const &rhs) noexcept -> bool { return lhs.data < rhs.data; } @@ -541,9 +615,10 @@ export template <typename CharT, typename Traits, typename Allocator> [[nodiscard]] auto to_string(uuid const &id) -> std::basic_string<CharT, Traits, Allocator> { - std::basic_string<CharT, Traits, Allocator> uustr{empty_guid<CharT>}; + auto uustr = std::basic_string<CharT, Traits, Allocator>( + std::from_range, empty_guid<CharT>); - for (size_t i = 0, index = 0; i < 36; ++i) { + for (std::size_t i = 0, index = 0; i < 36; ++i) { if (i == 8 || i == 13 || i == 18 || i == 23) continue; @@ -556,14 +631,14 @@ export template <typename CharT, typename Traits, typename Allocator> } export template <class Elem, class Traits> -auto operator<<(std::basic_ostream<Elem, Traits>& s, uuid const &id) - -> std::basic_ostream<Elem, Traits>& +auto operator<<(std::basic_ostream<Elem, Traits> &s, uuid const &id) + -> std::basic_ostream<Elem, Traits> & { s << to_string(id); return s; } -export void swap(uuid & lhs, uuid & rhs) noexcept +export auto swap(uuid &lhs, uuid &rhs) noexcept -> void { lhs.swap(rhs); } @@ -608,21 +683,24 @@ struct basic_uuid_random_generator { using engine_type = UniformRandomNumberGenerator; - explicit basic_uuid_random_generator(engine_type& gen) + explicit basic_uuid_random_generator(engine_type &gen) : generator(&gen, [](auto) {}) { } - explicit basic_uuid_random_generator(engine_type* gen) + explicit basic_uuid_random_generator(engine_type *gen) : generator(gen, [](auto) {}) { } - [[nodiscard]] uuid operator()() + [[nodiscard]] auto operator()() -> uuid { - alignas(uint32_t) uint8_t bytes[16]; + alignas(std::uint32_t) + auto bytes = std::array<std::uint8_t, 16>{}; + for (int i = 0; i < 16; i += 4) - *reinterpret_cast<uint32_t*>(bytes + i) = distribution(*generator); + *reinterpret_cast<std::uint32_t *>(bytes.data() + i) = + distribution(*generator); // variant must be 10xxxxxx bytes[8] &= 0xBF; @@ -636,7 +714,7 @@ struct basic_uuid_random_generator } private: - std::uniform_int_distribution<uint32_t> distribution; + std::uniform_int_distribution<std::uint32_t> distribution; std::shared_ptr<UniformRandomNumberGenerator> generator; }; @@ -644,13 +722,13 @@ export using uuid_random_generator = basic_uuid_random_generator<std::mt19937>; export struct uuid_name_generator { - explicit uuid_name_generator(uuid const& namespace_uuid) noexcept + explicit uuid_name_generator(uuid const &namespace_uuid) noexcept : nsuuid(namespace_uuid) { } template <typename StringType> - [[nodiscard]] uuid operator()(StringType const & name) + [[nodiscard]] auto operator()(StringType const &name) -> uuid { reset(); process_characters(to_string_view(name)); @@ -658,32 +736,38 @@ export struct uuid_name_generator } private: - void reset() + auto reset() -> void { hasher.reset(); - std::byte bytes[16]; + auto nsbytes = nsuuid.as_bytes(); - std::ranges::copy(nsbytes, bytes); - hasher.process_bytes(bytes, 16); + + auto bytes = std::array<std::byte, 16>(); + std::ranges::copy(nsbytes, std::ranges::begin(bytes)); + + hasher.process_bytes(bytes.data(), bytes.size()); } template <typename CharT, typename Traits> - void process_characters(std::basic_string_view<CharT, Traits> const str) + auto process_characters( + std::basic_string_view<CharT, Traits> const str) -> void { - for (uint32_t c : str) { - hasher.process_byte(static_cast<uint8_t>(c & 0xFF)); + for (std::uint32_t c : str) { + hasher.process_byte(static_cast<std::uint8_t>(c & 0xFF)); if constexpr (!std::is_same_v<CharT, char>) { - hasher.process_byte(static_cast<uint8_t>((c >> 8) & 0xFF)); - hasher.process_byte(static_cast<uint8_t>((c >> 16) & 0xFF)); - hasher.process_byte(static_cast<uint8_t>((c >> 24) & 0xFF)); + hasher.process_byte( + static_cast<uint8_t>((c >> 8) & 0xFF)); + hasher.process_byte( + static_cast<uint8_t>((c >> 16) & 0xFF)); + hasher.process_byte( + static_cast<uint8_t>((c >> 24) & 0xFF)); } } } - [[nodiscard]] uuid make_uuid() + [[nodiscard]] auto make_uuid() -> uuid { - sha1::digest8_t digest; - hasher.get_digest_bytes(digest); + auto digest = hasher.get_digest_bytes(); // variant must be 0b10xxxxxx digest[8] &= 0xBF; @@ -693,7 +777,7 @@ private: digest[6] &= 0x5F; digest[6] |= 0x50; - return uuid{ digest, digest + 16 }; + return uuid(std::span(digest).subspan(0, 16)); } private: @@ -708,9 +792,10 @@ export auto random_uuid() -> uuid { auto rd = std::random_device(); auto seed_data = std::array<int, std::mt19937::state_size> {}; - std::ranges::generate(seed_data, std::ref(rd)); - auto seq = std::seed_seq(std::begin(seed_data), std::end(seed_data)); + + auto seq = std::seed_seq(std::ranges::begin(seed_data), + std::ranges::end(seed_data)); auto generator = std::mt19937(seq); auto gen = uuid_random_generator{generator}; @@ -727,9 +812,10 @@ struct hash<nihil::uuid> using argument_type = nihil::uuid; using result_type = std::size_t; - [[nodiscard]] result_type operator()(argument_type const &uuid) const + [[nodiscard]] auto operator()(argument_type const &uuid) const + -> result_type { - uint64_t l = + std::uint64_t l = static_cast<uint64_t>(uuid.data[0]) << 56 | static_cast<uint64_t>(uuid.data[1]) << 48 | static_cast<uint64_t>(uuid.data[2]) << 40 | @@ -738,7 +824,8 @@ struct hash<nihil::uuid> static_cast<uint64_t>(uuid.data[5]) << 16 | static_cast<uint64_t>(uuid.data[6]) << 8 | static_cast<uint64_t>(uuid.data[7]); - uint64_t h = + + std::uint64_t h = static_cast<uint64_t>(uuid.data[8]) << 56 | static_cast<uint64_t>(uuid.data[9]) << 48 | static_cast<uint64_t>(uuid.data[10]) << 40 | @@ -748,12 +835,7 @@ struct hash<nihil::uuid> static_cast<uint64_t>(uuid.data[14]) << 8 | static_cast<uint64_t>(uuid.data[15]); - if constexpr (sizeof(result_type) > 4) { - return result_type(l ^ h); - } else { - uint64_t hash64 = l ^ h; - return result_type(uint32_t(hash64 >> 32) ^ uint32_t(hash64)); - } + return std::hash<std::uint64_t>{}(l ^ h); } }; |
