diff --git a/src/uuid.cpp b/src/uuid.cpp index ebb6997..00e7331 100644 --- a/src/uuid.cpp +++ b/src/uuid.cpp @@ -8,8 +8,83 @@ #include #endif +namespace +{ + 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); + } +} + namespace uuids { + uuid::uuid(std::string const & str) + { + create(str.c_str(), str.size()); + } + + uuid::uuid(std::wstring const & str) + { + create(str.c_str(), 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 || !is_hex(str[i])) + { + std::fill(std::begin(data), std::end(data), 0); + return; + } + + if (firstdigit) + { + digit = str[i]; + firstdigit = false; + } + else + { + data[index++] = hexpair2char(digit, str[i]); + firstdigit = true; + } + } + + if (index < 16) + { + std::fill(std::begin(data), std::end(data), 0); + } + } + uuid make_uuid() { #ifdef _WIN32 diff --git a/src/uuid.h b/src/uuid.h index 247d6ac..42b0cb2 100644 --- a/src/uuid.h +++ b/src/uuid.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace uuids { @@ -59,6 +60,7 @@ namespace uuids // indicated by a bit pattern in octet 6, marked with M in xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx enum class version_type { + 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 @@ -91,10 +93,17 @@ namespace uuids typedef std::ptrdiff_t difference_type; public: - constexpr uuid() {} - constexpr uuid(std::array const & bytes) :data{bytes} {} + constexpr explicit uuid() {} + constexpr explicit uuid(std::array const & bytes) :data{bytes} {} + explicit uuid(uint8_t const * const bytes) + { + std::copy(bytes, bytes + 16, std::begin(data)); + } - variant_type variant() const noexcept + explicit uuid(std::string const & str); + explicit uuid(std::wstring const & str); + + constexpr variant_type variant() const noexcept { if ((data[8] & 0x80) == 0x00) return variant_type::ncs; @@ -106,7 +115,7 @@ namespace uuids return variant_type::future; } - version_type version() const + constexpr version_type version() const { if ((data[6] & 0xF0) == 0x10) return version_type::time_based; @@ -119,14 +128,14 @@ namespace uuids else if ((data[6] & 0xF0) == 0x50) return version_type::name_based_sha1; else - throw guid_exception("invalid guid"); + return version_type::none; } - std::size_t size() const noexcept { return 16; } + constexpr std::size_t size() const noexcept { return 16; } - bool is_nil() const noexcept + constexpr bool is_nil() const noexcept { - for (auto const e : data) if (e != 0) return false; + for (size_t i = 0; i < data.size(); ++i) if (data[i] != 0) return false; return true; } @@ -174,6 +183,9 @@ namespace uuids 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); }; diff --git a/test/test_win/stdafx.cpp b/test/test_win/stdafx.cpp deleted file mode 100644 index b2a4568..0000000 Binary files a/test/test_win/stdafx.cpp and /dev/null differ diff --git a/test/test_win/stdafx.h b/test/test_win/stdafx.h deleted file mode 100644 index 94d4ed8..0000000 Binary files a/test/test_win/stdafx.h and /dev/null differ diff --git a/test/test_win/targetver.h b/test/test_win/targetver.h deleted file mode 100644 index 567cd34..0000000 Binary files a/test/test_win/targetver.h and /dev/null differ diff --git a/test/test_win/test_win.cpp b/test/test_win/test_win.cpp index 5354472..47cdec8 100644 Binary files a/test/test_win/test_win.cpp and b/test/test_win/test_win.cpp differ diff --git a/test/test_win/test_win.vcxproj b/test/test_win/test_win.vcxproj index f0db909..1fe8cc1 100644 --- a/test/test_win/test_win.vcxproj +++ b/test/test_win/test_win.vcxproj @@ -89,6 +89,7 @@ Disabled true WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + stdcpplatest Console @@ -102,6 +103,7 @@ Disabled true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + stdcpplatest Console @@ -117,6 +119,7 @@ true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + stdcpplatest Console @@ -134,6 +137,7 @@ true true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + stdcpplatest Console @@ -144,7 +148,6 @@ - diff --git a/test/test_win/test_win.vcxproj.filters b/test/test_win/test_win.vcxproj.filters index 7adf8d3..cc90555 100644 --- a/test/test_win/test_win.vcxproj.filters +++ b/test/test_win/test_win.vcxproj.filters @@ -15,9 +15,6 @@ - - Header Files - Header Files diff --git a/test/test_win/test_win.vcxproj.user b/test/test_win/test_win.vcxproj.user new file mode 100644 index 0000000..baf2417 --- /dev/null +++ b/test/test_win/test_win.vcxproj.user @@ -0,0 +1,6 @@ + + + + false + + \ No newline at end of file