QUuid: handle quint128 and Id128Bytes data in the same way

The QUuid(quint128) ctor was handing the incoming data differently
from the QUuid(Id128Bytes) ctor. Same was valid for the return
values of QUuid::toUint128() vs QUuid::toBytes().
The provided test didn't reveal it, because it was treating the same
128-bit input value as BE in one place, and as LE in another place.

This patch fixes the test, and updates the implementation of
QUuid(quint128) ctor and toUInt128() method to verify that the
updated test passes.

This commit amends 8566c2db85a6f579a1a0432d0b7621633158e04c

Change-Id: I24edb8ba0c8f7fd15062ba0b2a94ad387c3e98b6
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit 0393fa6bf244c1135a9ed20cba8649687da45b9b)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Ivan Solovev 2023-07-13 16:30:34 +02:00 committed by Qt Cherry-pick Bot
parent 9f1f2e3eed
commit 9a55243e53
2 changed files with 41 additions and 21 deletions

View File

@ -246,26 +246,40 @@ inline QUuid QUuid::fromBytes(const void *bytes, QSysInfo::Endian order) noexcep
constexpr QUuid::QUuid(quint128 uuid, QSysInfo::Endian order) noexcept
: QUuid()
{
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));
if (order == QSysInfo::BigEndian) {
data1 = qFromBigEndian<quint32>(int(uuid));
data2 = qFromBigEndian<quint16>(ushort(uuid >> 32));
data3 = qFromBigEndian<quint16>(ushort(uuid >> 48));
for (int i = 0; i < 8; ++i)
data4[i] = uchar(uuid >> (64 + i * 8));
} else {
data1 = qFromLittleEndian<quint32>(uint(uuid >> 96));
data2 = qFromLittleEndian<quint16>(ushort(uuid >> 80));
data3 = qFromLittleEndian<quint16>(ushort(uuid >> 64));
for (int i = 0; i < 8; ++i)
data4[i] = uchar(uuid >> (56 - i * 8));
}
}
constexpr 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);
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

View File

@ -250,15 +250,16 @@ 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");
| Q_UINT64_C(0xa43cee95d128b8c5); // This is LE
constexpr quint128 be = qToBigEndian(u);
constexpr QUuid uuid(be);
static_assert(uuid.toUInt128() == be, "Round-trip through QUuid failed");
QCOMPARE(uuid, uuidA);
QCOMPARE(quint64(uuid.toUInt128() >> 64), quint64(u >> 64));
QCOMPARE(quint64(uuid.toUInt128()), quint64(u));
QCOMPARE(quint64(uuid.toUInt128() >> 64), quint64(be >> 64));
QCOMPARE(quint64(uuid.toUInt128()), quint64(be));
quint128 le = qFromBigEndian(u);
quint128 le = qFromBigEndian(be);
QCOMPARE(quint64(uuid.toUInt128(QSysInfo::LittleEndian) >> 64), quint64(le >> 64));
QCOMPARE(quint64(uuid.toUInt128(QSysInfo::LittleEndian)), quint64(le));
QCOMPARE(QUuid(le, QSysInfo::LittleEndian), uuidA);
@ -266,6 +267,11 @@ void tst_QUuid::uint128()
QUuid::Id128Bytes bytes = { .data128 = { qToBigEndian(u) } };
QUuid uuid2(bytes);
QCOMPARE(uuid2, uuid);
// verify that toBytes() and toUInt128() provide bytewise similar result
constexpr quint128 val = uuid.toUInt128();
bytes = uuid.toBytes();
QVERIFY(memcmp(&val, bytes.data, sizeof(val)) == 0);
#else
QSKIP("This platform has no support for 128-bit integer");
#endif