summaryrefslogtreecommitdiffstats
path: root/src/corelib/plugin/quuid.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/plugin/quuid.cpp')
-rw-r--r--src/corelib/plugin/quuid.cpp329
1 files changed, 184 insertions, 145 deletions
diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp
index be67898f8a..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 };
@@ -151,16 +118,12 @@ static QUuid _q_uuidFromHex(const char *src)
static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCryptographicHash::Algorithm algorithm, int version)
{
- QByteArray hashResult;
-
- // create a scope so later resize won't reallocate
- {
- QCryptographicHash hash(algorithm);
- hash.addData(ns.toRfc4122());
- hash.addData(baseData);
- hashResult = hash.result();
- }
- hashResult.resize(16); // Sha1 will be too long
+ QCryptographicHash hash(algorithm);
+ hash.addData(ns.toRfc4122());
+ hash.addData(baseData);
+ QByteArrayView hashResult = hash.resultView();
+ Q_ASSERT(hashResult.size() >= 16);
+ hashResult.truncate(16); // Sha1 will be too long
QUuid result = QUuid::fromRfc4122(hashResult);
@@ -290,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
@@ -327,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.
@@ -369,6 +451,8 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto
*/
/*!
+ \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
@@ -377,17 +461,18 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto
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()
*/
-QUuid::QUuid(const QString &text)
- : QUuid(fromString(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,12 +480,16 @@ QUuid::QUuid(const QString &text)
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()
*/
-QUuid QUuid::fromString(QStringView text) noexcept
+static QUuid uuidFromString(QStringView text) noexcept
{
if (text.size() > MaxStringUuidLength)
- text = text.left(MaxStringUuidLength); // text.truncate(MaxStringUuidLength);
+ text.truncate(MaxStringUuidLength);
char latin1[MaxStringUuidLength + 1];
char *dst = latin1;
@@ -413,55 +502,27 @@ QUuid QUuid::fromString(QStringView text) noexcept
return _q_uuidFromHex(latin1);
}
-/*!
- \since 5.10
- \overload
-
- 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 returned. See
- toString() for an explanation of how the five hex fields map to the
- public data members in QUuid.
-
- \sa toString(), QUuid()
-*/
-QUuid QUuid::fromString(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());
}
-/*!
- \internal
-*/
-QUuid::QUuid(const char *text)
- : QUuid(_q_uuidFromHex(text))
+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()));
}
-/*!
- Creates a QUuid object from the QByteArray \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
- toByteArray() for an explanation of how the five hex fields map to the
- public data members in QUuid.
-
- \since 4.8
-
- \sa toByteArray(), QUuid()
-*/
-QUuid::QUuid(const QByteArray &text)
- : QUuid(fromString(QLatin1String(text.data(), text.size())))
+QUuid QUuid::fromString(QAnyStringView text) noexcept
{
+ return text.visit([] (auto text) { return uuidFromString(text); });
}
/*!
@@ -524,34 +585,18 @@ QUuid QUuid::createUuidV5(const QUuid &ns, const QByteArray &baseData)
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()
+ \sa toRfc4122(), QUuid(), fromBytes()
*/
-QUuid QUuid::fromRfc4122(const QByteArray &bytes)
+QUuid QUuid::fromRfc4122(QByteArrayView bytes) noexcept
{
- if (bytes.isEmpty() || bytes.length() != 16)
+ if (bytes.isEmpty() || bytes.size() != 16)
return QUuid();
-
- uint d1;
- ushort d2, d3;
- uchar d4[8];
-
- const uchar *data = reinterpret_cast<const uchar *>(bytes.constData());
-
- 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());
}
/*!
@@ -681,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
@@ -711,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);
@@ -732,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;
}
@@ -744,7 +783,7 @@ QDataStream &operator<<(QDataStream &s, const QUuid &id)
*/
QDataStream &operator>>(QDataStream &s, QUuid &id)
{
- QByteArray bytes(16, Qt::Uninitialized);
+ std::array<char, 16> bytes;
if (s.readRawData(bytes.data(), 16) != 16) {
s.setStatus(QDataStream::ReadPastEnd);
return s;
@@ -753,7 +792,7 @@ QDataStream &operator>>(QDataStream &s, QUuid &id)
if (s.byteOrder() == QDataStream::BigEndian) {
id = QUuid::fromRfc4122(bytes);
} else {
- const uchar *data = reinterpret_cast<const uchar *>(bytes.constData());
+ const uchar *data = reinterpret_cast<const uchar *>(bytes.data());
id.data1 = qFromLittleEndian<quint32>(data);
data += sizeof(quint32);
@@ -953,7 +992,7 @@ QUuid QUuid::createUuid()
return result;
}
-#else // Q_OS_WIN
+#elif !defined(QT_BOOTSTRAPPED)
QUuid QUuid::createUuid()
{
@@ -967,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