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
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
\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()
if the order is QSysInfo::BigEndian. See that function for more details.

View File

@ -60,6 +60,9 @@ public:
quint16 data16[8];
quint32 data32[4];
quint64 data64[2];
#ifdef __SIZEOF_INT128__
quint128 data128[1];
#endif
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,
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 QUuid(Id128Bytes id128, QSysInfo::Endian order = QSysInfo::BigEndian) noexcept;
explicit QUuid(QAnyStringView string) noexcept
: QUuid{fromString(string)} {}
@ -97,6 +100,11 @@ public:
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
{
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);
}
#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
{ return !(rhs < lhs); }
inline bool operator>=(const QUuid &lhs, const QUuid &rhs) noexcept

View File

@ -26,6 +26,7 @@ private slots:
void toRfc4122();
void fromRfc4122();
void id128();
void uint128();
void createUuidV3OrV5();
void check_QDataStream();
void isNull();
@ -245,6 +246,31 @@ void tst_QUuid::id128()
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()
{
//"www.widgets.com" is also from RFC4122