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