diff --git a/libs/util/include/psemek/util/uuid.hpp b/libs/util/include/psemek/util/uuid.hpp index 980ea8b8..e4b6881b 100644 --- a/libs/util/include/psemek/util/uuid.hpp +++ b/libs/util/include/psemek/util/uuid.hpp @@ -4,15 +4,66 @@ #include #include +#include +#include namespace psemek::util { - using uuid = std::array; + struct uuid + { + std::uint64_t values[2]; + + constexpr std::uint64_t & operator[](std::size_t i) + { + return values[i]; + } + + constexpr std::uint64_t const & operator[](std::size_t i) const + { + return values[i]; + } + + constexpr friend bool operator == (uuid const &, uuid const &) = default; + constexpr friend std::strong_ordering operator <=> (uuid const &, uuid const &) = default; + }; static_assert(sizeof(uuid) == 16); static_assert(alignof(uuid) == 8); + constexpr bool is_rfc_4122(uuid const & uuid) + { + return ((uuid[0] & 0x00f0000000000000ull) == 0x0040000000000000ull) + && ((uuid[1] & 0x00000000000000c0ull) == 0x0000000000000080ull); + } + + constexpr uuid make_rfc_4122(uuid uuid) + { + uuid[0] = (uuid[0] & 0xff0fffffffffffffull) | 0x0040000000000000ull; + uuid[1] = (uuid[1] & 0xffffffffffffff3full) | 0x0000000000000080ull; + return uuid; + } + + // TODO: use SHA-1 or something like that? + constexpr uuid make_uuid(std::string_view str) + { + struct char_hash + { + constexpr std::size_t operator()(char c) const noexcept + { + return static_cast(c); + } + }; + + uuid result{0x6eb49abceae6db24ull, 0x476c4c69fd7925a7ull}; + hash_sequence(result[0], str.begin(), str.end(), char_hash{}); + hash_sequence(result[1], str.begin(), str.end(), char_hash{}); + make_rfc_4122(result); + return result; + } + + std::ostream & operator << (std::ostream & os, uuid const & uuid); + } namespace std diff --git a/libs/util/source/uuid.cpp b/libs/util/source/uuid.cpp new file mode 100644 index 00000000..1505ebf6 --- /dev/null +++ b/libs/util/source/uuid.cpp @@ -0,0 +1,24 @@ +#include + +#include + +namespace psemek::util +{ + + std::ostream & operator << (std::ostream & os, uuid const & uuid) + { + os << std::hex << std::setfill('0') << std::left; + os << std::setw(8) << (uuid[0] & 0x00000000ffffffffull); + os << std::setw(1) << '-'; + os << std::setw(4) << ((uuid[0] & 0x0000ffff00000000ull) >> 32); + os << std::setw(1) << '-'; + os << std::setw(4) << ((uuid[0] & 0xffff000000000000ull) >> 48); + os << std::setw(1) << '-'; + os << std::setw(4) << (uuid[1] & 0x000000000000ffffull); + os << std::setw(1) << '-'; + os << std::setw(12) << ((uuid[1] & 0xffffffffffff0000ull) >> 16); + + return os; + } + +}