File indexing completed on 2025-09-17 09:09:38
0001
0002
0003
0004 #ifndef QUUID_H
0005 #define QUUID_H
0006
0007 #include <QtCore/qcompare.h>
0008 #include <QtCore/qendian.h>
0009 #include <QtCore/qstring.h>
0010 #include <QtCore/qsystemdetection.h>
0011
0012 #if defined(Q_OS_WIN) || defined(Q_QDOC)
0013 #ifndef GUID_DEFINED
0014 #define GUID_DEFINED
0015 typedef struct _GUID
0016 {
0017 ulong Data1;
0018 ushort Data2;
0019 ushort Data3;
0020 uchar Data4[8];
0021 } GUID, *REFGUID, *LPGUID;
0022 #endif
0023 #endif
0024
0025 #if defined(Q_OS_DARWIN) || defined(Q_QDOC)
0026 Q_FORWARD_DECLARE_CF_TYPE(CFUUID);
0027 Q_FORWARD_DECLARE_OBJC_CLASS(NSUUID);
0028 #endif
0029
0030 QT_BEGIN_NAMESPACE
0031
0032 class Q_CORE_EXPORT QUuid
0033 {
0034 QUuid(Qt::Initialization) {}
0035 public:
0036 enum Variant {
0037 VarUnknown =-1,
0038 NCS = 0,
0039 DCE = 2,
0040 Microsoft = 6,
0041 Reserved = 7
0042 };
0043
0044 enum Version {
0045 VerUnknown =-1,
0046 Time = 1,
0047 EmbeddedPOSIX = 2,
0048 Md5 = 3,
0049 Name = Md5,
0050 Random = 4,
0051 Sha1 = 5,
0052 UnixEpoch = 7,
0053 };
0054
0055 enum StringFormat {
0056 WithBraces = 0,
0057 WithoutBraces = 1,
0058 Id128 = 3
0059 };
0060
0061 union alignas(16) Id128Bytes {
0062 quint8 data[16];
0063 quint16 data16[8];
0064 quint32 data32[4];
0065 quint64 data64[2];
0066 #if defined(QT_COMPILER_SUPPORTS_INT128)
0067 QT_WARNING_PUSH
0068 QT_WARNING_DISABLE_GCC("-Wpedantic")
0069 unsigned __int128 data128[1];
0070 QT_WARNING_POP
0071 #elif defined(QT_SUPPORTS_INT128)
0072 # error "struct QUuid::Id128Bytes should not depend on QT_SUPPORTS_INT128 for ABI reasons."
0073 # error "Adjust the declaration of the `data128` member above so it is always defined if it's " \
0074 "supported by the current compiler/architecture in any configuration."
0075 #endif
0076
0077 constexpr explicit operator QByteArrayView() const noexcept
0078 {
0079 return QByteArrayView(data, sizeof(data));
0080 }
0081
0082 friend constexpr Id128Bytes qbswap(Id128Bytes b) noexcept
0083 {
0084
0085 auto b0 = qbswap(b.data64[0]);
0086 auto b1 = qbswap(b.data64[1]);
0087 b.data64[0] = b1;
0088 b.data64[1] = b0;
0089 return b;
0090 }
0091 };
0092
0093 constexpr QUuid() noexcept : data1(0), data2(0), data3(0), data4{0,0,0,0,0,0,0,0} {}
0094
0095 constexpr QUuid(uint l, ushort w1, ushort w2, uchar b1, uchar b2, uchar b3,
0096 uchar b4, uchar b5, uchar b6, uchar b7, uchar b8) noexcept
0097 : data1(l), data2(w1), data3(w2), data4{b1, b2, b3, b4, b5, b6, b7, b8} {}
0098 explicit inline QUuid(Id128Bytes id128, QSysInfo::Endian order = QSysInfo::BigEndian) noexcept;
0099
0100 explicit QUuid(QAnyStringView string) noexcept
0101 : QUuid{fromString(string)} {}
0102 static QUuid fromString(QAnyStringView string) noexcept;
0103 #if QT_CORE_REMOVED_SINCE(6, 3)
0104 explicit QUuid(const QString &);
0105 static QUuid fromString(QStringView string) noexcept;
0106 static QUuid fromString(QLatin1StringView string) noexcept;
0107 explicit QUuid(const char *);
0108 explicit QUuid(const QByteArray &);
0109 #endif
0110 QString toString(StringFormat mode = WithBraces) const;
0111 QByteArray toByteArray(StringFormat mode = WithBraces) const;
0112 inline Id128Bytes toBytes(QSysInfo::Endian order = QSysInfo::BigEndian) const noexcept;
0113 QByteArray toRfc4122() const;
0114
0115 static inline QUuid fromBytes(const void *bytes, QSysInfo::Endian order = QSysInfo::BigEndian);
0116 #if QT_CORE_REMOVED_SINCE(6, 3)
0117 static QUuid fromRfc4122(const QByteArray &);
0118 #endif
0119 static QUuid fromRfc4122(QByteArrayView) noexcept;
0120
0121 #if QT_CORE_REMOVED_SINCE(6, 9)
0122 bool isNull() const noexcept;
0123 #endif
0124 constexpr bool isNull(QT6_DECL_NEW_OVERLOAD) const noexcept
0125 {
0126 #if defined(__cpp_lib_bit_cast) && defined(QT_SUPPORTS_INT128)
0127 return std::bit_cast<quint128>(*this) == 0;
0128 #else
0129
0130
0131
0132
0133 for (size_t i = 0; i < 8; ++i) {
0134 if (data4[i] != 0)
0135 return false;
0136 }
0137 return data1 == 0 && data2 == 0 && data3 == 0;
0138 #endif
0139 }
0140
0141 #ifdef QT_SUPPORTS_INT128
0142 static constexpr QUuid fromUInt128(quint128 uuid, QSysInfo::Endian order = QSysInfo::BigEndian) noexcept;
0143 constexpr quint128 toUInt128(QSysInfo::Endian order = QSysInfo::BigEndian) const noexcept;
0144 #endif
0145
0146 private:
0147 friend constexpr bool comparesEqual(const QUuid &lhs, const QUuid &rhs) noexcept
0148 {
0149 return is_eq(compareThreeWay_helper(lhs, rhs));
0150 }
0151 static constexpr Qt::strong_ordering
0152 compareThreeWay_helper(const QUuid &lhs, const QUuid &rhs) noexcept
0153 {
0154 #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
0155 if (const auto c = Qt::compareThreeWay(lhs.data1, rhs.data1); !is_eq(c))
0156 return c;
0157 if (const auto c = Qt::compareThreeWay(lhs.data2, rhs.data2); !is_eq(c))
0158 return c;
0159 if (const auto c = Qt::compareThreeWay(lhs.data3, rhs.data3); !is_eq(c))
0160 return c;
0161 #elif defined(__cpp_lib_bit_cast) && defined(QT_SUPPORTS_INT128)
0162 quint128 lu = qFromBigEndian(std::bit_cast<quint128>(lhs));
0163 quint128 ru = qFromBigEndian(std::bit_cast<quint128>(rhs));
0164 return Qt::compareThreeWay(lu, ru);
0165 #else
0166 auto make_int = [](const QUuid &u) {
0167 quint64 result = quint64(u.data3) << 48;
0168 result |= quint64(u.data2) << 32;
0169 return qFromBigEndian(result | u.data1);
0170 };
0171 if (const auto c = Qt::compareThreeWay(make_int(lhs), make_int(rhs)); !is_eq(c))
0172 return c;
0173 #endif
0174 for (unsigned i = 0; i < sizeof(lhs.data4); ++i) {
0175 if (const auto c = Qt::compareThreeWay(lhs.data4[i], rhs.data4[i]); !is_eq(c))
0176 return c;
0177 }
0178 return Qt::strong_ordering::equal;
0179 }
0180 friend constexpr Qt::strong_ordering compareThreeWay(const QUuid &lhs, const QUuid &rhs) noexcept
0181 {
0182 #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
0183
0184
0185 auto fastVariant = [](const QUuid &uuid) {
0186 quint8 v = uuid.data4[0];
0187
0188 return v >= 0xC0 ? v & 0xE0 : v >= 0x80 ? 0x80 : 0;
0189 };
0190 if (const auto c = Qt::compareThreeWay(fastVariant(lhs), fastVariant(rhs)); !is_eq(c))
0191 return c;
0192 #endif
0193 return compareThreeWay_helper(lhs, rhs);
0194 }
0195
0196 public:
0197
0198
0199 #if QT_CORE_REMOVED_SINCE(6, 8)
0200 constexpr bool operator==(const QUuid &orig) const noexcept
0201 {
0202 return comparesEqual(*this, orig);
0203 }
0204
0205 constexpr bool operator!=(const QUuid &orig) const noexcept
0206 {
0207 return !operator==(orig);
0208 }
0209
0210 bool operator<(const QUuid &other) const noexcept;
0211 bool operator>(const QUuid &other) const noexcept;
0212 #else
0213 Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(QUuid)
0214 #endif
0215 #if defined(Q_OS_WIN) || defined(Q_QDOC)
0216
0217
0218 constexpr QUuid(const GUID &guid) noexcept
0219 : data1(guid.Data1), data2(guid.Data2), data3(guid.Data3),
0220 data4{guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
0221 guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]} {}
0222
0223 constexpr QUuid &operator=(const GUID &guid) noexcept
0224 {
0225 *this = QUuid(guid);
0226 return *this;
0227 }
0228
0229 constexpr operator GUID() const noexcept
0230 {
0231 GUID guid = { data1, data2, data3, { data4[0], data4[1], data4[2], data4[3], data4[4], data4[5], data4[6], data4[7] } };
0232 return guid;
0233 }
0234 private:
0235 friend constexpr bool comparesEqual(const QUuid &lhs, const GUID &rhs) noexcept
0236 {
0237 return comparesEqual(lhs, QUuid(rhs));
0238 }
0239 public:
0240
0241
0242 #if QT_CORE_REMOVED_SINCE(6, 8)
0243 constexpr bool operator==(const GUID &guid) const noexcept
0244 {
0245 return comparesEqual(*this, QUuid(guid));
0246 }
0247
0248 constexpr bool operator!=(const GUID &guid) const noexcept
0249 {
0250 return !operator==(guid);
0251 }
0252 #else
0253 Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QUuid, GUID)
0254 #endif
0255 #endif
0256 public:
0257 static QUuid createUuid();
0258 #if QT_CORE_REMOVED_SINCE(6, 8)
0259 static QUuid createUuidV3(const QUuid &ns, const QByteArray &baseData) noexcept;
0260 static QUuid createUuidV5(const QUuid &ns, const QByteArray &baseData) noexcept;
0261 #endif
0262 static QUuid createUuidV5(QUuid ns, QByteArrayView baseData) noexcept;
0263 #ifndef QT_BOOTSTRAPPED
0264 static QUuid createUuidV3(QUuid ns, QByteArrayView baseData) noexcept;
0265 #if !QT_CORE_REMOVED_SINCE(6, 8)
0266 Q_WEAK_OVERLOAD
0267 #endif
0268 static inline QUuid createUuidV3(const QUuid &ns, const QString &baseData)
0269 {
0270 return QUuid::createUuidV3(ns, qToByteArrayViewIgnoringNull(baseData.toUtf8()));
0271 }
0272 #endif
0273 #if !QT_CORE_REMOVED_SINCE(6, 8)
0274 Q_WEAK_OVERLOAD
0275 #endif
0276 static inline QUuid createUuidV5(const QUuid &ns, const QString &baseData)
0277 {
0278 return QUuid::createUuidV5(ns, qToByteArrayViewIgnoringNull(baseData.toUtf8()));
0279 }
0280
0281 static QUuid createUuidV7();
0282
0283 private:
0284 static constexpr bool isKnownVersion(Version v) noexcept
0285 {
0286 switch (v) {
0287 case VerUnknown:
0288 return false;
0289 case Time:
0290 case EmbeddedPOSIX:
0291 case Md5:
0292 case Random:
0293 case Sha1:
0294 case UnixEpoch:
0295 return true;
0296 }
0297 return false;
0298 }
0299
0300 public:
0301 #if QT_CORE_REMOVED_SINCE(6, 9)
0302 QUuid::Variant variant() const noexcept;
0303 QUuid::Version version() const noexcept;
0304 #endif
0305 constexpr Variant variant(QT6_DECL_NEW_OVERLOAD) const noexcept
0306 {
0307
0308 const quint8 var = data4[0] & 0xE0;
0309 if (var < 0x80)
0310 return isNull(QT6_CALL_NEW_OVERLOAD) ? VarUnknown : NCS;
0311 if (var < 0xC0)
0312 return DCE;
0313 return Variant(var >> 5);
0314 }
0315 constexpr Version version(QT6_DECL_NEW_OVERLOAD) const noexcept
0316 {
0317
0318 const Version ver = Version(data3 >> 12);
0319
0320 if (isKnownVersion(ver) && (data4[0] & 0xC0) == 0x80)
0321 return ver;
0322 return VerUnknown;
0323 }
0324
0325 #if defined(Q_OS_DARWIN) || defined(Q_QDOC)
0326 static QUuid fromCFUUID(CFUUIDRef uuid);
0327 CFUUIDRef toCFUUID() const Q_DECL_CF_RETURNS_RETAINED;
0328 static QUuid fromNSUUID(const NSUUID *uuid);
0329 NSUUID *toNSUUID() const Q_DECL_NS_RETURNS_AUTORELEASED;
0330 #endif
0331
0332 uint data1;
0333 ushort data2;
0334 ushort data3;
0335 uchar data4[8];
0336 };
0337
0338 Q_DECLARE_TYPEINFO(QUuid, Q_PRIMITIVE_TYPE);
0339
0340 #ifndef QT_NO_DATASTREAM
0341 Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QUuid &);
0342 Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QUuid &);
0343 #endif
0344
0345 #ifndef QT_NO_DEBUG_STREAM
0346 Q_CORE_EXPORT QDebug operator<<(QDebug, const QUuid &);
0347 #endif
0348
0349 Q_CORE_EXPORT size_t qHash(const QUuid &uuid, size_t seed = 0) noexcept;
0350
0351 QUuid::QUuid(Id128Bytes uuid, QSysInfo::Endian order) noexcept
0352 {
0353 char bytes[sizeof uuid];
0354 if (order == QSysInfo::LittleEndian)
0355 qbswap(uuid, bytes);
0356 else
0357 memcpy(bytes, &uuid, sizeof bytes);
0358 data1 = qFromBigEndian<quint32>(&bytes[0]);
0359 data2 = qFromBigEndian<quint16>(&bytes[4]);
0360 data3 = qFromBigEndian<quint16>(&bytes[6]);
0361 memcpy(data4, &bytes[8], sizeof(data4));
0362 }
0363
0364 QUuid::Id128Bytes QUuid::toBytes(QSysInfo::Endian order) const noexcept
0365 {
0366 Id128Bytes result = {};
0367 qToBigEndian(data1, &result.data[0]);
0368 qToBigEndian(data2, &result.data[4]);
0369 qToBigEndian(data3, &result.data[6]);
0370 memcpy(&result.data[8], data4, sizeof(data4));
0371 if (order == QSysInfo::LittleEndian)
0372 return qbswap(result);
0373 return result;
0374 }
0375
0376 QUuid QUuid::fromBytes(const void *bytes, QSysInfo::Endian order)
0377 {
0378 Id128Bytes result = {};
0379 memcpy(result.data, bytes, sizeof(result));
0380 return QUuid(result, order);
0381 }
0382
0383 #ifdef QT_SUPPORTS_INT128
0384 constexpr QUuid QUuid::fromUInt128(quint128 uuid, QSysInfo::Endian order) noexcept
0385 {
0386 QUuid result = {};
0387 if (order == QSysInfo::BigEndian) {
0388 result.data1 = qFromBigEndian<quint32>(int(uuid));
0389 result.data2 = qFromBigEndian<quint16>(ushort(uuid >> 32));
0390 result.data3 = qFromBigEndian<quint16>(ushort(uuid >> 48));
0391 for (int i = 0; i < 8; ++i)
0392 result.data4[i] = uchar(uuid >> (64 + i * 8));
0393 } else {
0394 result.data1 = qFromLittleEndian<quint32>(uint(uuid >> 96));
0395 result.data2 = qFromLittleEndian<quint16>(ushort(uuid >> 80));
0396 result.data3 = qFromLittleEndian<quint16>(ushort(uuid >> 64));
0397 for (int i = 0; i < 8; ++i)
0398 result.data4[i] = uchar(uuid >> (56 - i * 8));
0399 }
0400 return result;
0401 }
0402
0403 constexpr quint128 QUuid::toUInt128(QSysInfo::Endian order) const noexcept
0404 {
0405 quint128 result = {};
0406 if (order == QSysInfo::BigEndian) {
0407 for (int i = 0; i < 8; ++i)
0408 result |= quint64(data4[i]) << (i * 8);
0409 result = result << 64;
0410 result |= quint64(qToBigEndian<quint16>(data3)) << 48;
0411 result |= quint64(qToBigEndian<quint16>(data2)) << 32;
0412 result |= qToBigEndian<quint32>(data1);
0413 } else {
0414 result = qToLittleEndian<quint32>(data1);
0415 result = result << 32;
0416 result |= quint64(qToLittleEndian<quint16>(data2)) << 16;
0417 result |= quint64(qToLittleEndian<quint16>(data3));
0418 result = result << 64;
0419 for (int i = 0; i < 8; ++i)
0420 result |= quint64(data4[i]) << (56 - i * 8);
0421 }
0422 return result;
0423 }
0424 #endif
0425
0426 #if defined(Q_QDOC)
0427
0428
0429 QUuid::Id128Bytes qFromBigEndian(QUuid::Id128Bytes src);
0430 QUuid::Id128Bytes qFromLittleEndian(QUuid::Id128Bytes src);
0431 QUuid::Id128Bytes qToBigEndian(QUuid::Id128Bytes src);
0432 QUuid::Id128Bytes qToLittleEndian(QUuid::Id128Bytes src);
0433 #endif
0434
0435 QT_END_NAMESPACE
0436
0437 #endif