Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
490{
493
494 char latin1[MaxStringUuidLength + 1];
495 char *dst = latin1;
496
497 for (QChar ch : text)
498 *dst++ = ch.toLatin1();
499
500 *dst++ = '\0'; // don't read garbage as potentially valid data
501
502 return _q_uuidFromHex(latin1);
503}
504
506{
508 || (text.front() == '{' && text.size() < MaxStringUuidLength - 1))) {
509 // Too short. Don't call _q_uuidFromHex(); QL1Ss need not be NUL-terminated,
510 // and we don't want to read trailing garbage as potentially valid data.
512 }
513 return _q_uuidFromHex(text.data());
514}
515
517// can treat UTF-8 the same as Latin-1:
522
524{
525 return text.visit([] (auto text) { return uuidFromString(text); });
526}
527
567#ifndef QT_BOOTSTRAPPED
569{
570 return createFromName(ns, baseData, QCryptographicHash::Md5, 3);
571}
572#endif
573
575{
576 return createFromName(ns, baseData, QCryptographicHash::Sha1, 5);
577}
578
596{
597 if (bytes.isEmpty() || bytes.size() != 16)
598 return QUuid();
599 return fromBytes(bytes.data());
600}
601
651{
652 char latin1[MaxStringUuidLength];
653 const auto end = _q_uuidToHex(*this, latin1, mode);
654 return QString::fromLatin1(latin1, end - latin1);
655}
656
692{
694 const auto end = _q_uuidToHex(*this, const_cast<char *>(result.constData()), mode);
695 result.resize(end - result.constData());
696 return result;
697}
698
736{
737 Id128Bytes bytes = toBytes();
738 return QByteArrayView(bytes).toByteArray();
739}
740
741#ifndef QT_NO_DATASTREAM
747{
748 constexpr int NumBytes = sizeof(QUuid);
749 static_assert(NumBytes == 16, "Change the serialization format when this ever hits");
750 char bytes[NumBytes];
751 if (s.byteOrder() == QDataStream::BigEndian) {
752 const auto id128 = id.toBytes();
753 static_assert(sizeof(id128) == NumBytes);
754 memcpy(bytes, &id128, NumBytes);
755 } else {
756 auto *data = bytes;
757
758 // for historical reasons, our little-endian serialization format
759 // stores each of the UUID fields in little endian, instead of storing
760 // a little endian Id128
761 qToLittleEndian(id.data1, data);
762 data += sizeof(quint32);
763 qToLittleEndian(id.data2, data);
764 data += sizeof(quint16);
765 qToLittleEndian(id.data3, data);
766 data += sizeof(quint16);
767
768 for (int i = 0; i < 8; ++i) {
769 *(data) = id.data4[i];
770 data++;
771 }
772 }
773
774 if (s.writeRawData(bytes, NumBytes) != NumBytes)
775 s.setStatus(QDataStream::WriteFailed);
776
777 return s;
778}
779
785{
786 std::array<char, 16> bytes;
787 if (s.readRawData(bytes.data(), 16) != 16) {
788 s.setStatus(QDataStream::ReadPastEnd);
789 return s;
790 }
791
792 if (s.byteOrder() == QDataStream::BigEndian) {
793 id = QUuid::fromRfc4122(bytes);
794 } else {
795 const uchar *data = reinterpret_cast<const uchar *>(bytes.data());
796
797 id.data1 = qFromLittleEndian<quint32>(data);
798 data += sizeof(quint32);
799 id.data2 = qFromLittleEndian<quint16>(data);
800 data += sizeof(quint16);
801 id.data3 = qFromLittleEndian<quint16>(data);
802 data += sizeof(quint16);
803
804 for (int i = 0; i < 8; ++i) {
805 id.data4[i] = *(data);
806 data++;
807 }
808 }
809
810 return s;
811}
812#endif // QT_NO_DATASTREAM
813
818bool QUuid::isNull() const noexcept
819{
820 return data4[0] == 0 && data4[1] == 0 && data4[2] == 0 && data4[3] == 0 &&
821 data4[4] == 0 && data4[5] == 0 && data4[6] == 0 && data4[7] == 0 &&
822 data1 == 0 && data2 == 0 && data3 == 0;
823}
824
868{
869 if (isNull())
870 return VarUnknown;
871 // Check the 3 MSB of data4[0]
872 if ((data4[0] & 0x80) == 0x00) return NCS;
873 else if ((data4[0] & 0xC0) == 0x80) return DCE;
874 else if ((data4[0] & 0xE0) == 0xC0) return Microsoft;
875 else if ((data4[0] & 0xE0) == 0xE0) return Reserved;
876 return VarUnknown;
877}
878
889{
890 // Check the 4 MSB of data3
891 Version ver = (Version)(data3>>12);
892 if (isNull()
893 || (variant() != DCE)
894 || ver < Time
895 || ver > Sha1)
896 return VerUnknown;
897 return ver;
898}
899
911bool QUuid::operator<(const QUuid &other) const noexcept
912{
913 if (variant() != other.variant())
914 return variant() < other.variant();
915
916#define ISLESS(f1, f2) if (f1!=f2) return (f1<f2);
917 ISLESS(data1, other.data1);
918 ISLESS(data2, other.data2);
919 ISLESS(data3, other.data3);
920 for (int n = 0; n < 8; n++) {
921 ISLESS(data4[n], other.data4[n]);
922 }
923#undef ISLESS
924 return false;
925}
926
938bool QUuid::operator>(const QUuid &other) const noexcept
939{
940 return other < *this;
941}
942
981#if defined(Q_OS_WIN)
982
984#include <objbase.h> // For CoCreateGuid
986
988{
989 GUID guid;
990 CoCreateGuid(&guid);
991 QUuid result = guid;
992 return result;
993}
994
995#elif !defined(QT_BOOTSTRAPPED)
996
998{
1000 uint *data = &(result.data1);
1001 enum { AmountToRead = 4 };
1002 QRandomGenerator::system()->fillRange(data, AmountToRead);
1003
1004 result.data4[0] = (result.data4[0] & 0x3F) | 0x80; // UV_DCE
1005 result.data3 = (result.data3 & 0x0FFF) | 0x4000; // UV_Random
1006
1007 return result;
1008}
1009#endif // !Q_OS_WIN && !QT_BOOTSTRAPPED
1010
1025#ifndef QT_NO_DEBUG_STREAM
1031{
1032 QDebugStateSaver saver(dbg);
1033 dbg.nospace() << "QUuid(" << id.toString() << ')';
1034 return dbg;
1035}
1036#endif
1037
1043size_t qHash(const QUuid &uuid, size_t seed) noexcept
1044{
1045 return uuid.data1 ^ uuid.data2 ^ (uuid.data3 << 16)
1046 ^ ((uuid.data4[0] << 24) | (uuid.data4[1] << 16) | (uuid.data4[2] << 8) | uuid.data4[3])
1047 ^ ((uuid.data4[4] << 24) | (uuid.data4[5] << 16) | (uuid.data4[6] << 8) | uuid.data4[7])
1048 ^ seed;
1049}
1050
1051
\inmodule QtCore
QByteArray toByteArray() const
Definition qbytearray.h:796
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore
\inmodule QtCore\reentrant
Definition qdatastream.h:46
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
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
void truncate(qsizetype pos)
Truncates the string at the given position index.
Definition qstring.cpp:6319
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
QChar front() const
Definition qstring.h:230
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1240
\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:1043
static QUuid createUuid()
On any platform other than Windows, this function returns a new UUID with variant QUuid::DCE and vers...
Definition quuid.cpp:997
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:650
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:938
static QUuid createUuidV5(const QUuid &ns, const QByteArray &baseData)
Definition quuid.cpp:574
QUuid::Variant variant() const noexcept
Returns the value in the \l{Variant field} {variant field} of the UUID.
Definition quuid.cpp:867
Id128Bytes toBytes(QSysInfo::Endian order=QSysInfo::BigEndian) const noexcept
Definition quuid.h:232
static QUuid createUuidV3(const QUuid &ns, const QByteArray &baseData)
Definition quuid.cpp:568
uint data1
Definition quuid.h:203
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:595
QByteArray toByteArray(StringFormat mode=WithBraces) const
Definition quuid.cpp:691
ushort data3
Definition quuid.h:205
static QUuid fromString(QAnyStringView string) noexcept
Definition quuid.cpp:523
uchar data4[8]
Definition quuid.h:206
bool isNull() const noexcept
Returns true if this is the null UUID {00000000-0000-0000-0000-000000000000}; otherwise returns false...
Definition quuid.cpp:818
QDataStream & operator>>(QDataStream &s, QUuid &id)
Reads a UUID from the stream s into id.
Definition quuid.cpp:784
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:888
ushort data2
Definition quuid.h:204
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:911
QByteArray toRfc4122() const
Returns the binary representation of this QUuid.
Definition quuid.cpp:735
QDebug operator<<(QDebug dbg, const QUuid &id)
Writes the UUID id to the output stream for debugging information dbg.
Definition quuid.cpp:1030
QDataStream & operator<<(QDataStream &s, const QUuid &id)
Writes the UUID id to the data stream s.
Definition quuid.cpp:746
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
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum src
GLenum GLenum dst
GLfloat n
GLdouble s
[6]
Definition qopenglext.h:235
GLuint64EXT * result
[6]
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:50
unsigned char uchar
Definition qtypes.h:32
unsigned short quint16
Definition qtypes.h:48
unsigned int uint
Definition qtypes.h:34
unsigned short ushort
Definition qtypes.h:33
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:489
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