Qt 4.8
quuid.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "quuid.h"
43 
44 #include "qdatastream.h"
45 #include "qendian.h"
46 
48 
49 #ifndef QT_NO_QUUID_STRING
50 template <class Char, class Integral>
51 void _q_toHex(Char *&dst, Integral value)
52 {
53  static const char digits[] = "0123456789abcdef";
54 
55  value = qToBigEndian(value);
56 
57  const char* p = reinterpret_cast<const char*>(&value);
58 
59  for (uint i = 0; i < sizeof(Integral); ++i, dst += 2) {
60  uint j = (p[i] >> 4) & 0xf;
61  dst[0] = Char(digits[j]);
62  j = p[i] & 0xf;
63  dst[1] = Char(digits[j]);
64  }
65 }
66 
67 template <class Char, class Integral>
68 bool _q_fromHex(const Char *&src, Integral &value)
69 {
70  value = 0;
71 
72  for (uint i = 0; i < sizeof(Integral) * 2; ++i) {
73  int ch = *src++;
74  int tmp;
75  if (ch >= '0' && ch <= '9')
76  tmp = ch - '0';
77  else if (ch >= 'a' && ch <= 'f')
78  tmp = ch - 'a' + 10;
79  else if (ch >= 'A' && ch <= 'F')
80  tmp = ch - 'A' + 10;
81  else
82  return false;
83 
84  value = value * 16 + tmp;
85  }
86 
87  return true;
88 }
89 
90 template <class Char>
91 void _q_uuidToHex(Char *&dst, const uint &d1, const ushort &d2, const ushort &d3, const uchar (&d4)[8])
92 {
93  *dst++ = Char('{');
94  _q_toHex(dst, d1);
95  *dst++ = Char('-');
96  _q_toHex(dst, d2);
97  *dst++ = Char('-');
98  _q_toHex(dst, d3);
99  *dst++ = Char('-');
100  for (int i = 0; i < 2; i++)
101  _q_toHex(dst, d4[i]);
102  *dst++ = Char('-');
103  for (int i = 2; i < 8; i++)
104  _q_toHex(dst, d4[i]);
105  *dst = Char('}');
106 }
107 
108 template <class Char>
109 bool _q_uuidFromHex(const Char *&src, uint &d1, ushort &d2, ushort &d3, uchar (&d4)[8])
110 {
111  if (*src == Char('{'))
112  src++;
113  if (!_q_fromHex(src, d1)
114  || *src++ != Char('-')
115  || !_q_fromHex(src, d2)
116  || *src++ != Char('-')
117  || !_q_fromHex(src, d3)
118  || *src++ != Char('-')
119  || !_q_fromHex(src, d4[0])
120  || !_q_fromHex(src, d4[1])
121  || *src++ != Char('-')
122  || !_q_fromHex(src, d4[2])
123  || !_q_fromHex(src, d4[3])
124  || !_q_fromHex(src, d4[4])
125  || !_q_fromHex(src, d4[5])
126  || !_q_fromHex(src, d4[6])
127  || !_q_fromHex(src, d4[7])) {
128  return false;
129  }
130 
131  return true;
132 }
133 #endif
134 
323 #ifndef QT_NO_QUUID_STRING
324 
336 {
337  if (text.length() < 36) {
338  *this = QUuid();
339  return;
340  }
341 
342  const ushort *data = reinterpret_cast<const ushort *>(text.unicode());
343 
344  if (*data == '{' && text.length() < 37) {
345  *this = QUuid();
346  return;
347  }
348 
349  if (!_q_uuidFromHex(data, data1, data2, data3, data4)) {
350  *this = QUuid();
351  return;
352  }
353 }
354 
358 QUuid::QUuid(const char *text)
359 {
360  if (!text) {
361  *this = QUuid();
362  return;
363  }
364 
365  if (!_q_uuidFromHex(text, data1, data2, data3, data4)) {
366  *this = QUuid();
367  return;
368  }
369 }
370 
385 {
386  if (text.length() < 36) {
387  *this = QUuid();
388  return;
389  }
390 
391  const char *data = text.constData();
392 
393  if (*data == '{' && text.length() < 37) {
394  *this = QUuid();
395  return;
396  }
397 
398  if (!_q_uuidFromHex(data, data1, data2, data3, data4)) {
399  *this = QUuid();
400  return;
401  }
402 }
403 #endif
404 
422 {
423  if (bytes.isEmpty() || bytes.length() != 16)
424  return QUuid();
425 
426  uint d1;
427  ushort d2, d3;
428  uchar d4[8];
429 
430  const uchar *data = reinterpret_cast<const uchar *>(bytes.constData());
431 
433  data += sizeof(quint32);
435  data += sizeof(quint16);
437  data += sizeof(quint16);
438 
439  for (int i = 0; i < 8; ++i) {
440  d4[i] = *(data);
441  data++;
442  }
443 
444  return QUuid(d1, d2, d3, d4[0], d4[1], d4[2], d4[3], d4[4], d4[5], d4[6], d4[7]);
445 }
446 
466 #ifndef QT_NO_QUUID_STRING
467 
513 {
514  QString result(38, Qt::Uninitialized);
515  ushort *data = (ushort *)result.unicode();
516 
517  _q_uuidToHex(data, data1, data2, data3, data4);
518 
519  return result;
520 }
521 
559 {
560  QByteArray result(38, Qt::Uninitialized);
561  char *data = result.data();
562 
563  _q_uuidToHex(data, data1, data2, data3, data4);
564 
565  return result;
566 }
567 #endif
568 
602 {
603  // we know how many bytes a UUID has, I hope :)
604  QByteArray bytes(16, Qt::Uninitialized);
605  uchar *data = reinterpret_cast<uchar*>(bytes.data());
606 
607  qToBigEndian(data1, data);
608  data += sizeof(quint32);
609  qToBigEndian(data2, data);
610  data += sizeof(quint16);
611  qToBigEndian(data3, data);
612  data += sizeof(quint16);
613 
614  for (int i = 0; i < 8; ++i) {
615  *(data) = data4[i];
616  data++;
617  }
618 
619  return bytes;
620 }
621 
622 #ifndef QT_NO_DATASTREAM
623 
631 {
632  QByteArray bytes;
633  if (s.byteOrder() == QDataStream::BigEndian) {
634  bytes = id.toRfc4122();
635  } else {
636  // we know how many bytes a UUID has, I hope :)
637  bytes = QByteArray(16, Qt::Uninitialized);
638  uchar *data = reinterpret_cast<uchar*>(bytes.data());
639 
640  qToLittleEndian(id.data1, data);
641  data += sizeof(quint32);
642  qToLittleEndian(id.data2, data);
643  data += sizeof(quint16);
644  qToLittleEndian(id.data3, data);
645  data += sizeof(quint16);
646 
647  for (int i = 0; i < 8; ++i) {
648  *(data) = id.data4[i];
649  data++;
650  }
651  }
652 
653  if (s.writeRawData(bytes.data(), 16) != 16) {
655  }
656  return s;
657 }
658 
667 {
668  QByteArray bytes(16, Qt::Uninitialized);
669  if (s.readRawData(bytes.data(), 16) != 16) {
671  return s;
672  }
673 
674  if (s.byteOrder() == QDataStream::BigEndian) {
675  id = QUuid::fromRfc4122(bytes);
676  } else {
677  const uchar *data = reinterpret_cast<const uchar *>(bytes.constData());
678 
679  id.data1 = qFromLittleEndian<quint32>(data);
680  data += sizeof(quint32);
681  id.data2 = qFromLittleEndian<quint16>(data);
682  data += sizeof(quint16);
683  id.data3 = qFromLittleEndian<quint16>(data);
684  data += sizeof(quint16);
685 
686  for (int i = 0; i < 8; ++i) {
687  id.data4[i] = *(data);
688  data++;
689  }
690  }
691 
692  return s;
693 }
694 #endif // QT_NO_DATASTREAM
695 
700 bool QUuid::isNull() const
701 {
702  return data4[0] == 0 && data4[1] == 0 && data4[2] == 0 && data4[3] == 0 &&
703  data4[4] == 0 && data4[5] == 0 && data4[6] == 0 && data4[7] == 0 &&
704  data1 == 0 && data2 == 0 && data3 == 0;
705 }
706 
757 {
758  if (isNull())
759  return VarUnknown;
760  // Check the 3 MSB of data4[0]
761  if ((data4[0] & 0x80) == 0x00) return NCS;
762  else if ((data4[0] & 0xC0) == 0x80) return DCE;
763  else if ((data4[0] & 0xE0) == 0xC0) return Microsoft;
764  else if ((data4[0] & 0xE0) == 0xE0) return Reserved;
765  return VarUnknown;
766 }
767 
781 {
782  // Check the 4 MSB of data3
783  Version ver = (Version)(data3>>12);
784  if (isNull()
785  || (variant() != DCE)
786  || ver < Time
787  || ver > Random)
788  return VerUnknown;
789  return ver;
790 }
791 
806 #define ISLESS(f1, f2) if (f1!=f2) return (f1<f2);
807 bool QUuid::operator<(const QUuid &other) const
808 {
809  if (variant() != other.variant())
810  return variant() < other.variant();
811 
812  ISLESS(data1, other.data1);
813  ISLESS(data2, other.data2);
814  ISLESS(data3, other.data3);
815  for (int n = 0; n < 8; n++) {
816  ISLESS(data4[n], other.data4[n]);
817  }
818  return false;
819 }
820 
835 #define ISMORE(f1, f2) if (f1!=f2) return (f1>f2);
836 bool QUuid::operator>(const QUuid &other) const
837 {
838  if (variant() != other.variant())
839  return variant() > other.variant();
840 
841  ISMORE(data1, other.data1);
842  ISMORE(data2, other.data2);
843  ISMORE(data3, other.data3);
844  for (int n = 0; n < 8; n++) {
845  ISMORE(data4[n], other.data4[n]);
846  }
847  return false;
848 }
849 
870 #if defined(Q_OS_WIN32) && ! defined(Q_CC_MWERKS)
871 
873 #include <objbase.h> // For CoCreateGuid
875 
877 {
878  GUID guid;
879  CoCreateGuid(&guid);
880  QUuid result = guid;
881  return result;
882 }
883 
884 #else // !Q_OS_WIN32
885 
887 #include "qdatetime.h"
888 #include "qfile.h"
889 #include "qthreadstorage.h"
890 #include <stdlib.h> // for RAND_MAX
892 
893 #if !defined(QT_BOOTSTRAPPED) && defined(Q_OS_UNIX)
894 Q_GLOBAL_STATIC(QThreadStorage<QFile *>, devUrandomStorage);
895 #endif
896 
898 {
899  QUuid result;
900  uint *data = &(result.data1);
901 
902 #if defined(Q_OS_UNIX)
903  QFile *devUrandom;
904 # if !defined(QT_BOOTSTRAPPED)
905  devUrandom = devUrandomStorage()->localData();
906  if (!devUrandom) {
907  devUrandom = new QFile(QLatin1String("/dev/urandom"));
909  devUrandomStorage()->setLocalData(devUrandom);
910  }
911 # else
912  QFile file(QLatin1String("/dev/urandom"));
913  devUrandom = &file;
915 # endif
916  enum { AmountToRead = 4 * sizeof(uint) };
917  if (devUrandom->isOpen()
918  && devUrandom->read((char *) data, AmountToRead) == AmountToRead) {
919  // we got what we wanted, nothing more to do
920  ;
921  } else
922 #endif
923  {
924  static const int intbits = sizeof(int)*8;
925  static int randbits = 0;
926  if (!randbits) {
927  int r = 0;
928  int max = RAND_MAX;
929  do { ++r; } while ((max=max>>1));
930  randbits = r;
931  }
932 
933  // Seed the PRNG once per thread with a combination of current time, a
934  // stack address and a serial counter (since thread stack addresses are
935  // re-used).
936 #ifndef QT_BOOTSTRAPPED
937  static QThreadStorage<int *> uuidseed;
938  if (!uuidseed.hasLocalData())
939  {
940  int *pseed = new int;
941  static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(2);
942  qsrand(*pseed = QDateTime::currentDateTime().toTime_t()
943  + quintptr(&pseed)
944  + serial.fetchAndAddRelaxed(1));
945  uuidseed.setLocalData(pseed);
946  }
947 #else
948  static bool seeded = false;
949  if (!seeded)
951  + quintptr(&seeded));
952 #endif
953 
954  int chunks = 16 / sizeof(uint);
955  while (chunks--) {
956  uint randNumber = 0;
957  for (int filled = 0; filled < intbits; filled += randbits)
958  randNumber |= qrand()<<filled;
959 #if defined(Q_OS_SYMBIAN)
960  // Symbian does not have /dev/urandom, so entropy is low.
961  // Add more entropy from the kernel tick count (1ms resolution).
962  // big multipler used to splatter the tick count bits over the whole 32 bits
963  randNumber ^= User::NTickCount() * 0x3b9aca07;
964 #endif
965  *(data+chunks) = randNumber;
966  }
967  }
968 
969  result.data4[0] = (result.data4[0] & 0x3F) | 0x80; // UV_DCE
970  result.data3 = (result.data3 & 0x0FFF) | 0x4000; // UV_Random
971 
972  return result;
973 }
974 #endif // !Q_OS_WIN32
975 
QByteArray toRfc4122() const
Returns the binary representation of this QUuid.
Definition: quuid.cpp:601
uint data1
Definition: quuid.h:179
QIntegerForSizeof< void * >::Unsigned quintptr
Definition: qglobal.h:986
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
#define ISMORE(f1, f2)
Definition: quuid.cpp:835
void _q_uuidToHex(Char *&dst, const uint &d1, const ushort &d2, const ushort &d3, const uchar(&d4)[8])
Definition: quuid.cpp:91
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
Definition: quuid.h:52
bool open(OpenMode flags)
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition: qfile.cpp:1064
static QUuid createUuid()
On any platform other than Windows, this function returns a new UUID with variant QUuid::DCE and vers...
Definition: quuid.cpp:897
quint16 qFromLittleEndian< quint16 >(const uchar *src)
Definition: qendian.h:157
ByteOrder byteOrder() const
Returns the current byte order setting – either BigEndian or LittleEndian.
Definition: qdatastream.h:209
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
Version
This enum defines the values used in the Version field {version field} of the UUID.
Definition: quuid.h:77
QDataStream & operator>>(QDataStream &s, QUuid &id)
Reads a UUID from the stream s into id.
Definition: quuid.cpp:666
QByteArray toByteArray() const
Returns the binary representation of this QUuid.
Definition: quuid.cpp:558
#define QT_END_INCLUDE_NAMESPACE
This macro is equivalent to QT_BEGIN_NAMESPACE.
Definition: qglobal.h:92
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
void setStatus(Status status)
Sets the status of the data stream to the status given.
quint32 qFromBigEndian< quint32 >(const uchar *src)
Definition: qendian.h:239
bool _q_fromHex(const Char *&src, Integral &value)
Definition: quuid.cpp:68
The QString class provides a Unicode character string.
Definition: qstring.h:83
Q_CORE_EXPORT int qrand()
QUuid::Variant variant() const
Returns the value in the Variant field {variant field} of the UUID.
Definition: quuid.cpp:756
#define Q_BASIC_ATOMIC_INITIALIZER(a)
Definition: qbasicatomic.h:218
bool _q_uuidFromHex(const Char *&src, uint &d1, ushort &d2, ushort &d3, uchar(&d4)[8])
Definition: quuid.cpp:109
QString toString() const
Returns the string representation of this QUuid.
Definition: quuid.cpp:512
bool isNull() const
Returns true if this is the null UUID {00000000-0000-0000-0000-000000000000}; otherwise returns false...
Definition: quuid.cpp:700
ushort data3
Definition: quuid.h:181
bool operator>(const QUuid &other) const
Returns true if this QUuid has the same Variant field {variant field} as the other QUuid and is lexic...
Definition: quuid.cpp:836
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read...
Definition: qiodevice.cpp:791
QDataStream & operator<<(QDataStream &s, const QUuid &id)
Writes the UUID id to the data stream s.
Definition: quuid.cpp:630
unsigned char uchar
Definition: qglobal.h:994
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
bool isOpen() const
Returns true if the device is open; otherwise returns false.
Definition: qiodevice.cpp:530
int readRawData(char *, int len)
Reads at most len bytes from the stream into s and returns the number of bytes read.
const QChar * unicode() const
Returns a &#39;\0&#39;-terminated Unicode representation of the string.
Definition: qstring.h:706
#define ISLESS(f1, f2)
Definition: quuid.cpp:806
QUuid()
Creates the null UUID.
Definition: quuid.h:85
#define CoCreateGuid
T qToBigEndian(T source)
Definition: qendian.h:337
unsigned short quint16
Definition: qglobal.h:936
quint32 qFromLittleEndian< quint32 >(const uchar *src)
Definition: qendian.h:148
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
ushort Char
void _q_toHex(Char *&dst, Integral value)
Definition: quuid.cpp:51
Variant
This enum defines the values used in the Variant field {variant field} of the UUID.
Definition: quuid.h:69
quint16 qFromBigEndian< quint16 >(const uchar *src)
Definition: qendian.h:249
int length() const
Same as size().
Definition: qbytearray.h:356
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
bool hasLocalData() const
If T is a pointer type, returns true if the calling thread has non-zero data available.
The QFile class provides an interface for reading from and writing to files.
Definition: qfile.h:65
unsigned short ushort
Definition: qglobal.h:995
void setLocalData(T t)
Sets the local data for the calling thread to data.
unsigned int quint32
Definition: qglobal.h:938
int fetchAndAddRelaxed(int valueToAdd)
static QDateTime currentDateTime()
Returns the current datetime, as reported by the system clock, in the local time zone.
Definition: qdatetime.cpp:3138
static QUuid fromRfc4122(const QByteArray &)
Creates a QUuid object from the binary representation of the UUID given by bytes, as specified by RFC...
Definition: quuid.cpp:421
#define QT_BEGIN_INCLUDE_NAMESPACE
This macro is equivalent to QT_END_NAMESPACE.
Definition: qglobal.h:91
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
Q_GLOBAL_STATIC(QThreadStorage< QFile *>, devUrandomStorage)
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:71
Q_CORE_EXPORT void qsrand(uint seed)
uchar data4[8]
Definition: quuid.h:182
QUuid::Version version() const
Returns the Version field {version field} of the UUID, if the UUID&#39;s Variant field {variant field} is...
Definition: quuid.cpp:780
The QThreadStorage class provides per-thread data storage.
T qToLittleEndian(T source)
Definition: qendian.h:341
int writeRawData(const char *, int len)
Writes len bytes from s to the stream.
ushort data2
Definition: quuid.h:180
The QUuid class stores a Universally Unique Identifier (UUID).
Definition: quuid.h:67
bool operator<(const QUuid &other) const
Returns true if this QUuid has the same Variant field {variant field} as the other QUuid and is lexic...
Definition: quuid.cpp:807
#define text
Definition: qobjectdefs.h:80