diff --git a/src/corelib/compat/removed_api.cpp b/src/corelib/compat/removed_api.cpp index 827bed9bf74..df30d44aa8c 100644 --- a/src/corelib/compat/removed_api.cpp +++ b/src/corelib/compat/removed_api.cpp @@ -1240,6 +1240,22 @@ QUuid QUuid::createUuidV5(const QUuid &ns, const QByteArray &baseData) noexcept #if QT_CORE_REMOVED_SINCE(6, 9) +#include "quuid.h" + +bool QUuid::isNull() const noexcept +{ + return isNull(QT6_CALL_NEW_OVERLOAD); +} + +QUuid::Variant QUuid::variant() const noexcept +{ + return variant(QT6_CALL_NEW_OVERLOAD); +} + +QUuid::Version QUuid::version() const noexcept +{ + return version(QT6_CALL_NEW_OVERLOAD); +} // #include "qotherheader.h" // // implement removed functions from qotherheader.h diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp index af7c07d23e6..3dcfa1faf2c 100644 --- a/src/corelib/plugin/quuid.cpp +++ b/src/corelib/plugin/quuid.cpp @@ -823,15 +823,11 @@ QDataStream &operator>>(QDataStream &s, QUuid &id) #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. */ -bool QUuid::isNull() const noexcept -{ - return data4[0] == 0 && data4[1] == 0 && data4[2] == 0 && data4[3] == 0 && - data4[4] == 0 && data4[5] == 0 && data4[6] == 0 && data4[7] == 0 && - data1 == 0 && data2 == 0 && data3 == 0; -} /*! \enum QUuid::Variant @@ -875,17 +871,6 @@ bool QUuid::isNull() const noexcept \sa version() */ -QUuid::Variant QUuid::variant() const noexcept -{ - if (isNull()) - return VarUnknown; - // Check the 3 MSB of data4[0] - if ((data4[0] & 0x80) == 0x00) return NCS; - else if ((data4[0] & 0xC0) == 0x80) return DCE; - else if ((data4[0] & 0xE0) == 0xC0) return Microsoft; - else if ((data4[0] & 0xE0) == 0xE0) return Reserved; - return VarUnknown; -} /*! \fn QUuid::Version QUuid::version() const @@ -896,17 +881,6 @@ QUuid::Variant QUuid::variant() const noexcept \sa variant() */ -QUuid::Version QUuid::version() const noexcept -{ - // Check the 4 MSB of data3 - Version ver = (Version)(data3>>12); - if (isNull() - || (variant() != DCE) - || ver < Time - || ver > Sha1) - return VerUnknown; - return ver; -} /*! \fn bool QUuid::operator<(const QUuid &lhs, const QUuid &rhs) diff --git a/src/corelib/plugin/quuid.h b/src/corelib/plugin/quuid.h index 435b7bb572d..c6aea2591c8 100644 --- a/src/corelib/plugin/quuid.h +++ b/src/corelib/plugin/quuid.h @@ -117,7 +117,25 @@ QT_WARNING_POP #endif static QUuid fromRfc4122(QByteArrayView) noexcept; +#if QT_CORE_REMOVED_SINCE(6, 9) bool isNull() const noexcept; +#endif + constexpr bool isNull(QT6_DECL_NEW_OVERLOAD) const noexcept + { +#if defined(__cpp_lib_bit_cast) && defined(QT_SUPPORTS_INT128) + return std::bit_cast(*this) == 0; +#else + // QNX fails to compile + // data4[0] == 0 && data4[1] == 0 && ... + // in constexpr context, so rewrite it using a loop. This way we have + // only single data4[i] != 0 check at each iteration + for (size_t i = 0; i < 8; ++i) { + if (data4[i] != 0) + return false; + } + return data1 == 0 && data2 == 0 && data3 == 0; +#endif + } #ifdef QT_SUPPORTS_INT128 static constexpr QUuid fromUInt128(quint128 uuid, QSysInfo::Endian order = QSysInfo::BigEndian) noexcept; @@ -253,8 +271,29 @@ public: return QUuid::createUuidV5(ns, qToByteArrayViewIgnoringNull(baseData.toUtf8())); } +#if QT_CORE_REMOVED_SINCE(6, 9) QUuid::Variant variant() const noexcept; QUuid::Version version() const noexcept; +#endif + constexpr Variant variant(QT6_DECL_NEW_OVERLOAD) const noexcept + { + // Check the 3 MSB of data4[0] + const quint8 var = data4[0] & 0xE0; + if (var < 0x80) + return isNull(QT6_CALL_NEW_OVERLOAD) ? VarUnknown : NCS; + if (var < 0xC0) + return DCE; + return Variant(var >> 5); // Microsoft or Reserved + } + constexpr Version version(QT6_DECL_NEW_OVERLOAD) const noexcept + { + // Check the 4 MSB of data3 + const Version ver = Version(data3 >> 12); + // Check that variant() == DCE and version is in a valid range + if (ver >= Time && ver <= Sha1 && (data4[0] & 0xC0) == 0x80) + return ver; + return VerUnknown; + } #if defined(Q_OS_DARWIN) || defined(Q_QDOC) static QUuid fromCFUUID(CFUUIDRef uuid); diff --git a/tests/auto/corelib/plugin/quuid/tst_quuid.cpp b/tests/auto/corelib/plugin/quuid/tst_quuid.cpp index d2a7cdf7c36..3527764f931 100644 --- a/tests/auto/corelib/plugin/quuid/tst_quuid.cpp +++ b/tests/auto/corelib/plugin/quuid/tst_quuid.cpp @@ -349,6 +349,12 @@ void tst_QUuid::check_QDataStream() void tst_QUuid::isNull() { + constexpr QUuid null; + static_assert(null.isNull()); + + constexpr QUuid nonNull{1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6}; + static_assert(!nonNull.isNull()); + QVERIFY( !uuidA.isNull() ); QUuid should_be_null_uuid; @@ -561,6 +567,12 @@ void tst_QUuid::variants_data() QTest::newRow("uuidA") << uuidA << QUuid::DCE; QTest::newRow("uuidB") << uuidB << QUuid::DCE; QTest::newRow("NCS") << QUuid("{3a2f883c-4000-000d-0000-00fb40000000}") << QUuid::NCS; + + // compile-time checks + constexpr QUuid defaultConstructed; + static_assert(defaultConstructed.variant() == QUuid::Variant::VarUnknown); + constexpr QUuid minDCE = make_minimal(QUuid::Variant::DCE); + static_assert(minDCE.variant() == QUuid::Variant::DCE); } void tst_QUuid::variants() @@ -607,6 +619,12 @@ void tst_QUuid::versions_data() << QUuid::VerUnknown; QTest::newRow("uuidA") << uuidA << QUuid::Random; QTest::newRow("uuidB") << uuidB << QUuid::Random; + + // compile-time checks + constexpr QUuid defaultConstructed; + static_assert(defaultConstructed.version() == QUuid::Version::VerUnknown); + constexpr QUuid timeVer = {0, 0, 0x1000, 0b1000'0000, 0, 0, 0, 0, 0, 0, 0}; + static_assert(timeVer.version() == QUuid::Version::Time); } void tst_QUuid::versions()