From febb9c275b5247df596876e4eea7fa17b7ec45e7 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 22 Aug 2018 17:26:08 +0200 Subject: Add support for UUID generation --- libbutl/uuid.hxx | 234 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 libbutl/uuid.hxx (limited to 'libbutl/uuid.hxx') diff --git a/libbutl/uuid.hxx b/libbutl/uuid.hxx new file mode 100644 index 0000000..92397f6 --- /dev/null +++ b/libbutl/uuid.hxx @@ -0,0 +1,234 @@ +// file : libbutl/uuid.hxx -*- C++ -*- +// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#pragma once + +#include +#include +#include +#include // hash + +#include +#include + +#ifdef _WIN32 +struct _GUID; // GUID and UUID. +#endif + +namespace butl +{ + // Universally-unique identifier (UUID), RFC4122: + // + // https://tools.ietf.org/html/rfc4122 + + // The UUID variant (type). Nil UUID is DCE. + // + enum class uuid_variant + { + ncs, // NCS backward compatibility. + dce, // DCE 1.1/RFC4122. + microsoft, // Microsoft backward compatibility. + other // Currently reserved for possible future definition. + }; + + // The DCE UUID version (sub-type). Nil UUID is random. + // + enum class uuid_version + { + time = 1, // Time-based. + security = 2, // DCE Security with embedded POSIX UIDs. + md5 = 3, // Name-based with MD5 hashing. + random = 4, // Randomly or pseudo-randomly generated. + sha1 = 5 // Name-based with SHA1 hashing. + }; + + class LIBBUTL_SYMEXPORT uuid_system_generator; + + struct LIBBUTL_SYMEXPORT uuid + { + // Normally not accessed directly (see RFC4122 Section 4.1.2). + // + std::uint32_t time_low; + std::uint16_t time_mid; + std::uint16_t time_hiv; // hi_and_version + std::uint8_t clock_seq_hir; // hi_and_reserved + std::uint8_t clock_seq_low; + std::uint8_t node[6]; + + // System UUID generator. See the uuid_generator interface for details. + // + // Note: system generator cannot be called during static initialization. + // + static uuid_system_generator system_generator; + + static uuid + generate (bool strong = true); + + // Create a nil UUID (all members are 0). + // + uuid (); + + bool + nil () const; + + explicit operator bool () const; + + // Create a UUID from a 16-octet binary representation with the sizes and + // order of the fields as defined in RFC4122 Section 4.1.2 and with each + // field encoded with the most significant byte first (also known as + // big-endian or network byte order). + // + using binary_type = std::array; + + explicit + uuid (const binary_type&); + + void + assign (const binary_type&); + + binary_type + binary () const noexcept; + + // Note that this constructor is compatible with libuuid's uuid_t type. + // + explicit + uuid (const std::uint8_t (&)[16]); + + void + assign (const std::uint8_t (&)[16]); + +#ifdef _WIN32 + // Create a UUID from Win32 GUID. + // + uuid (const _GUID&); + + void + assign (const _GUID&); + + template + G + guid () const; +#endif + + // Create a UUID from a 36-character string representation in the + // + // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + // + // form which can be in lower or upper case. Throw std::invalid_argument + // if the representation is invalid. + // + // The returned string representation is by default in lower case. + // + explicit + uuid (const std::string&); + + explicit + uuid (const char*); + + void + assign (const std::string&); + + void + assign (const char*); + + std::string + string (bool upper = false) const; + + std::array + c_string (bool upper = false) const; + + // UUID variant (type) and version (sub-type). + // + using variant_type = uuid_variant; + using version_type = uuid_version; + + variant_type + variant () const; + + version_type + version () const; + + // UUID comparison. + // + int + compare (const uuid&) const; + + // Swapping and moving. On move we make the moved-from instance nil. + // + void + swap (uuid&); + + uuid (uuid&&); + uuid (const uuid&) = default; + + uuid& operator= (uuid&&); + uuid& operator= (const uuid&) = default; + }; + + bool operator== (const uuid&, const uuid&); + bool operator!= (const uuid&, const uuid&); + bool operator< (const uuid&, const uuid&); + bool operator> (const uuid&, const uuid&); + bool operator<= (const uuid&, const uuid&); + bool operator>= (const uuid&, const uuid&); + + // For iostream operators see uuid-io.hxx. + + // UUID generator interface. + // + class LIBBUTL_SYMEXPORT uuid_generator + { + public: + virtual + ~uuid_generator () = default; + + // Generate a UUID. If strong is true (default), generate a strongly- + // unique UUID. Throw std::runtime_error to report errors, including if + // strong uniqueness cannot be guaranteed. + // + // A weak UUID is not guaranteed to be unique, neither universialy nor + // locally (that is, on the machine it has been generated). + // + virtual uuid + generate (bool strong = true) = 0; + }; + + // System UUID generator. + // + class LIBBUTL_SYMEXPORT uuid_system_generator: public uuid_generator + { + public: + // Throw std::system_error with the generic category and ENOTSUP error + // code if strong uniqueness cannot be guaranteed. + // + virtual uuid + generate (bool strong = true) override; + + // Optional explicit initialization and termination. Note that it is not + // thread-safe and must only be performed once (normally from main()) + // before/after any calls to generate(), respectively. Both functions may + // throw std::runtime_error to report errors. + // + static void + initialize (); + + static void + terminate (); + }; +} + +namespace std +{ + template <> + struct hash + { + using argument_type = butl::uuid; + using result_type = size_t; + + size_t + operator() (const butl::uuid&) const noexcept; + }; +} + +#include -- cgit v1.1