diff options
Diffstat (limited to 'src/corelib/plugin/quuid.h')
-rw-r--r-- | src/corelib/plugin/quuid.h | 249 |
1 files changed, 152 insertions, 97 deletions
diff --git a/src/corelib/plugin/quuid.h b/src/corelib/plugin/quuid.h index bdd74f4b77..7125e8e2cc 100644 --- a/src/corelib/plugin/quuid.h +++ b/src/corelib/plugin/quuid.h @@ -1,48 +1,13 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** 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. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QUUID_H #define QUUID_H +#include <QtCore/qendian.h> #include <QtCore/qstring.h> -#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC) +#if defined(Q_OS_WIN) || defined(Q_QDOC) #ifndef GUID_DEFINED #define GUID_DEFINED typedef struct _GUID @@ -55,14 +20,13 @@ typedef struct _GUID #endif #endif -#if defined(Q_OS_DARWIN) || defined(Q_CLANG_QDOC) +#if defined(Q_OS_DARWIN) || defined(Q_QDOC) Q_FORWARD_DECLARE_CF_TYPE(CFUUID); Q_FORWARD_DECLARE_OBJC_CLASS(NSUUID); #endif QT_BEGIN_NAMESPACE - class Q_CORE_EXPORT QUuid { QUuid(Qt::Initialization) {} @@ -91,52 +55,74 @@ public: Id128 = 3 }; -#if defined(Q_COMPILER_UNIFORM_INIT) && !defined(Q_CLANG_QDOC) + union alignas(16) Id128Bytes { + quint8 data[16]; + quint16 data16[8]; + quint32 data32[4]; + quint64 data64[2]; +#if defined(__SIZEOF_INT128__) +QT_WARNING_PUSH +QT_WARNING_DISABLE_GCC("-Wpedantic") // ISO C++ does not support ‘__int128’ for ‘data128’ + unsigned __int128 data128[1]; +QT_WARNING_POP +#elif defined(QT_SUPPORTS_INT128) +# error "struct QUuid::Id128Bytes should not depend on QT_SUPPORTS_INT128 for ABI reasons." +# error "Adjust the declaration of the `data128` member above so it is always defined if it's " \ + "supported by the current compiler/architecture in any configuration." +#endif + + constexpr explicit operator QByteArrayView() const noexcept + { + return QByteArrayView(data, sizeof(data)); + } + + friend constexpr Id128Bytes qbswap(Id128Bytes b) noexcept + { + // 128-bit byte swap + auto b0 = qbswap(b.data64[0]); + auto b1 = qbswap(b.data64[1]); + b.data64[0] = b1; + b.data64[1] = b0; + return b; + } + }; - Q_DECL_CONSTEXPR QUuid() noexcept : data1(0), data2(0), data3(0), data4{0,0,0,0,0,0,0,0} {} + constexpr QUuid() noexcept : data1(0), data2(0), data3(0), data4{0,0,0,0,0,0,0,0} {} - Q_DECL_CONSTEXPR QUuid(uint l, ushort w1, ushort w2, uchar b1, uchar b2, uchar b3, + constexpr QUuid(uint l, ushort w1, ushort w2, uchar b1, uchar b2, uchar b3, uchar b4, uchar b5, uchar b6, uchar b7, uchar b8) noexcept : data1(l), data2(w1), data3(w2), data4{b1, b2, b3, b4, b5, b6, b7, b8} {} -#else - QUuid() noexcept - { - data1 = 0; - data2 = 0; - data3 = 0; - for(int i = 0; i < 8; i++) - data4[i] = 0; - } - QUuid(uint l, ushort w1, ushort w2, uchar b1, uchar b2, uchar b3, uchar b4, uchar b5, uchar b6, uchar b7, uchar b8) noexcept - { - data1 = l; - data2 = w1; - data3 = w2; - data4[0] = b1; - data4[1] = b2; - data4[2] = b3; - data4[3] = b4; - data4[4] = b5; - data4[5] = b6; - data4[6] = b7; - data4[7] = b8; - } -#endif + explicit inline QUuid(Id128Bytes id128, QSysInfo::Endian order = QSysInfo::BigEndian) noexcept; - QUuid(const QString &); + explicit QUuid(QAnyStringView string) noexcept + : QUuid{fromString(string)} {} + static QUuid fromString(QAnyStringView string) noexcept; +#if QT_CORE_REMOVED_SINCE(6, 3) + explicit QUuid(const QString &); static QUuid fromString(QStringView string) noexcept; - static QUuid fromString(QLatin1String string) noexcept; - QUuid(const char *); - QString toString() const; - QString toString(StringFormat mode) const; // ### Qt6: merge with previous - QUuid(const QByteArray &); - QByteArray toByteArray() const; - QByteArray toByteArray(StringFormat mode) const; // ### Qt6: merge with previous + static QUuid fromString(QLatin1StringView string) noexcept; + explicit QUuid(const char *); + explicit QUuid(const QByteArray &); +#endif + QString toString(StringFormat mode = WithBraces) const; + QByteArray toByteArray(StringFormat mode = WithBraces) const; + inline Id128Bytes toBytes(QSysInfo::Endian order = QSysInfo::BigEndian) const noexcept; QByteArray toRfc4122() const; + + static inline QUuid fromBytes(const void *bytes, QSysInfo::Endian order = QSysInfo::BigEndian); +#if QT_CORE_REMOVED_SINCE(6, 3) static QUuid fromRfc4122(const QByteArray &); +#endif + static QUuid fromRfc4122(QByteArrayView) noexcept; + bool isNull() const noexcept; - Q_DECL_RELAXED_CONSTEXPR bool operator==(const QUuid &orig) const noexcept +#ifdef QT_SUPPORTS_INT128 + static constexpr QUuid fromUInt128(quint128 uuid, QSysInfo::Endian order = QSysInfo::BigEndian) noexcept; + constexpr quint128 toUInt128(QSysInfo::Endian order = QSysInfo::BigEndian) const noexcept; +#endif + + constexpr bool operator==(const QUuid &orig) const noexcept { if (data1 != orig.data1 || data2 != orig.data2 || data3 != orig.data3) @@ -149,7 +135,7 @@ public: return true; } - Q_DECL_RELAXED_CONSTEXPR bool operator!=(const QUuid &orig) const noexcept + constexpr bool operator!=(const QUuid &orig) const noexcept { return !(*this == orig); } @@ -157,43 +143,32 @@ public: bool operator<(const QUuid &other) const noexcept; bool operator>(const QUuid &other) const noexcept; -#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC) +#if defined(Q_OS_WIN) || defined(Q_QDOC) // On Windows we have a type GUID that is used by the platform API, so we // provide convenience operators to cast from and to this type. -#if defined(Q_COMPILER_UNIFORM_INIT) && !defined(Q_CLANG_QDOC) - Q_DECL_CONSTEXPR QUuid(const GUID &guid) noexcept + constexpr QUuid(const GUID &guid) noexcept : data1(guid.Data1), data2(guid.Data2), data3(guid.Data3), data4{guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]} {} -#else - QUuid(const GUID &guid) noexcept - { - data1 = guid.Data1; - data2 = guid.Data2; - data3 = guid.Data3; - for(int i = 0; i < 8; i++) - data4[i] = guid.Data4[i]; - } -#endif - Q_DECL_RELAXED_CONSTEXPR QUuid &operator=(const GUID &guid) noexcept + constexpr QUuid &operator=(const GUID &guid) noexcept { *this = QUuid(guid); return *this; } - Q_DECL_RELAXED_CONSTEXPR operator GUID() const noexcept + constexpr operator GUID() const noexcept { GUID guid = { data1, data2, data3, { data4[0], data4[1], data4[2], data4[3], data4[4], data4[5], data4[6], data4[7] } }; return guid; } - Q_DECL_RELAXED_CONSTEXPR bool operator==(const GUID &guid) const noexcept + constexpr bool operator==(const GUID &guid) const noexcept { return *this == QUuid(guid); } - Q_DECL_RELAXED_CONSTEXPR bool operator!=(const GUID &guid) const noexcept + constexpr bool operator!=(const GUID &guid) const noexcept { return !(*this == guid); } @@ -215,11 +190,10 @@ public: return QUuid::createUuidV5(ns, baseData.toUtf8()); } - QUuid::Variant variant() const noexcept; QUuid::Version version() const noexcept; -#if defined(Q_OS_DARWIN) || defined(Q_CLANG_QDOC) +#if defined(Q_OS_DARWIN) || defined(Q_QDOC) static QUuid fromCFUUID(CFUUIDRef uuid); CFUUIDRef toCFUUID() const Q_DECL_CF_RETURNS_RETAINED; static QUuid fromNSUUID(const NSUUID *uuid); @@ -245,11 +219,92 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QUuid &); Q_CORE_EXPORT size_t qHash(const QUuid &uuid, size_t seed = 0) noexcept; +QUuid::QUuid(Id128Bytes uuid, QSysInfo::Endian order) noexcept +{ + if (order == QSysInfo::LittleEndian) + uuid = qbswap(uuid); + data1 = qFromBigEndian<quint32>(&uuid.data[0]); + data2 = qFromBigEndian<quint16>(&uuid.data[4]); + data3 = qFromBigEndian<quint16>(&uuid.data[6]); + memcpy(data4, &uuid.data[8], sizeof(data4)); +} + +QUuid::Id128Bytes QUuid::toBytes(QSysInfo::Endian order) const noexcept +{ + Id128Bytes result = {}; + qToBigEndian(data1, &result.data[0]); + qToBigEndian(data2, &result.data[4]); + qToBigEndian(data3, &result.data[6]); + memcpy(&result.data[8], data4, sizeof(data4)); + if (order == QSysInfo::LittleEndian) + return qbswap(result); + return result; +} + +QUuid QUuid::fromBytes(const void *bytes, QSysInfo::Endian order) +{ + Id128Bytes result = {}; + memcpy(result.data, bytes, sizeof(result)); + return QUuid(result, order); +} + +#ifdef QT_SUPPORTS_INT128 +constexpr QUuid QUuid::fromUInt128(quint128 uuid, QSysInfo::Endian order) noexcept +{ + QUuid result = {}; + if (order == QSysInfo::BigEndian) { + result.data1 = qFromBigEndian<quint32>(int(uuid)); + result.data2 = qFromBigEndian<quint16>(ushort(uuid >> 32)); + result.data3 = qFromBigEndian<quint16>(ushort(uuid >> 48)); + for (int i = 0; i < 8; ++i) + result.data4[i] = uchar(uuid >> (64 + i * 8)); + } else { + result.data1 = qFromLittleEndian<quint32>(uint(uuid >> 96)); + result.data2 = qFromLittleEndian<quint16>(ushort(uuid >> 80)); + result.data3 = qFromLittleEndian<quint16>(ushort(uuid >> 64)); + for (int i = 0; i < 8; ++i) + result.data4[i] = uchar(uuid >> (56 - i * 8)); + } + return result; +} + +constexpr quint128 QUuid::toUInt128(QSysInfo::Endian order) const noexcept +{ + quint128 result = {}; + if (order == QSysInfo::BigEndian) { + for (int i = 0; i < 8; ++i) + result |= quint64(data4[i]) << (i * 8); + result = result << 64; + result |= quint64(qToBigEndian<quint16>(data3)) << 48; + result |= quint64(qToBigEndian<quint16>(data2)) << 32; + result |= qToBigEndian<quint32>(data1); + } else { + result = qToLittleEndian<quint32>(data1); + result = result << 32; + result |= quint64(qToLittleEndian<quint16>(data2)) << 16; + result |= quint64(qToLittleEndian<quint16>(data3)); + result = result << 64; + for (int i = 0; i < 8; ++i) + result |= quint64(data4[i]) << (56 - i * 8); + } + return result; +} +#endif + inline bool operator<=(const QUuid &lhs, const QUuid &rhs) noexcept { return !(rhs < lhs); } inline bool operator>=(const QUuid &lhs, const QUuid &rhs) noexcept { return !(lhs < rhs); } +#if defined(Q_QDOC) +// provide fake declarations of qXXXEndian() functions, so that qDoc could +// distinguish them from the general template +QUuid::Id128Bytes qFromBigEndian(QUuid::Id128Bytes src); +QUuid::Id128Bytes qFromLittleEndian(QUuid::Id128Bytes src); +QUuid::Id128Bytes qToBigEndian(QUuid::Id128Bytes src); +QUuid::Id128Bytes qToLittleEndian(QUuid::Id128Bytes src); +#endif + QT_END_NAMESPACE #endif // QUUID_H |