Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component bdlb_guidutil
[Package bdlb]

Provide functions that produce Globally Unique Identifiers. More...

Namespaces

namespace  bdlb

Detailed Description

Outline
Purpose:
Provide functions that produce Globally Unique Identifiers.
Classes:
bdlb::GuidUtil namespace for methods for creating GUIDs
See also:
Component 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.
  class MyEmployee {
      // This class provides a value-semantic type to represent an employee
      // record.  These records are for internal use only.
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
      MyEmployee(const string& name, double salary);
          // Create an object with the specified 'name' and specified
          //'salary', generating a new GUID to represent the employee.

      // ...

      // ACCESSORS
      const bdlb::Guid& Guid() const;
          // Return the 'guid' of this object.

      const bsl::string& name() const;
          // Return the 'name' of this object.

      double salary() const;
          // Return the 'salary' of this object.
      // ...
  };
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.
  bool operator== (const MyEmployee& lhs, const MyEmployee& rhs);
      // 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.
 ...

  // CREATORS
  MyEmployee::MyEmployee(const string& name, double salary)
  : d_name(name)
  , d_salary(salary)
  {
      bdlb::GuidUtil::generate(&d_guid);
  }

  // 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();
  }
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);