diff options
Diffstat (limited to 'src/corelib/plugin/quuid.cpp')
-rw-r--r-- | src/corelib/plugin/quuid.cpp | 249 |
1 files changed, 155 insertions, 94 deletions
diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp index 33fac4b892..9c7216c3c5 100644 --- a/src/corelib/plugin/quuid.cpp +++ b/src/corelib/plugin/quuid.cpp @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** 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> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// 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 #include "quuid.h" @@ -49,6 +13,9 @@ 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 }; @@ -286,7 +253,7 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto \endtable The field layouts for the DCE versions listed in the table above - are specified in the \l{http://www.ietf.org/rfc/rfc4122.txt} + are specified in the \l{RFC 4122} {Network Working Group UUID Specification}. Most platforms provide a tool for generating new UUIDs, e.g. \c @@ -323,6 +290,125 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto */ /*! + \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. @@ -383,10 +469,10 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto */ /*! - \fn static QUuid::fromString(QAnyStringView text) + \fn static QUuid::fromString(QAnyStringView string) \since 5.10 - Creates a QUuid object from the string \a text, which must be + 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 @@ -395,7 +481,7 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto public data members in QUuid. \note In Qt versions prior to 6.3, this function was an overload - set consisting of QStringView and QLatin1String instead of + set consisting of QStringView and QLatin1StringView instead of one function taking QAnyStringView. \sa toString(), QUuid() @@ -416,13 +502,13 @@ static QUuid uuidFromString(QStringView text) noexcept return _q_uuidFromHex(latin1); } -static QUuid uuidFromString(QLatin1String text) noexcept +static QUuid uuidFromString(QLatin1StringView text) noexcept { if (Q_UNLIKELY(text.size() < MaxStringUuidLength - 2 - || (text.front() == QLatin1Char('{') && text.size() < MaxStringUuidLength - 1))) { + || (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 = QLatin1String(); + text = QLatin1StringView(); } return _q_uuidFromHex(text.data()); } @@ -431,7 +517,7 @@ Q_ALWAYS_INLINE // can treat UTF-8 the same as Latin-1: static QUuid uuidFromString(QUtf8StringView text) noexcept { - return uuidFromString(QLatin1String(text.data(), text.size())); + return uuidFromString(QLatin1StringView(text.data(), text.size())); } QUuid QUuid::fromString(QAnyStringView text) noexcept @@ -504,32 +590,13 @@ QUuid QUuid::createUuidV5(const QUuid &ns, const QByteArray &baseData) \since 4.8 - \sa toRfc4122(), QUuid() + \sa toRfc4122(), QUuid(), fromBytes() */ QUuid QUuid::fromRfc4122(QByteArrayView bytes) noexcept { if (bytes.isEmpty() || bytes.size() != 16) return QUuid(); - - uint d1; - ushort d2, d3; - uchar d4[8]; - - const uchar *data = reinterpret_cast<const uchar *>(bytes.data()); - - d1 = qFromBigEndian<quint32>(data); - data += sizeof(quint32); - d2 = qFromBigEndian<quint16>(data); - data += sizeof(quint16); - d3 = qFromBigEndian<quint16>(data); - data += sizeof(quint16); - - for (int i = 0; i < 8; ++i) { - d4[i] = *(data); - data++; - } - - return QUuid(d1, d2, d3, d4[0], d4[1], d4[2], d4[3], d4[4], d4[5], d4[6], d4[7]); + return fromBytes(bytes.data()); } /*! @@ -659,27 +726,16 @@ QByteArray QUuid::toByteArray(QUuid::StringFormat mode) const \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 { - // we know how many bytes a UUID has, I hope :) - QByteArray bytes(16, Qt::Uninitialized); - uchar *data = reinterpret_cast<uchar *>(bytes.data()); - - qToBigEndian(data1, data); - data += sizeof(quint32); - qToBigEndian(data2, data); - data += sizeof(quint16); - qToBigEndian(data3, data); - data += sizeof(quint16); - - for (int i = 0; i < 8; ++i) { - *(data) = data4[i]; - data++; - } - - return bytes; + Id128Bytes bytes = toBytes(); + return QByteArrayView(bytes).toByteArray(); } #ifndef QT_NO_DATASTREAM @@ -689,14 +745,19 @@ QByteArray QUuid::toRfc4122() const */ QDataStream &operator<<(QDataStream &s, const QUuid &id) { - QByteArray bytes; + 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) { - bytes = id.toRfc4122(); + const auto id128 = id.toBytes(); + static_assert(sizeof(id128) == NumBytes); + memcpy(bytes, &id128, NumBytes); } else { - // we know how many bytes a UUID has, I hope :) - bytes = QByteArray(16, Qt::Uninitialized); - uchar *data = reinterpret_cast<uchar *>(bytes.data()); + 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); @@ -710,9 +771,9 @@ QDataStream &operator<<(QDataStream &s, const QUuid &id) } } - if (s.writeRawData(bytes.data(), 16) != 16) { + if (s.writeRawData(bytes, NumBytes) != NumBytes) s.setStatus(QDataStream::WriteFailed); - } + return s; } @@ -931,7 +992,7 @@ QUuid QUuid::createUuid() return result; } -#else // Q_OS_WIN +#elif !defined(QT_BOOTSTRAPPED) QUuid QUuid::createUuid() { @@ -945,7 +1006,7 @@ QUuid QUuid::createUuid() return result; } -#endif // !Q_OS_WIN +#endif // !Q_OS_WIN && !QT_BOOTSTRAPPED /*! \fn bool QUuid::operator==(const GUID &guid) const |