source: trunk/src/corelib/plugin/quuid.cpp@ 552

Last change on this file since 552 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 16.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "quuid.h"
43
44#include "qdatastream.h"
45
46QT_BEGIN_NAMESPACE
47
48/*!
49 \class QUuid
50 \brief The QUuid class stores a Universally Unique Identifier (UUID).
51
52 \reentrant
53 \ingroup misc
54
55 Using \e{U}niversally \e{U}nique \e{ID}entifiers (UUID) is a
56 standard way to uniquely identify entities in a distributed
57 computing environment. A UUID is a 16-byte (128-bit) number
58 generated by some algorithm that is meant to guarantee that the
59 UUID will be unique in the distributed computing environment where
60 it is used. The acronym GUID is often used instead, \e{G}lobally
61 \e{U}nique \e{ID}entifiers, but it refers to the same thing.
62
63 \target Variant field
64 Actually, the GUID is one \e{variant} of UUID. Multiple variants
65 are in use. Each UUID contains a bit field that specifies which
66 type (variant) of UUID it is. Call variant() to discover which
67 type of UUID an instance of QUuid contains. It extracts the three
68 most signifcant bits of byte 8 of the 16 bytes. In QUuid, byte 8
69 is \c{QUuid::data4[0]}. If you create instances of QUuid using the
70 constructor that accepts all the numeric values as parameters, use
71 the following table to set the three most significant bits of
72 parameter \c{b1}, which becomes \c{QUuid::data4[0]} and contains
73 the variant field in its three most significant bits. In the
74 table, 'x' means \e {don't care}.
75
76 \table
77 \header
78 \o msb0
79 \o msb1
80 \o msb2
81 \o Variant
82
83 \row
84 \o 0
85 \o x
86 \o x
87 \o NCS (Network Computing System)
88
89 \row
90 \o 1
91 \o 0
92 \o x
93 \o DCE (Distributed Computing Environment)
94
95 \row
96 \o 1
97 \o 1
98 \o 0
99 \o Microsoft (GUID)
100
101 \row
102 \o 1
103 \o 1
104 \o 1
105 \o Reserved for future expansion
106
107 \endtable
108
109 \target Version field
110 If variant() returns QUuid::DCE, the UUID also contains a
111 \e{version} field in the four most significant bits of
112 \c{QUuid::data3}, and you can call version() to discover which
113 version your QUuid contains. If you create instances of QUuid
114 using the constructor that accepts all the numeric values as
115 parameters, use the following table to set the four most
116 significant bits of parameter \c{w2}, which becomes
117 \c{QUuid::data3} and contains the version field in its four most
118 significant bits.
119
120 \table
121 \header
122 \o msb0
123 \o msb1
124 \o msb2
125 \o msb3
126 \o Version
127
128 \row
129 \o 0
130 \o 0
131 \o 0
132 \o 1
133 \o Time
134
135 \row
136 \o 0
137 \o 0
138 \o 1
139 \o 0
140 \o Embedded POSIX
141
142 \row
143 \o 0
144 \o 0
145 \o 1
146 \o 1
147 \o Name
148
149 \row
150 \o 0
151 \o 1
152 \o 0
153 \o 0
154 \o Random
155
156 \endtable
157
158 The field layouts for the DCE versions listed in the table above
159 are specified in the \l{http://www.ietf.org/rfc/rfc4122.txt}
160 {Network Working Group UUID Specification}.
161
162 Most platforms provide a tool for generating new UUIDs, e.g. \c
163 uuidgen and \c guidgen. You can also use createUuid(). UUIDs
164 generated by createUuid() are of the random type. Their
165 QUuid::Version bits are set to QUuid::Random, and their
166 QUuid::Variant bits are set to QUuid::DCE. The rest of the UUID is
167 composed of random numbers. Theoretically, this means there is a
168 small chance that a UUID generated by createUuid() will not be
169 unique. But it is
170 \l{http://en.wikipedia.org/wiki/Universally_Unique_Identifier#Random_UUID_probability_of_duplicates}
171 {a \e{very} small chance}.
172
173 UUIDs can be constructed from numeric values or from strings, or
174 using the static createUuid() function. They can be converted to a
175 string with toString(). UUIDs have a variant() and a version(),
176 and null UUIDs return true from isNull().
177*/
178
179/*!
180 \fn QUuid::QUuid(const GUID &guid)
181
182 Casts a Windows \a guid to a Qt QUuid.
183
184 \warning This function is only for Windows platforms.
185*/
186
187/*!
188 \fn QUuid &QUuid::operator=(const GUID &guid)
189
190 Assigns a Windows \a guid to a Qt QUuid.
191
192 \warning This function is only for Windows platforms.
193*/
194
195/*!
196 \fn QUuid::operator GUID() const
197
198 Returns a Windows GUID from a QUuid.
199
200 \warning This function is only for Windows platforms.
201*/
202
203/*!
204 \fn QUuid::QUuid()
205
206 Creates the null UUID. toString() will output the null UUID
207 as "{00000000-0000-0000-0000-000000000000}".
208*/
209
210/*!
211 \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)
212
213 Creates a UUID with the value specified by the parameters, \a l,
214 \a w1, \a w2, \a b1, \a b2, \a b3, \a b4, \a b5, \a b6, \a b7, \a
215 b8.
216
217 Example:
218 \snippet doc/src/snippets/code/src_corelib_plugin_quuid.cpp 0
219*/
220
221#ifndef QT_NO_QUUID_STRING
222/*!
223 Creates a QUuid object from the string \a text, which must be
224 formatted as five hex fields separated by '-', e.g.,
225 "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where 'x' is a hex
226 digit. The curly braces shown here are optional, but it is normal to
227 include them. If the conversion fails, a null UUID is created. See
228 toString() for an explanation of how the five hex fields map to the
229 public data members in QUuid.
230
231 \sa toString(), QUuid()
232*/
233QUuid::QUuid(const QString &text)
234{
235 bool ok;
236 if (text.isEmpty()) {
237 *this = QUuid();
238 return;
239 }
240 QString temp = text.toUpper();
241 if (temp[0] != QLatin1Char('{'))
242 temp = QLatin1Char('{') + text;
243 if (text[(int)text.length()-1] != QLatin1Char('}'))
244 temp += QLatin1Char('}');
245
246 data1 = temp.mid(1, 8).toULongLong(&ok, 16);
247 if (!ok) {
248 *this = QUuid();
249 return;
250 }
251
252 data2 = temp.mid(10, 4).toUInt(&ok, 16);
253 if (!ok) {
254 *this = QUuid();
255 return;
256 }
257 data3 = temp.mid(15, 4).toUInt(&ok, 16);
258 if (!ok) {
259 *this = QUuid();
260 return;
261 }
262 data4[0] = temp.mid(20, 2).toUInt(&ok, 16);
263 if (!ok) {
264 *this = QUuid();
265 return;
266 }
267 data4[1] = temp.mid(22, 2).toUInt(&ok, 16);
268 if (!ok) {
269 *this = QUuid();
270 return;
271 }
272 for (int i = 2; i<8; i++) {
273 data4[i] = temp.mid(25 + (i-2)*2, 2).toUShort(&ok, 16);
274 if (!ok) {
275 *this = QUuid();
276 return;
277 }
278 }
279}
280
281/*!
282 \internal
283*/
284QUuid::QUuid(const char *text)
285{
286 *this = QUuid(QString::fromLatin1(text));
287}
288#endif
289
290/*!
291 \fn bool QUuid::operator==(const QUuid &other) const
292
293 Returns true if this QUuid and the \a other QUuid are identical;
294 otherwise returns false.
295*/
296
297/*!
298 \fn bool QUuid::operator!=(const QUuid &other) const
299
300 Returns true if this QUuid and the \a other QUuid are different;
301 otherwise returns false.
302*/
303#ifndef QT_NO_QUUID_STRING
304/*!
305 \fn QUuid::operator QString() const
306
307 Returns the string representation of the uuid.
308
309 \sa toString()
310*/
311
312static QString uuidhex(uint data, int digits)
313{
314 return QString::number(data, 16).rightJustified(digits, QLatin1Char('0'));
315}
316
317/*!
318 Returns the string representation of this QUuid. The string is
319 formatted as five hex fields separated by '-' and enclosed in
320 curly braces, i.e., "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where
321 'x' is a hex digit. From left to right, the five hex fields are
322 obtained from the four public data members in QUuid as follows:
323
324 \table
325 \header
326 \o Field #
327 \o Source
328
329 \row
330 \o 1
331 \o data1
332
333 \row
334 \o 2
335 \o data2
336
337 \row
338 \o 3
339 \o data3
340
341 \row
342 \o 4
343 \o data4[0] .. data4[1]
344
345 \row
346 \o 5
347 \o data4[2] .. data4[7]
348
349 \endtable
350*/
351QString QUuid::toString() const
352{
353 QString result;
354
355 QChar dash = QLatin1Char('-');
356 result = QLatin1Char('{') + uuidhex(data1,8);
357 result += dash;
358 result += uuidhex(data2,4);
359 result += dash;
360 result += uuidhex(data3,4);
361 result += dash;
362 result += uuidhex(data4[0],2);
363 result += uuidhex(data4[1],2);
364 result += dash;
365 for (int i = 2; i < 8; i++)
366 result += uuidhex(data4[i],2);
367
368 return result + QLatin1Char('}');
369}
370#endif
371
372#ifndef QT_NO_DATASTREAM
373/*!
374 \relates QUuid
375 Writes the UUID \a id to the data stream \a s.
376*/
377QDataStream &operator<<(QDataStream &s, const QUuid &id)
378{
379 s << (quint32)id.data1;
380 s << (quint16)id.data2;
381 s << (quint16)id.data3;
382 for (int i = 0; i < 8; i++)
383 s << (quint8)id.data4[i];
384 return s;
385}
386
387/*!
388 \relates QUuid
389 Reads a UUID from the stream \a s into \a id.
390*/
391QDataStream &operator>>(QDataStream &s, QUuid &id)
392{
393 quint32 u32;
394 quint16 u16;
395 quint8 u8;
396 s >> u32;
397 id.data1 = u32;
398 s >> u16;
399 id.data2 = u16;
400 s >> u16;
401 id.data3 = u16;
402 for (int i = 0; i < 8; i++) {
403 s >> u8;
404 id.data4[i] = u8;
405 }
406 return s;
407}
408#endif
409
410/*!
411 Returns true if this is the null UUID
412 {00000000-0000-0000-0000-000000000000}; otherwise returns false.
413*/
414bool QUuid::isNull() const
415{
416 return data4[0] == 0 && data4[1] == 0 && data4[2] == 0 && data4[3] == 0 &&
417 data4[4] == 0 && data4[5] == 0 && data4[6] == 0 && data4[7] == 0 &&
418 data1 == 0 && data2 == 0 && data3 == 0;
419}
420
421/*!
422 \enum QUuid::Variant
423
424 This enum defines the values used in the \l{Variant field}
425 {variant field} of the UUID. The value in the variant field
426 determines the layout of the 128-bit value.
427
428 \value VarUnknown Variant is unknown
429 \value NCS Reserved for NCS (Network Computing System) backward compatibility
430 \value DCE Distributed Computing Environment, the scheme used by QUuid
431 \value Microsoft Reserved for Microsoft backward compatibility (GUID)
432 \value Reserved Reserved for future definition
433*/
434
435/*!
436 \enum QUuid::Version
437
438 This enum defines the values used in the \l{Version field}
439 {version field} of the UUID. The version field is meaningful
440 only if the value in the \l{Variant field} {variant field}
441 is QUuid::DCE.
442
443 \value VerUnknown Version is unknown
444 \value Time Time-based, by using timestamp, clock sequence, and
445 MAC network card address (if available) for the node sections
446 \value EmbeddedPOSIX DCE Security version, with embedded POSIX UUIDs
447 \value Name Name-based, by using values from a name for all sections
448 \value Random Random-based, by using random numbers for all sections
449*/
450
451/*!
452 \fn QUuid::Variant QUuid::variant() const
453
454 Returns the value in the \l{Variant field} {variant field} of the
455 UUID. If the return value is QUuid::DCE, call version() to see
456 which layout it uses. The null UUID is considered to be of an
457 unknown variant.
458
459 \sa version()
460*/
461QUuid::Variant QUuid::variant() const
462{
463 if (isNull())
464 return VarUnknown;
465 // Check the 3 MSB of data4[0]
466 if ((data4[0] & 0x80) == 0x00) return NCS;
467 else if ((data4[0] & 0xC0) == 0x80) return DCE;
468 else if ((data4[0] & 0xE0) == 0xC0) return Microsoft;
469 else if ((data4[0] & 0xE0) == 0xE0) return Reserved;
470 return VarUnknown;
471}
472
473/*!
474 \fn QUuid::Version QUuid::version() const
475
476 Returns the \l{Version field} {version field} of the UUID, if the
477 UUID's \l{Variant field} {variant field} is QUuid::DCE. Otherwise
478 it returns QUuid::VerUnknown.
479
480 \sa variant()
481*/
482QUuid::Version QUuid::version() const
483{
484 // Check the 4 MSB of data3
485 Version ver = (Version)(data3>>12);
486 if (isNull()
487 || (variant() != DCE)
488 || ver < Time
489 || ver > Random)
490 return VerUnknown;
491 return ver;
492}
493
494/*!
495 \fn bool QUuid::operator<(const QUuid &other) const
496
497 Returns true if this QUuid has the same \l{Variant field}
498 {variant field} as the \a other QUuid and is lexicographically
499 \e{before} the \a other QUuid. If the \a other QUuid has a
500 different variant field, the return value is determined by
501 comparing the two \l{QUuid::Variant} {variants}.
502
503 \sa variant()
504*/
505#define ISLESS(f1, f2) if (f1!=f2) return (f1<f2);
506bool QUuid::operator<(const QUuid &other) const
507{
508 if (variant() != other.variant())
509 return variant() < other.variant();
510
511 ISLESS(data1, other.data1);
512 ISLESS(data2, other.data2);
513 ISLESS(data3, other.data3);
514 for (int n = 0; n < 8; n++) {
515 ISLESS(data4[n], other.data4[n]);
516 }
517 return false;
518}
519
520/*!
521 \fn bool QUuid::operator>(const QUuid &other) const
522
523 Returns true if this QUuid has the same \l{Variant field}
524 {variant field} as the \a other QUuid and is lexicographically
525 \e{after} the \a other QUuid. If the \a other QUuid has a
526 different variant field, the return value is determined by
527 comparing the two \l{QUuid::Variant} {variants}.
528
529 \sa variant()
530*/
531#define ISMORE(f1, f2) if (f1!=f2) return (f1>f2);
532bool QUuid::operator>(const QUuid &other) const
533{
534 if (variant() != other.variant())
535 return variant() > other.variant();
536
537 ISMORE(data1, other.data1);
538 ISMORE(data2, other.data2);
539 ISMORE(data3, other.data3);
540 for (int n = 0; n < 8; n++) {
541 ISMORE(data4[n], other.data4[n]);
542 }
543 return false;
544}
545
546/*!
547 \fn QUuid QUuid::createUuid()
548
549 On any platform other than Windows, this function returns a new
550 UUID with variant QUuid::DCE and version QUuid::Random. The random
551 numbers used to construct the UUID are obtained from the local
552 pseudo-random generator, which is usually not a cryptographic
553 quality random number generator. Therefore, a UUID generated by
554 this function can't be guaranteed to be unique.
555
556 On a Windows platform, a GUID is generated, which almost certainly
557 \e{will} be unique, on this or any other system, networked or not.
558
559 \sa variant(), version()
560*/
561#if defined(Q_OS_WIN32)
562
563QT_BEGIN_INCLUDE_NAMESPACE
564#include <objbase.h> // For CoCreateGuid
565QT_END_INCLUDE_NAMESPACE
566
567QUuid QUuid::createUuid()
568{
569 GUID guid;
570 CoCreateGuid(&guid);
571 QUuid result = guid;
572 return result;
573}
574
575#else // !Q_OS_WIN32
576
577QT_BEGIN_INCLUDE_NAMESPACE
578#include "qdatetime.h"
579#include "stdlib.h" // For srand/rand
580QT_END_INCLUDE_NAMESPACE
581
582QUuid QUuid::createUuid()
583{
584 static const int intbits = sizeof(int)*8;
585 static int randbits = 0;
586 if (!randbits) {
587 int max = RAND_MAX;
588 do { ++randbits; } while ((max=max>>1));
589 qsrand((uint)QDateTime::currentDateTime().toTime_t());
590 qrand(); // Skip first
591 }
592
593 QUuid result;
594 uint *data = &(result.data1);
595 int chunks = 16 / sizeof(uint);
596 while (chunks--) {
597 uint randNumber = 0;
598 for (int filled = 0; filled < intbits; filled += randbits)
599 randNumber |= qrand()<<filled;
600 *(data+chunks) = randNumber;
601 }
602
603 result.data4[0] = (result.data4[0] & 0x3F) | 0x80; // UV_DCE
604 result.data3 = (result.data3 & 0x0FFF) | 0x4000; // UV_Random
605
606 return result;
607}
608#endif // !Q_OS_WIN32
609
610/*!
611 \fn bool QUuid::operator==(const GUID &guid) const
612
613 Returns true if this UUID is equal to the Windows GUID \a guid;
614 otherwise returns false.
615*/
616
617/*!
618 \fn bool QUuid::operator!=(const GUID &guid) const
619
620 Returns true if this UUID is not equal to the Windows GUID \a
621 guid; otherwise returns false.
622*/
623
624QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.