From 2d2362d85c9e05e4b5660904b9fb5a7794bad079 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Wed, 23 Aug 2023 00:04:05 +0300 Subject: [PATCH] More util::uuid functions: create from string, check for/convert to RFC 4122 --- libs/util/include/psemek/util/uuid.hpp | 53 +++++++++++++++++++++++++- libs/util/source/uuid.cpp | 24 ++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 libs/util/source/uuid.cpp 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; + } + +}