Go to file
2018-01-23 11:11:14 +02:00
build std::byte instead of uint_8, constructors 2017-12-19 11:53:42 +02:00
include sha1 name generator 2018-01-17 12:17:31 +02:00
test sha1 name generator 2018-01-17 12:17:31 +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 to_string/to_wstring examples 2018-01-23 11:11:14 +02:00
README.md update on uuid_default_generator 2018-01-22 11:00:52 +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. Althoug the specification says this can be a type alias for another generator (that is default constructible), in this implementation it is using an operating system methods to create UUIDs (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>
uuid_name_generator a function object that generates version 5, name-based UUIDs using SHA1 hashing.

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);
  • Creating a new UUID with the name generator
uuids::uuid_name_generator gen;
uuid const guid = gen();
assert(!guid.nil());
assert(guid.size() == 16);
assert(guid.version() == uuids::uuid_version::name_based_sha1);
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));

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.

Credits

The SHA1 implementation is based on the TinySHA1 library.