BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlb_guidutil

Detailed Description

Outline

Purpose

Provide functions that produce Globally Unique Identifiers.

Classes

See also
bdlb_guid

Description

This component provides a struct, bdlb::GuidUtil, that serves as a namespace for utility functions that create and work with Globally Unique Identifiers (GUIDs).

Note that all the GUIDs generated by this component are actually Universally Unique Identifiers (UUIDs), which are a type of GUID. The two terms will be used interchangeably in the documentation below.

Grammar for GUIDs Used in guidFromString

This conversion performed by guidFromString is intended to be used for GUIDs generated by external sources that have a variety of formats.

GUID String Format

<SPEC> ::= <BRACED GUID> | <GUID>
<BRACED GUID> ::= '[' <GUID> ']' | '[ ' <GUID> ' ]'
'{' <GUID> '}' | '{ ' <GUID> ' }'
<GUID> ::= <FORMATTED GUID> | <UNFORMATTED GUID>
<FORMATTED GUID> ::= <X>{4} '-' <X>{2} '-' <X>{2} '-' <X>{2} '-' <X>{6}
<UNFORMATTED GUID> ::= <X>{16}
<X> ::= [0123456789ABCDEFabcdef]{2}
EXAMPLES:
---------
{ 87654321-AAAA-BBBB-CCCC-012345654321 }
00010203-0405-0607-0809-101112131415
[00112233445566778899aAbBcCdDeEfF]

Cryptographic Security

GuidUtil provides three families of functions for generating GUIDs: generate, generateNonSecure, and generateFromName. The generate and generateNonSecure methods use random number generators, with the slower generate methods aiming to produce cryptographically secure UUIDs by accessing underlying system resources to obtain truly random numbers, and the faster generateNonSecure methods using a fast high-quality (but not strictly cryptographically secure) in-process random-number generator.

The generateFromName method does not use random numbers, but produces a UUID deterministically based on a given name and namespace. The user should heed the following admonition in RFC 4122: "Do not assume that UUIDs are hard to guess; they should not be used as security capabilities (identifiers whose mere possession grants access), for example." In addition, applications that generate name-based UUIDs from untrusted inputs must not assume that such UUIDs will be unique, since collision attacks are already known against the SHA-1 hash algorithm.

Usage

Suppose we are building a system for managing records for employees in a large international firm. These records have no natural field which can be used as a unique ID, so a GUID must be created for each employee.

First let us define a value-type for employees.

/// This class provides a value-semantic type to represent an employee
/// record. These records are for internal use only.
class MyEmployee {

For the sake of brevity, we provide a limited amount of data in each record. We additionally show a very limited scope of functionality.

// DATA
bsl::string d_name; // name of the employee
double d_salary; // salary in some common currency
bdlb::Guid d_guid; // a GUID for the employee
public:
// CREATORS
/// Create an object with the specified `name` and specified
/// `salary`, generating a new GUID to represent the employee.
MyEmployee(const string& name, double salary);
// ...
// ACCESSORS
/// Return the `guid` of this object.
const bdlb::Guid& Guid() const;
/// Return the `name` of this object.
const bsl::string& name() const;
/// Return the `salary` of this object.
double salary() const;
// ...
};
Definition bdlb_guid.h:201
Definition bslstl_string.h:1281

Next, we create free functions operator< and operator== to allow comparison of MyEmployee objects. We take advantage of the monotonically increasing nature of sequential GUIDs to implement these methods.

/// Return `true` if the specified `lhs` object has the same value as
/// the specified `rhs` object, and `false` otherwise. Note that two
/// `MyEmployee` objects have the same value if they have the same
/// guid.
bool operator== (const MyEmployee& lhs, const MyEmployee& rhs);
/// Return `true` if the value of the specified `lhs` MyEmployee object
/// is less than the value of the specified `rhs` MyEmployee object,
/// and `false` otherwise. A MyEmployee object is less than another if
/// the guid is less than the other.
bool operator< (const MyEmployee& lhs, const MyEmployee& rhs);
// CREATORS
MyEmployee::MyEmployee(const string& name, double salary)
: d_name(name)
, d_salary(salary)
{
}
// ACCESSORS
const bdlb::Guid& MyEmployee::Guid() const
{
return d_guid;
}
const bsl::string& MyEmployee::name() const
{
return d_name;
}
double MyEmployee::salary() const
{
return d_salary;
}
// FREE FUNCTIONS
bool operator==(const MyEmployee& lhs, const MyEmployee& rhs)
{
return lhs.Guid() == rhs.Guid();
}
bool operator<(const MyEmployee& lhs, const MyEmployee& rhs)
{
return lhs.Guid() < rhs.Guid();
}
bool operator==(const FileCleanerConfiguration &lhs, const FileCleanerConfiguration &rhs)
bool operator<(const MetricId &lhs, const MetricId &rhs)
static Guid generate()

Next, we create some employees:

MyEmployee e1("Foo Bar" , 1011970);
MyEmployee e2("John Doe" , 12345);
MyEmployee e3("Joe Six-pack", 1);

Finally, we verify that the generated GUIDs are unique.

assert(e1 < e2 || e2 < e1);
assert(e2 < e3 || e3 < e2);
assert(e1 < e3 || e3 < e1);