From 3e9c292dbceb54ddf9b88b0417e0dfe26d91d405 Mon Sep 17 00:00:00 2001 From: Ivan Solovev Date: Tue, 15 Aug 2023 17:18:55 +0200 Subject: [PATCH] QUuid: convert bswap(Id128Bytes) to a hidden friend of Id128Bytes ... and rename it to qbswap(), thus enabling the endian conversions for Id128bytes via q{To,From}{Little,Big}Endian() functions. Found during Qt 6.6 API Review. Change-Id: Ie320cee52ec2b9de0aaa112adec8febb7f5b68a2 Reviewed-by: Marc Mutz (cherry picked from commit 470b2b8ad9f28eaf24518dfa3f48cc13fcdc421f) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/plugin/quuid.cpp | 48 +++++++++++++++++++ src/corelib/plugin/quuid.h | 34 ++++++++----- tests/auto/corelib/plugin/quuid/tst_quuid.cpp | 17 +++++++ 3 files changed, 86 insertions(+), 13 deletions(-) diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp index 6169e0632ca..1e263a44e8f 100644 --- a/src/corelib/plugin/quuid.cpp +++ b/src/corelib/plugin/quuid.cpp @@ -300,6 +300,54 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto 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 +*/ + +/*! + \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 +*/ + +/*! + \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 +*/ + +/*! + \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 +*/ + /*! \fn QUuid::QUuid(Id128Bytes id128, QSysInfo::Endian order) noexcept \since 6.6 diff --git a/src/corelib/plugin/quuid.h b/src/corelib/plugin/quuid.h index 68f6e943d03..416fe028eb9 100644 --- a/src/corelib/plugin/quuid.h +++ b/src/corelib/plugin/quuid.h @@ -68,6 +68,16 @@ public: { 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 : data1(0), data2(0), data3(0), data4{0,0,0,0,0,0,0,0} {} @@ -188,17 +198,6 @@ public: ushort data2; ushort data3; uchar data4[8]; - -private: - static constexpr Id128Bytes bswap(Id128Bytes b) - { - // 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_DECLARE_TYPEINFO(QUuid, Q_PRIMITIVE_TYPE); @@ -217,7 +216,7 @@ 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 = bswap(uuid); + uuid = qbswap(uuid); data1 = qFromBigEndian(&uuid.data[0]); data2 = qFromBigEndian(&uuid.data[4]); data3 = qFromBigEndian(&uuid.data[6]); @@ -232,7 +231,7 @@ 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; } @@ -291,6 +290,15 @@ inline bool operator<=(const QUuid &lhs, const QUuid &rhs) noexcept 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 diff --git a/tests/auto/corelib/plugin/quuid/tst_quuid.cpp b/tests/auto/corelib/plugin/quuid/tst_quuid.cpp index 80924daa603..b6375965363 100644 --- a/tests/auto/corelib/plugin/quuid/tst_quuid.cpp +++ b/tests/auto/corelib/plugin/quuid/tst_quuid.cpp @@ -244,6 +244,23 @@ void tst_QUuid::id128() leBytesA.data[15 - i] = bytesA.data[i]; QCOMPARE(QUuid(leBytesA, QSysInfo::LittleEndian), uuidA); QVERIFY(memcmp(uuidA.toBytes(QSysInfo::LittleEndian).data, leBytesA.data, sizeof(leBytesA)) == 0); + + // check the new q{To,From}{Big,Little}Endian() overloads + QUuid::Id128Bytes roundtrip = qFromLittleEndian(qToLittleEndian(bytesA)); + QVERIFY(memcmp(roundtrip.data, bytesA.data, sizeof(bytesA)) == 0); + roundtrip = qFromBigEndian(qToBigEndian(bytesA)); + QVERIFY(memcmp(roundtrip.data, bytesA.data, sizeof(bytesA)) == 0); +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + const QUuid::Id128Bytes beBytesA = qToBigEndian(leBytesA); + QVERIFY(memcmp(beBytesA.data, bytesA.data, sizeof(beBytesA)) == 0); + const QUuid::Id128Bytes otherLeBytesA = qFromBigEndian(bytesA); + QVERIFY(memcmp(otherLeBytesA.data, leBytesA.data, sizeof(leBytesA)) == 0); +#else // Q_BIG_ENDIAN + const QUuid::Id128Bytes otherLeBytesA = qToLittleEndian(bytesA); + QVERIFY(memcmp(otherLeBytesA.data, leBytesA.data, sizeof(leBytesA)) == 0); + const QUuid::Id128Bytes beBytesA = qFromLittleEndian(leBytesA); + QVERIFY(memcmp(beBytesA.data, bytesA.data, sizeof(beBytesA)) == 0); +#endif // Q_BYTE_ORDER == Q_LITTLE_ENDIAN } void tst_QUuid::uint128()