diff --git a/include/uuid.h b/include/uuid.h index 3bc0542..cf75155 100644 --- a/include/uuid.h +++ b/include/uuid.h @@ -21,6 +21,36 @@ namespace uuids { + namespace detail + { + template + constexpr inline unsigned char hex2char(TChar const ch) + { + if (ch >= static_cast('0') && ch <= static_cast('9')) + return ch - static_cast('0'); + if (ch >= static_cast('a') && ch <= static_cast('f')) + return 10 + ch - static_cast('a'); + if (ch >= static_cast('A') && ch <= static_cast('F')) + return 10 + ch - static_cast('A'); + return 0; + } + + template + constexpr inline bool is_hex(TChar const ch) + { + return + (ch >= static_cast('0') && ch <= static_cast('9')) || + (ch >= static_cast('a') && ch <= static_cast('f')) || + (ch >= static_cast('A') && ch <= static_cast('F')); + } + + template + constexpr inline unsigned char hexpair2char(TChar const a, TChar const b) + { + return (hex2char(a) << 4) | hex2char(b); + } + } + // UUID format https://tools.ietf.org/html/rfc4122 // Field NDR Data Type Octet # Note // -------------------------------------------------------------------------------------------------------------------------- @@ -397,8 +427,15 @@ namespace uuids std::copy(first, last, std::begin(data)); } - explicit uuid(std::string_view str); - explicit uuid(std::wstring_view str); + explicit uuid(std::string_view str) + { + create(str.data(), str.size()); + } + + explicit uuid(std::wstring_view str) + { + create(str.data(), str.size()); + } constexpr uuid_variant variant() const noexcept { @@ -457,11 +494,43 @@ namespace uuids friend bool operator==(uuid const & lhs, uuid const & rhs) noexcept; friend bool operator<(uuid const & lhs, uuid const & rhs) noexcept; - template - void create(TChar const * const str, size_t const size); - template friend std::basic_ostream & operator<<(std::basic_ostream &s, uuid const & id); + + template + void create(TChar const * const str, size_t const size) + { + TChar digit = 0; + bool firstdigit = true; + size_t index = 0; + + for (size_t i = 0; i < size; ++i) + { + if (str[i] == static_cast('-')) continue; + + if (index >= 16 || !detail::is_hex(str[i])) + { + std::fill(std::begin(data), std::end(data), 0); + return; + } + + if (firstdigit) + { + digit = str[i]; + firstdigit = false; + } + else + { + data[index++] = detail::hexpair2char(digit, str[i]); + firstdigit = true; + } + } + + if (index < 16) + { + std::fill(std::begin(data), std::end(data), 0); + } + } }; inline bool operator== (uuid const& lhs, uuid const& rhs) noexcept @@ -655,81 +724,6 @@ namespace uuids }; using uuid_random_generator = basic_uuid_random_generator; - - namespace detail - { - template - constexpr inline unsigned char hex2char(TChar const ch) - { - if (ch >= static_cast('0') && ch <= static_cast('9')) - return ch - static_cast('0'); - if (ch >= static_cast('a') && ch <= static_cast('f')) - return 10 + ch - static_cast('a'); - if (ch >= static_cast('A') && ch <= static_cast('F')) - return 10 + ch - static_cast('A'); - return 0; - } - - template - constexpr inline bool is_hex(TChar const ch) - { - return - (ch >= static_cast('0') && ch <= static_cast('9')) || - (ch >= static_cast('a') && ch <= static_cast('f')) || - (ch >= static_cast('A') && ch <= static_cast('F')); - } - - template - constexpr inline unsigned char hexpair2char(TChar const a, TChar const b) - { - return (hex2char(a) << 4) | hex2char(b); - } - } - - uuid::uuid(std::string_view str) - { - create(str.data(), str.size()); - } - - uuid::uuid(std::wstring_view str) - { - create(str.data(), str.size()); - } - - template - void uuid::create(TChar const * const str, size_t const size) - { - TChar digit = 0; - bool firstdigit = true; - size_t index = 0; - - for (size_t i = 0; i < size; ++i) - { - if (str[i] == static_cast('-')) continue; - - if (index >= 16 || !detail::is_hex(str[i])) - { - std::fill(std::begin(data), std::end(data), 0); - return; - } - - if (firstdigit) - { - digit = str[i]; - firstdigit = false; - } - else - { - data[index++] = detail::hexpair2char(digit, str[i]); - firstdigit = true; - } - } - - if (index < 16) - { - std::fill(std::begin(data), std::end(data), 0); - } - } } namespace std diff --git a/test/test.cpp b/test/test.cpp index a8d7a1a..d8e455c 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -52,7 +52,7 @@ int main() using namespace std::string_literals; { - std::array arr{ { + std::array arr{ { 0x47, 0x18, 0x38, 0x23, 0x25, 0x74, 0x4b, 0xfd, @@ -64,7 +64,7 @@ int main() } { - uint8_t arr[16] = { + uuids::uuid::value_type arr[16] = { 0x47, 0x18, 0x38, 0x23, 0x25, 0x74, 0x4b, 0xfd, @@ -91,16 +91,17 @@ int main() std::cout << "Test comparison" << std::endl; auto empty = uuid{}; - auto id = uuids::uuid_default_generator{}(); + uuids::uuid_default_generator gen; + auto id = gen(); assert(empty < id); std::set ids{ uuid{}, - uuids::uuid_default_generator{}(), - uuids::uuid_default_generator{}(), - uuids::uuid_default_generator{}(), - uuids::uuid_default_generator{}() + gen(), + gen(), + gen(), + gen() }; assert(ids.size() == 5); @@ -118,12 +119,14 @@ int main() auto h2 = std::hash{}; assert(h1(str) == h2(guid)); + uuids::uuid_default_generator gen; + std::unordered_set ids{ uuid{}, - uuids::uuid_default_generator{}(), - uuids::uuid_default_generator{}(), - uuids::uuid_default_generator{}(), - uuids::uuid_default_generator{}() + gen(), + gen(), + gen(), + gen() }; assert(ids.size() == 5); @@ -161,7 +164,7 @@ int main() { std::cout << "Test iterators" << std::endl; - std::array arr{{ + std::array arr{{ 0x47, 0x18, 0x38, 0x23, 0x25, 0x74, 0x4b, 0xfd,