diff options
Diffstat (limited to 'src/corelib/plugin/quuid.h')
-rw-r--r-- | src/corelib/plugin/quuid.h | 203 |
1 files changed, 159 insertions, 44 deletions
diff --git a/src/corelib/plugin/quuid.h b/src/corelib/plugin/quuid.h index 9ba6564ef0..aa6e200ecb 100644 --- a/src/corelib/plugin/quuid.h +++ b/src/corelib/plugin/quuid.h @@ -4,6 +4,7 @@ #ifndef QUUID_H #define QUUID_H +#include <QtCore/qcompare.h> #include <QtCore/qendian.h> #include <QtCore/qstring.h> @@ -55,24 +56,44 @@ public: Id128 = 3 }; - union Id128Bytes { + 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; + } }; - constexpr QUuid() noexcept {} + constexpr QUuid() noexcept : data1(0), data2(0), data3(0), data4{0,0,0,0,0,0,0,0} {} 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} {} - QUuid(Id128Bytes id128, QSysInfo::Endian order = QSysInfo::BigEndian) noexcept; + explicit inline QUuid(Id128Bytes id128, QSysInfo::Endian order = QSysInfo::BigEndian) noexcept; explicit QUuid(QAnyStringView string) noexcept : QUuid{fromString(string)} {} @@ -86,10 +107,10 @@ public: #endif QString toString(StringFormat mode = WithBraces) const; QByteArray toByteArray(StringFormat mode = WithBraces) const; - Id128Bytes toBytes(QSysInfo::Endian order = QSysInfo::BigEndian) const noexcept; + inline Id128Bytes toBytes(QSysInfo::Endian order = QSysInfo::BigEndian) const noexcept; QByteArray toRfc4122() const; - static QUuid fromBytes(const void *bytes, QSysInfo::Endian order = QSysInfo::BigEndian) noexcept; + 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 @@ -97,27 +118,65 @@ public: bool isNull() const noexcept; - 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 + +private: + friend constexpr bool comparesEqual(const QUuid &lhs, const QUuid &rhs) noexcept { - if (data1 != orig.data1 || data2 != orig.data2 || - data3 != orig.data3) + if (lhs.data1 != rhs.data1 || lhs.data2 != rhs.data2 || lhs.data3 != rhs.data3) return false; - for (uint i = 0; i < 8; i++) - if (data4[i] != orig.data4[i]) + for (uint i = 0; i < 8; i++) { + if (lhs.data4[i] != rhs.data4[i]) return false; + } return true; } + friend Qt::strong_ordering compareThreeWay(const QUuid &lhs, const QUuid &rhs) noexcept + { + if (const auto c = Qt::compareThreeWay(lhs.variant(), rhs.variant()); !is_eq(c)) + return c; + if (const auto c = Qt::compareThreeWay(lhs.data1, rhs.data1); !is_eq(c)) + return c; + if (const auto c = Qt::compareThreeWay(lhs.data2, rhs.data2); !is_eq(c)) + return c; + if (const auto c = Qt::compareThreeWay(lhs.data3, rhs.data3); !is_eq(c)) + return c; + + int c = std::memcmp(lhs.data4, rhs.data4, sizeof(lhs.data4)); + return Qt::compareThreeWay(c, 0); + } + +public: +/* To prevent a meta-type creation ambiguity on Windows, we put comparison + macros under NOT QT_CORE_REMOVED_SINCE(6, 8) part. */ +#if QT_CORE_REMOVED_SINCE(6, 8) + constexpr bool operator==(const QUuid &orig) const noexcept + { + return comparesEqual(*this, orig); + } constexpr bool operator!=(const QUuid &orig) const noexcept { - return !(*this == orig); + return !operator==(orig); } bool operator<(const QUuid &other) const noexcept; bool operator>(const QUuid &other) const noexcept; - +#else +private: +#if defined(__cpp_lib_three_way_comparison) && !defined(Q_QDOC) + QT_DECLARE_3WAY_HELPER_STRONG(QUuid, QUuid, /* non-constexpr */, /* no attributes */) +#else + QT_DECLARE_ORDERING_HELPER_STRONG(QUuid, QUuid, /* non-constexpr */, /* no attributes */) +#endif // defined(__cpp_lib_three_way_comparison) && !defined(Q_QDOC) + Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QUuid) +#endif // QT_CORE_REMOVED_SINCE(6, 8) +public: #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. @@ -137,32 +196,51 @@ public: GUID guid = { data1, data2, data3, { data4[0], data4[1], data4[2], data4[3], data4[4], data4[5], data4[6], data4[7] } }; return guid; } - +private: + friend constexpr bool comparesEqual(const QUuid &lhs, const GUID &rhs) noexcept + { + return comparesEqual(lhs, QUuid(rhs)); + } +public: +/* To prevent a meta-type creation ambiguity on Windows, we put comparison + macros under NOT QT_CORE_REMOVED_SINCE(6, 8) part. */ +#if QT_CORE_REMOVED_SINCE(6, 8) constexpr bool operator==(const GUID &guid) const noexcept { - return *this == QUuid(guid); + return comparesEqual(*this, QUuid(guid)); } constexpr bool operator!=(const GUID &guid) const noexcept { - return !(*this == guid); + return !operator==(guid); } +#else + Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QUuid, GUID) +#endif // !QT_CORE_REMOVED_SINCE(6, 8) #endif +public: static QUuid createUuid(); -#ifndef QT_BOOTSTRAPPED - static QUuid createUuidV3(const QUuid &ns, const QByteArray &baseData); +#if QT_CORE_REMOVED_SINCE(6, 8) + static QUuid createUuidV3(const QUuid &ns, const QByteArray &baseData) noexcept; + static QUuid createUuidV5(const QUuid &ns, const QByteArray &baseData) noexcept; #endif - static QUuid createUuidV5(const QUuid &ns, const QByteArray &baseData); + static QUuid createUuidV5(QUuid ns, QByteArrayView baseData) noexcept; #ifndef QT_BOOTSTRAPPED + static QUuid createUuidV3(QUuid ns, QByteArrayView baseData) noexcept; +#if !QT_CORE_REMOVED_SINCE(6, 8) + Q_WEAK_OVERLOAD +#endif static inline QUuid createUuidV3(const QUuid &ns, const QString &baseData) { - return QUuid::createUuidV3(ns, baseData.toUtf8()); + return QUuid::createUuidV3(ns, qToByteArrayViewIgnoringNull(baseData.toUtf8())); } #endif - +#if !QT_CORE_REMOVED_SINCE(6, 8) + Q_WEAK_OVERLOAD +#endif static inline QUuid createUuidV5(const QUuid &ns, const QString &baseData) { - return QUuid::createUuidV5(ns, baseData.toUtf8()); + return QUuid::createUuidV5(ns, qToByteArrayViewIgnoringNull(baseData.toUtf8())); } QUuid::Variant variant() const noexcept; @@ -175,20 +253,10 @@ public: NSUUID *toNSUUID() const Q_DECL_NS_RETURNS_AUTORELEASED; #endif - uint data1 = 0; - ushort data2 = 0; - ushort data3 = 0; - uchar data4[8] = {}; - -private: - static constexpr Id128Bytes bswap(Id128Bytes b) - { - // 128-bit byte swap - b.data64[0] = qbswap(b.data64[0]); - b.data64[1] = qbswap(b.data64[1]); - qSwap(b.data64[0], b.data64[1]); - return b; - } + uint data1; + ushort data2; + ushort data3; + uchar data4[8]; }; Q_DECLARE_TYPEINFO(QUuid, Q_PRIMITIVE_TYPE); @@ -204,17 +272,17 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QUuid &); Q_CORE_EXPORT size_t qHash(const QUuid &uuid, size_t seed = 0) noexcept; -inline QUuid::QUuid(Id128Bytes uuid, QSysInfo::Endian order) noexcept +QUuid::QUuid(Id128Bytes uuid, QSysInfo::Endian order) noexcept { if (order == QSysInfo::LittleEndian) - uuid = bswap(uuid); + 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)); } -inline QUuid::Id128Bytes QUuid::toBytes(QSysInfo::Endian order) const noexcept +QUuid::Id128Bytes QUuid::toBytes(QSysInfo::Endian order) const noexcept { Id128Bytes result = {}; qToBigEndian(data1, &result.data[0]); @@ -222,21 +290,68 @@ inline QUuid::Id128Bytes QUuid::toBytes(QSysInfo::Endian order) const noexcept qToBigEndian(data3, &result.data[6]); memcpy(&result.data[8], data4, sizeof(data4)); if (order == QSysInfo::LittleEndian) - return bswap(result); + return qbswap(result); return result; } -inline QUuid QUuid::fromBytes(const void *bytes, QSysInfo::Endian order) noexcept +QUuid QUuid::fromBytes(const void *bytes, QSysInfo::Endian order) { Id128Bytes result = {}; memcpy(result.data, bytes, sizeof(result)); return QUuid(result, order); } -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); } +#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 + +#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 |