Go to file
2018-01-15 17:48:46 +02:00
build std::byte instead of uint_8, constructors 2017-12-19 11:53:42 +02:00
include uuid iterators 2018-01-15 17:20:14 +02:00
test uuid iterators 2018-01-15 17:20:14 +02:00
.gitignore Initial commit 2017-12-07 09:58:37 +02:00
CMakeLists.txt include refs to CoreFoundation and Libuuid 2017-12-18 23:29:47 +02:00
LICENSE Initial commit 2017-12-07 09:58:37 +02:00
paper.md std:byte, constructors 2017-12-19 12:22:28 +02:00
README.md random generator 2018-01-15 17:48:46 +02:00

stduuid

A C++ cross-platform single-header library implementation for universally unique identifiers, simply know as either UUID or GUID (mostly on Windows). A UUID is a 128-bit number used to uniquely identify information in computer systems, such as database table keys, COM interfaces, classes and type libraries, and many others.

For information about UUID/GUIDs see:

Library overview

The library defines a namespace uuids with the following types and functions:

Basic types:

Name Description
uuid a class representing a UUID; this can be default constructed (a nil UUID), constructed from a range (defined by a pair of iterators), or from a string.
uuid_variant a strongly type enum representing the type of a UUID
uuid_version a strongly type enum representing the version of a UUID

Generators:

Name Description
uuid_default_generator a function object that generates new UUIDs, using an operating system method to create one (CoCreateGuid on Windows, uuid_generate on Linux, CFUUIDCreate on Mac)
basic_uuid_random_generator a function object that generates version 4 UUIDs using a pseudo-random number generator engine.
uuid_random_generator a basic_uuid_random_generator using the Marsenne Twister engine, i.e. basic_uuid_random_generator<std::mt19937>

Utilities:

Name Description
std::swap<> specialization of swap for uuid
std::hash<> specialization of hash for uuid (necessary for storing UUIDs in unordered associative containers, such as std::unordered_set)

Other:

Name Description
operator== and operator!= for UUIDs comparison for equality/inequality
operator< for comparing whether one UUIDs is less than another. Although this operation does not make much logical sense, it is necessary in order to store UUIDs in a std::set.
operator<< to write a UUID to an output stream using the canonical textual representation.
to_string() creates a std::string with the canonical textual representation of a UUID.
to_wstring() creates a std::wstring with the canonical textual representation of a UUID.

This project is currently under development and should be ignored until further notice.

Using the library

The following is a list of examples for using the library:

  • Creating a nil UUID
uuid empty;
assert(empty.nil());
assert(empty.size() == 16);
  • Creating a new UUID
uuid const guid = uuids::uuid_default_generator{}();
assert(!guid.nil());
assert(guid.size() == 16);
assert(guid.version() == uuids::uuid_version::random_number_based);
assert(guid.variant() == uuids::uuid_variant::rfc);
  • Creating a new UUID with a default random generator
uuids::uuid_random_generator gen;
uuid const guid = gen();
assert(!guid.nil());
assert(guid.size() == 16);
assert(guid.version() == uuids::uuid_version::random_number_based);
assert(guid.variant() == uuids::uuid_variant::rfc);
  • Creating a new UUID with a particular random generator
std::random_device rd;
std::ranlux48_base generator(rd());
uuids::basic_uuid_random_generator<std::ranlux48_base> gen(&generator);

uuid const guid = gen();
assert(!guid.nil());
assert(guid.size() == 16);
assert(guid.version() == uuids::uuid_version::random_number_based);
assert(guid.variant() == uuids::uuid_variant::rfc);
  • Create a UUID from a string
using namespace std::string_literals;

auto str = "47183823-2574-4bfd-b411-99ed177d3e43"s;
uuid guid(str);
assert(guid.string() == str);

or

auto str = L"47183823-2574-4bfd-b411-99ed177d3e43"s;
uuid guid(str);
assert(guid.wstring() == str);      
  • Creating a UUID from an array
std::array<uuids::uuid::value_type, 16> arr{{
   0x47, 0x18, 0x38, 0x23,
   0x25, 0x74,
   0x4b, 0xfd,
   0xb4, 0x11,
   0x99, 0xed, 0x17, 0x7d, 0x3e, 0x43}};
uuid guid(std::begin(arr), std::end(arr));
assert(id.string() == "47183823-2574-4bfd-b411-99ed177d3e43");

or

uuids::uuid::value_type arr[16] = {
   0x47, 0x18, 0x38, 0x23,
   0x25, 0x74,
   0x4b, 0xfd,
   0xb4, 0x11,
   0x99, 0xed, 0x17, 0x7d, 0x3e, 0x43 };
uuid guid(std::begin(arr), std::end(arr));
assert(guid.string() == "47183823-2574-4bfd-b411-99ed177d3e43");
  • Comparing UUIDS
uuid empty;
uuid guid = uuids::uuid_default_generator{}();

assert(empty == empty);
assert(guid == guid);
assert(empty != guid);
  • Swapping UUIDS
uuid empty;
uuid guid = uuids::uuid_default_generator{}();

assert(empty.nil());
assert(!guid.nil());

std::swap(empty, guid);

assert(!empty.nil());
assert(guid.nil());

empty.swap(guid);

assert(empty.nil());
assert(!guid.nil());
  • Converting to string
uuid empty;
assert(uuids::to_string(empty) == "00000000-0000-0000-0000-000000000000");
assert(uuids::to_wstring(empty) == L"00000000-0000-0000-0000-000000000000");
  • Iterating through the UUID data
std::array<uuids::uuid::value_type, 16> arr{{
   0x47, 0x18, 0x38, 0x23,
   0x25, 0x74,
   0x4b, 0xfd,
   0xb4, 0x11,
   0x99, 0xed, 0x17, 0x7d, 0x3e, 0x43}};

uuid guid;
assert(guid.nil());

std::copy(std::cbegin(arr), std::cend(arr), std::begin(guid));
assert(!guid.nil());
assert(guid.string() == "47183823-2574-4bfd-b411-99ed177d3e43");

size_t i = 0;
for (auto const & b : guid)
   assert(arr[i++] == b);
  • Using with an orderered associative container
uuids::uuid_default_generator gen;
std::set<uuids::uuid> ids{uuid{}, gen(), gen(), gen(), gen()};

assert(ids.size() == 5);
assert(ids.find(uuid{}) != ids.end());
  • Using in an unordered associative container
uuids::uuid_default_generator gen;
std::unordered_set<uuids::uuid> ids{uuid{}, gen(), gen(), gen(), gen()};

assert(ids.size() == 5);
assert(ids.find(uuid{}) != ids.end());
  • Hashing UUIDs
auto h1 = std::hash<std::string>{};
auto h2 = std::hash<uuid>{};
assert(h1(str) == h2(guid));

Limitations

The library can only create new uuids using the underlaying operating system resources.

An alternative to this library could be the boost::uuid library. This has a similar model, but supports creating all variant of uuids, including md5 and sha1 name based, time based, and random number based values.

Support

The library is supported on all major operating systems: Windows, Linux and Mac OS.

Testing

A testing project is available in the sources. To build and execute the tests do the following:

  • Clone or download this repository
  • Create a build directory in the root directory of the sources
  • Run the command cmake .. from the build directory; if you do not have CMake you must install it first.
  • Build the project created in the previous step
  • Run the executable.