// bdlb_guidutil.h                                                    -*-C++-*-
#ifndef INCLUDED_BDLB_GUIDUTIL
#define INCLUDED_BDLB_GUIDUTIL

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Provide functions that produce Globally Unique Identifiers.
//
//@CLASSES:
//  bdlb::GuidUtil: namespace for methods for creating GUIDs
//
//@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;
//
//     // ...
// };
// ```
// 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)
// {
//     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);
// ```

#include <bdlscm_version.h>

#include <bdlb_guid.h>
#include <bdlb_pcgrandomgenerator.h>

#include <bslmf_assert.h>

#include <bsls_assert.h>
#include <bsls_libraryfeatures.h>
#include <bsls_types.h>

#include <bsl_array.h>
#include <bsl_cstddef.h>
#include <bsl_cstdint.h>
#include <bsl_string.h>

#include <string>

namespace BloombergLP {
namespace bdlb {

                              // ===================
                              // class GuidState_Imp
                              // ===================

/// This component-private `class` describes holds the PCG generators and
/// generation functions for use by `GuidUtil`.
class GuidState_Imp {

  public:
    // PUBLIC CLASS CONSTANTS
    enum {
        k_GENERATOR_COUNT = 4
    };

  private:
    // DATA
    bsl::array<bdlb::PcgRandomGenerator, k_GENERATOR_COUNT> d_generators;

  public:

    // MANIPULATORS

    /// Populate the specified `out` with the results of calling `generate`
    /// on the internal random generators.
    void generateRandomBits(
                       bsl::uint32_t (*out)[GuidState_Imp::k_GENERATOR_COUNT]);

    /// Seed the internal generators based on the specified `state` values.
    void seed(const bsl::array<bsl::uint64_t, k_GENERATOR_COUNT>& state);
};

                              // ===============
                              // struct GuidUtil
                              // ===============

/// This `struct` provides a namespace for functions that create Universally
/// Unique Identifiers per RFC 4122 (http://www.ietf.org/rfc/rfc4122.txt).
struct GuidUtil {

    // CLASS METHODS

    /// Generate a sequence of GUIDs meeting the RFC 4122 version 4
    /// specification, and load the resulting GUIDs into the array referred
    /// to by the specified `result`.  Optionally specify `numGuids`,
    /// indicating the number of GUIDs to load into the `result` array.  If
    /// `numGuids` is not supplied, a default of 1 is used.  An RFC 4122
    /// version 4 GUID consists of 122 randomly generated bits, two
    /// "variant" bits set to `10`, and four "version" bits set to `0100`.
    /// The behavior is undefined unless `result` refers to a contiguous
    /// sequence of at least `numGuids` `Guid` objects.
    static void generate(Guid *result, bsl::size_t numGuids = 1);

    /// Generate and return a single GUID meeting the RFC 4122 version 4
    /// specification, consisting of 122 randomly generated bits, two
    /// "variant" bits set to `10`, and four "version" bits set to `0100`.
    static Guid generate();

    /// Generate a sequence of GUIDs meeting the RFC 4122 version 4
    /// specification, and load the resulting GUIDs into the array referred
    /// to by the specified `result`.  Optionally specify `numGuids`,
    /// indicating the number of GUIDs to load into the `result` array.  If
    /// `numGuids` is not supplied, a default of 1 is used.  An RFC 4122
    /// version 4 GUID consists of 122 randomly generated bits, two
    /// "variant" bits set to `10`, and four "version" bits set to `0100`.
    /// The behavior is undefined unless `result` refers to a contiguous
    /// sequence of at least `numGuids` `Guid` objects.  Note that this
    /// function generates high quality, albeit not cryptographically
    /// secure, random numbers for GUIDs.
    static void generateNonSecure(Guid *result, bsl::size_t numGuids = 1);

    /// Generate and return a single GUID meeting the RFC 4122 version 4
    /// specification, consisting of 122 randomly generated bits, two
    /// "variant" bits set to `10`, and four "version" bits set to `0100`.
    /// Note that this function generates high quality, albeit not
    /// cryptographically secure, random numbers for GUIDs.
    static Guid generateNonSecure();

    /// Generate and return a single GUID meeting the RFC 4122 version 5
    /// specification from the specified `namespaceId` and `name`.
    /// `namespaceId` may (but need not) be one of the pre-defined namespace
    /// IDs.  Note that this method is a pure function of its arguments.
    static Guid generateFromName(const Guid&             namespaceId,
                                 const bsl::string_view& name);

    /// Return the pre-defined namespace ID for the DNS namespace from
    /// Appendix C of RFC 4122, for use with the `generateFromName` method
    /// when the name string is a fully-qualified domain name.
    static Guid dnsNamespace();

    /// Return the pre-defined namespace ID for the URL namespace from
    /// Appendix C of RFC 4122, for use with the `generateFromName` method
    /// when the name string is a URL.
    static Guid urlNamespace();

    /// Return the pre-defined namespace ID for the OID namespace from
    /// Appendix C of RFC 4122, for use with the `generateFromName` method
    /// when the name string is an ISO Object ID (OID).
    static Guid oidNamespace();

    /// Return the pre-defined namespace ID for the X500 namespace from
    /// Appendix C of RFC 4122, for use with the `generateFromName` method
    /// when the name string is an X.500 Distinguished Name.
    static Guid x500Namespace();

    /// Parse the specified `guidString` (in {GUID String Format}) and load
    /// its value into the specified `result`.  Return 0 if `result`
    /// successfully loaded, and a non-zero value otherwise.
    static int guidFromString(Guid                    *result,
                              const bsl::string_view&  guidString);

    /// Parse the specified `guidString` (in {GUID String Format}) and
    /// return the converted GUID, or a default-constructed `Guid` if the
    /// string is improperly formatted.
    static Guid guidFromString(const bsl::string_view& guidString);

    /// Serialize the specified `guid` into the specified `result`.  The
    /// `result` string will be in a format suitable for `guidFromString`.
    static void guidToString(bsl::string *result, const Guid& guid);
    static void guidToString(std::string *result, const Guid& guid);
#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
    static void guidToString(std::pmr::string *result, const Guid& guid);
#endif

    /// Convert the specified `guid` into a string suitable for
    /// `guidFromString`, and return the string.
    static bsl::string guidToString(const Guid& guid);

    /// Return the version of the specified `guid` object.  The behavior is
    /// undefined unless the contents of the `guid` object are compliant
    /// with RFC 4122.
    static int getVersion(const bdlb::Guid& guid);

    /// Return the most significant 8 bytes of the specified `guid`.
    static bsls::Types::Uint64 getMostSignificantBits(const Guid& guid);

    /// Return the least significant 8 bytes of the specified `guid`.
    static bsls::Types::Uint64 getLeastSignificantBits(const Guid& guid);

    // DEPRECATED CLASS METHODS

    /// Generate a sequence of GUIDs meeting the RFC 4122 version 4
    /// specification, and load the bytes of the resulting GUIDs into the
    /// array referred to by the specified `result`.  Optionally specify
    /// `numGuids`, indicating the number of GUIDs to load into the `result`
    /// array.  If `numGuids` is not supplied, a default of 1 is used.  An
    /// RFC 4122 version 4 GUID consists of 122 randomly generated bits, two
    /// "variant" bits set to `10`, and four "version" bits set to `0100`.
    /// The behavior is undefined unless `result` refers to a contiguous
    /// sequence of at least `16 * numGuids` bytes.
    ///
    /// @DEPRECATED: Use `generate(Guid *, size_t)` instead.
    static void generate(unsigned char *result, bsl::size_t numGuids = 1);
};

// ============================================================================
//                      INLINE DEFINITIONS
// ============================================================================

                              // -------------------
                              // class GuidState_Imp
                              // -------------------


// MANIPULATORS
inline
void GuidState_Imp::generateRandomBits(
              bsl::uint32_t (*out)[GuidState_Imp::k_GENERATOR_COUNT])
{
    for (int i = 0;  i < GuidState_Imp::k_GENERATOR_COUNT; i++) {
        (*out)[i] = d_generators[i].generate();
    }
}

                              // ---------------
                              // struct GuidUtil
                              // ---------------
// CLASS METHODS
inline
void GuidUtil::generate(Guid *result, bsl::size_t numGuids)
{
    generate(reinterpret_cast<unsigned char *>(result), numGuids);
}

inline
int GuidUtil::getVersion(const Guid& guid)
{
    return (guid[6] & 0xF0) >> 4;
}

}  // close package namespace
}  // close enterprise namespace

#endif

// ----------------------------------------------------------------------------
// Copyright 2015 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------
