diff --git a/src/uuid.h b/src/uuid.h new file mode 100644 index 0000000..6e1a8e3 --- /dev/null +++ b/src/uuid.h @@ -0,0 +1,234 @@ +#pragma once + +#include +#include +#include +#include + +namespace uuids +{ + // 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. + // -------------------------------------------------------------------------------------------------------------------------- + // 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 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | time_low | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | time_mid | time_hi_and_version | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // |clk_seq_hi_res | clk_seq_low | node (0-1) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | node (2-5) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + // indicated by a bit pattern in octet 8, marked with N in xxxxxxxx-xxxx-xxxx-Nxxx-xxxxxxxxxxxx + enum class variant_type + { + // 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 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 + ncs, + + // RFC 4122/DCE 1.1 + // N bit pattern: 10xx + // > big-endian byte order + rfc, + + // Microsoft Corporation backward compatibility + // N bit pattern: 110x + // > little endian byte order + // > formely used in the Component Object Model (COM) library + microsoft, + + // reserved for possible future definition + // N bit pattern: 111x + future + }; + + // indicated by a bit pattern in octet 6, marked with M in xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx + enum class version_type + { + 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 + }; + + struct guid_exception : public std::runtime_error + { + explicit guid_exception(std::string const & message) + : std::runtime_error(message.c_str()) + { + } + + explicit guid_exception(char const * const message) + : std::runtime_error(message) + { + } + }; + + struct uuid + { + public: + typedef uint8_t value_type; + typedef uint8_t& reference; + typedef uint8_t const& const_reference; + typedef uint8_t* iterator; + typedef uint8_t const* const_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + public: + constexpr uuid() {} + + variant_type variant() const noexcept + { + if ((data[8] & 0x80) == 0x00) + return variant_type::ncs; + else if ((data[8] & 0xC0) == 0x80) + return variant_type::rfc; + else if ((data[8] & 0xE0) == 0xC0) + return variant_type::microsoft; + else + return variant_type::future; + } + + version_type version() const + { + if ((data[6] & 0xF0) == 0x10) + return version_type::time_based; + else if ((data[6] & 0xF0) == 0x20) + return version_type::dce_security; + else if ((data[6] & 0xF0) == 0x30) + return version_type::name_based_md5; + else if ((data[6] & 0xF0) == 0x40) + return version_type::random_number_based; + else if ((data[6] & 0xF0) == 0x50) + return version_type::name_based_sha1; + else + throw guid_exception("invalid guid"); + } + + std::size_t size() const noexcept { return 16; } + + bool is_nil() const noexcept + { + for (auto const e : data) if (e != 0) return false; + return true; + } + + void swap(uuid & other) noexcept + { + data.swap(other.data); + } + + friend void swap(uuid& lhs, uuid& rhs) noexcept + { + std::swap(lhs.data, rhs.data); + } + + iterator begin() noexcept { return &data[0]; } + const_iterator begin() const noexcept { return &data[0]; } + iterator end() noexcept { return &data[0] + size(); } + const_iterator end() const noexcept { return &data[0] + size(); } + + template, + class Alloc = std::allocator> + std::basic_string string(Alloc const & a = Alloc()) const + { + std::basic_stringstream sstr; + sstr << *this; + return sstr.str(); + } + + std::string string() const + { + std::stringstream sstr; + sstr << *this; + return sstr.str(); + } + + std::wstring wstring() const + { + std::wstringstream sstr; + sstr << *this; + return sstr.str(); + } + + private: + std::array data{ 0 }; + + friend bool operator==(uuid const & lhs, uuid const & rhs) noexcept; + + template + friend std::basic_ostream & operator<<(std::basic_ostream &s, uuid const & id); + }; + + inline bool operator== (uuid const& lhs, uuid const& rhs) noexcept + { + return lhs.data == rhs.data; + } + + inline bool operator!= (uuid const& lhs, uuid const& rhs) noexcept + { + return !(lhs == rhs); + } + + template + std::basic_ostream & operator<<(std::basic_ostream &s, uuid const & id) + { + return s << std::hex << std::setfill(static_cast('0')) + << std::setw(2) << (int)id.data[0] + << std::setw(2) << (int)id.data[1] + << std::setw(2) << (int)id.data[2] + << std::setw(2) << (int)id.data[3] + << '-' + << std::setw(2) << (int)id.data[4] + << std::setw(2) << (int)id.data[5] + << '-' + << std::setw(2) << (int)id.data[6] + << std::setw(2) << (int)id.data[7] + << '-' + << std::setw(2) << (int)id.data[8] + << std::setw(2) << (int)id.data[9] + << '-' + << std::setw(2) << (int)id.data[10] + << std::setw(2) << (int)id.data[11] + << std::setw(2) << (int)id.data[12] + << std::setw(2) << (int)id.data[13] + << std::setw(2) << (int)id.data[14] + << std::setw(2) << (int)id.data[15]; + } +} + +namespace std +{ + template <> + void swap(uuids::uuid & lhs, uuids::uuid & rhs); + + template <> + struct hash + { + typedef uuids::uuid argument_type; + typedef std::size_t result_type; + + result_type operator()(argument_type const &uuid) const + { + std::hash hasher; + return static_cast(hasher(uuid.string())); + } + }; +} \ No newline at end of file diff --git a/test/test_win/.gitignore b/test/test_win/.gitignore new file mode 100644 index 0000000..02032ac --- /dev/null +++ b/test/test_win/.gitignore @@ -0,0 +1,3 @@ +.vs +Debug +Release diff --git a/test/test_win/stdafx.cpp b/test/test_win/stdafx.cpp new file mode 100644 index 0000000..b2a4568 Binary files /dev/null and b/test/test_win/stdafx.cpp differ diff --git a/test/test_win/stdafx.h b/test/test_win/stdafx.h new file mode 100644 index 0000000..94d4ed8 Binary files /dev/null and b/test/test_win/stdafx.h differ diff --git a/test/test_win/targetver.h b/test/test_win/targetver.h new file mode 100644 index 0000000..567cd34 Binary files /dev/null and b/test/test_win/targetver.h differ diff --git a/test/test_win/test_win.cpp b/test/test_win/test_win.cpp new file mode 100644 index 0000000..e71e04a Binary files /dev/null and b/test/test_win/test_win.cpp differ diff --git a/test/test_win/test_win.sln b/test/test_win/test_win.sln new file mode 100644 index 0000000..06d07b1 --- /dev/null +++ b/test/test_win/test_win.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27004.2010 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_win", "test_win.vcxproj", "{380B7F43-F7E1-4847-960B-978D0DD1E268}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {380B7F43-F7E1-4847-960B-978D0DD1E268}.Debug|x64.ActiveCfg = Debug|x64 + {380B7F43-F7E1-4847-960B-978D0DD1E268}.Debug|x64.Build.0 = Debug|x64 + {380B7F43-F7E1-4847-960B-978D0DD1E268}.Debug|x86.ActiveCfg = Debug|Win32 + {380B7F43-F7E1-4847-960B-978D0DD1E268}.Debug|x86.Build.0 = Debug|Win32 + {380B7F43-F7E1-4847-960B-978D0DD1E268}.Release|x64.ActiveCfg = Release|x64 + {380B7F43-F7E1-4847-960B-978D0DD1E268}.Release|x64.Build.0 = Release|x64 + {380B7F43-F7E1-4847-960B-978D0DD1E268}.Release|x86.ActiveCfg = Release|Win32 + {380B7F43-F7E1-4847-960B-978D0DD1E268}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {78BC8B73-C809-4F3C-9000-66F27E2F5E07} + EndGlobalSection +EndGlobal diff --git a/test/test_win/test_win.vcxproj b/test/test_win/test_win.vcxproj new file mode 100644 index 0000000..80338d4 --- /dev/null +++ b/test/test_win/test_win.vcxproj @@ -0,0 +1,162 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {380B7F43-F7E1-4847-960B-978D0DD1E268} + Win32Proj + testwin + 10.0.16299.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Use + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Use + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Use + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + + Create + Create + Create + Create + + + + + + + \ No newline at end of file diff --git a/test/test_win/test_win.vcxproj.filters b/test/test_win/test_win.vcxproj.filters new file mode 100644 index 0000000..2c975bc --- /dev/null +++ b/test/test_win/test_win.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file