QUuid: add support for 128-bit integers

[ChangeLog][QtCore][QUuid] Added support for converting between QUuid and
quint128, on platforms that offer 128-bit integer types (all 64-bit ones
supported by Qt, except MSVC).

Change-Id: Id8e48e8f498c4a029619fffd1728c9553e871df5
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
Thiago Macieira 2022-11-18 12:57:09 -08:00 committed by Volker Hilsheimer
parent befda1acca
commit 8566c2db85
3 changed files with 92 additions and 3 deletions

View File

@ -307,14 +307,42 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto
Creates a QUuid based on the integral \a id128 parameter and respecting the Creates a QUuid based on the integral \a id128 parameter and respecting the
byte order \a order. byte order \a order.
\sa fromBytes(), toBytes(), toRfc4122() \sa fromBytes(), toBytes(), toRfc4122(), toUInt128()
*/
/*!
\fn QUuid::QUuid(quint128 uuid, QSysInfo::Endian order) noexcept
\since 6.6
Creates a QUuid based on the integral \a uuid parameter and respecting the
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(), toBytes(), fromBytes(), QUuid()
*/ */
/*! /*!
\fn QUuid::Id128Bytes QUuid::toBytes(QSysInfo::Endian order) const noexcept \fn QUuid::Id128Bytes QUuid::toBytes(QSysInfo::Endian order) const noexcept
\since 6.6 \since 6.6
Returns an 128-bit ID created from this QUuid on the byte order specified 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() 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. if the order is QSysInfo::BigEndian. See that function for more details.

View File

@ -60,6 +60,9 @@ public:
quint16 data16[8]; quint16 data16[8];
quint32 data32[4]; quint32 data32[4];
quint64 data64[2]; quint64 data64[2];
#ifdef __SIZEOF_INT128__
quint128 data128[1];
#endif
constexpr explicit operator QByteArrayView() const noexcept constexpr explicit operator QByteArrayView() const noexcept
{ {
@ -72,7 +75,7 @@ public:
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 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} {} : 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 QUuid(Id128Bytes id128, QSysInfo::Endian order = QSysInfo::BigEndian) noexcept;
explicit QUuid(QAnyStringView string) noexcept explicit QUuid(QAnyStringView string) noexcept
: QUuid{fromString(string)} {} : QUuid{fromString(string)} {}
@ -97,6 +100,11 @@ public:
bool isNull() const noexcept; bool isNull() const noexcept;
#ifdef __SIZEOF_INT128__
constexpr QUuid(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 constexpr bool operator==(const QUuid &orig) const noexcept
{ {
if (data1 != orig.data1 || data2 != orig.data2 || if (data1 != orig.data1 || data2 != orig.data2 ||
@ -233,6 +241,33 @@ inline QUuid QUuid::fromBytes(const void *bytes, QSysInfo::Endian order) noexcep
return QUuid(result, order); return QUuid(result, order);
} }
#ifdef __SIZEOF_INT128__
constexpr inline QUuid::QUuid(quint128 uuid, QSysInfo::Endian order) noexcept
{
if (order == QSysInfo::LittleEndian)
uuid = qbswap(uuid);
data1 = uint(uuid >> 96);
data2 = ushort(uuid >> 80);
data3 = ushort(uuid >> 64);
for (int i = 0; i < 8; ++i)
data4[i] = uchar(uuid >> (56 - i * 8));
}
constexpr inline quint128 QUuid::toUInt128(QSysInfo::Endian order) const noexcept
{
quint128 result = {};
result = data1;
result <<= 32;
result |= (data2 << 16) | uint(data3);
result <<= 64;
for (int i = 0; i < 8; ++i)
result |= quint64(data4[i]) << (56 - i * 8);
if (order == QSysInfo::LittleEndian)
return qbswap(result);
return result;
}
#endif
inline bool operator<=(const QUuid &lhs, const QUuid &rhs) noexcept inline bool operator<=(const QUuid &lhs, const QUuid &rhs) noexcept
{ return !(rhs < lhs); } { return !(rhs < lhs); }
inline bool operator>=(const QUuid &lhs, const QUuid &rhs) noexcept inline bool operator>=(const QUuid &lhs, const QUuid &rhs) noexcept

View File

@ -26,6 +26,7 @@ private slots:
void toRfc4122(); void toRfc4122();
void fromRfc4122(); void fromRfc4122();
void id128(); void id128();
void uint128();
void createUuidV3OrV5(); void createUuidV3OrV5();
void check_QDataStream(); void check_QDataStream();
void isNull(); void isNull();
@ -245,6 +246,31 @@ void tst_QUuid::id128()
QVERIFY(memcmp(uuidA.toBytes(QSysInfo::LittleEndian).data, leBytesA.data, sizeof(leBytesA)) == 0); QVERIFY(memcmp(uuidA.toBytes(QSysInfo::LittleEndian).data, leBytesA.data, sizeof(leBytesA)) == 0);
} }
void tst_QUuid::uint128()
{
#ifdef __SIZEOF_INT128__
constexpr quint128 u = quint128(Q_UINT64_C(0xfc69b59ecc344436)) << 64
| Q_UINT64_C(0xa43cee95d128b8c5);
constexpr QUuid uuid(u);
static_assert(uuid.toUInt128() == u, "Round-trip through QUuid failed");
QCOMPARE(uuid, uuidA);
QCOMPARE(quint64(uuid.toUInt128() >> 64), quint64(u >> 64));
QCOMPARE(quint64(uuid.toUInt128()), quint64(u));
quint128 le = qFromBigEndian(u);
QCOMPARE(quint64(uuid.toUInt128(QSysInfo::LittleEndian) >> 64), quint64(le >> 64));
QCOMPARE(quint64(uuid.toUInt128(QSysInfo::LittleEndian)), quint64(le));
QCOMPARE(QUuid(le, QSysInfo::LittleEndian), uuidA);
QUuid::Id128Bytes bytes = { .data128 = { qToBigEndian(u) } };
QUuid uuid2(bytes);
QCOMPARE(uuid2, uuid);
#else
QSKIP("This platform has no support for 128-bit integer");
#endif
}
void tst_QUuid::createUuidV3OrV5() void tst_QUuid::createUuidV3OrV5()
{ {
//"www.widgets.com" is also from RFC4122 //"www.widgets.com" is also from RFC4122