Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
quuid.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "quuid.h"
6
8#include "qdatastream.h"
9#include "qdebug.h"
10#include "qendian.h"
11#include "qrandom.h"
12#include "private/qtools_p.h"
13
15
16// ensure QList of this is efficient
18
19// 16 bytes (a uint, two shorts and a uchar[8]), each represented by two hex
20// digits; plus four dashes and a pair of enclosing brace: 16*2 + 4 + 2 = 38.
21enum { MaxStringUuidLength = 38 };
22
23template <class Integral>
24void _q_toHex(char *&dst, Integral value)
25{
27
28 const char *p = reinterpret_cast<const char *>(&value);
29
30 for (uint i = 0; i < sizeof(Integral); ++i, dst += 2) {
31 dst[0] = QtMiscUtils::toHexLower((p[i] >> 4) & 0xf);
32 dst[1] = QtMiscUtils::toHexLower(p[i] & 0xf);
33 }
34}
35
36template <class Integral>
37bool _q_fromHex(const char *&src, Integral &value)
38{
39 value = 0;
40
41 for (uint i = 0; i < sizeof(Integral) * 2; ++i) {
42 uint ch = *src++;
43 int tmp = QtMiscUtils::fromHex(ch);
44 if (tmp == -1)
45 return false;
46
47 value = value * 16 + tmp;
48 }
49
50 return true;
51}
52
54{
55 if ((mode & QUuid::WithoutBraces) == 0)
56 *dst++ = '{';
57 _q_toHex(dst, uuid.data1);
59 *dst++ = '-';
60 _q_toHex(dst, uuid.data2);
62 *dst++ = '-';
63 _q_toHex(dst, uuid.data3);
65 *dst++ = '-';
66 for (int i = 0; i < 2; i++)
67 _q_toHex(dst, uuid.data4[i]);
69 *dst++ = '-';
70 for (int i = 2; i < 8; i++)
71 _q_toHex(dst, uuid.data4[i]);
72 if ((mode & QUuid::WithoutBraces) == 0)
73 *dst++ = '}';
74 return dst;
75}
76
88static QUuid _q_uuidFromHex(const char *src)
89{
90 uint d1;
91 ushort d2, d3;
92 uchar d4[8];
93
94 if (src) {
95 if (*src == '{')
96 src++;
98 && *src++ == '-'
99 && _q_fromHex(src, d2)
100 && *src++ == '-'
101 && _q_fromHex(src, d3)
102 && *src++ == '-'
103 && _q_fromHex(src, d4[0])
104 && _q_fromHex(src, d4[1])
105 && *src++ == '-'
106 && _q_fromHex(src, d4[2])
107 && _q_fromHex(src, d4[3])
108 && _q_fromHex(src, d4[4])
109 && _q_fromHex(src, d4[5])
110 && _q_fromHex(src, d4[6])
111 && _q_fromHex(src, d4[7]))) {
112 return QUuid(d1, d2, d3, d4[0], d4[1], d4[2], d4[3], d4[4], d4[5], d4[6], d4[7]);
113 }
114 }
115
116 return QUuid();
117}
118
119static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCryptographicHash::Algorithm algorithm, int version)
120{
121 QCryptographicHash hash(algorithm);
122 hash.addData(ns.toRfc4122());
123 hash.addData(baseData);
124 QByteArrayView hashResult = hash.resultView();
125 Q_ASSERT(hashResult.size() >= 16);
126 hashResult.truncate(16); // Sha1 will be too long
127
128 QUuid result = QUuid::fromRfc4122(hashResult);
129
130 result.data3 &= 0x0FFF;
131 result.data3 |= (version << 12);
132 result.data4[0] &= 0x3F;
133 result.data4[0] |= 0x80;
134
135 return result;
136}
137
442{
445
446 char latin1[MaxStringUuidLength + 1];
447 char *dst = latin1;
448
449 for (QChar ch : text)
450 *dst++ = ch.toLatin1();
451
452 *dst++ = '\0'; // don't read garbage as potentially valid data
453
454 return _q_uuidFromHex(latin1);
455}
456
458{
460 || (text.front() == '{' && text.size() < MaxStringUuidLength - 1))) {
461 // Too short. Don't call _q_uuidFromHex(); QL1Ss need not be NUL-terminated,
462 // and we don't want to read trailing garbage as potentially valid data.
464 }
465 return _q_uuidFromHex(text.data());
466}
467
469// can treat UTF-8 the same as Latin-1:
471{
473}
474
476{
477 return text.visit([] (auto text) { return uuidFromString(text); });
478}
479
519#ifndef QT_BOOTSTRAPPED
521{
522 return createFromName(ns, baseData, QCryptographicHash::Md5, 3);
523}
524#endif
525
527{
528 return createFromName(ns, baseData, QCryptographicHash::Sha1, 5);
529}
530
548{
549 if (bytes.isEmpty() || bytes.size() != 16)
550 return QUuid();
551 return fromBytes(bytes.data());
552}
553
603{
604 char latin1[MaxStringUuidLength];
605 const auto end = _q_uuidToHex(*this, latin1, mode);
606 return QString::fromLatin1(latin1, end - latin1);
607}
608
644{
646 const auto end = _q_uuidToHex(*this, const_cast<char *>(result.constData()), mode);
647 result.resize(end - result.constData());
648 return result;
649}
650
688{
689 Id128Bytes bytes = toBytes();
690 return QByteArrayView(bytes).toByteArray();
691}
692
693#ifndef QT_NO_DATASTREAM
699{
700 QByteArray bytes;
701 if (s.byteOrder() == QDataStream::BigEndian) {
702 bytes = id.toRfc4122();
703 } else {
704 // we know how many bytes a UUID has, I hope :)
705 bytes = QByteArray(16, Qt::Uninitialized);
706 uchar *data = reinterpret_cast<uchar *>(bytes.data());
707
708 // for historical reasons, our little-endian serialization format
709 // stores each of the UUID fields in little endian, instead of storing
710 // a little endian Id128
711 qToLittleEndian(id.data1, data);
712 data += sizeof(quint32);
713 qToLittleEndian(id.data2, data);
714 data += sizeof(quint16);
715 qToLittleEndian(id.data3, data);
716 data += sizeof(quint16);
717
718 for (int i = 0; i < 8; ++i) {
719 *(data) = id.data4[i];
720 data++;
721 }
722 }
723
724 if (s.writeRawData(bytes.data(), 16) != 16) {
725 s.setStatus(QDataStream::WriteFailed);
726 }
727 return s;
728}
729
735{
736 std::array<char, 16> bytes;
737 if (s.readRawData(bytes.data(), 16) != 16) {
739 return s;
740 }
741
742 if (s.byteOrder() == QDataStream::BigEndian) {
743 id = QUuid::fromRfc4122(bytes);
744 } else {
745 const uchar *data = reinterpret_cast<const uchar *>(bytes.data());
746
747 id.data1 = qFromLittleEndian<quint32>(data);
748 data += sizeof(quint32);
749 id.data2 = qFromLittleEndian<quint16>(data);
750 data += sizeof(quint16);
751 id.data3 = qFromLittleEndian<quint16>(data);
752 data += sizeof(quint16);
753
754 for (int i = 0; i < 8; ++i) {
755 id.data4[i] = *(data);
756 data++;
757 }
758 }
759
760 return s;
761}
762#endif // QT_NO_DATASTREAM
763
768bool QUuid::isNull() const noexcept
769{
770 return data4[0] == 0 && data4[1] == 0 && data4[2] == 0 && data4[3] == 0 &&
771 data4[4] == 0 && data4[5] == 0 && data4[6] == 0 && data4[7] == 0 &&
772 data1 == 0 && data2 == 0 && data3 == 0;
773}
774
818{
819 if (isNull())
820 return VarUnknown;
821 // Check the 3 MSB of data4[0]
822 if ((data4[0] & 0x80) == 0x00) return NCS;
823 else if ((data4[0] & 0xC0) == 0x80) return DCE;
824 else if ((data4[0] & 0xE0) == 0xC0) return Microsoft;
825 else if ((data4[0] & 0xE0) == 0xE0) return Reserved;
826 return VarUnknown;
827}
828
839{
840 // Check the 4 MSB of data3
841 Version ver = (Version)(data3>>12);
842 if (isNull()
843 || (variant() != DCE)
844 || ver < Time
845 || ver > Sha1)
846 return VerUnknown;
847 return ver;
848}
849
861bool QUuid::operator<(const QUuid &other) const noexcept
862{
863 if (variant() != other.variant())
864 return variant() < other.variant();
865
866#define ISLESS(f1, f2) if (f1!=f2) return (f1<f2);
867 ISLESS(data1, other.data1);
868 ISLESS(data2, other.data2);
869 ISLESS(data3, other.data3);
870 for (int n = 0; n < 8; n++) {
871 ISLESS(data4[n], other.data4[n]);
872 }
873#undef ISLESS
874 return false;
875}
876
888bool QUuid::operator>(const QUuid &other) const noexcept
889{
890 return other < *this;
891}
892
931#if defined(Q_OS_WIN)
932
934#include <objbase.h> // For CoCreateGuid
936
938{
939 GUID guid;
940 CoCreateGuid(&guid);
941 QUuid result = guid;
942 return result;
943}
944
945#else // Q_OS_WIN
946
948{
950 uint *data = &(result.data1);
951 enum { AmountToRead = 4 };
952 QRandomGenerator::system()->fillRange(data, AmountToRead);
953
954 result.data4[0] = (result.data4[0] & 0x3F) | 0x80; // UV_DCE
955 result.data3 = (result.data3 & 0x0FFF) | 0x4000; // UV_Random
956
957 return result;
958}
959#endif // !Q_OS_WIN
960
975#ifndef QT_NO_DEBUG_STREAM
981{
982 QDebugStateSaver saver(dbg);
983 dbg.nospace() << "QUuid(" << id.toString() << ')';
984 return dbg;
985}
986#endif
987
993size_t qHash(const QUuid &uuid, size_t seed) noexcept
994{
995 return uuid.data1 ^ uuid.data2 ^ (uuid.data3 << 16)
996 ^ ((uuid.data4[0] << 24) | (uuid.data4[1] << 16) | (uuid.data4[2] << 8) | uuid.data4[3])
997 ^ ((uuid.data4[4] << 24) | (uuid.data4[5] << 16) | (uuid.data4[6] << 8) | uuid.data4[7])
998 ^ seed;
999}
1000
1001
\inmodule QtCore
QByteArray toByteArray() const
Definition qbytearray.h:709
constexpr void truncate(qsizetype n)
constexpr qsizetype size() const noexcept
\inmodule QtCore
Definition qbytearray.h:57
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
Definition qbytearray.h:534
\inmodule QtCore
Definition qchar.h:48
\inmodule QtCore\reentrant
Definition qdatastream.h:30
void setStatus(Status status)
Sets the status of the data stream to the status given.
\inmodule QtCore
\inmodule QtCore
static Q_DECL_CONST_FUNCTION QRandomGenerator * system()
\threadsafe
Definition qrandom.h:270
void fillRange(UInt *buffer, qsizetype count)
Generates count 32- or 64-bit quantities (depending on the type UInt) and stores them in the buffer p...
Definition qrandom.h:141
\inmodule QtCore
Definition qstringview.h:76
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5710
void truncate(qsizetype pos)
Truncates the string at the given position index.
Definition qstring.cpp:6159
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
QChar front() const
Definition qstring.h:214
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1095
\inmodule QtCore
Definition quuid.h:31
Version
This enum defines the values used in the \l{Version field} {version field} of the UUID.
Definition quuid.h:42
@ Time
Definition quuid.h:44
@ Sha1
Definition quuid.h:49
@ VerUnknown
Definition quuid.h:43
size_t qHash(const QUuid &uuid, size_t seed) noexcept
Definition quuid.cpp:993
static QUuid createUuid()
On any platform other than Windows, this function returns a new UUID with variant QUuid::DCE and vers...
Definition quuid.cpp:947
Variant
This enum defines the values used in the \l{Variant field} {variant field} of the UUID.
Definition quuid.h:34
@ DCE
Definition quuid.h:37
@ Microsoft
Definition quuid.h:38
@ Reserved
Definition quuid.h:39
@ VarUnknown
Definition quuid.h:35
@ NCS
Definition quuid.h:36
StringFormat
Definition quuid.h:52
@ WithBraces
Definition quuid.h:53
@ Id128
Definition quuid.h:55
@ WithoutBraces
Definition quuid.h:54
QString toString(StringFormat mode=WithBraces) const
Definition quuid.cpp:602
bool operator>(const QUuid &other) const noexcept
Returns true if this QUuid has the same \l{Variant field} {variant field} as the other QUuid and is l...
Definition quuid.cpp:888
static QUuid createUuidV5(const QUuid &ns, const QByteArray &baseData)
Definition quuid.cpp:526
QUuid::Variant variant() const noexcept
Returns the value in the \l{Variant field} {variant field} of the UUID.
Definition quuid.cpp:817
Id128Bytes toBytes(QSysInfo::Endian order=QSysInfo::BigEndian) const noexcept
Definition quuid.h:226
static QUuid createUuidV3(const QUuid &ns, const QByteArray &baseData)
Definition quuid.cpp:520
uint data1
Definition quuid.h:186
static QUuid fromRfc4122(QByteArrayView) noexcept
Creates a QUuid object from the binary representation of the UUID, as specified by RFC 4122 section 4...
Definition quuid.cpp:547
QByteArray toByteArray(StringFormat mode=WithBraces) const
Definition quuid.cpp:643
ushort data3
Definition quuid.h:188
static QUuid fromString(QAnyStringView string) noexcept
Definition quuid.cpp:475
uchar data4[8]
Definition quuid.h:189
bool isNull() const noexcept
Returns true if this is the null UUID {00000000-0000-0000-0000-000000000000}; otherwise returns false...
Definition quuid.cpp:768
QDataStream & operator>>(QDataStream &s, QUuid &id)
Reads a UUID from the stream s into id.
Definition quuid.cpp:734
QUuid::Version version() const noexcept
Returns the \l{Version field} {version field} of the UUID, if the UUID's \l{Variant field} {variant f...
Definition quuid.cpp:838
ushort data2
Definition quuid.h:187
bool operator<(const QUuid &other) const noexcept
Returns true if this QUuid has the same \l{Variant field} {variant field} as the other QUuid and is l...
Definition quuid.cpp:861
QByteArray toRfc4122() const
Returns the binary representation of this QUuid.
Definition quuid.cpp:687
QDebug operator<<(QDebug dbg, const QUuid &id)
Writes the UUID id to the output stream for debugging information dbg.
Definition quuid.cpp:980
QDataStream & operator<<(QDataStream &s, const QUuid &id)
Writes the UUID id to the data stream s.
Definition quuid.cpp:698
QHash< int, QWidget * > hash
[35multi]
QString text
Combined button and popup list for selecting options.
constexpr char toHexLower(char32_t value) noexcept
Definition qtools_p.h:32
constexpr int fromHex(char32_t c) noexcept
Definition qtools_p.h:44
constexpr Initialization Uninitialized
#define Q_UNLIKELY(x)
#define Q_NEVER_INLINE
#define Q_LIKELY(x)
#define Q_ALWAYS_INLINE
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
constexpr T qToBigEndian(T source)
Definition qendian.h:172
constexpr T qToLittleEndian(T source)
Definition qendian.h:176
GLenum mode
GLuint GLuint end
GLenum src
GLenum GLenum dst
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat n
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
Definition qrandom.cpp:196
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QT_BEGIN_INCLUDE_NAMESPACE
#define QT_END_INCLUDE_NAMESPACE
unsigned int quint32
Definition qtypes.h:45
unsigned char uchar
Definition qtypes.h:27
unsigned short quint16
Definition qtypes.h:43
unsigned int uint
Definition qtypes.h:29
unsigned short ushort
Definition qtypes.h:28
bool _q_fromHex(const char *&src, Integral &value)
Definition quuid.cpp:37
static char * _q_uuidToHex(const QUuid &uuid, char *dst, QUuid::StringFormat mode=QUuid::WithBraces)
Definition quuid.cpp:53
void _q_toHex(char *&dst, Integral value)
Definition quuid.cpp:24
@ MaxStringUuidLength
Definition quuid.cpp:21
static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCryptographicHash::Algorithm algorithm, int version)
Definition quuid.cpp:119
static Q_NEVER_INLINE QUuid _q_uuidFromHex(const char *src)
Definition quuid.cpp:88
#define ISLESS(f1, f2)
static QUuid uuidFromString(QStringView text) noexcept
Definition quuid.cpp:441
QVariant variant
[1]
QDate d1(1995, 5, 17)
[0]
QDate d2(1995, 5, 20)
QSharedPointer< T > other(t)
[5]
\inmodule QtCore
Definition quuid.h:58