BDE 4.39.x 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).
284///
285/// See @ref bdlb_guidutil
286struct GuidUtil {
287
288 // CLASS METHODS
289
290 /// Generate a sequence of GUIDs meeting the RFC 4122 version 4
291 /// specification, and load the resulting GUIDs into the array referred
292 /// to by the specified `result`. Optionally specify `numGuids`,
293 /// indicating the number of GUIDs to load into the `result` array. If
294 /// `numGuids` is not supplied, a default of 1 is used. An RFC 4122
295 /// version 4 GUID consists of 122 randomly generated bits, two
296 /// "variant" bits set to `10`, and four "version" bits set to `0100`.
297 ///
298 /// \pre The behavior is undefined unless `result` refers to a contiguous
299 /// sequence of at least `numGuids` `Guid` objects.
300 static void generate(Guid *result, bsl::size_t numGuids = 1);
301
302 /// Generate and return a single GUID meeting the RFC 4122 version 4
303 /// specification, consisting of 122 randomly generated bits, two
304 /// "variant" bits set to `10`, and four "version" bits set to `0100`.
305 static Guid generate();
306
307 /// Generate a sequence of GUIDs meeting the RFC 4122 version 4
308 /// specification, and load the resulting GUIDs into the array referred
309 /// to by the specified `result`. Optionally specify `numGuids`,
310 /// indicating the number of GUIDs to load into the `result` array. If
311 /// `numGuids` is not supplied, a default of 1 is used. An RFC 4122
312 /// version 4 GUID consists of 122 randomly generated bits, two
313 /// "variant" bits set to `10`, and four "version" bits set to `0100`.
314 ///
315 /// \pre The behavior is undefined unless `result` refers to a contiguous sequence of at least `numGuids` `Guid` objects.
316 ///
317 /// \note Note that this
318 /// function generates high quality, albeit not cryptographically
319 /// secure, random numbers for GUIDs.
320 static void generateNonSecure(Guid *result, bsl::size_t numGuids = 1);
321
322 /// Generate and return a single GUID meeting the RFC 4122 version 4
323 /// specification, consisting of 122 randomly generated bits, two
324 /// "variant" bits set to `10`, and four "version" bits set to `0100`.
325 ///
326 /// \note Note that this function generates high quality, albeit not
327 /// cryptographically secure, random numbers for GUIDs.
329
330 /// Generate and return a single GUID meeting the RFC 4122 version 5
331 /// specification from the specified `namespaceId` and `name`.
332 /// `namespaceId` may (but need not) be one of the pre-defined namespace IDs.
333 ///
334 /// \note Note that this method is a pure function of its arguments.
335 static Guid generateFromName(const Guid& namespaceId,
336 const bsl::string_view& name);
337
338 /// Return the pre-defined namespace ID for the DNS namespace from
339 /// Appendix C of RFC 4122, for use with the `generateFromName` method
340 /// when the name string is a fully-qualified domain name.
342
343 /// Return the pre-defined namespace ID for the URL namespace from
344 /// Appendix C of RFC 4122, for use with the `generateFromName` method
345 /// when the name string is a URL.
347
348 /// Return the pre-defined namespace ID for the OID namespace from
349 /// Appendix C of RFC 4122, for use with the `generateFromName` method
350 /// when the name string is an ISO Object ID (OID).
352
353 /// Return the pre-defined namespace ID for the X500 namespace from
354 /// Appendix C of RFC 4122, for use with the `generateFromName` method
355 /// when the name string is an X.500 Distinguished Name.
357
358 /// Parse the specified `guidString` (in {GUID String Format}) and load
359 /// its value into the specified `result`. Return 0 if `result`
360 /// successfully loaded, and a non-zero value otherwise.
361 static int guidFromString(Guid *result,
362 const bsl::string_view& guidString);
363
364 /// Parse the specified `guidString` (in {GUID String Format}) and
365 /// return the converted GUID, or a default-constructed `Guid` if the
366 /// string is improperly formatted.
367 static Guid guidFromString(const bsl::string_view& guidString);
368
369 /// Serialize the specified `guid` into the specified `result`. The
370 /// `result` string will be in a format suitable for `guidFromString`.
371 static void guidToString(bsl::string *result, const Guid& guid);
372 static void guidToString(std::string *result, const Guid& guid);
373#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
374 static void guidToString(std::pmr::string *result, const Guid& guid);
375#endif
376
377 /// Convert the specified `guid` into a string suitable for
378 /// `guidFromString`, and return the string.
379 static bsl::string guidToString(const Guid& guid);
380
381 /// Return the version of the specified `guid` object.
382 ///
383 /// \pre The behavior is undefined unless the contents of the `guid` object are compliant
384 /// with RFC 4122.
385 static int getVersion(const bdlb::Guid& guid);
386
387 /// Return the most significant 8 bytes of the specified `guid`.
389
390 /// Return the least significant 8 bytes of the specified `guid`.
392
393 // DEPRECATED CLASS METHODS
394
395 /// Generate a sequence of GUIDs meeting the RFC 4122 version 4
396 /// specification, and load the bytes of the resulting GUIDs into the
397 /// array referred to by the specified `result`. Optionally specify
398 /// `numGuids`, indicating the number of GUIDs to load into the `result`
399 /// array. If `numGuids` is not supplied, a default of 1 is used. An
400 /// RFC 4122 version 4 GUID consists of 122 randomly generated bits, two
401 /// "variant" bits set to `10`, and four "version" bits set to `0100`.
402 ///
403 /// \pre The behavior is undefined unless `result` refers to a contiguous
404 /// sequence of at least `16 * numGuids` bytes.
405 ///
406 /// @deprecated Use @ref generate(Guid *, size_t) instead.
407 static void generate(unsigned char *result, bsl::size_t numGuids = 1);
408};
409
410// ============================================================================
411// INLINE DEFINITIONS
412// ============================================================================
413
414 // -------------------
415 // class GuidState_Imp
416 // -------------------
417
418
419// MANIPULATORS
420inline
422 bsl::uint32_t (*out)[GuidState_Imp::k_GENERATOR_COUNT])
423{
424 for (int i = 0; i < GuidState_Imp::k_GENERATOR_COUNT; i++) {
425 (*out)[i] = d_generators[i].generate();
426 }
427}
428
429 // ---------------
430 // struct GuidUtil
431 // ---------------
432// CLASS METHODS
433inline
434void GuidUtil::generate(Guid *result, bsl::size_t numGuids)
435{
436 generate(reinterpret_cast<unsigned char *>(result), numGuids);
437}
438
439inline
441{
442 return (guid[6] & 0xF0) >> 4;
443}
444
445} // close package namespace
446
447
448#endif
449
450// ----------------------------------------------------------------------------
451// Copyright 2015 Bloomberg Finance L.P.
452//
453// Licensed under the Apache License, Version 2.0 (the "License");
454// you may not use this file except in compliance with the License.
455// You may obtain a copy of the License at
456//
457// http://www.apache.org/licenses/LICENSE-2.0
458//
459// Unless required by applicable law or agreed to in writing, software
460// distributed under the License is distributed on an "AS IS" BASIS,
461// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
462// See the License for the specific language governing permissions and
463// limitations under the License.
464// ----------------------------- END-OF-FILE ----------------------------------
465
466/** @} */
467/** @} */
468/** @} */
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:421
Definition bdlb_guid.h:201
Definition bslstl_stringview.h:471
Definition bslstl_string.h:1252
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bdlb_algorithmworkaroundutil.h:74
Definition bdlb_guidutil.h:286
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:440
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:293
unsigned long long Uint64
Definition bsls_types.h:139