src/corelib/plugin/quuid.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    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. The random
       
   550     numbers used to construct the UUID are obtained from the local
       
   551     pseudo-random generator, qrand(), which is usually not a cryptographic
       
   552     quality random number generator. Therefore, a UUID generated by
       
   553     this function can't be guaranteed to be unique. If the pseudo-random
       
   554     number generator for the calling thread has not yet been seeded, this
       
   555     function will seed the pseudo-random number generator by calling qsrand().
       
   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 "stdlib.h" // For srand/rand
       
   581 QT_END_INCLUDE_NAMESPACE
       
   582 
       
   583 extern void qsrand(); // in qglobal.cpp
       
   584 
       
   585 QUuid QUuid::createUuid()
       
   586 {
       
   587     static const int intbits = sizeof(int)*8;
       
   588     static int randbits = 0;
       
   589     if (!randbits) {
       
   590         int max = RAND_MAX;
       
   591         do { ++randbits; } while ((max=max>>1));
       
   592     }
       
   593 
       
   594     // reseed, but only if not already seeded
       
   595     qsrand();
       
   596 
       
   597     QUuid result;
       
   598     uint *data = &(result.data1);
       
   599     int chunks = 16 / sizeof(uint);
       
   600     while (chunks--) {
       
   601         uint randNumber = 0;
       
   602         for (int filled = 0; filled < intbits; filled += randbits)
       
   603             randNumber |= qrand()<<filled;
       
   604          *(data+chunks) = randNumber;
       
   605     }
       
   606 
       
   607     result.data4[0] = (result.data4[0] & 0x3F) | 0x80;        // UV_DCE
       
   608     result.data3 = (result.data3 & 0x0FFF) | 0x4000;        // UV_Random
       
   609 
       
   610     return result;
       
   611 }
       
   612 #endif // !Q_OS_WIN32
       
   613 
       
   614 /*!
       
   615     \fn bool QUuid::operator==(const GUID &guid) const
       
   616 
       
   617     Returns true if this UUID is equal to the Windows GUID \a guid;
       
   618     otherwise returns false.
       
   619 */
       
   620 
       
   621 /*!
       
   622     \fn bool QUuid::operator!=(const GUID &guid) const
       
   623 
       
   624     Returns true if this UUID is not equal to the Windows GUID \a
       
   625     guid; otherwise returns false.
       
   626 */
       
   627 
       
   628 QT_END_NAMESPACE