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 | |
14 | QT_BEGIN_NAMESPACE |
15 | |
16 | // ensure QList of this is efficient |
17 | static_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. |
21 | enum { MaxStringUuidLength = 38 }; |
22 | |
23 | template <class Integral> |
24 | void _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 |
39 | template <class Integral> |
40 | bool _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 | |
56 | static 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 | */ |
90 | Q_NEVER_INLINE |
91 | static 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 | |
122 | static 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 | */ |
497 | static 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 | |
513 | static 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 | |
524 | Q_ALWAYS_INLINE |
525 | // can treat UTF-8 the same as Latin-1: |
526 | static QUuid uuidFromString(QUtf8StringView text) noexcept |
527 | { |
528 | return uuidFromString(text: QLatin1StringView(text.data(), text.size())); |
529 | } |
530 | |
531 | QUuid 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 |
582 | QUuid QUuid::createUuidV3(QUuid ns, QByteArrayView baseData) noexcept |
583 | { |
584 | return createFromName(ns, baseData, algorithm: QCryptographicHash::Md5, version: 3); |
585 | } |
586 | #endif |
587 | |
588 | QUuid 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 | */ |
609 | QUuid 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 | */ |
664 | QString 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 | */ |
705 | QByteArray 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 | */ |
749 | QByteArray 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 | */ |
760 | QDataStream &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 | */ |
798 | QDataStream &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 | */ |
832 | bool 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 | */ |
881 | QUuid::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 | */ |
902 | QUuid::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 | |
943 | QT_BEGIN_INCLUDE_NAMESPACE |
944 | #include <objbase.h> // For CoCreateGuid |
945 | QT_END_INCLUDE_NAMESPACE |
946 | |
947 | QUuid QUuid::createUuid() |
948 | { |
949 | GUID guid; |
950 | CoCreateGuid(&guid); |
951 | QUuid result = guid; |
952 | return result; |
953 | } |
954 | |
955 | #elif !defined(QT_BOOTSTRAPPED) |
956 | |
957 | QUuid 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 | */ |
990 | QDebug 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 | */ |
1003 | size_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 | |
1012 | QT_END_NAMESPACE |
1013 | |