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
7#include "qcryptographichash.h"
8#include "qdatastream.h"
9#include "qdebug.h"
10#include "qendian.h"
11#include "qrandom.h"
12#include "private/qtools_p.h"
13
14QT_BEGIN_NAMESPACE
15
16// ensure QList of this is efficient
17static_assert(QTypeInfo<QUuid::Id128Bytes>::isRelocatable);
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{
26 value = qToBigEndian(value);
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(value: (p[i] >> 4) & 0xf);
32 dst[1] = QtMiscUtils::toHexLower(value: p[i] & 0xf);
33 }
34}
35
36#if QT_VERSION_MAJOR == 7
37# warning Consider storing the UUID as simple bytes, not as {uint, ushort, short, array}
38#endif
39template <class Integral>
40bool _q_fromHex(const char *&src, Integral &value)
41{
42 value = 0;
43
44 for (uint i = 0; i < sizeof(Integral) * 2; ++i) {
45 uint ch = *src++;
46 int tmp = QtMiscUtils::fromHex(c: ch);
47 if (tmp == -1)
48 return false;
49
50 value = value * 16 + tmp;
51 }
52
53 return true;
54}
55
56static char *_q_uuidToHex(const QUuid &uuid, char *dst, QUuid::StringFormat mode = QUuid::WithBraces)
57{
58 if ((mode & QUuid::WithoutBraces) == 0)
59 *dst++ = '{';
60 _q_toHex(dst, value: uuid.data1);
61 if ((mode & QUuid::Id128) != QUuid::Id128)
62 *dst++ = '-';
63 _q_toHex(dst, value: uuid.data2);
64 if ((mode & QUuid::Id128) != QUuid::Id128)
65 *dst++ = '-';
66 _q_toHex(dst, value: uuid.data3);
67 if ((mode & QUuid::Id128) != QUuid::Id128)
68 *dst++ = '-';
69 for (int i = 0; i < 2; i++)
70 _q_toHex(dst, value: uuid.data4[i]);
71 if ((mode & QUuid::Id128) != QUuid::Id128)
72 *dst++ = '-';
73 for (int i = 2; i < 8; i++)
74 _q_toHex(dst, value: uuid.data4[i]);
75 if ((mode & QUuid::WithoutBraces) == 0)
76 *dst++ = '}';
77 return dst;
78}
79
80/*!
81 \internal
82
83 Parses the string representation of a UUID (with optional surrounding "{}")
84 by reading at most MaxStringUuidLength (38) characters from \a src, which
85 may be \nullptr. Stops at the first invalid character (which includes a
86 premature NUL).
87
88 Returns the successfully parsed QUuid, or a null QUuid in case of failure.
89*/
90Q_NEVER_INLINE
91static QUuid _q_uuidFromHex(const char *src)
92{
93 uint d1;
94 ushort d2, d3;
95 uchar d4[8];
96
97 if (src) {
98 if (*src == '{')
99 src++;
100 if (Q_LIKELY( _q_fromHex(src, d1)
101 && *src++ == '-'
102 && _q_fromHex(src, d2)
103 && *src++ == '-'
104 && _q_fromHex(src, d3)
105 && *src++ == '-'
106 && _q_fromHex(src, d4[0])
107 && _q_fromHex(src, d4[1])
108 && *src++ == '-'
109 && _q_fromHex(src, d4[2])
110 && _q_fromHex(src, d4[3])
111 && _q_fromHex(src, d4[4])
112 && _q_fromHex(src, d4[5])
113 && _q_fromHex(src, d4[6])
114 && _q_fromHex(src, d4[7]))) {
115 return QUuid(d1, d2, d3, d4[0], d4[1], d4[2], d4[3], d4[4], d4[5], d4[6], d4[7]);
116 }
117 }
118
119 return QUuid();
120}
121
122static QUuid createFromName(QUuid ns, QByteArrayView baseData, QCryptographicHash::Algorithm algorithm, int version) noexcept
123{
124 std::byte buffer[20];
125 Q_ASSERT(sizeof buffer >= size_t(QCryptographicHash::hashLength(algorithm)));
126 QByteArrayView hashResult
127 = QCryptographicHash::hashInto(buffer, data: {QByteArrayView{ns.toBytes()}, baseData}, method: algorithm);
128 Q_ASSERT(hashResult.size() >= 16);
129 hashResult.truncate(n: 16); // Sha1 will be too long
130
131 QUuid result = QUuid::fromRfc4122(hashResult);
132
133 result.data3 &= 0x0FFF;
134 result.data3 |= (version << 12);
135 result.data4[0] &= 0x3F;
136 result.data4[0] |= 0x80;
137
138 return result;
139}
140
141/*!
142 \class QUuid
143 \inmodule QtCore
144 \brief The QUuid class stores a Universally Unique Identifier (UUID).
145
146 \reentrant
147
148 \compares strong
149 \compareswith strong GUID
150 \note Comparison with GUID is Windows-only.
151 \endcompareswith
152
153 Using \e{U}niversally \e{U}nique \e{ID}entifiers (UUID) is a
154 standard way to uniquely identify entities in a distributed
155 computing environment. A UUID is a 16-byte (128-bit) number
156 generated by some algorithm that is meant to guarantee that the
157 UUID will be unique in the distributed computing environment where
158 it is used. The acronym GUID is often used instead, \e{G}lobally
159 \e{U}nique \e{ID}entifiers, but it refers to the same thing.
160
161 \target Variant field
162 Actually, the GUID is one \e{variant} of UUID. Multiple variants
163 are in use. Each UUID contains a bit field that specifies which
164 type (variant) of UUID it is. Call variant() to discover which
165 type of UUID an instance of QUuid contains. It extracts the three
166 most significant bits of byte 8 of the 16 bytes. In QUuid, byte 8
167 is \c{QUuid::data4[0]}. If you create instances of QUuid using the
168 constructor that accepts all the numeric values as parameters, use
169 the following table to set the three most significant bits of
170 parameter \c{b1}, which becomes \c{QUuid::data4[0]} and contains
171 the variant field in its three most significant bits. In the
172 table, 'x' means \e {don't care}.
173
174 \table
175 \header
176 \li msb0
177 \li msb1
178 \li msb2
179 \li Variant
180
181 \row
182 \li 0
183 \li x
184 \li x
185 \li NCS (Network Computing System)
186
187 \row
188 \li 1
189 \li 0
190 \li x
191 \li DCE (Distributed Computing Environment)
192
193 \row
194 \li 1
195 \li 1
196 \li 0
197 \li Microsoft (GUID)
198
199 \row
200 \li 1
201 \li 1
202 \li 1
203 \li Reserved for future expansion
204
205 \endtable
206
207 \target Version field
208 If variant() returns QUuid::DCE, the UUID also contains a
209 \e{version} field in the four most significant bits of
210 \c{QUuid::data3}, and you can call version() to discover which
211 version your QUuid contains. If you create instances of QUuid
212 using the constructor that accepts all the numeric values as
213 parameters, use the following table to set the four most
214 significant bits of parameter \c{w2}, which becomes
215 \c{QUuid::data3} and contains the version field in its four most
216 significant bits.
217
218 \table
219 \header
220 \li msb0
221 \li msb1
222 \li msb2
223 \li msb3
224 \li Version
225
226 \row
227 \li 0
228 \li 0
229 \li 0
230 \li 1
231 \li Time
232
233 \row
234 \li 0
235 \li 0
236 \li 1
237 \li 0
238 \li Embedded POSIX
239
240 \row
241 \li 0
242 \li 0
243 \li 1
244 \li 1
245 \li Md5(Name)
246
247 \row
248 \li 0
249 \li 1
250 \li 0
251 \li 0
252 \li Random
253
254 \row
255 \li 0
256 \li 1
257 \li 0
258 \li 1
259 \li Sha1
260
261 \endtable
262
263 The field layouts for the DCE versions listed in the table above
264 are specified in the \l{RFC 4122}
265 {Network Working Group UUID Specification}.
266
267 Most platforms provide a tool for generating new UUIDs, e.g. \c
268 uuidgen and \c guidgen. You can also use createUuid(). UUIDs
269 generated by createUuid() are of the random type. Their
270 QUuid::Version bits are set to QUuid::Random, and their
271 QUuid::Variant bits are set to QUuid::DCE. The rest of the UUID is
272 composed of random numbers. Theoretically, this means there is a
273 small chance that a UUID generated by createUuid() will not be
274 unique. But it is
275 \l{http://en.wikipedia.org/wiki/Universally_Unique_Identifier#Random_UUID_probability_of_duplicates}
276 {a \e{very} small chance}.
277
278 UUIDs can be constructed from numeric values or from strings, or
279 using the static createUuid() function. They can be converted to a
280 string with toString(). UUIDs have a variant() and a version(),
281 and null UUIDs return true from isNull().
282*/
283
284/*!
285 \enum QUuid::StringFormat
286 \since 5.11
287
288 This enum is used by toString(StringFormat) to control the formatting of the
289 string representation. The possible values are:
290
291 \value WithBraces The default, toString() will return five hex fields, separated by
292 dashes and surrounded by braces. Example:
293 {00000000-0000-0000-0000-000000000000}.
294 \value WithoutBraces Only the five dash-separated fields, without the braces. Example:
295 00000000-0000-0000-0000-000000000000.
296 \value Id128 Only the hex digits, without braces or dashes. Note that QUuid
297 cannot parse this back again as input.
298*/
299
300/*!
301 \class QUuid::Id128Bytes
302 \inmodule QtCore
303 \since 6.6
304
305 This trivial structure is 128 bits (16 bytes) in size and holds the binary
306 representation of a UUID. Applications can \c{memcpy()} its contents to and
307 from many other libraries' UUID or GUID structures that take 128-bit
308 values.
309*/
310
311/*!
312 \fn QUuid::Id128Bytes qFromBigEndian(QUuid::Id128Bytes src)
313 \since 6.6
314 \relates QUuid::Id128Bytes
315 \overload
316
317 Converts \a src from big-endian byte order and returns the struct holding
318 the binary representation of UUID in host byte order.
319
320 \sa <QtEndian>
321*/
322
323/*!
324 \fn QUuid::Id128Bytes qFromLittleEndian(QUuid::Id128Bytes src)
325 \since 6.6
326 \relates QUuid::Id128Bytes
327 \overload
328
329 Converts \a src from little-endian byte order and returns the struct holding
330 the binary representation of UUID in host byte order.
331
332 \sa <QtEndian>
333*/
334
335/*!
336 \fn QUuid::Id128Bytes qToBigEndian(QUuid::Id128Bytes src)
337 \since 6.6
338 \relates QUuid::Id128Bytes
339 \overload
340
341 Converts \a src from host byte order and returns the struct holding the
342 binary representation of UUID in big-endian byte order.
343
344 \sa <QtEndian>
345*/
346
347/*!
348 \fn QUuid::Id128Bytes qToLittleEndian(QUuid::Id128Bytes src)
349 \since 6.6
350 \relates QUuid::Id128Bytes
351 \overload
352
353 Converts \a src from host byte order and returns the struct holding the
354 binary representation of UUID in little-endian byte order.
355
356 \sa <QtEndian>
357*/
358
359/*!
360 \fn QUuid::QUuid(Id128Bytes id128, QSysInfo::Endian order) noexcept
361 \since 6.6
362
363 Creates a QUuid based on the integral \a id128 parameter. The input
364 \a id128 parameter is considered to have byte order \a order.
365
366 \sa fromBytes(), toBytes(), toRfc4122(), toUInt128()
367*/
368
369/*!
370 \fn QUuid::fromUInt128(quint128 uuid, QSysInfo::Endian order) noexcept
371 \since 6.6
372
373 Creates a QUuid based on the integral \a uuid parameter. The input \a uuid
374 parameter is considered to have byte order \a order.
375
376 \note This function is only present on platforms that offer a 128-bit
377 integer type.
378
379 \sa toUInt128(), fromBytes(), toBytes(), toRfc4122()
380*/
381
382/*!
383 \fn quint128 QUuid::toUInt128(QSysInfo::Endian order) const noexcept
384 \since 6.6
385
386 Returns a 128-bit integer created from this QUuid on the byte order
387 specified by \a order. The binary content of this function is the same as
388 toRfc4122() if the order is QSysInfo::BigEndian. See that function for more
389 details.
390
391 \note This function is only present on platforms that offer a 128-bit
392 integer type.
393
394 \sa toRfc4122(), fromUInt128(), toBytes(), fromBytes(), QUuid()
395*/
396
397/*!
398 \fn QUuid::Id128Bytes QUuid::toBytes(QSysInfo::Endian order) const noexcept
399 \since 6.6
400
401 Returns a 128-bit ID created from this QUuid on the byte order specified
402 by \a order. The binary content of this function is the same as toRfc4122()
403 if the order is QSysInfo::BigEndian. See that function for more details.
404
405 \sa toRfc4122(), fromBytes(), QUuid()
406*/
407
408/*!
409 \fn QUuid QUuid::fromBytes(const void *bytes, QSysInfo::Endian order) noexcept
410 \since 6.6
411
412 Reads 128 bits (16 bytes) from \a bytes using byte order \a order and
413 returns the QUuid corresponding to those bytes. This function does the same
414 as fromRfc4122() if the byte order \a order is QSysInfo::BigEndian.
415
416 \sa fromRfc4122()
417*/
418
419/*!
420 \fn QUuid::QUuid(const GUID &guid)
421
422 Casts a Windows \a guid to a Qt QUuid.
423
424 \warning This function is only for Windows platforms.
425*/
426
427/*!
428 \fn QUuid &QUuid::operator=(const GUID &guid)
429
430 Assigns a Windows \a guid to a Qt QUuid.
431
432 \warning This function is only for Windows platforms.
433*/
434
435/*!
436 \fn QUuid::operator GUID() const
437
438 Returns a Windows GUID from a QUuid.
439
440 \warning This function is only for Windows platforms.
441*/
442
443/*!
444 \fn QUuid::QUuid()
445
446 Creates the null UUID. toString() will output the null UUID
447 as "{00000000-0000-0000-0000-000000000000}".
448*/
449
450/*!
451 \fn QUuid::QUuid(uint l, ushort w1, ushort w2, uchar b1, uchar b2, uchar b3, uchar b4, uchar b5, uchar b6, uchar b7, uchar b8)
452
453 Creates a UUID with the value specified by the parameters, \a l,
454 \a w1, \a w2, \a b1, \a b2, \a b3, \a b4, \a b5, \a b6, \a b7, \a
455 b8.
456
457 Example:
458 \snippet code/src_corelib_plugin_quuid.cpp 0
459*/
460
461/*!
462 \fn QUuid::QUuid(QAnyStringView text)
463
464 Creates a QUuid object from the string \a text, which must be
465 formatted as five hex fields separated by '-', e.g.,
466 "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where each 'x' is a hex
467 digit. The curly braces shown here are optional, but it is normal to
468 include them. If the conversion fails, a null UUID is created. See
469 toString() for an explanation of how the five hex fields map to the
470 public data members in QUuid.
471
472 \note In Qt versions prior to 6.3, this constructor was an overload
473 set consisting of QString, QByteArray and \c{const char*}
474 instead of one constructor taking QAnyStringView.
475
476 \sa toString(), QUuid()
477*/
478
479/*!
480 \fn static QUuid::fromString(QAnyStringView string)
481 \since 5.10
482
483 Creates a QUuid object from the string \a string, which must be
484 formatted as five hex fields separated by '-', e.g.,
485 "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where each 'x' is a hex
486 digit. The curly braces shown here are optional, but it is normal to
487 include them. If the conversion fails, a null UUID is returned. See
488 toString() for an explanation of how the five hex fields map to the
489 public data members in QUuid.
490
491 \note In Qt versions prior to 6.3, this function was an overload
492 set consisting of QStringView and QLatin1StringView instead of
493 one function taking QAnyStringView.
494
495 \sa toString(), QUuid()
496*/
497static QUuid uuidFromString(QStringView text) noexcept
498{
499 if (text.size() > MaxStringUuidLength)
500 text.truncate(n: MaxStringUuidLength);
501
502 char latin1[MaxStringUuidLength + 1];
503 char *dst = latin1;
504
505 for (QChar ch : text)
506 *dst++ = ch.toLatin1();
507
508 *dst++ = '\0'; // don't read garbage as potentially valid data
509
510 return _q_uuidFromHex(src: latin1);
511}
512
513static QUuid uuidFromString(QLatin1StringView text) noexcept
514{
515 if (Q_UNLIKELY(text.size() < MaxStringUuidLength - 2
516 || (text.front() == '{' && text.size() < MaxStringUuidLength - 1))) {
517 // Too short. Don't call _q_uuidFromHex(); QL1Ss need not be NUL-terminated,
518 // and we don't want to read trailing garbage as potentially valid data.
519 text = QLatin1StringView();
520 }
521 return _q_uuidFromHex(src: text.data());
522}
523
524Q_ALWAYS_INLINE
525// can treat UTF-8 the same as Latin-1:
526static QUuid uuidFromString(QUtf8StringView text) noexcept
527{
528 return uuidFromString(text: QLatin1StringView(text.data(), text.size()));
529}
530
531QUuid QUuid::fromString(QAnyStringView text) noexcept
532{
533 return text.visit(v: [] (auto text) { return uuidFromString(text); });
534}
535
536/*!
537 \since 5.0
538 \fn QUuid QUuid::createUuidV3(QUuid ns, QByteArrayView baseData);
539
540 This function returns a new UUID with variant QUuid::DCE and version QUuid::Md5.
541 \a ns is the namespace and \a baseData is the basic data as described by RFC 4122.
542
543 \note In Qt versions prior to 6.8, this function took QByteArray, not
544 QByteArrayView.
545
546 \sa variant(), version(), createUuidV5()
547*/
548
549/*!
550 \since 5.0
551 \fn QUuid QUuid::createUuidV3(const QUuid &ns, const QString &baseData);
552
553 This function returns a new UUID with variant QUuid::DCE and version QUuid::Md5.
554 \a ns is the namespace and \a baseData is the basic data as described by RFC 4122.
555
556 \sa variant(), version(), createUuidV5()
557*/
558
559/*!
560 \since 5.0
561 \fn QUuid QUuid::createUuidV5(QUuid ns, QByteArrayView baseData);
562
563 This function returns a new UUID with variant QUuid::DCE and version QUuid::Sha1.
564 \a ns is the namespace and \a baseData is the basic data as described by RFC 4122.
565
566 \note In Qt versions prior to 6.8, this function took QByteArray, not
567 QByteArrayView.
568
569 \sa variant(), version(), createUuidV3()
570*/
571
572/*!
573 \since 5.0
574 \fn QUuid QUuid::createUuidV5(const QUuid &ns, const QString &baseData);
575
576 This function returns a new UUID with variant QUuid::DCE and version QUuid::Sha1.
577 \a ns is the namespace and \a baseData is the basic data as described by RFC 4122.
578
579 \sa variant(), version(), createUuidV3()
580*/
581#ifndef QT_BOOTSTRAPPED
582QUuid QUuid::createUuidV3(QUuid ns, QByteArrayView baseData) noexcept
583{
584 return createFromName(ns, baseData, algorithm: QCryptographicHash::Md5, version: 3);
585}
586#endif
587
588QUuid QUuid::createUuidV5(QUuid ns, QByteArrayView baseData) noexcept
589{
590 return createFromName(ns, baseData, algorithm: QCryptographicHash::Sha1, version: 5);
591}
592
593/*!
594 Creates a QUuid object from the binary representation of the UUID, as
595 specified by RFC 4122 section 4.1.2. See toRfc4122() for a further
596 explanation of the order of \a bytes required.
597
598 The byte array accepted is NOT a human readable format.
599
600 If the conversion fails, a null UUID is created.
601
602 \note In Qt versions prior to 6.3, this function took QByteArray, not
603 QByteArrayView.
604
605 \since 4.8
606
607 \sa toRfc4122(), QUuid(), fromBytes()
608*/
609QUuid QUuid::fromRfc4122(QByteArrayView bytes) noexcept
610{
611 if (bytes.isEmpty() || bytes.size() != 16)
612 return QUuid();
613 return fromBytes(bytes: bytes.data());
614}
615
616/*!
617 \fn bool QUuid::operator==(const QUuid &lhs, const QUuid &rhs)
618
619 Returns \c true if \a lhs QUuid and the \a rhs QUuid are identical;
620 otherwise returns \c false.
621*/
622
623/*!
624 \fn bool QUuid::operator!=(const QUuid &lhs, const QUuid &rhs)
625
626 Returns \c true if \a lhs QUuid and the \a rhs QUuid are different;
627 otherwise returns \c false.
628*/
629
630/*!
631 \since 5.11
632
633 Returns the string representation of this QUuid, with the formattiong
634 controlled by the \a mode parameter. From left to right, the five hex
635 fields are obtained from the four public data members in QUuid as follows:
636
637 \table
638 \header
639 \li Field #
640 \li Source
641
642 \row
643 \li 1
644 \li data1
645
646 \row
647 \li 2
648 \li data2
649
650 \row
651 \li 3
652 \li data3
653
654 \row
655 \li 4
656 \li data4[0] .. data4[1]
657
658 \row
659 \li 5
660 \li data4[2] .. data4[7]
661
662 \endtable
663*/
664QString QUuid::toString(QUuid::StringFormat mode) const
665{
666 char latin1[MaxStringUuidLength];
667 const auto end = _q_uuidToHex(uuid: *this, dst: latin1, mode);
668 return QString::fromLatin1(str: latin1, size: end - latin1);
669}
670
671/*!
672 \since 5.11
673
674 Returns the string representation of this QUuid, with the formattiong
675 controlled by the \a mode parameter. From left to right, the five hex
676 fields are obtained from the four public data members in QUuid as follows:
677
678 \table
679 \header
680 \li Field #
681 \li Source
682
683 \row
684 \li 1
685 \li data1
686
687 \row
688 \li 2
689 \li data2
690
691 \row
692 \li 3
693 \li data3
694
695 \row
696 \li 4
697 \li data4[0] .. data4[1]
698
699 \row
700 \li 5
701 \li data4[2] .. data4[7]
702
703 \endtable
704*/
705QByteArray QUuid::toByteArray(QUuid::StringFormat mode) const
706{
707 QByteArray result(MaxStringUuidLength, Qt::Uninitialized);
708 const auto end = _q_uuidToHex(uuid: *this, dst: const_cast<char *>(result.constData()), mode);
709 result.resize(size: end - result.constData());
710 return result;
711}
712
713/*!
714 Returns the binary representation of this QUuid. The byte array is in big
715 endian format, and formatted according to RFC 4122, section 4.1.2 -
716 "Layout and byte order".
717
718 The order is as follows:
719
720 \table
721 \header
722 \li Field #
723 \li Source
724
725 \row
726 \li 1
727 \li data1
728
729 \row
730 \li 2
731 \li data2
732
733 \row
734 \li 3
735 \li data3
736
737 \row
738 \li 4
739 \li data4[0] .. data4[7]
740
741 \endtable
742
743 The bytes in the byte array returned by this function contains the same
744 binary content as toBytes().
745
746 \sa toBytes()
747 \since 4.8
748*/
749QByteArray QUuid::toRfc4122() const
750{
751 Id128Bytes bytes = toBytes();
752 return QByteArrayView(bytes).toByteArray();
753}
754
755#ifndef QT_NO_DATASTREAM
756/*!
757 \relates QUuid
758 Writes the UUID \a id to the data stream \a s.
759*/
760QDataStream &operator<<(QDataStream &s, const QUuid &id)
761{
762 constexpr int NumBytes = sizeof(QUuid);
763 static_assert(NumBytes == 16, "Change the serialization format when this ever hits");
764 char bytes[NumBytes];
765 if (s.byteOrder() == QDataStream::BigEndian) {
766 const auto id128 = id.toBytes();
767 static_assert(sizeof(id128) == NumBytes);
768 memcpy(dest: bytes, src: &id128, n: NumBytes);
769 } else {
770 auto *data = bytes;
771
772 // for historical reasons, our little-endian serialization format
773 // stores each of the UUID fields in little endian, instead of storing
774 // a little endian Id128
775 qToLittleEndian(src: id.data1, dest: data);
776 data += sizeof(quint32);
777 qToLittleEndian(src: id.data2, dest: data);
778 data += sizeof(quint16);
779 qToLittleEndian(src: id.data3, dest: data);
780 data += sizeof(quint16);
781
782 for (int i = 0; i < 8; ++i) {
783 *(data) = id.data4[i];
784 data++;
785 }
786 }
787
788 if (s.writeRawData(bytes, len: NumBytes) != NumBytes)
789 s.setStatus(QDataStream::WriteFailed);
790
791 return s;
792}
793
794/*!
795 \relates QUuid
796 Reads a UUID from the stream \a s into \a id.
797*/
798QDataStream &operator>>(QDataStream &s, QUuid &id)
799{
800 std::array<char, 16> bytes;
801 if (s.readRawData(bytes.data(), len: 16) != 16) {
802 s.setStatus(QDataStream::ReadPastEnd);
803 return s;
804 }
805
806 if (s.byteOrder() == QDataStream::BigEndian) {
807 id = QUuid::fromRfc4122(bytes);
808 } else {
809 const uchar *data = reinterpret_cast<const uchar *>(bytes.data());
810
811 id.data1 = qFromLittleEndian<quint32>(src: data);
812 data += sizeof(quint32);
813 id.data2 = qFromLittleEndian<quint16>(src: data);
814 data += sizeof(quint16);
815 id.data3 = qFromLittleEndian<quint16>(src: data);
816 data += sizeof(quint16);
817
818 for (int i = 0; i < 8; ++i) {
819 id.data4[i] = *(data);
820 data++;
821 }
822 }
823
824 return s;
825}
826#endif // QT_NO_DATASTREAM
827
828/*!
829 Returns \c true if this is the null UUID
830 {00000000-0000-0000-0000-000000000000}; otherwise returns \c false.
831*/
832bool QUuid::isNull() const noexcept
833{
834 return data4[0] == 0 && data4[1] == 0 && data4[2] == 0 && data4[3] == 0 &&
835 data4[4] == 0 && data4[5] == 0 && data4[6] == 0 && data4[7] == 0 &&
836 data1 == 0 && data2 == 0 && data3 == 0;
837}
838
839/*!
840 \enum QUuid::Variant
841
842 This enum defines the values used in the \l{Variant field}
843 {variant field} of the UUID. The value in the variant field
844 determines the layout of the 128-bit value.
845
846 \value VarUnknown Variant is unknown
847 \value NCS Reserved for NCS (Network Computing System) backward compatibility
848 \value DCE Distributed Computing Environment, the scheme used by QUuid
849 \value Microsoft Reserved for Microsoft backward compatibility (GUID)
850 \value Reserved Reserved for future definition
851*/
852
853/*!
854 \enum QUuid::Version
855
856 This enum defines the values used in the \l{Version field}
857 {version field} of the UUID. The version field is meaningful
858 only if the value in the \l{Variant field} {variant field}
859 is QUuid::DCE.
860
861 \value VerUnknown Version is unknown
862 \value Time Time-based, by using timestamp, clock sequence, and
863 MAC network card address (if available) for the node sections
864 \value EmbeddedPOSIX DCE Security version, with embedded POSIX UUIDs
865 \value Name Name-based, by using values from a name for all sections
866 \value Md5 Alias for Name
867 \value Random Random-based, by using random numbers for all sections
868 \value Sha1
869*/
870
871/*!
872 \fn QUuid::Variant QUuid::variant() const
873
874 Returns the value in the \l{Variant field} {variant field} of the
875 UUID. If the return value is QUuid::DCE, call version() to see
876 which layout it uses. The null UUID is considered to be of an
877 unknown variant.
878
879 \sa version()
880*/
881QUuid::Variant QUuid::variant() const noexcept
882{
883 if (isNull())
884 return VarUnknown;
885 // Check the 3 MSB of data4[0]
886 if ((data4[0] & 0x80) == 0x00) return NCS;
887 else if ((data4[0] & 0xC0) == 0x80) return DCE;
888 else if ((data4[0] & 0xE0) == 0xC0) return Microsoft;
889 else if ((data4[0] & 0xE0) == 0xE0) return Reserved;
890 return VarUnknown;
891}
892
893/*!
894 \fn QUuid::Version QUuid::version() const
895
896 Returns the \l{Version field} {version field} of the UUID, if the
897 UUID's \l{Variant field} {variant field} is QUuid::DCE. Otherwise
898 it returns QUuid::VerUnknown.
899
900 \sa variant()
901*/
902QUuid::Version QUuid::version() const noexcept
903{
904 // Check the 4 MSB of data3
905 Version ver = (Version)(data3>>12);
906 if (isNull()
907 || (variant() != DCE)
908 || ver < Time
909 || ver > Sha1)
910 return VerUnknown;
911 return ver;
912}
913
914/*!
915 \fn bool QUuid::operator<(const QUuid &lhs, const QUuid &rhs)
916 \fn bool QUuid::operator>(const QUuid &lhs, const QUuid &rhs)
917 \fn bool QUuid::operator<=(const QUuid &lhs, const QUuid &rhs)
918 \fn bool QUuid::operator>=(const QUuid &lhs, const QUuid &rhs)
919 \since 5.5
920
921 Performs a comparison of \a lhs against \a rhs and returns \c true if the
922 relative sorting of \a lhs and \a rhs is correct for the operation in
923 question, \c false otherwise. Note that the sorting performed by this
924 functions may not be equal to the sorting of the strings created by
925 toString(), nor the integers toId128(), or the byte array returned by
926 toBytes() and toRfc4122().
927
928 \sa {QUuid::}{variant()}
929*/
930
931/*!
932 \fn QUuid QUuid::createUuid()
933
934 On any platform other than Windows, this function returns a new UUID with
935 variant QUuid::DCE and version QUuid::Random. On Windows, a GUID is
936 generated using the Windows API and will be of the type that the API
937 decides to create.
938
939 \sa variant(), version()
940*/
941#if defined(Q_OS_WIN)
942
943QT_BEGIN_INCLUDE_NAMESPACE
944#include <objbase.h> // For CoCreateGuid
945QT_END_INCLUDE_NAMESPACE
946
947QUuid QUuid::createUuid()
948{
949 GUID guid;
950 CoCreateGuid(&guid);
951 QUuid result = guid;
952 return result;
953}
954
955#elif !defined(QT_BOOTSTRAPPED)
956
957QUuid QUuid::createUuid()
958{
959 QUuid result(Qt::Uninitialized);
960 uint *data = &(result.data1);
961 enum { AmountToRead = 4 };
962 QRandomGenerator::system()->fillRange(buffer: data, count: AmountToRead);
963
964 result.data4[0] = (result.data4[0] & 0x3F) | 0x80; // UV_DCE
965 result.data3 = (result.data3 & 0x0FFF) | 0x4000; // UV_Random
966
967 return result;
968}
969#endif // !Q_OS_WIN && !QT_BOOTSTRAPPED
970
971/*!
972 \fn bool QUuid::operator==(const QUuid &lhs, const GUID &rhs)
973
974 Returns \c true if \a lhs UUID is equal to the Windows GUID \a rhs;
975 otherwise returns \c false.
976*/
977
978/*!
979 \fn bool QUuid::operator!=(const QUuid &lhs, const GUID &rhs)
980
981 Returns \c true if \a lhs UUID is not equal to the Windows GUID \a rhs;
982 otherwise returns \c false.
983*/
984
985#ifndef QT_NO_DEBUG_STREAM
986/*!
987 \relates QUuid
988 Writes the UUID \a id to the output stream for debugging information \a dbg.
989*/
990QDebug operator<<(QDebug dbg, const QUuid &id)
991{
992 QDebugStateSaver saver(dbg);
993 dbg.nospace() << "QUuid(" << id.toString() << ')';
994 return dbg;
995}
996#endif
997
998/*!
999 \since 5.0
1000 \relates QUuid
1001 Returns a hash of the UUID \a uuid, using \a seed to seed the calculation.
1002*/
1003size_t qHash(const QUuid &uuid, size_t seed) noexcept
1004{
1005 return uuid.data1 ^ uuid.data2 ^ (uuid.data3 << 16)
1006 ^ ((uuid.data4[0] << 24) | (uuid.data4[1] << 16) | (uuid.data4[2] << 8) | uuid.data4[3])
1007 ^ ((uuid.data4[4] << 24) | (uuid.data4[5] << 16) | (uuid.data4[6] << 8) | uuid.data4[7])
1008 ^ seed;
1009}
1010
1011
1012QT_END_NAMESPACE
1013

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtbase/src/corelib/plugin/quuid.cpp