BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlb_guidutil.h
Go to the documentation of this file.
1/// @file bdlb_guidutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlb_guidutil.h -*-C++-*-
8#ifndef INCLUDED_BDLB_GUIDUTIL
9#define INCLUDED_BDLB_GUIDUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlb_guidutil bdlb_guidutil
15/// @brief Provide functions that produce Globally Unique Identifiers.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlb
19/// @{
20/// @addtogroup bdlb_guidutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlb_guidutil-purpose"> Purpose</a>
25/// * <a href="#bdlb_guidutil-classes"> Classes </a>
26/// * <a href="#bdlb_guidutil-description"> Description </a>
27/// * <a href="#bdlb_guidutil-grammar-for-guids-used-in-guidfromstring"> Grammar for GUIDs Used in guidFromString </a>
28/// * <a href="#bdlb_guidutil-guid-string-format"> GUID String Format </a>
29/// * <a href="#bdlb_guidutil-cryptographic-security"> Cryptographic Security </a>
30/// * <a href="#bdlb_guidutil-usage"> Usage </a>
31///
32/// # Purpose {#bdlb_guidutil-purpose}
33/// Provide functions that produce Globally Unique Identifiers.
34///
35/// # Classes {#bdlb_guidutil-classes}
36///
37/// - bdlb::GuidUtil: namespace for methods for creating GUIDs
38///
39/// @see bdlb_guid
40///
41/// # Description {#bdlb_guidutil-description}
42/// This component provides a `struct`, `bdlb::GuidUtil`, that
43/// serves as a namespace for utility functions that create and work with
44/// Globally Unique Identifiers (GUIDs).
45///
46/// Note that all the GUIDs generated by this component are actually Universally
47/// Unique Identifiers (UUIDs), which are a type of GUID. The two terms will be
48/// used interchangeably in the documentation below.
49///
50/// ## Grammar for GUIDs Used in guidFromString {#bdlb_guidutil-grammar-for-guids-used-in-guidfromstring}
51///
52///
53/// This conversion performed by `guidFromString` is intended to be used for
54/// GUIDs generated by external sources that have a variety of formats.
55///
56/// ## GUID String Format {#bdlb_guidutil-guid-string-format}
57///
58///
59/// @code
60/// <SPEC> ::= <BRACED GUID> | <GUID>
61///
62/// <BRACED GUID> ::= '[' <GUID> ']' | '[ ' <GUID> ' ]'
63/// '{' <GUID> '}' | '{ ' <GUID> ' }'
64///
65/// <GUID> ::= <FORMATTED GUID> | <UNFORMATTED GUID>
66///
67/// <FORMATTED GUID> ::= <X>{4} '-' <X>{2} '-' <X>{2} '-' <X>{2} '-' <X>{6}
68///
69/// <UNFORMATTED GUID> ::= <X>{16}
70///
71/// <X> ::= [0123456789ABCDEFabcdef]{2}
72///
73///
74/// EXAMPLES:
75/// ---------
76/// { 87654321-AAAA-BBBB-CCCC-012345654321 }
77/// 00010203-0405-0607-0809-101112131415
78/// [00112233445566778899aAbBcCdDeEfF]
79/// @endcode
80///
81/// ## Cryptographic Security {#bdlb_guidutil-cryptographic-security}
82///
83///
84/// `GuidUtil` provides three families of functions for generating GUIDs:
85/// `generate`, `generateNonSecure`, and `generateFromName`. The `generate` and
86/// `generateNonSecure` methods use random number generators, with the slower
87/// `generate` methods aiming to produce cryptographically secure UUIDs by
88/// accessing underlying system resources to obtain truly random numbers, and
89/// the faster `generateNonSecure` methods using a fast high-quality (but not
90/// strictly cryptographically secure) in-process random-number generator.
91///
92/// The `generateFromName` method does not use random numbers, but produces a
93/// UUID deterministically based on a given name and namespace. The user should
94/// heed the following admonition in RFC 4122: "Do not assume that UUIDs are
95/// hard to guess; they should not be used as security capabilities (identifiers
96/// whose mere possession grants access), for example." In addition,
97/// applications that generate name-based UUIDs from untrusted inputs must not
98/// assume that such UUIDs will be unique, since collision attacks are already
99/// known against the SHA-1 hash algorithm.
100///
101/// ## Usage {#bdlb_guidutil-usage}
102///
103///
104/// Suppose we are building a system for managing records for employees in a
105/// large international firm. These records have no natural field which can be
106/// used as a unique ID, so a GUID must be created for each employee.
107///
108/// First let us define a value-type for employees.
109/// @code
110/// /// This class provides a value-semantic type to represent an employee
111/// /// record. These records are for internal use only.
112/// class MyEmployee {
113/// @endcode
114/// For the sake of brevity, we provide a limited amount of data in each record.
115/// We additionally show a very limited scope of functionality.
116/// @code
117/// // DATA
118/// bsl::string d_name; // name of the employee
119/// double d_salary; // salary in some common currency
120/// bdlb::Guid d_guid; // a GUID for the employee
121///
122/// public:
123/// // CREATORS
124///
125/// /// Create an object with the specified `name` and specified
126/// /// `salary`, generating a new GUID to represent the employee.
127/// MyEmployee(const string& name, double salary);
128///
129/// // ...
130///
131/// // ACCESSORS
132///
133/// /// Return the `guid` of this object.
134/// const bdlb::Guid& Guid() const;
135///
136/// /// Return the `name` of this object.
137/// const bsl::string& name() const;
138///
139/// /// Return the `salary` of this object.
140/// double salary() const;
141///
142/// // ...
143/// };
144/// @endcode
145/// Next, we create free functions `operator<` and `operator==` to allow
146/// comparison of `MyEmployee` objects. We take advantage of the monotonically
147/// increasing nature of sequential GUIDs to implement these methods.
148/// @code
149///
150/// /// Return `true` if the specified `lhs` object has the same value as
151/// /// the specified `rhs` object, and `false` otherwise. Note that two
152/// /// `MyEmployee` objects have the same value if they have the same
153/// /// guid.
154/// bool operator== (const MyEmployee& lhs, const MyEmployee& rhs);
155///
156/// /// Return `true` if the value of the specified `lhs` MyEmployee object
157/// /// is less than the value of the specified `rhs` MyEmployee object,
158/// /// and `false` otherwise. A MyEmployee object is less than another if
159/// /// the guid is less than the other.
160/// bool operator< (const MyEmployee& lhs, const MyEmployee& rhs);
161///
162///
163/// // CREATORS
164/// MyEmployee::MyEmployee(const string& name, double salary)
165/// : d_name(name)
166/// , d_salary(salary)
167/// {
168/// bdlb::GuidUtil::generate(&d_guid);
169/// }
170///
171/// // ACCESSORS
172/// const bdlb::Guid& MyEmployee::Guid() const
173/// {
174/// return d_guid;
175/// }
176///
177/// const bsl::string& MyEmployee::name() const
178/// {
179/// return d_name;
180/// }
181///
182/// double MyEmployee::salary() const
183/// {
184/// return d_salary;
185/// }
186///
187/// // FREE FUNCTIONS
188/// bool operator==(const MyEmployee& lhs, const MyEmployee& rhs)
189/// {
190/// return lhs.Guid() == rhs.Guid();
191/// }
192///
193/// bool operator<(const MyEmployee& lhs, const MyEmployee& rhs)
194/// {
195/// return lhs.Guid() < rhs.Guid();
196/// }
197/// @endcode
198/// Next, we create some employees:
199/// @code
200/// MyEmployee e1("Foo Bar" , 1011970);
201/// MyEmployee e2("John Doe" , 12345);
202/// MyEmployee e3("Joe Six-pack", 1);
203/// @endcode
204/// Finally, we verify that the generated GUIDs are unique.
205/// @code
206/// assert(e1 < e2 || e2 < e1);
207/// assert(e2 < e3 || e3 < e2);
208/// assert(e1 < e3 || e3 < e1);
209/// @endcode
210/// @}
211/** @} */
212/** @} */
213
214/** @addtogroup bdl
215 * @{
216 */
217/** @addtogroup bdlb
218 * @{
219 */
220/** @addtogroup bdlb_guidutil
221 * @{
222 */
223
224#include <bdlscm_version.h>
225
226#include <bdlb_guid.h>
228
229#include <bslmf_assert.h>
230
231#include <bsls_assert.h>
232#include <bsls_libraryfeatures.h>
233#include <bsls_types.h>
234
235#include <bsl_array.h>
236#include <bsl_cstddef.h>
237#include <bsl_cstdint.h>
238#include <bsl_string.h>
239
240#include <string>
241
242
243namespace bdlb {
244
245 // ===================
246 // class GuidState_Imp
247 // ===================
248
249/// This component-private `class` describes holds the PCG generators and
250/// generation functions for use by `GuidUtil`.
251///
252/// See @ref bdlb_guidutil
254
255 public:
256 // PUBLIC CLASS CONSTANTS
257 enum {
259 };
260
261 private:
262 // DATA
264
265 public:
266
267 // MANIPULATORS
268
269 /// Populate the specified `out` with the results of calling `generate`
270 /// on the internal random generators.
272 bsl::uint32_t (*out)[GuidState_Imp::k_GENERATOR_COUNT]);
273
274 /// Seed the internal generators based on the specified `state` values.
276};
277
278 // ===============
279 // struct GuidUtil
280 // ===============
281
282/// This `struct` provides a namespace for functions that create Universally
283/// Unique Identifiers per RFC 4122 (http://www.ietf.org/rfc/rfc4122.txt).
284struct GuidUtil {
285
286 // CLASS METHODS
287
288 /// Generate a sequence of GUIDs meeting the RFC 4122 version 4
289 /// specification, and load the resulting GUIDs into the array referred
290 /// to by the specified `result`. Optionally specify `numGuids`,
291 /// indicating the number of GUIDs to load into the `result` array. If
292 /// `numGuids` is not supplied, a default of 1 is used. An RFC 4122
293 /// version 4 GUID consists of 122 randomly generated bits, two
294 /// "variant" bits set to `10`, and four "version" bits set to `0100`.
295 /// The behavior is undefined unless `result` refers to a contiguous
296 /// sequence of at least `numGuids` `Guid` objects.
297 static void generate(Guid *result, bsl::size_t numGuids = 1);
298
299 /// Generate and return a single GUID meeting the RFC 4122 version 4
300 /// specification, consisting of 122 randomly generated bits, two
301 /// "variant" bits set to `10`, and four "version" bits set to `0100`.
302 static Guid generate();
303
304 /// Generate a sequence of GUIDs meeting the RFC 4122 version 4
305 /// specification, and load the resulting GUIDs into the array referred
306 /// to by the specified `result`. Optionally specify `numGuids`,
307 /// indicating the number of GUIDs to load into the `result` array. If
308 /// `numGuids` is not supplied, a default of 1 is used. An RFC 4122
309 /// version 4 GUID consists of 122 randomly generated bits, two
310 /// "variant" bits set to `10`, and four "version" bits set to `0100`.
311 /// The behavior is undefined unless `result` refers to a contiguous
312 /// sequence of at least `numGuids` `Guid` objects. Note that this
313 /// function generates high quality, albeit not cryptographically
314 /// secure, random numbers for GUIDs.
315 static void generateNonSecure(Guid *result, bsl::size_t numGuids = 1);
316
317 /// Generate and return a single GUID meeting the RFC 4122 version 4
318 /// specification, consisting of 122 randomly generated bits, two
319 /// "variant" bits set to `10`, and four "version" bits set to `0100`.
320 /// Note that this function generates high quality, albeit not
321 /// cryptographically secure, random numbers for GUIDs.
323
324 /// Generate and return a single GUID meeting the RFC 4122 version 5
325 /// specification from the specified `namespaceId` and `name`.
326 /// `namespaceId` may (but need not) be one of the pre-defined namespace
327 /// IDs. Note that this method is a pure function of its arguments.
328 static Guid generateFromName(const Guid& namespaceId,
329 const bsl::string_view& name);
330
331 /// Return the pre-defined namespace ID for the DNS namespace from
332 /// Appendix C of RFC 4122, for use with the `generateFromName` method
333 /// when the name string is a fully-qualified domain name.
335
336 /// Return the pre-defined namespace ID for the URL namespace from
337 /// Appendix C of RFC 4122, for use with the `generateFromName` method
338 /// when the name string is a URL.
340
341 /// Return the pre-defined namespace ID for the OID namespace from
342 /// Appendix C of RFC 4122, for use with the `generateFromName` method
343 /// when the name string is an ISO Object ID (OID).
345
346 /// Return the pre-defined namespace ID for the X500 namespace from
347 /// Appendix C of RFC 4122, for use with the `generateFromName` method
348 /// when the name string is an X.500 Distinguished Name.
350
351 /// Parse the specified `guidString` (in {GUID String Format}) and load
352 /// its value into the specified `result`. Return 0 if `result`
353 /// successfully loaded, and a non-zero value otherwise.
354 static int guidFromString(Guid *result,
355 const bsl::string_view& guidString);
356
357 /// Parse the specified `guidString` (in {GUID String Format}) and
358 /// return the converted GUID, or a default-constructed `Guid` if the
359 /// string is improperly formatted.
360 static Guid guidFromString(const bsl::string_view& guidString);
361
362 static void guidToString(bsl::string *result, const Guid& guid);
363 /// Serialize the specified `guid` into the specified `result`. The
364 /// `result` string will be in a format suitable for `guidFromString`.
365 static void guidToString(std::string *result, const Guid& guid);
366#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
367 static void guidToString(std::pmr::string *result, const Guid& guid);
368#endif
369
370 /// Convert the specified `guid` into a string suitable for
371 /// `guidFromString`, and return the string.
372 static bsl::string guidToString(const Guid& guid);
373
374 /// Return the version of the specified `guid` object. The behavior is
375 /// undefined unless the contents of the `guid` object are compliant
376 /// with RFC 4122.
377 static int getVersion(const bdlb::Guid& guid);
378
379 /// Return the most significant 8 bytes of the specified `guid`.
381
382 /// Return the least significant 8 bytes of the specified `guid`.
384
385 // DEPRECATED CLASS METHODS
386
387 /// @deprecated Use @ref generate(Guid *, size_t) instead.
388 ///
389 /// Generate a sequence of GUIDs meeting the RFC 4122 version 4
390 /// specification, and load the bytes of the resulting GUIDs into the
391 /// array referred to by the specified `result`. Optionally specify
392 /// `numGuids`, indicating the number of GUIDs to load into the `result`
393 /// array. If `numGuids` is not supplied, a default of 1 is used. An
394 /// RFC 4122 version 4 GUID consists of 122 randomly generated bits, two
395 /// "variant" bits set to `10`, and four "version" bits set to `0100`.
396 /// The behavior is undefined unless `result` refers to a contiguous
397 /// sequence of at least `16 * numGuids` bytes.
398 static void generate(unsigned char *result, bsl::size_t numGuids = 1);
399};
400
401// ============================================================================
402// INLINE DEFINITIONS
403// ============================================================================
404
405 // -------------------
406 // class GuidState_Imp
407 // -------------------
408
409
410// MANIPULATORS
411inline
413 bsl::uint32_t (*out)[GuidState_Imp::k_GENERATOR_COUNT])
414{
415 for (int i = 0; i < GuidState_Imp::k_GENERATOR_COUNT; i++) {
416 (*out)[i] = d_generators[i].generate();
417 }
418}
419
420 // ---------------
421 // struct GuidUtil
422 // ---------------
423// CLASS METHODS
424inline
425void GuidUtil::generate(Guid *result, bsl::size_t numGuids)
426{
427 generate(reinterpret_cast<unsigned char *>(result), numGuids);
428}
429
430inline
432{
433 return (guid[6] & 0xF0) >> 4;
434}
435
436} // close package namespace
437
438
439#endif
440
441// ----------------------------------------------------------------------------
442// Copyright 2015 Bloomberg Finance L.P.
443//
444// Licensed under the Apache License, Version 2.0 (the "License");
445// you may not use this file except in compliance with the License.
446// You may obtain a copy of the License at
447//
448// http://www.apache.org/licenses/LICENSE-2.0
449//
450// Unless required by applicable law or agreed to in writing, software
451// distributed under the License is distributed on an "AS IS" BASIS,
452// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
453// See the License for the specific language governing permissions and
454// limitations under the License.
455// ----------------------------- END-OF-FILE ----------------------------------
456
457/** @} */
458/** @} */
459/** @} */
Definition bdlb_guidutil.h:253
@ k_GENERATOR_COUNT
Definition bdlb_guidutil.h:258
void seed(const bsl::array< bsl::uint64_t, k_GENERATOR_COUNT > &state)
Seed the internal generators based on the specified state values.
void generateRandomBits(bsl::uint32_t(*out)[GuidState_Imp::k_GENERATOR_COUNT])
Definition bdlb_guidutil.h:412
Definition bdlb_guid.h:201
Definition bslstl_stringview.h:441
Definition bslstl_string.h:1281
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlb_algorithmworkaroundutil.h:74
Definition bdlb_guidutil.h:284
static Guid generate()
static Guid generateFromName(const Guid &namespaceId, const bsl::string_view &name)
static Guid dnsNamespace()
static Guid generateNonSecure()
static Guid urlNamespace()
static void generateNonSecure(Guid *result, bsl::size_t numGuids=1)
static void guidToString(bsl::string *result, const Guid &guid)
static Guid guidFromString(const bsl::string_view &guidString)
static bsls::Types::Uint64 getLeastSignificantBits(const Guid &guid)
Return the least significant 8 bytes of the specified guid.
static Guid x500Namespace()
static void guidToString(std::string *result, const Guid &guid)
static bsls::Types::Uint64 getMostSignificantBits(const Guid &guid)
Return the most significant 8 bytes of the specified guid.
static int getVersion(const bdlb::Guid &guid)
Definition bdlb_guidutil.h:431
static void generate(unsigned char *result, bsl::size_t numGuids=1)
static Guid oidNamespace()
static bsl::string guidToString(const Guid &guid)
static int guidFromString(Guid *result, const bsl::string_view &guidString)
Definition bslstl_array.h:290
unsigned long long Uint64
Definition bsls_types.h:137