Sans Pareil Technologies, Inc.

Key To Your Business

UUID



The UUID class is taken from the Poco project. The current implementation supports generating only time based UUID values. This class depends upon the DateTime class for time. The class needs to be initialised before first use with the MAC address associated with the device network shield. Initialisation is necessary since the Arduino ethernet library does not expose a way to programmatically determine the MAC address (the WiFi library does however). Unique MAC addresses are essential for generating unique UUID values.

UUID.h

The header that defines the UUID class.

    1:
    2: /*
    3: Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
    4: and Contributors.
    5:
    6: Permission is hereby granted, free of charge, to any person or organization
    7: obtaining a copy of the software and accompanying documentation covered by
    8: this license (the "Software") to use, reproduce, display, distribute,
    9: execute, and transmit the Software, and to prepare derivative works of the
   10: Software, and to permit third-parties to whom the Software is furnished to
   11: do so, all subject to the following:
   12:
   13: The copyright notices in the Software and this entire statement, including
   14: the above license grant, this restriction and the following disclaimer,
   15: must be included in all copies of the Software, in whole or in part, and
   16: all derivative works of the Software, unless such copies or derivative
   17: works are solely in the form of machine-executable object code generated by
   18: a source language processor.
   19:
   20: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   21: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   22: FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
   23: SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
   24: FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
   25: ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   26: DEALINGS IN THE SOFTWARE.
   27: */
   28:
   29: #ifndef SPT_UUID_H
   30: #define SPT_UUID_H
   31:
   32: #if defined( ARDUINO )
   33: #include "../StandardCplusplus/iostream"
   34: #include "../StandardCplusplus/string"
   35: #else
   36: #include <iostream>
   37: #include <string>
   38: #endif
   39:
   40: namespace spt
   41: {
   42:   /**
   43:    * @brief A class that represents a UUID/GUID
   44:    *
   45:    * A UUID is an identifier that is unique across both space and time,
   46:    * with respect to the space of all UUIDs. Since a UUID is a fixed
   47:    * size and contains a time field, it is possible for values to
   48:    * rollover (around A.D. 3400, depending on the specific algorithm
   49:    * used). A UUID can be used for multiple purposes, from tagging
   50:    * objects with an extremely short lifetime, to reliably identifying
   51:    * very persistent objects across a network.
   52:    *
   53:    * This class implements a Universal Unique Identifier,
   54:    * as specified in Appendix A of the DCE 1.1 Remote Procedure
   55:    * Call Specification (http://www.opengroup.org/onlinepubs/9629399/),
   56:    * RFC 2518 (WebDAV), section 6.4.1 and the UUIDs and GUIDs internet
   57:    * draft by Leach/Salz from February, 1998
   58:    * (http://www.ics.uci.edu/~ejw/authoring/uuid-guid/draft-leach-uuids-guids-01.txt)
   59:    * and also http://tools.ietf.org/html/draft-mealling-uuid-urn-05
   60:    */
   61:   class UUID
   62:   {
   63:   public:
   64:     enum Version
   65:     {
   66:       UUID_TIME_BASED = 0x01,
   67:       UUID_DCE_UID    = 0x02,
   68:       UUID_NAME_BASED = 0x03,
   69:       UUID_RANDOM     = 0x04
   70:     };
   71:
   72:     /// Creates a nil (all zero) UUID.
   73:     UUID();
   74:
   75:     /// Copy constructor.
   76:     UUID( const UUID& uuid );
   77:
   78:     /// Parses the UUID from a string.
   79:     explicit UUID( const std::string& uuid );
   80:
   81:     /// Parses the UUID from a char array.
   82:     explicit UUID( const char* uuid );
   83:
   84:     /// Destroys the UUID.
   85:     ~UUID();
   86:
   87:     /// Assignment operator.
   88:     UUID& operator = ( const UUID& uuid );
   89:
   90:     /**
   91:      * @brief Tries to interpret the given string as an UUID.
   92:      * @param uuid The value to parse
   93:      * @return If the UUID is syntactically valid, assigns the
   94:      *   members and returns true. Otherwise leaves the
   95:      *   object unchanged and returns false.
   96:      */
   97:     bool parse( const std::string& uuid );
   98:
   99:     /**
  100:      * @brief Returns a string representation of the UUID
  101:      * consisting of groups of hexadecimal digits separated by hyphens.
  102:      */
  103:     std::string toString() const;
  104:
  105:     /**
  106:      * @brief Copies the UUID (16 bytes) from a buffer or byte array.
  107:      * The UUID fields are expected to be stored in network byte order.
  108:      * @param buffer The buffer need not be aligned.
  109:      */
  110:     void copyFrom( const char* buffer );
  111:
  112:     /**
  113:      * @brief Copies the UUID to the buffer.
  114:      * The fields are in network byte order. The buffer need not be aligned.
  115:      * @param buffer There must be room for at least 16 bytes.
  116:      */
  117:     void copyTo( char* buffer ) const;
  118:
  119:     /// Returns the version of the UUID.
  120:     Version version() const;
  121:
  122:     /**
  123:      * @brief Returns the variant number of the UUID:
  124:      * @return
  125:      *   - 0 reserved for NCS backward compatibility
  126:      *   - 2 the Leach-Salz variant (used by this class)
  127:      *   - 6 reserved, Microsoft Corporation backward compatibility
  128:      *   - 7 reserved for future definition
  129:      */
  130:     int variant() const;
  131:
  132:     bool operator == ( const UUID& uuid ) const;
  133:     bool operator != ( const UUID& uuid ) const;
  134:     bool operator <  ( const UUID& uuid ) const;
  135:     bool operator <= ( const UUID& uuid ) const;
  136:     bool operator >  ( const UUID& uuid ) const;
  137:     bool operator >= ( const UUID& uuid ) const;
  138:
  139:     /// @return Returns true if the UUID is nil (in other words, consists of all zeros).
  140:     bool isNull() const;
  141:
  142:     /// Returns a null/nil UUID.
  143:     static const UUID& null();
  144:
  145:     /// Returns the namespace identifier for the DNS namespace.
  146:     static const UUID& dns();
  147:
  148:     /// Returns the namespace identifier for the URI (former URL) namespace.
  149:     static const UUID& uri();
  150:
  151:     /// Returns the namespace identifier for the OID namespace.
  152:     static const UUID& oid();
  153:
  154:     /// Returns the namespace identifier for the X500 namespace.
  155:     static const UUID& x500();
  156:
  157:     /// Generate a time based UUID instance
  158:     static const UUID create();
  159:
  160:     /**
  161:      * @brief Initialise the UUID engine.  On application start,
  162:      * invoke with the current MAC address.
  163:      * @param node The MAC address.
  164:      */
  165:     static void init( uint8_t node[6] );
  166:
  167:   protected:
  168:     UUID( uint32_t timeLow, uint32_t timeMid, uint32_t timeHiAndVersion,
  169:       uint16_t clockSeq, uint8_t node[6] );
  170:
  171:     UUID( const char* bytes, Version version );
  172:     int compare( const UUID& uuid ) const;
  173:     static void appendHex( std::string& str, uint8_t n );
  174:     static void appendHex( std::string& str, uint16_t n );
  175:     static void appendHex( std::string& str, uint32_t n );
  176:     static uint8_t nibble( char hex );
  177:     void fromNetwork();
  178:     void toNetwork();
  179:     static uint32_t randomNumber( int32_t input );
  180:
  181:   private:
  182:     uint32_t timeLow;
  183:     uint16_t timeMid;
  184:     uint16_t timeHiAndVersion;
  185:     uint16_t clockSeq;
  186:     uint8_t node[6];
  187:   };
  188:
  189:
  190:   /// Serialise the string representation of the uuid into the output stream
  191:   inline std::ostream& operator << ( std::ostream& os, const UUID& uuid )
  192:   {
  193:     os << uuid.toString();
  194:     return os;
  195:   }
  196:
  197:
  198:   /// Append the string representation of the uuid to the specified string
  199:   inline std::string& operator += ( std::string& str, const UUID& uuid )
  200:   {
  201:     return str.append( uuid.toString() );
  202:   }
  203:
  204:
  205:   inline bool UUID::operator == (const UUID& uuid) const
  206:   {
  207:     return compare(uuid) == 0;
  208:   }
  209:
  210:
  211:   inline bool UUID::operator != (const UUID& uuid) const
  212:   {
  213:     return compare(uuid) != 0;
  214:   }
  215:
  216:
  217:   inline bool UUID::operator < (const UUID& uuid) const
  218:   {
  219:     return compare(uuid) < 0;
  220:   }
  221:
  222:
  223:   inline bool UUID::operator <= (const UUID& uuid) const
  224:   {
  225:     return compare(uuid) <= 0;
  226:   }
  227:
  228:
  229:   inline bool UUID::operator > (const UUID& uuid) const
  230:   {
  231:     return compare(uuid) > 0;
  232:   }
  233:
  234:
  235:   inline bool UUID::operator >= (const UUID& uuid) const
  236:   {
  237:     return compare(uuid) >= 0;
  238:   }
  239:
  240:
  241:   inline UUID::Version UUID::version() const
  242:   {
  243:     return Version( timeHiAndVersion >> 12 );
  244:   }
  245:
  246:
  247:   inline bool UUID::isNull() const
  248:   {
  249:     return compare( null() ) == 0;
  250:   }
  251:
  252: } // namespace spt
  253:
  254: #endif // SPT_UUID_H



UUID.cpp

The implementation of the UUID class.

    1: /*
    2: Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
    3: and Contributors.
    4:
    5: Permission is hereby granted, free of charge, to any person or organization
    6: obtaining a copy of the software and accompanying documentation covered by
    7: this license (the "Software") to use, reproduce, display, distribute,
    8: execute, and transmit the Software, and to prepare derivative works of the
    9: Software, and to permit third-parties to whom the Software is furnished to
   10: do so, all subject to the following:
   11:
   12: The copyright notices in the Software and this entire statement, including
   13: the above license grant, this restriction and the following disclaimer,
   14: must be included in all copies of the Software, in whole or in part, and
   15: all derivative works of the Software, unless such copies or derivative
   16: works are solely in the form of machine-executable object code generated by
   17: a source language processor.
   18:
   19: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   20: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   21: FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
   22: SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
   23: FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
   24: ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   25: DEALINGS IN THE SOFTWARE.
   26: */
   27:
   28: #include "UUID.h"
   29: #include "ByteOrder.h"
   30:
   31: #if defined( ARDUINO )
   32: #include "../StandardCplusplus/algorithm"
   33: #include "../StandardCplusplus/cstring"
   34: #include "../StandardCplusplus/string"
   35: #include "DateTime.h"
   36: #else
   37: #include <algorithm>
   38: #include <cstring>
   39: #include <string>
   40: #include <net/DateTime.h>
   41: #endif
   42:
   43: namespace spt
   44: {
   45:   namespace data
   46:   {
   47:     static uint8_t mac[6];
   48:     static bool UUIDInitialised = false;
   49:   }
   50: }
   51:
   52:
   53: using spt::ByteOrder;
   54: using spt::UUID;
   55: using std::string;
   56:
   57:
   58: UUID::UUID():  timeLow( 0 ),  timeMid( 0 ), timeHiAndVersion( 0 ), clockSeq( 0 )
   59: {
   60:   memset( node, 0, sizeof( node ) );
   61: }
   62:
   63:
   64: UUID::UUID( const UUID& uuid ):
   65:   timeLow( uuid.timeLow ), timeMid( uuid.timeMid ),
   66:   timeHiAndVersion( uuid.timeHiAndVersion ), clockSeq( uuid.clockSeq )
   67: {
   68:   memcpy( node, uuid.node, sizeof( node ) );
   69: }
   70:
   71:
   72: UUID::UUID( const string& uuid )
   73: {
   74:   parse( uuid );
   75: }
   76:
   77:  
   78: UUID::UUID( const char* uuid )
   79: {
   80:   parse( string( uuid ) );
   81: }
   82:
   83:
   84: UUID::UUID( uint32_t tl, uint32_t tm, uint32_t thv, uint16_t cs, uint8_t n[6] ):
   85:   timeLow( tl ), timeMid( tm ), timeHiAndVersion( thv ), clockSeq( cs )
   86: {
   87:   memcpy( node, n, sizeof( node ) );
   88: }
   89:
   90:
   91: UUID::UUID( const char* bytes, Version version )
   92: {
   93:   uint32_t i32;
   94:   uint16_t i16;
   95:
   96:   memcpy( &i32, bytes, sizeof(i32) );
   97:   timeLow = ByteOrder::fromNetwork(i32);
   98:   bytes += sizeof(i32);
   99:
  100:   memcpy( &i16, bytes, sizeof(i16) );
  101:   timeMid = ByteOrder::fromNetwork(i16);
  102:   bytes += sizeof(i16);
  103:
  104:   memcpy( &i16, bytes, sizeof(i16) );
  105:   timeHiAndVersion = ByteOrder::fromNetwork(i16);
  106:   bytes += sizeof(i16);
  107:
  108:   memcpy( &i16, bytes, sizeof(i16) );
  109:   clockSeq = ByteOrder::fromNetwork(i16);
  110:   bytes += sizeof(i16);
  111:
  112:   memcpy( node, bytes, sizeof(node) );
  113:
  114:   timeHiAndVersion &= 0x0FFF;
  115:   timeHiAndVersion |= ( version << 12 );
  116:   clockSeq &= 0x3FFF;
  117:   clockSeq |= 0x8000;
  118: }
  119:
  120:
  121: UUID::~UUID() {}
  122:
  123:
  124: UUID& UUID::operator = ( const UUID& uuid )
  125: {
  126:   if ( &uuid != this )
  127:   {
  128:     timeLow = uuid.timeLow;
  129:     timeMid = uuid.timeMid;
  130:     timeHiAndVersion = uuid.timeHiAndVersion;
  131:     clockSeq = uuid.clockSeq;
  132:     memcpy( node, uuid.node, sizeof( node ) );
  133:   }
  134:
  135:   return *this;
  136: }
  137:
  138:
  139: bool UUID::parse( const string& uuid )
  140: {
  141:   if ( uuid.size() < 32 ) return false;
  142:
  143:   bool haveHyphens = false;
  144:   if ( uuid[8] == '-' && uuid[13] == '-' && uuid[18] == '-' && uuid[23] == '-' )
  145:   {
  146:     if ( uuid.size() >= 36 )  haveHyphens = true;
  147:     else return false;
  148:   }
  149:  
  150:   string::const_iterator it = uuid.begin();
  151:   timeLow = 0;
  152:
  153:   for ( int i = 0; i < 8; ++i )
  154:   {
  155:     timeLow = (timeLow << 4) | nibble(*it++);
  156:   }
  157:   if ( haveHyphens ) ++it;
  158:
  159:   timeMid = 0;
  160:   for ( int i = 0; i < 4; ++i )
  161:   {
  162:     timeMid = (timeMid << 4) | nibble(*it++);
  163:   }
  164:   if ( haveHyphens ) ++it;
  165:
  166:   timeHiAndVersion = 0;
  167:   for ( int i = 0; i < 4; ++i )
  168:   {
  169:     timeHiAndVersion = (timeHiAndVersion << 4) | nibble(*it++);
  170:   }
  171:   if ( haveHyphens ) ++it;
  172:
  173:   clockSeq = 0;
  174:   for ( int i = 0; i < 4; ++i )
  175:   {
  176:     clockSeq = (clockSeq << 4) | nibble(*it++);
  177:   }
  178:   if ( haveHyphens ) ++it;
  179:
  180:   for ( int i = 0; i < 6; ++i )
  181:   {
  182:     node[i] = (nibble(*it++) << 4) | nibble(*it++) ;
  183:   }
  184:
  185:   return true;
  186: }
  187:
  188:
  189: string UUID::toString() const
  190: {
  191:   string result;
  192:   result.reserve( 36 );
  193:
  194:   appendHex( result, timeLow );
  195:   result += '-';
  196:   appendHex( result, timeMid );
  197:   result += '-';
  198:   appendHex( result, timeHiAndVersion );
  199:   result += '-';
  200:   appendHex( result, clockSeq );
  201:   result += '-';
  202:   for ( unsigned int i = 0; i < sizeof(node); ++i ) appendHex( result, node[i] );
  203:
  204:   return result;
  205: }
  206:
  207:
  208: void UUID::copyFrom( const char* buffer )
  209: {
  210:   uint32_t i32;
  211:   uint16_t i16;
  212:
  213:   memcpy( &i32, buffer, sizeof(i32) );
  214:   timeLow = ByteOrder::fromNetwork( i32 );
  215:   buffer += sizeof(i32);
  216:
  217:   memcpy( &i16, buffer, sizeof(i16) );
  218:   timeMid = ByteOrder::fromNetwork( i16 );
  219:   buffer += sizeof(i16);
  220:
  221:   memcpy( &i16, buffer, sizeof(i16) );
  222:   timeHiAndVersion = ByteOrder::fromNetwork(i16);
  223:   buffer += sizeof(i16);
  224:
  225:   memcpy( &i16, buffer, sizeof(i16) );
  226:   clockSeq = ByteOrder::fromNetwork(i16);
  227:   buffer += sizeof(i16);
  228:
  229:   memcpy( node, buffer, sizeof(node) );
  230: }
  231:
  232:
  233: void UUID::copyTo( char* buffer ) const
  234: {
  235:   uint32_t i32 = ByteOrder::toNetwork( timeLow );
  236:   memcpy( buffer, &i32, sizeof(i32) );
  237:   buffer += sizeof(i32);
  238:
  239:   uint16_t i16 = ByteOrder::toNetwork( timeMid );
  240:   memcpy( buffer, &i16, sizeof(i16) );
  241:   buffer += sizeof(i16);
  242:
  243:   i16 = ByteOrder::toNetwork( timeHiAndVersion );
  244:   memcpy( buffer, &i16, sizeof(i16) );
  245:   buffer += sizeof(i16);
  246:
  247:   i16 = ByteOrder::toNetwork( clockSeq );
  248:   memcpy( buffer, &i16, sizeof(i16) );
  249:   buffer += sizeof(i16);
  250:   memcpy( buffer, node, sizeof(node) );
  251: }
  252:
  253:
  254: int UUID::variant() const
  255: {
  256:   int v = clockSeq >> 13;
  257:   if ( (v & 6) == 6 ) return v;
  258:   else if ( v & 4 ) return 2;
  259:   else return 0;
  260: }
  261:
  262:
  263: int UUID::compare( const UUID& uuid ) const
  264: {
  265:   if ( timeLow != uuid.timeLow ) return timeLow < uuid.timeLow ? -1 : 1;
  266:   if ( timeMid != uuid.timeMid ) return timeMid < uuid.timeMid ? -1 : 1;
  267:   if ( timeHiAndVersion != uuid.timeHiAndVersion ) return timeHiAndVersion < uuid.timeHiAndVersion ? -1 : 1;
  268:   if ( clockSeq != uuid.clockSeq ) return clockSeq < uuid.clockSeq ? -1 : 1;
  269:
  270:   for ( unsigned int i = 0; i < sizeof(node); ++i )
  271:   {
  272:     if (node[i] < uuid.node[i]) return -1;
  273:     else if (node[i] > uuid.node[i]) return 1;
  274:   }
  275:
  276:   return 0;
  277: }
  278:
  279:
  280: void UUID::appendHex( string& str, uint8_t n )
  281: {
  282:   static const char* digits = "0123456789abcdef";
  283:   str += digits[(n >> 4) & 0xF];
  284:   str += digits[n & 0xF];
  285: }
  286:
  287:
  288: void UUID::appendHex( string& str, uint16_t n )
  289: {
  290:   appendHex( str, uint8_t( n >> 8 ) );
  291:   appendHex( str, uint8_t( n & 0xFF ) );
  292: }
  293:
  294:
  295: void UUID::appendHex( string& str, uint32_t n )
  296: {
  297:   appendHex( str, uint16_t( n >> 16 ) );
  298:   appendHex( str, uint16_t( n & 0xFFFF ) );
  299: }
  300:
  301:
  302: uint8_t UUID::nibble( char hex )
  303: {
  304:   if ( hex >= 'a' && hex <= 'f' ) return uint8_t( hex - 'a' + 10 );
  305:   else if ( hex >= 'A' && hex <= 'F' ) return uint8_t( hex - 'A' + 10 );
  306:   else if ( hex >= '0' && hex <= '9' ) return uint8_t( hex - '0' );
  307:   else return uint8_t( 0 );
  308: }
  309:
  310:
  311: void UUID::fromNetwork()
  312: {
  313:   timeLow = ByteOrder::fromNetwork( timeLow );
  314:   timeMid = ByteOrder::fromNetwork( timeMid );
  315:   timeHiAndVersion = ByteOrder::fromNetwork( timeHiAndVersion );
  316:   clockSeq = ByteOrder::fromNetwork( clockSeq );
  317: }
  318:
  319:
  320: void UUID::toNetwork()
  321: {
  322:   timeLow = ByteOrder::toNetwork( timeLow );
  323:   timeMid = ByteOrder::toNetwork( timeMid );
  324:   timeHiAndVersion = ByteOrder::toNetwork( timeHiAndVersion );
  325:   clockSeq = ByteOrder::toNetwork( clockSeq );
  326: }
  327:
  328:
  329: uint32_t UUID::randomNumber( int32_t x )
  330: {
  331:   int32_t hi, lo;
  332:
  333:   if ( x == 0 ) x = 123459876;
  334:   hi = x / 127773;
  335:   lo = x % 127773;
  336:   x = 16807 * lo - 2836 * hi;
  337:   if ( x < 0 ) x += 0x7FFFFFFF;
  338:
  339:   return x;
  340: }
  341:
  342:
  343: namespace
  344: {
  345:   static UUID uuidNull;
  346:   static UUID uuidDNS( "6ba7b810-9dad-11d1-80b4-00c04fd430c8" );
  347:   static UUID uuidURI( "6ba7b811-9dad-11d1-80b4-00c04fd430c8" );
  348:   static UUID uuidOID( "6ba7b812-9dad-11d1-80b4-00c04fd430c8" );
  349:   static UUID uuidX500( "6ba7b814-9dad-11d1-80b4-00c04fd430c8" );
  350: }
  351:
  352:
  353: const UUID& UUID::null()
  354: {
  355:   return uuidNull;
  356: }
  357:
  358:
  359: const UUID& UUID::dns()
  360: {
  361:   return uuidDNS;
  362: }
  363:
  364:  
  365: const UUID& UUID::uri()
  366: {
  367:   return uuidURI;
  368: }
  369:
  370:
  371: const UUID& UUID::oid()
  372: {
  373:   return uuidOID;
  374: }
  375:
  376:
  377: const UUID& UUID::x500()
  378: {
  379:   return uuidX500;
  380: }
  381:
  382:
  383: const UUID UUID::create()
  384: {
  385:   using spt::net::DateTime;
  386:   int64_t millis = DateTime::singleton().currentTimeMillis();
  387:
  388:   uint32_t timeLow = uint32_t( millis & 0xFFFFFFFF );
  389:   uint16_t timeMid = uint16_t( ( millis >> 32 ) & 0xFFFF );
  390:   uint16_t timeHiAndVersion = uint16_t( ( millis >> 48 ) & 0x0FFF ) + ( UUID::UUID_TIME_BASED << 12 );
  391:   uint16_t clockSeq = ( uint16_t( randomNumber( timeLow ) >> 4 ) & 0x3FFF) | 0x8000;
  392:
  393:   return UUID( timeLow, timeMid, timeHiAndVersion, clockSeq, spt::data::mac );
  394: }
  395:
  396:
  397: void UUID::init( uint8_t node[6] )
  398: {
  399:   if ( ! spt::data::UUIDInitialised )
  400:   {
  401:     for ( int i = 0; i < 6; ++i ) spt::data::mac[i] = node[i];
  402:     spt::data::UUIDInitialised = true;
  403:   }
  404: }



UUIDTest.cpp

The unit test suite for the UUID class that runs on the Arduino board.

    1: #if defined( ARDUINO )
    2: #include "tut.hpp"
    3: #include "UUID.h"
    4: #else
    5: #include <tut/tut.hpp>
    6: #include <UUID.h>
    7: #endif
    8:
    9: using spt::UUID;
   10:
   11: namespace tut
   12: {
   13:   struct UUIDTestData {};
   14:
   15:   typedef test_group<UUIDTestData> UUIDTestGroup;
   16:   typedef UUIDTestGroup::object UUIDTest;
   17:   UUIDTestGroup uuidTestGroup( "UUID test suite" );
   18:
   19:   template<>
   20:   template<>
   21:   void UUIDTest::test<1>()
   22:   {
   23:     set_test_name( "empty" );
   24:     UUID uuid;
   25:     ensure( "Empty UUID invalid", uuid.toString() == "00000000-0000-0000-0000-000000000000" );
   26:   }
   27:
   28:   template<>
   29:   template<>
   30:   void UUIDTest::test<2>()
   31:   {
   32:     set_test_name( "parse" );
   33:
   34:     UUID uuid("6ba7b810-9dad-11d1-80b4-00c04fd430c8");
   35:     ensure( "Constructed uuid not same", uuid.toString() == "6ba7b810-9dad-11d1-80b4-00c04fd430c8" );
   36:
   37:     uuid.parse( "6BA7B810-9DAD-11D1-80B4-00C04FD430C8" );
   38:     ensure( "Second parsed uuid not same", uuid.toString() == "6ba7b810-9dad-11d1-80b4-00c04fd430c8" );
   39:
   40:     uuid.parse( "6BA7B8109DAD11D180B400C04FD430C8" );
   41:     ensure( "UUID without dashes not parsed", uuid.toString() == "6ba7b810-9dad-11d1-80b4-00c04fd430c8" );
   42:   }
   43:
   44:   template<>
   45:   template<>
   46:   void UUIDTest::test<3>()
   47:   {
   48:     set_test_name( "buffer" );
   49:
   50:     UUID uuid( "6ba7b810-9dad-11d1-80b4-00c04fd430c8" );
   51:     char buffer[16];
   52:     uuid.copyTo( buffer );
   53:
   54:     UUID uuid2;
   55:     uuid2.copyFrom( buffer );
   56:     ensure( "UUID from buffer not same", uuid2.toString() == "6ba7b810-9dad-11d1-80b4-00c04fd430c8" );
   57:   }
   58:
   59:   template<>
   60:   template<>
   61:   void UUIDTest::test<4>()
   62:   {
   63:     set_test_name( "compare" );
   64:
   65:     UUID null;
   66:     ensure( null.isNull());
   67:     ensure( UUID::null().isNull() );
   68:
   69:     UUID uuid1 = null;
   70:     UUID uuid2;
   71:     ensure( uuid1.isNull() );
   72:     ensure( uuid1 == null );
   73:     ensure( !(uuid1 != null ) );
   74:     ensure( uuid1 >= null );
   75:     ensure( uuid1 <= null );
   76:     ensure( !(uuid1 > null ) );
   77:     ensure( !(uuid1 < null ) );
   78:     ensure( uuid1.toString() == "00000000-0000-0000-0000-000000000000" );
   79:
   80:     uuid1 = UUID::dns();
   81:     ensure( !uuid1.isNull() );
   82:     ensure( uuid1 != null );
   83:     ensure( !(uuid1 == null ) );
   84:     ensure( uuid1 >= null );
   85:     ensure( !(uuid1 <= null ) );
   86:     ensure( uuid1 > null );
   87:     ensure( !(uuid1 < null ) );
   88:     ensure( uuid1.toString() == "6ba7b810-9dad-11d1-80b4-00c04fd430c8" );
   89:
   90:     ensure( null != uuid1 );
   91:     ensure( !(null == uuid1 ) );
   92:     ensure( !(null >= uuid1 ) );
   93:     ensure( null <= uuid1 );
   94:     ensure( !(null > uuid1 ) );
   95:     ensure( null < uuid1 );
   96:
   97:     uuid2 = uuid1;
   98:     ensure( uuid2 == uuid1 );
   99:     ensure( !(uuid2 != uuid1 ) );
  100:     ensure( uuid2 >= uuid1 );
  101:     ensure( uuid2 <= uuid1 );
  102:     ensure( !(uuid2 > uuid1 ) );
  103:     ensure( !(uuid2 < uuid1 ) );
  104:   }
  105:
  106:   template<>
  107:   template<>
  108:   void UUIDTest::test<5>()
  109:   {
  110:     set_test_name( "version" );
  111:
  112:     UUID uuid( "db4fa7e9-9e62-4597-99e0-b1ec0b59800e" );
  113:     UUID::Version v = uuid.version();
  114:     ensure( v == UUID::UUID_RANDOM );
  115:
  116:     uuid.parse( "6ba7b810-9dad-11d1-80b4-00c04fd430c8" );
  117:     v = uuid.version();
  118:     ensure( v == UUID::UUID_TIME_BASED );
  119:
  120:     uuid.parse( "d2ee4220-3625-11d9-9669-0800200c9a66" );
  121:     v = uuid.version();
  122:     ensure( v == UUID::UUID_TIME_BASED );
  123:
  124:     uuid.parse( "360d3652-4411-4786-bbe6-b9675b548559" );
  125:     v = uuid.version();
  126:     ensure( v == UUID::UUID_RANDOM );
  127:   }
  128:
  129:   template<>
  130:   template<>
  131:   void UUIDTest::test<6>()
  132:   {
  133:     set_test_name( "variant" );
  134:
  135:     UUID uuid( "db4fa7e9-9e62-4597-99e0-b1ec0b59800e" );
  136:     int v = uuid.variant();
  137:     ensure(  v == 2 );
  138:
  139:     uuid.parse( "6ba7b810-9dad-11d1-80b4-00c04fd430c8" );
  140:     v = uuid.variant();
  141:     ensure( v == 2 );
  142:
  143:     uuid.parse( "d2ee4220-3625-11d9-9669-0800200c9a66" );
  144:     v = uuid.variant();
  145:     ensure( v == 2 );
  146:
  147:     uuid.parse( "360d3652-4411-4786-bbe6-b9675b548559" );
  148:     v = uuid.variant();
  149:     ensure( v == 2 );
  150:   }
  151:
  152:   template<>
  153:   template<>
  154:   void UUIDTest::test<7>()
  155:   {
  156:     set_test_name( "invalid" );
  157:
  158:     UUID uuid;
  159:     ensure( uuid.parse("6BA7B810-9DAD-11D1-80B4-00C04FD430C8" ) );
  160:     ensure( uuid.toString() == "6ba7b810-9dad-11d1-80b4-00c04fd430c8" );
  161:
  162:     UUID notUuid;
  163:     ensure( !notUuid.parse( "not a uuid" ) );
  164:     ensure( notUuid.isNull() );
  165:   }
  166: }