diff --git a/paper.md b/paper.md index 846c3f7..7396db6 100644 --- a/paper.md +++ b/paper.md @@ -91,8 +91,237 @@ assert(id.string() == "47183823-2574-4bfd-b411-99ed177d3e43"); assert(id.wstring() == L"47183823-2574-4bfd-b411-99ed177d3e43"); ``` +### Iterators + +Constant and mutable iterators allow direct access to the underlaying `uuid` data. This enables both direct reading and writing of the `uuid` bits. + +``` +std::array arr{ + 0x47, 0x18, 0x38, 0x23, + 0x25, 0x74, + 0x4b, 0xfd, + 0xb4, 0x11, + 0x99, 0xed, 0x17, 0x7d, 0x3e, 0x43}; + +uuid id; +assert(id.nil()); + +std::copy(std::cbegin(arr), std::cend(arr), std::begin(id)); +assert(!id.nil()); +assert(id.string() == "47183823-2574-4bfd-b411-99ed177d3e43"); + +size_t i = 0; +for (auto const & b : id) + assert(arr[i++] == b); +``` + +### `variant` and `version` + +Member functions `variant()` and `version()` allows to check the variant type of the uuid and respetively the version type. These are defined by two strongly typed enums called `uuid_variant` and `uuid_version`. + +``` +uuid id("47183823-2574-4bfd-b411-99ed177d3e43"); +assert(id.version() == uuids::uuid_version::random_number_based); +assert(id.variant() == uuids::uuid_variant::rfc); +``` + +### Swapping + +Both member and non-member swap functions including a `std::swap<>` specialization that enable the swapping of `uuid` values. + +``` +uuid empty; +uuid id("47183823-2574-4bfd-b411-99ed177d3e43"); + +assert(empty.nil()); +assert(!id.nil()); + +std::swap(empty, id); + +assert(!empty.nil()); +assert(id.nil()); + +empty.swap(id); + +assert(empty.nil()); +assert(!id.nil()); +``` + +### `operator==` and `operator!=` + +Non-member operators == and != are provided in order to test the equality/inequality of two `uuid` values. + +``` +uuid empty; +uuid id("47183823-2574-4bfd-b411-99ed177d3e43"); + +assert(empty == empty); +assert(id == id); +assert(empty != id); +``` + +### `operator<` + +Although it does not make sense to check whether a uuid is less or less or equal then another uuid, the overloading of this operator for `uuid` is necessary in order to be able to store `uuid` values in some containers such as `std::set` that by default use the operator to compare keys. + +``` +std::set ids{ + uuid{}, + uuids::uuid("47183823-2574-4bfd-b411-99ed177d3e43"), + uuids::make_uuid() +}; + +assert(ids.size() == 3); +assert(ids.find(uuid{}) != ids.end()); +``` + +### Hashing + +A `std::hash<>` specialization for `uuid` is provided in order to enable the use of `uuid`s in associative unordered containers such as `std::unordered_set`. + +``` +std::unordered_set ids{ + uuid{}, + uuids::uuid("47183823-2574-4bfd-b411-99ed177d3e43"), + uuids::make_uuid() +}; + +assert(ids.size() == 3); +assert(ids.find(uuid{}) != ids.end()); +``` + +### Generating new uuids + +Non-member `make_uuid` function creates a new uuid by relying on the operating system APIs for this purpose. In practice, all the major operating system APIs (`CoCreateGuid` on Windows, `uuid_generate` on Linux, `CFUUIDCreate` on Max OS) produce version 4 UUIDs of the RFC variant. + +``` +auto id = make_uuid(); +assert(!id.nil()); +assert(id.version() == uuids::uuid_version::random_number_based); +assert(id.variant() == uuids::uuid_variant::rfc); +``` + ## IV. Technical Specifications +### Header +Add a new header called ``. + +### `uuid_variant` enum + +``` +namespace std::uuid { + enum class uuid_variant + { + ncs, + rfc, + microsoft, + future + }; +} +``` + +### `uuid_version` enum + +``` +namespace std::uuid { + enum class uuid_version + { + none = 0, + time_based = 1, + dce_security = 2, + name_based_md5 = 3, + random_number_based = 4, + name_based_sha1 = 5 + }; +} +``` + +### `uuid` class + +``` +namespace std::uuid { +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 explicit uuid(); + constexpr explicit uuid(std::array const & bytes); + explicit uuid(uint8_t const * const bytes); + explicit uuid(std::string const & str); + explicit uuid(std::wstring const & str); + + constexpr uuid_variant variant() const noexcept; + constexpr uuid_version version() const noexcept; + constexpr std::size_t size() const noexcept; + constexpr bool nil() const noexcept; + + void swap(uuid & other) noexcept; + friend void swap(uuid& lhs, uuid& rhs) noexcept; + + iterator begin() noexcept; + const_iterator begin() const noexcept; + iterator end() noexcept; + const_iterator end() const noexcept; + + template, + class Alloc = std::allocator> + std::basic_string string(Alloc const & a = Alloc()) const; + std::string string() const; + std::wstring wstring() const; + + private: + friend bool operator==(uuid const & lhs, uuid const & rhs) noexcept; + friend bool operator<(uuid const & lhs, uuid const & rhs) noexcept; + + template + friend std::basic_ostream & operator<<(std::basic_ostream &s, uuid const & id); + }; +} +``` + +### non-member functions + +``` +namespace std::uuid { + inline bool operator== (uuid const& lhs, uuid const& rhs) noexcept; + inline bool operator!= (uuid const& lhs, uuid const& rhs) noexcept; + inline bool operator< (uuid const& lhs, uuid const& rhs) noexcept; + + template + std::basic_ostream & operator<<(std::basic_ostream &s, uuid const & id); + + uuid make_uuid(); +} +``` + +### Specialization + +``` +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; + }; +} +``` + ## V. Limitations ## VI. References