Revision control

++ // Copyright (C) 2020 The Qt Company Ltd.
++ // Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++ // Qt-Security score:critical reason:data-parser
++
++ #include "quuid.h"
++ #include "quuid_p.h"
++
++ #include "qcryptographichash.h"
++ #include "qdatastream.h"
++ #include "qdebug.h"
++ #include "qendian.h"
++ #include "qrandom.h"
++ #include "private/qtools_p.h"
++
++ QT_BEGIN_NAMESPACE
++
++ // ensure QList of this is efficient
++ static_assert(QTypeInfo<QUuid::Id128Bytes>::isRelocatable);
++
++ // 16 bytes (a uint, two shorts and a uchar[8]), each represented by two hex
++ // digits; plus four dashes and a pair of enclosing brace: 16*2 + 4 + 2 = 38.
++ enum { MaxStringUuidLength = 38 };
++
++ template <class Integral>
++ void _q_toHex(char *&dst, Integral value)
++ {
++ value = qToBigEndian(value);
++
++ const char *p = reinterpret_cast<const char *>(&value);
++
++ for (uint i = 0; i < sizeof(Integral); ++i, dst += 2) {
++ dst[0] = QtMiscUtils::toHexLower((p[i] >> 4) & 0xf);
++ dst[1] = QtMiscUtils::toHexLower(p[i] & 0xf);
++ }
++ }
++
++ #if QT_VERSION_MAJOR == 7
++ # warning Consider storing the UUID as simple bytes, not as {uint, ushort, short, array}
++ #endif
++ template <class Integral>
++ bool _q_fromHex(const char *&src, Integral &value)
++ {
++ value = 0;
++
++ for (uint i = 0; i < sizeof(Integral) * 2; ++i) {
++ uint ch = *src++;
++ int tmp = QtMiscUtils::fromHex(ch);
++ if (tmp == -1)
++ return false;
++
++ value = value * 16 + tmp;
++ }
++
++ return true;
++ }
++
++ static char *_q_uuidToHex(const QUuid &uuid, char *dst, QUuid::StringFormat mode = QUuid::WithBraces)
++ {
++ if ((mode & QUuid::WithoutBraces) == 0)
++ *dst++ = '{';
++ _q_toHex(dst, uuid.data1);
++ if ((mode & QUuid::Id128) != QUuid::Id128)
++ *dst++ = '-';
++ _q_toHex(dst, uuid.data2);
++ if ((mode & QUuid::Id128) != QUuid::Id128)
++ *dst++ = '-';
++ _q_toHex(dst, uuid.data3);
++ if ((mode & QUuid::Id128) != QUuid::Id128)
++ *dst++ = '-';
++ for (int i = 0; i < 2; i++)
++ _q_toHex(dst, uuid.data4[i]);
++ if ((mode & QUuid::Id128) != QUuid::Id128)
++ *dst++ = '-';
++ for (int i = 2; i < 8; i++)
++ _q_toHex(dst, uuid.data4[i]);
++ if ((mode & QUuid::WithoutBraces) == 0)
++ *dst++ = '}';
++ return dst;
++ }
++
++ /*!
++ \internal
++
++ Parses the string representation of a UUID (with optional surrounding "{}")
++ by reading at most MaxStringUuidLength (38) characters from \a src, which
++ may be \nullptr. Stops at the first invalid character (which includes a
++ premature NUL).
++
++ Returns the successfully parsed QUuid, or a null QUuid in case of failure.
++ */
++ Q_NEVER_INLINE
++ static QUuid _q_uuidFromHex(const char *src)
++ {
++ uint d1;
++ ushort d2, d3;
++ uchar d4[8];
++
++ if (src) {
++ if (*src == '{')
++ src++;
++ if (Q_LIKELY( _q_fromHex(src, d1)
++ && *src++ == '-'
++ && _q_fromHex(src, d2)
++ && *src++ == '-'
++ && _q_fromHex(src, d3)
++ && *src++ == '-'
++ && _q_fromHex(src, d4[0])
++ && _q_fromHex(src, d4[1])
++ && *src++ == '-'
++ && _q_fromHex(src, d4[2])
++ && _q_fromHex(src, d4[3])
++ && _q_fromHex(src, d4[4])
++ && _q_fromHex(src, d4[5])
++ && _q_fromHex(src, d4[6])
++ && _q_fromHex(src, d4[7]))) {
++ return QUuid(d1, d2, d3, d4[0], d4[1], d4[2], d4[3], d4[4], d4[5], d4[6], d4[7]);
++ }
++ }
++
++ return QUuid();
++ }
++
++ static QUuid createFromName(QUuid ns, QByteArrayView baseData, QCryptographicHash::Algorithm algorithm, int version) noexcept
++ {
++ std::byte buffer[20];
++ Q_ASSERT(sizeof buffer >= size_t(QCryptographicHash::hashLength(algorithm)));
++ QByteArrayView hashResult
++ = QCryptographicHash::hashInto(buffer, {QByteArrayView{ns.toBytes()}, baseData}, algorithm);
++ Q_ASSERT(hashResult.size() >= 16);
++ hashResult.truncate(16); // Sha1 will be too long
++
++ QUuid result = QUuid::fromRfc4122(hashResult);
++
++ result.data3 &= 0x0FFF;
++ result.data3 |= (version << 12);
++ result.data4[0] &= 0x3F;
++ result.data4[0] |= 0x80;
++
++ return result;
++ }
++
++ /*!
++ \class QUuid
++ \inmodule QtCore
++ \brief The QUuid class stores a Universally Unique Identifier (UUID).
++
++ \reentrant
++
++ \compares strong
++ \compareswith strong GUID
++ \note Comparison with GUID is Windows-only.
++ \endcompareswith
++
++ Using \e{U}niversally \e{U}nique \e{ID}entifiers (UUID) is a
++ standard way to uniquely identify entities in a distributed
++ computing environment. A UUID is a 16-byte (128-bit) number
++ generated by some algorithm that is meant to guarantee that the
++ UUID will be unique in the distributed computing environment where
++ it is used. The acronym GUID is often used instead, \e{G}lobally
++ \e{U}nique \e{ID}entifiers, but it refers to the same thing.
++
++ \target Variant field
++ Actually, the GUID is one \e{variant} of UUID. Multiple variants
++ are in use. Each UUID contains a bit field that specifies which
++ type (variant) of UUID it is. Call variant() to discover which
++ type of UUID an instance of QUuid contains. It extracts the three
++ most significant bits of byte 8 of the 16 bytes. In QUuid, byte 8
++ is \c{QUuid::data4[0]}. If you create instances of QUuid using the
++ constructor that accepts all the numeric values as parameters, use
++ the following table to set the three most significant bits of
++ parameter \c{b1}, which becomes \c{QUuid::data4[0]} and contains
++ the variant field in its three most significant bits. In the
++ table, 'x' means \e {don't care}.
++
++ \table
++ \header
++ \li msb0
++ \li msb1
++ \li msb2
++ \li Variant
++
++ \row
++ \li 0
++ \li x
++ \li x
++ \li NCS (Network Computing System)
++
++ \row
++ \li 1
++ \li 0
++ \li x
++ \li DCE (Distributed Computing Environment)
++
++ \row
++ \li 1
++ \li 1
++ \li 0
++ \li Microsoft (GUID)
++
++ \row
++ \li 1
++ \li 1
++ \li 1
++ \li Reserved for future expansion
++
++ \endtable
++
++ \target Version field
++ If variant() returns QUuid::DCE, the UUID also contains a
++ \e{version} field in the four most significant bits of
++ \c{QUuid::data3}, and you can call version() to discover which
++ version your QUuid contains. If you create instances of QUuid
++ using the constructor that accepts all the numeric values as
++ parameters, use the following table to set the four most
++ significant bits of parameter \c{w2}, which becomes
++ \c{QUuid::data3} and contains the version field in its four most
++ significant bits.
++
++ \table
++ \header
++ \li msb0
++ \li msb1
++ \li msb2
++ \li msb3
++ \li Version
++
++ \row
++ \li 0
++ \li 0
++ \li 0
++ \li 1
++ \li Time
++
++ \row
++ \li 0
++ \li 0
++ \li 1
++ \li 0
++ \li Embedded POSIX
++
++ \row
++ \li 0
++ \li 0
++ \li 1
++ \li 1
++ \li Md5(Name)
++
++ \row
++ \li 0
++ \li 1
++ \li 0
++ \li 0
++ \li Random
++
++ \row
++ \li 0
++ \li 1
++ \li 0
++ \li 1
++ \li Sha1
++
++ \endtable
++
++ The field layouts for the DCE versions listed in the table above
++ are specified in the \l{RFC 4122}
++ {Network Working Group UUID Specification}.
++
++ Most platforms provide a tool for generating new UUIDs, e.g. \c
++ uuidgen and \c guidgen. You can also use createUuid(). UUIDs
++ generated by createUuid() are of the random type. Their
++ QUuid::Version bits are set to QUuid::Random, and their
++ QUuid::Variant bits are set to QUuid::DCE. The rest of the UUID is
++ composed of random numbers. Theoretically, this means there is a
++ small chance that a UUID generated by createUuid() will not be
++ unique. But it is
++ {a \e{very} small chance}.
++
++ UUIDs can be constructed from numeric values or from strings, or
++ using the static createUuid() function. They can be converted to a
++ string with toString(). UUIDs have a variant() and a version(),
++ and null UUIDs return true from isNull().
++ */
++
++ /*!
++ \enum QUuid::StringFormat
++ \since 5.11
++
++ This enum is used by toString(StringFormat) to control the formatting of the
++ string representation. The possible values are:
++
++ \value WithBraces The default, toString() will return five hex fields, separated by
++ dashes and surrounded by braces. Example:
++ {00000000-0000-0000-0000-000000000000}.
++ \value WithoutBraces Only the five dash-separated fields, without the braces. Example:
++ 00000000-0000-0000-0000-000000000000.
++ \value Id128 Only the hex digits, without braces or dashes. Note that QUuid
++ cannot parse this back again as input.
++ */
++
++ /*!
++ \class QUuid::Id128Bytes
++ \inmodule QtCore
++ \since 6.6
++
++ This trivial structure is 128 bits (16 bytes) in size and holds the binary
++ representation of a UUID. Applications can \c{memcpy()} its contents to and
++ from many other libraries' UUID or GUID structures that take 128-bit
++ values.
++ */
++
++ /*!
++ \fn QUuid::Id128Bytes qFromBigEndian(QUuid::Id128Bytes src)
++ \since 6.6
++ \relates QUuid::Id128Bytes
++ \overload
++
++ Converts \a src from big-endian byte order and returns the struct holding
++ the binary representation of UUID in host byte order.
++
++ \sa <QtEndian>
++ */
++
++ /*!
++ \fn QUuid::Id128Bytes qFromLittleEndian(QUuid::Id128Bytes src)
++ \since 6.6
++ \relates QUuid::Id128Bytes
++ \overload
++
++ Converts \a src from little-endian byte order and returns the struct holding
++ the binary representation of UUID in host byte order.
++
++ \sa <QtEndian>
++ */
++
++ /*!
++ \fn QUuid::Id128Bytes qToBigEndian(QUuid::Id128Bytes src)
++ \since 6.6
++ \relates QUuid::Id128Bytes
++ \overload
++
++ Converts \a src from host byte order and returns the struct holding the
++ binary representation of UUID in big-endian byte order.
++
++ \sa <QtEndian>
++ */
++
++ /*!
++ \fn QUuid::Id128Bytes qToLittleEndian(QUuid::Id128Bytes src)
++ \since 6.6
++ \relates QUuid::Id128Bytes
++ \overload
++
++ Converts \a src from host byte order and returns the struct holding the
++ binary representation of UUID in little-endian byte order.
++
++ \sa <QtEndian>
++ */
++
++ /*!
++ \fn QUuid::QUuid(Id128Bytes id128, QSysInfo::Endian order) noexcept
++ \since 6.6
++
++ Creates a QUuid based on the integral \a id128 parameter. The input
++ \a id128 parameter is considered to have byte order \a order.
++
++ \sa fromBytes(), toBytes(), toRfc4122(), toUInt128()
++ */
++
++ /*!
++ \fn QUuid::fromUInt128(quint128 uuid, QSysInfo::Endian order) noexcept
++ \since 6.6
++
++ Creates a QUuid based on the integral \a uuid parameter. The input \a uuid
++ parameter is considered to have byte order \a order.
++
++ \note This function is only present on platforms that offer a 128-bit
++ integer type.
++
++ \sa toUInt128(), fromBytes(), toBytes(), toRfc4122()
++ */
++
++ /*!
++ \fn quint128 QUuid::toUInt128(QSysInfo::Endian order) const noexcept
++ \since 6.6
++
++ Returns a 128-bit integer created from this QUuid on the byte order
++ specified by \a order. The binary content of this function is the same as
++ toRfc4122() if the order is QSysInfo::BigEndian. See that function for more
++ details.
++
++ \note This function is only present on platforms that offer a 128-bit
++ integer type.
++
++ \sa toRfc4122(), fromUInt128(), toBytes(), fromBytes(), QUuid()
++ */
++
++ /*!
++ \fn QUuid::Id128Bytes QUuid::toBytes(QSysInfo::Endian order) const noexcept
++ \since 6.6
++
++ Returns a 128-bit ID created from this QUuid on the byte order specified
++ by \a order. The binary content of this function is the same as toRfc4122()
++ if the order is QSysInfo::BigEndian. See that function for more details.
++
++ \sa toRfc4122(), fromBytes(), QUuid()
++ */
++
++ /*!
++ \fn QUuid QUuid::fromBytes(const void *bytes, QSysInfo::Endian order) noexcept
++ \since 6.6
++
++ Reads 128 bits (16 bytes) from \a bytes using byte order \a order and
++ returns the QUuid corresponding to those bytes. This function does the same
++ as fromRfc4122() if the byte order \a order is QSysInfo::BigEndian.
++
++ \sa fromRfc4122()
++ */
++
++ /*!
++ \fn QUuid::QUuid(const GUID &guid)
++
++ Casts a Windows \a guid to a Qt QUuid.
++
++ \warning This function is only for Windows platforms.
++ */
++
++ /*!
++ \fn QUuid &QUuid::operator=(const GUID &guid)
++
++ Assigns a Windows \a guid to a Qt QUuid.
++
++ \warning This function is only for Windows platforms.
++ */
++
++ /*!
++ \fn QUuid::operator GUID() const
++
++ Returns a Windows GUID from a QUuid.
++
++ \warning This function is only for Windows platforms.
++ */
++
++ /*!
++ \fn QUuid::QUuid()
++
++ Creates the null UUID. toString() will output the null UUID
++ as "{00000000-0000-0000-0000-000000000000}".
++ */
++
++ /*!
++ \fn QUuid::QUuid(uint l, ushort w1, ushort w2, uchar b1, uchar b2, uchar b3, uchar b4, uchar b5, uchar b6, uchar b7, uchar b8)
++
++ Creates a UUID with the value specified by the parameters, \a l,
++ \a w1, \a w2, \a b1, \a b2, \a b3, \a b4, \a b5, \a b6, \a b7, \a
++ b8.
++
++ Example:
++ \snippet code/src_corelib_plugin_quuid.cpp 0
++ */
++
++ /*!
++ \fn QUuid::QUuid(QAnyStringView text)
++
++ Creates a QUuid object from the string \a text, which must be
++ formatted as five hex fields separated by '-', e.g.,
++ "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where each 'x' is a hex
++ digit. The curly braces shown here are optional, but it is normal to
++ include them. If the conversion fails, a null UUID is created. See
++ toString() for an explanation of how the five hex fields map to the
++ public data members in QUuid.
++
++ \note In Qt versions prior to 6.3, this constructor was an overload
++ set consisting of QString, QByteArray and \c{const char*}
++ instead of one constructor taking QAnyStringView.
++
++ \sa toString(), QUuid()
++ */
++
++ /*!
++ \fn static QUuid::fromString(QAnyStringView string)
++ \since 5.10
++
++ Creates a QUuid object from the string \a string, which must be
++ formatted as five hex fields separated by '-', e.g.,
++ "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where each 'x' is a hex
++ digit. The curly braces shown here are optional, but it is normal to
++ include them. If the conversion fails, a null UUID is returned. See
++ toString() for an explanation of how the five hex fields map to the
++ public data members in QUuid.
++
++ \note In Qt versions prior to 6.3, this function was an overload
++ set consisting of QStringView and QLatin1StringView instead of
++ one function taking QAnyStringView.
++
++ \sa toString(), QUuid()
++ */
++ static QUuid uuidFromString(QStringView text) noexcept
++ {
++ if (text.size() > MaxStringUuidLength)
++ text.truncate(MaxStringUuidLength);
++
++ char latin1[MaxStringUuidLength + 1];
++ char *dst = latin1;
++
++ for (QChar ch : text)
++ *dst++ = ch.toLatin1();
++
++ *dst++ = '\0'; // don't read garbage as potentially valid data
++
++ return _q_uuidFromHex(latin1);
++ }
++
++ static QUuid uuidFromString(QLatin1StringView text) noexcept
++ {
++ if (Q_UNLIKELY(text.size() < MaxStringUuidLength - 2
++ || (text.front() == '{' && text.size() < MaxStringUuidLength - 1))) {
++ // Too short. Don't call _q_uuidFromHex(); QL1Ss need not be NUL-terminated,
++ // and we don't want to read trailing garbage as potentially valid data.
++ text = QLatin1StringView();
++ }
++ return _q_uuidFromHex(text.data());
++ }
++
++ Q_ALWAYS_INLINE
++ // can treat UTF-8 the same as Latin-1:
++ static QUuid uuidFromString(QUtf8StringView text) noexcept
++ {
++ return uuidFromString(QLatin1StringView(text.data(), text.size()));
++ }
++
++ QUuid QUuid::fromString(QAnyStringView text) noexcept
++ {
++ return text.visit([] (auto text) { return uuidFromString(text); });
++ }
++
++ /*!
++ \since 5.0
++ \fn QUuid QUuid::createUuidV3(QUuid ns, QByteArrayView baseData);
++
++ This function returns a new UUID with variant QUuid::DCE and version QUuid::Md5.
++ \a ns is the namespace and \a baseData is the basic data as described by RFC 4122.
++
++ \note In Qt versions prior to 6.8, this function took QByteArray, not
++ QByteArrayView.
++
++ \sa variant(), version(), createUuidV5(), createUuidV7()
++ */
++
++ /*!
++ \since 5.0
++ \fn QUuid QUuid::createUuidV3(const QUuid &ns, const QString &baseData);
++
++ This function returns a new UUID with variant QUuid::DCE and version QUuid::Md5.
++ \a ns is the namespace and \a baseData is the basic data as described by RFC 4122.
++
++ \sa variant(), version(), createUuidV5(), createUuidV7()
++ */
++
++ /*!
++ \since 5.0
++ \fn QUuid QUuid::createUuidV5(QUuid ns, QByteArrayView baseData);
++
++ This function returns a new UUID with variant QUuid::DCE and version QUuid::Sha1.
++ \a ns is the namespace and \a baseData is the basic data as described by RFC 4122.
++
++ \note In Qt versions prior to 6.8, this function took QByteArray, not
++ QByteArrayView.
++
++ \sa variant(), version(), createUuidV3()
++ */
++
++ /*!
++ \since 5.0
++ \fn QUuid QUuid::createUuidV5(const QUuid &ns, const QString &baseData);
++
++ This function returns a new UUID with variant QUuid::DCE and version QUuid::Sha1.
++ \a ns is the namespace and \a baseData is the basic data as described by RFC 4122.
++
++ \sa variant(), version(), createUuidV3()
++ */
++ QUuid QUuid::createUuidV3(QUuid ns, QByteArrayView baseData) noexcept
++ {
++ return createFromName(ns, baseData, QCryptographicHash::Md5, 3);
++ }
++
++ QUuid QUuid::createUuidV5(QUuid ns, QByteArrayView baseData) noexcept
++ {
++ return createFromName(ns, baseData, QCryptographicHash::Sha1, 5);
++ }
++
++ /*!
++ \since 6.9
++
++ This function returns a new UUID with variant QUuid::DCE and version
++ QUuid::UnixEpoch.
++
++ It uses a time-ordered value field derived from the number of milliseconds
++ since the UNIX Epoch as described by
++
++ \sa variant(), version(), createUuidV3(), createUuidV5()
++ */
++ QUuid QUuid::createUuidV7()
++ {
++ return createUuidV7_internal(std::chrono::system_clock::now());
++ }
++
++ /*!
++ Creates a QUuid object from the binary representation of the UUID, as
++ specified by RFC 4122 section 4.1.2. See toRfc4122() for a further
++ explanation of the order of \a bytes required.
++
++ The byte array accepted is NOT a human readable format.
++
++ If the conversion fails, a null UUID is created.
++
++ \note In Qt versions prior to 6.3, this function took QByteArray, not
++ QByteArrayView.
++
++ \since 4.8
++
++ \sa toRfc4122(), QUuid(), fromBytes()
++ */
++ QUuid QUuid::fromRfc4122(QByteArrayView bytes) noexcept
++ {
++ if (bytes.isEmpty() || bytes.size() != 16)
++ return QUuid();
++ return fromBytes(bytes.data());
++ }
++
++ /*!
++ \fn bool QUuid::operator==(const QUuid &lhs, const QUuid &rhs)
++
++ Returns \c true if \a lhs QUuid and the \a rhs QUuid are identical;
++ otherwise returns \c false.
++ */
++
++ /*!
++ \fn bool QUuid::operator!=(const QUuid &lhs, const QUuid &rhs)
++
++ Returns \c true if \a lhs QUuid and the \a rhs QUuid are different;
++ otherwise returns \c false.
++ */
++
++ /*!
++ \since 5.11
++
++ Returns the string representation of this QUuid, with the formattiong
++ controlled by the \a mode parameter. From left to right, the five hex
++ fields are obtained from the four public data members in QUuid as follows:
++
++ \table
++ \header
++ \li Field #
++ \li Source
++
++ \row
++ \li 1
++ \li data1
++
++ \row
++ \li 2
++ \li data2
++
++ \row
++ \li 3
++ \li data3
++
++ \row
++ \li 4
++ \li data4[0] .. data4[1]
++
++ \row
++ \li 5
++ \li data4[2] .. data4[7]
++
++ \endtable
++ */
++ QString QUuid::toString(QUuid::StringFormat mode) const
++ {
++ char latin1[MaxStringUuidLength];
++ const auto end = _q_uuidToHex(*this, latin1, mode);
++ return QString::fromLatin1(latin1, end - latin1);
++ }
++
++ /*!
++ \since 5.11
++
++ Returns the string representation of this QUuid, with the formattiong
++ controlled by the \a mode parameter. From left to right, the five hex
++ fields are obtained from the four public data members in QUuid as follows:
++
++ \table
++ \header
++ \li Field #
++ \li Source
++
++ \row
++ \li 1
++ \li data1
++
++ \row
++ \li 2
++ \li data2
++
++ \row
++ \li 3
++ \li data3
++
++ \row
++ \li 4
++ \li data4[0] .. data4[1]
++
++ \row
++ \li 5
++ \li data4[2] .. data4[7]
++
++ \endtable
++ */
++ QByteArray QUuid::toByteArray(QUuid::StringFormat mode) const
++ {
++ QByteArray result(MaxStringUuidLength, Qt::Uninitialized);
++ const auto end = _q_uuidToHex(*this, const_cast<char *>(result.constData()), mode);
++ result.resize(end - result.constData());
++ return result;
++ }
++
++ /*!
++ Returns the binary representation of this QUuid. The byte array is in big
++ endian format, and formatted according to RFC 4122, section 4.1.2 -
++ "Layout and byte order".
++
++ The order is as follows:
++
++ \table
++ \header
++ \li Field #
++ \li Source
++
++ \row
++ \li 1
++ \li data1
++
++ \row
++ \li 2
++ \li data2
++
++ \row
++ \li 3
++ \li data3
++
++ \row
++ \li 4
++ \li data4[0] .. data4[7]
++
++ \endtable
++
++ The bytes in the byte array returned by this function contains the same
++ binary content as toBytes().
++
++ \sa toBytes()
++ \since 4.8
++ */
++ QByteArray QUuid::toRfc4122() const
++ {
++ Id128Bytes bytes = toBytes();
++ return QByteArrayView(bytes).toByteArray();
++ }
++
++ #ifndef QT_NO_DATASTREAM
++ /*!
++ \relates QUuid
++ Writes the UUID \a id to the data stream \a s.
++ */
++ QDataStream &operator<<(QDataStream &s, const QUuid &id)
++ {
++ constexpr int NumBytes = sizeof(QUuid);
++ static_assert(NumBytes == 16, "Change the serialization format when this ever hits");
++ char bytes[NumBytes];
++ if (s.byteOrder() == QDataStream::BigEndian) {
++ const auto id128 = id.toBytes();
++ static_assert(sizeof(id128) == NumBytes);
++ memcpy(bytes, &id128, NumBytes);
++ } else {
++ auto *data = bytes;
++
++ // for historical reasons, our little-endian serialization format
++ // stores each of the UUID fields in little endian, instead of storing
++ // a little endian Id128
++ qToLittleEndian(id.data1, data);
++ data += sizeof(quint32);
++ qToLittleEndian(id.data2, data);
++ data += sizeof(quint16);
++ qToLittleEndian(id.data3, data);
++ data += sizeof(quint16);
++
++ for (int i = 0; i < 8; ++i) {
++ *(data) = id.data4[i];
++ data++;
++ }
++ }
++
++ if (s.writeRawData(bytes, NumBytes) != NumBytes)
++ s.setStatus(QDataStream::WriteFailed);
++
++ return s;
++ }
++
++ /*!
++ \relates QUuid
++ Reads a UUID from the stream \a s into \a id.
++ */
++ QDataStream &operator>>(QDataStream &s, QUuid &id)
++ {
++ std::array<char, 16> bytes;
++ if (s.readRawData(bytes.data(), 16) != 16) {
++ s.setStatus(QDataStream::ReadPastEnd);
++ return s;
++ }
++
++ if (s.byteOrder() == QDataStream::BigEndian) {
++ id = QUuid::fromRfc4122(bytes);
++ } else {
++ const uchar *data = reinterpret_cast<const uchar *>(bytes.data());
++
++ id.data1 = qFromLittleEndian<quint32>(data);
++ data += sizeof(quint32);
++ id.data2 = qFromLittleEndian<quint16>(data);
++ data += sizeof(quint16);
++ id.data3 = qFromLittleEndian<quint16>(data);
++ data += sizeof(quint16);
++
++ for (int i = 0; i < 8; ++i) {
++ id.data4[i] = *(data);
++ data++;
++ }
++ }
++
++ return s;
++ }
++ #endif // QT_NO_DATASTREAM
++
++ /*!
++ \fn bool QUuid::isNull() const
++
++ Returns \c true if this is the null UUID
++ {00000000-0000-0000-0000-000000000000}; otherwise returns \c false.
++ */
++
++ /*!
++ \enum QUuid::Variant
++
++ This enum defines the values used in the \l{Variant field}
++ {variant field} of the UUID. The value in the variant field
++ determines the layout of the 128-bit value.
++
++ \value VarUnknown Variant is unknown
++ \value NCS Reserved for NCS (Network Computing System) backward compatibility
++ \value DCE Distributed Computing Environment, the scheme used by QUuid
++ \value Microsoft Reserved for Microsoft backward compatibility (GUID)
++ \value Reserved Reserved for future definition
++ */
++
++ /*!
++ \enum QUuid::Version
++
++ This enum defines the values used in the \l{Version field}
++ {version field} of the UUID. The version field is meaningful
++ only if the value in the \l{Variant field} {variant field}
++ is QUuid::DCE.
++
++ \value VerUnknown Version is unknown
++ \value Time Time-based, by using timestamp, clock sequence, and
++ MAC network card address (if available) for the node sections
++ \value EmbeddedPOSIX DCE Security version, with embedded POSIX UUIDs
++ \value Name Name-based, by using values from a name for all sections
++ \value Md5 Alias for Name
++ \value Random Random-based, by using random numbers for all sections
++ \value Sha1 Name-based version that uses SHA-1 hashing
++ \value [since 6.9] UnixEpoch Time-based UUID using the number of
++ milliseconds since the UNIX epoch
++ */
++
++ /*!
++ \fn QUuid::Variant QUuid::variant() const
++
++ Returns the value in the \l{Variant field} {variant field} of the
++ UUID. If the return value is QUuid::DCE, call version() to see
++ which layout it uses. The null UUID is considered to be of an
++ unknown variant.
++
++ \sa version()
++ */
++
++ /*!
++ \fn QUuid::Version QUuid::version() const
++
++ Returns the \l{Version field} {version field} of the UUID, if the
++ UUID's \l{Variant field} {variant field} is QUuid::DCE. Otherwise
++ it returns QUuid::VerUnknown.
++
++ \sa variant()
++ */
++
++ /*!
++ \fn bool QUuid::operator<(const QUuid &lhs, const QUuid &rhs)
++ \fn bool QUuid::operator>(const QUuid &lhs, const QUuid &rhs)
++ \fn bool QUuid::operator<=(const QUuid &lhs, const QUuid &rhs)
++ \fn bool QUuid::operator>=(const QUuid &lhs, const QUuid &rhs)
++ \since 5.5
++
++ Performs a comparison of \a lhs against \a rhs and returns \c true if the
++ relative sorting of \a lhs and \a rhs is correct for the operation in
++ question, \c false otherwise. Note that the sorting performed by this
++ functions may not be equal to the sorting of the strings created by
++ toString(), nor the integers toId128(), or the byte array returned by
++ toBytes() and toRfc4122().
++
++ \sa {QUuid::}{variant()}
++ */
++
++ /*!
++ \fn QUuid QUuid::createUuid()
++
++ On any platform other than Windows, this function returns a new UUID with
++ variant QUuid::DCE and version QUuid::Random. On Windows, a GUID is
++ generated using the Windows API and will be of the type that the API
++ decides to create.
++
++ \sa variant(), version()
++ */
++ #if defined(Q_OS_WIN)
++
++ QT_BEGIN_INCLUDE_NAMESPACE
++ #include <objbase.h> // For CoCreateGuid
++ QT_END_INCLUDE_NAMESPACE
++
++ QUuid QUuid::createUuid()
++ {
++ GUID guid;
++ CoCreateGuid(&guid);
++ QUuid result = guid;
++ return result;
++ }
++
++ #else
++
++ QUuid QUuid::createUuid()
++ {
++ QUuid result(Qt::Uninitialized);
++ uint *data = &(result.data1);
++ enum { AmountToRead = 4 };
++ QRandomGenerator::system()->fillRange(data, AmountToRead);
++
++ result.data4[0] = (result.data4[0] & 0x3F) | 0x80; // UV_DCE
++ result.data3 = (result.data3 & 0x0FFF) | 0x4000; // UV_Random
++
++ return result;
++ }
++ #endif // !Q_OS_WIN
++
++ /*!
++ \fn bool QUuid::operator==(const QUuid &lhs, const GUID &rhs)
++
++ Returns \c true if \a lhs UUID is equal to the Windows GUID \a rhs;
++ otherwise returns \c false.
++ */
++
++ /*!
++ \fn bool QUuid::operator!=(const QUuid &lhs, const GUID &rhs)
++
++ Returns \c true if \a lhs UUID is not equal to the Windows GUID \a rhs;
++ otherwise returns \c false.
++ */
++
++ #ifndef QT_NO_DEBUG_STREAM
++ /*!
++ \relates QUuid
++ Writes the UUID \a id to the output stream for debugging information \a dbg.
++ */
++ QDebug operator<<(QDebug dbg, const QUuid &id)
++ {
++ QDebugStateSaver saver(dbg);
++ dbg.nospace() << "QUuid(" << id.toString() << ')';
++ return dbg;
++ }
++ #endif
++
++ /*!
++ \fn size_t qHash(const QUuid &key, size_t seed)
++ \since 5.0
++ \qhashold{QUuid}
++ */
++ size_t qHash(const QUuid &uuid, size_t seed) noexcept
++ {
++ static_assert(std::has_unique_object_representations_v<QUuid>,
++ "Can't use qHashBits() if the type has padding holes.");
++ return qHashBits(&uuid, sizeof(QUuid), seed);
++ }
++
++
++ QT_END_NAMESPACE