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(QUuid ns, QByteArrayView baseData, QCryptographicHash::Algorithm algorithm, int version) noexcept
120{
121 std::byte buffer[20];
122 Q_ASSERT(sizeof buffer >= size_t(QCryptographicHash::hashLength(algorithm)));
123 QByteArrayView hashResult
124 = QCryptographicHash::hashInto(buffer, {QByteArrayView{ns.toBytes()}, baseData}, algorithm);
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
495{
498
499 char latin1[MaxStringUuidLength + 1];
500 char *dst = latin1;
501
502 for (QChar ch : text)
503 *dst++ = ch.toLatin1();
504
505 *dst++ = '\0'; // don't read garbage as potentially valid data
506
507 return _q_uuidFromHex(latin1);
508}
509
511{
513 || (text.front() == '{' && text.size() < MaxStringUuidLength - 1))) {
514 // Too short. Don't call _q_uuidFromHex(); QL1Ss need not be NUL-terminated,
515 // and we don't want to read trailing garbage as potentially valid data.
517 }
518 return _q_uuidFromHex(text.data());
519}
520
522// can treat UTF-8 the same as Latin-1:
527
529{
530 return text.visit([] (auto text) { return uuidFromString(text); });
531}
532
578#ifndef QT_BOOTSTRAPPED
580{
581 return createFromName(ns, baseData, QCryptographicHash::Md5, 3);
582}
583#endif
584
586{
587 return createFromName(ns, baseData, QCryptographicHash::Sha1, 5);
588}
589
607{
608 if (bytes.isEmpty() || bytes.size() != 16)
609 return QUuid();
610 return fromBytes(bytes.data());
611}
612
662{
663 char latin1[MaxStringUuidLength];
664 const auto end = _q_uuidToHex(*this, latin1, mode);
665 return QString::fromLatin1(latin1, end - latin1);
666}
667
703{
705 const auto end = _q_uuidToHex(*this, const_cast<char *>(result.constData()), mode);
706 result.resize(end - result.constData());
707 return result;
708}
709
747{
748 Id128Bytes bytes = toBytes();
749 return QByteArrayView(bytes).toByteArray();
750}
751
752#ifndef QT_NO_DATASTREAM
758{
759 constexpr int NumBytes = sizeof(QUuid);
760 static_assert(NumBytes == 16, "Change the serialization format when this ever hits");
761 char bytes[NumBytes];
762 if (s.byteOrder() == QDataStream::BigEndian) {
763 const auto id128 = id.toBytes();
764 static_assert(sizeof(id128) == NumBytes);
765 memcpy(bytes, &id128, NumBytes);
766 } else {
767 auto *data = bytes;
768
769 // for historical reasons, our little-endian serialization format
770 // stores each of the UUID fields in little endian, instead of storing
771 // a little endian Id128
772 qToLittleEndian(id.data1, data);
773 data += sizeof(quint32);
774 qToLittleEndian(id.data2, data);
775 data += sizeof(quint16);
776 qToLittleEndian(id.data3, data);
777 data += sizeof(quint16);
778
779 for (int i = 0; i < 8; ++i) {
780 *(data) = id.data4[i];
781 data++;
782 }
783 }
784
785 if (s.writeRawData(bytes, NumBytes) != NumBytes)
786 s.setStatus(QDataStream::WriteFailed);
787
788 return s;
789}
790
796{
797 std::array<char, 16> bytes;
798 if (s.readRawData(bytes.data(), 16) != 16) {
799 s.setStatus(QDataStream::ReadPastEnd);
800 return s;
801 }
802
803 if (s.byteOrder() == QDataStream::BigEndian) {
804 id = QUuid::fromRfc4122(bytes);
805 } else {
806 const uchar *data = reinterpret_cast<const uchar *>(bytes.data());
807
808 id.data1 = qFromLittleEndian<quint32>(data);
809 data += sizeof(quint32);
810 id.data2 = qFromLittleEndian<quint16>(data);
811 data += sizeof(quint16);
812 id.data3 = qFromLittleEndian<quint16>(data);
813 data += sizeof(quint16);
814
815 for (int i = 0; i < 8; ++i) {
816 id.data4[i] = *(data);
817 data++;
818 }
819 }
820
821 return s;
822}
823#endif // QT_NO_DATASTREAM
824
829bool QUuid::isNull() const noexcept
830{
831 return data4[0] == 0 && data4[1] == 0 && data4[2] == 0 && data4[3] == 0 &&
832 data4[4] == 0 && data4[5] == 0 && data4[6] == 0 && data4[7] == 0 &&
833 data1 == 0 && data2 == 0 && data3 == 0;
834}
835
879{
880 if (isNull())
881 return VarUnknown;
882 // Check the 3 MSB of data4[0]
883 if ((data4[0] & 0x80) == 0x00) return NCS;
884 else if ((data4[0] & 0xC0) == 0x80) return DCE;
885 else if ((data4[0] & 0xE0) == 0xC0) return Microsoft;
886 else if ((data4[0] & 0xE0) == 0xE0) return Reserved;
887 return VarUnknown;
888}
889
900{
901 // Check the 4 MSB of data3
902 Version ver = (Version)(data3>>12);
903 if (isNull()
904 || (variant() != DCE)
905 || ver < Time
906 || ver > Sha1)
907 return VerUnknown;
908 return ver;
909}
910
971#if defined(Q_OS_WIN)
972
974#include <objbase.h> // For CoCreateGuid
976
978{
979 GUID guid;
980 CoCreateGuid(&guid);
981 QUuid result = guid;
982 return result;
983}
984
985#elif !defined(QT_BOOTSTRAPPED)
986
988{
990 uint *data = &(result.data1);
991 enum { AmountToRead = 4 };
992 QRandomGenerator::system()->fillRange(data, AmountToRead);
993
994 result.data4[0] = (result.data4[0] & 0x3F) | 0x80; // UV_DCE
995 result.data3 = (result.data3 & 0x0FFF) | 0x4000; // UV_Random
996
997 return result;
998}
999#endif // !Q_OS_WIN && !QT_BOOTSTRAPPED
1000
1015#ifndef QT_NO_DEBUG_STREAM
1021{
1022 QDebugStateSaver saver(dbg);
1023 dbg.nospace() << "QUuid(" << id.toString() << ')';
1024 return dbg;
1025}
1026#endif
1027
1033size_t qHash(const QUuid &uuid, size_t seed) noexcept
1034{
1035 return uuid.data1 ^ uuid.data2 ^ (uuid.data3 << 16)
1036 ^ ((uuid.data4[0] << 24) | (uuid.data4[1] << 16) | (uuid.data4[2] << 8) | uuid.data4[3])
1037 ^ ((uuid.data4[4] << 24) | (uuid.data4[5] << 16) | (uuid.data4[6] << 8) | uuid.data4[7])
1038 ^ seed;
1039}
1040
1041
\inmodule QtCore
QByteArray toByteArray() const
Definition qbytearray.h:797
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore
static int hashLength(Algorithm method)
Returns the size of the output of the selected hash method in bytes.
static QByteArrayView hashInto(QSpan< char > buffer, QByteArrayView data, Algorithm method) noexcept
\inmodule QtCore\reentrant
Definition qdatastream.h:47
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:5881
void truncate(qsizetype pos)
Truncates the string starting from, and including, the element at index position.
Definition qstring.cpp:6330
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:32
Version
This enum defines the values used in the \l{Version field} {version field} of the UUID.
Definition quuid.h:43
@ Time
Definition quuid.h:45
@ Sha1
Definition quuid.h:50
@ VerUnknown
Definition quuid.h:44
size_t qHash(const QUuid &uuid, size_t seed) noexcept
Definition quuid.cpp:1033
static QUuid createUuid()
On any platform other than Windows, this function returns a new UUID with variant QUuid::DCE and vers...
Definition quuid.cpp:987
Variant
This enum defines the values used in the \l{Variant field} {variant field} of the UUID.
Definition quuid.h:35
@ DCE
Definition quuid.h:38
@ Microsoft
Definition quuid.h:39
@ Reserved
Definition quuid.h:40
@ VarUnknown
Definition quuid.h:36
@ NCS
Definition quuid.h:37
StringFormat
Definition quuid.h:53
@ WithBraces
Definition quuid.h:54
@ Id128
Definition quuid.h:56
@ WithoutBraces
Definition quuid.h:55
QString toString(StringFormat mode=WithBraces) const
Definition quuid.cpp:661
QUuid::Variant variant() const noexcept
Returns the value in the \l{Variant field} {variant field} of the UUID.
Definition quuid.cpp:878
Id128Bytes toBytes(QSysInfo::Endian order=QSysInfo::BigEndian) const noexcept
Definition quuid.h:285
uint data1
Definition quuid.h:256
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:606
QByteArray toByteArray(StringFormat mode=WithBraces) const
Definition quuid.cpp:702
ushort data3
Definition quuid.h:258
static QUuid fromString(QAnyStringView string) noexcept
Definition quuid.cpp:528
uchar data4[8]
Definition quuid.h:259
bool isNull() const noexcept
Returns true if this is the null UUID {00000000-0000-0000-0000-000000000000}; otherwise returns false...
Definition quuid.cpp:829
QDataStream & operator>>(QDataStream &s, QUuid &id)
Reads a UUID from the stream s into id.
Definition quuid.cpp:795
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:899
ushort data2
Definition quuid.h:257
QByteArray toRfc4122() const
Returns the binary representation of this QUuid.
Definition quuid.cpp:746
static QUuid createUuidV3(QUuid ns, QByteArrayView baseData) noexcept
Definition quuid.cpp:579
QDebug operator<<(QDebug dbg, const QUuid &id)
Writes the UUID id to the output stream for debugging information dbg.
Definition quuid.cpp:1020
static QUuid createUuidV5(QUuid ns, QByteArrayView baseData) noexcept
Definition quuid.cpp:585
QDataStream & operator<<(QDataStream &s, const QUuid &id)
Writes the UUID id to the data stream s.
Definition quuid.cpp:757
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 GLuint buffer
GLenum GLenum dst
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 Q_NEVER_INLINE QUuid _q_uuidFromHex(const char *src)
Definition quuid.cpp:88
static QUuid uuidFromString(QStringView text) noexcept
Definition quuid.cpp:494
static QUuid createFromName(QUuid ns, QByteArrayView baseData, QCryptographicHash::Algorithm algorithm, int version) noexcept
Definition quuid.cpp:119
QDate d1(1995, 5, 17)
[0]
QDate d2(1995, 5, 20)
\inmodule QtCore
Definition quuid.h:59