opennurbs_uuid.cpp
Go to the documentation of this file.
00001 /* $NoKeywords: $ */
00002 /*
00003 //
00004 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
00005 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
00006 // McNeel & Associates.
00007 //
00008 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
00009 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
00010 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
00011 //                              
00012 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
00013 //
00015 */
00016 
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018 
00019 #if defined(ON_UUID_DECLARED_AS_CLASS)
00020 
00021 // When ON_UUID is a typdef for Microsoft 's UUID,
00022 // the Microsoft compiler handles == and !=.
00023 // When a ON_UUID is not a typedef for a Microsoft UUID,
00024 // it is declared as a class and operator== and operator!= 
00025 // need to be explicitly defined.
00026 
00027 bool ON_UUID::operator==(const ON_UUID& other) const
00028 {
00029   return (0==memcmp(this,&other,sizeof(*this)));
00030 }
00031 
00032 bool ON_UUID::operator!=(const ON_UUID& other) const
00033 {
00034   return (0!=memcmp(this,&other,sizeof(*this)));
00035 }
00036 
00037 #endif
00038 
00039 // used to map the correspondence between uuid strings and
00040 // ON_UUIDs as an array of 16 bytes.
00041 
00042 // for little endian CPUs (Intel, etc)
00043 static const int little_endian_rho[16] = {3,2,1,0, 5,4, 7,6, 8,9, 10,11,12,13,14,15};
00044 
00045 // for big endian CPUs (Motorola, MIPS, Sparc, etc.)
00046 static const int big_endian_rho[16] = {0,1,2,3, 4,5, 6,7, 8,9, 10,11,12,13,14,15};
00047 
00048  
00049 bool ON_CreateUuid( ON_UUID& new_uuid )
00050 {
00051   // See http://www.faqs.org/rfcs/rfc4122.html for uuid details.
00052 
00053 #if 0
00054   {
00055     // Use this code when testing reqires "repeatable uniqueness".
00056     // NEVER check in this code.
00057     static ON_UUID blank = {
00058       0,                                        // unsigned long  Data1;
00059       0,                                        // unsigned short Data2;
00060       0x11dc,                                   // unsigned short Data3;
00061       {0x98,0x85,0x00,0x13,0x72,0xc3,0x38,0x78} // unsigned char  Data4[8];
00062     };
00063     if ( 0 == ++blank.Data1)
00064       blank.Data2++;
00065     new_uuid = blank;
00066   }
00067   return true;
00068 
00069 #else
00070 
00071 #if defined(ON_OS_WINDOWS)
00072   // Header: Declared in Rpcdce.h.
00073   // Library: Use Rpcrt4.lib  
00074   ::UuidCreate(&new_uuid);
00075   //::UuidCreateSequential(&new_uuid); // faster but computer MAC address
00076                                        // identifies the user and some
00077                                        // customers may object.
00078   return true;
00079 #elif defined(ON_COMPILER_XCODE)
00080   // Header: #include <uuid/uuid.h>
00081   if ( ON::little_endian == ON::Endian() )
00082   {
00083     // Intel cpu mac
00084     // The uuid_generate() function returns a UUID in network or 
00085     // big-endian order.  The rest of OpenNURBS assumes that a UUID
00086     // is stored in native byte order, so we switch the byte order
00087     // of the UUID.
00088     uuid_t apple_osx_uuid;
00089     uuid_generate(apple_osx_uuid);
00090     unsigned char* dst = (unsigned char*)&new_uuid;
00091     const unsigned char* src = (const unsigned char*)&apple_osx_uuid;
00092     *dst++ = src[little_endian_rho[ 0]]; 
00093     *dst++ = src[little_endian_rho[ 1]]; 
00094     *dst++ = src[little_endian_rho[ 2]]; 
00095     *dst++ = src[little_endian_rho[ 3]]; 
00096     *dst++ = src[little_endian_rho[ 4]]; 
00097     *dst++ = src[little_endian_rho[ 5]]; 
00098     *dst++ = src[little_endian_rho[ 6]]; 
00099     *dst++ = src[little_endian_rho[ 7]]; 
00100     *dst++ = src[little_endian_rho[ 8]]; 
00101     *dst++ = src[little_endian_rho[ 9]]; 
00102     *dst++ = src[little_endian_rho[10]]; 
00103     *dst++ = src[little_endian_rho[11]]; 
00104     *dst++ = src[little_endian_rho[12]]; 
00105     *dst++ = src[little_endian_rho[13]]; 
00106     *dst++ = src[little_endian_rho[14]]; 
00107     *dst   = src[little_endian_rho[15]]; 
00108   }
00109   else
00110   {
00111     // Motorola cpu mac
00112     uuid_generate((unsigned char*)&new_uuid);
00113   }
00114 
00115   //#if defined (ON_DEBUG)
00116   //  // OS X generates version 4 UUIDs.  Check that this is still true after mangling.
00117   //  if ((new_uuid.Data3 & 0xF000) != 0x4000)
00118   //    ON_ERROR("ON_CreateUuid() failure 1");
00119   //  if (new_uuid.Data4[0] < 0x80 || new_uuid.Data4[0] >= 0xC0)
00120   //    ON_ERROR("ON_CreateUuid() failure 2");
00121   //#endif
00122   return true;
00123 #else
00124   // You must supply a way to create unique ids or you 
00125   // will not be able to write 3dm files.
00126   memset(&new_uuid,0,sizeof(ON_UUID));
00127   return false;
00128 #endif
00129 
00130 #endif
00131 }
00132 
00133  
00134 ON_UUID ON_UuidFromString( const char* sUUID )
00135 {
00136   // NOTE WELL: This code has to work on non-Windows OSs and on
00137   //            both big and little endian CPUs.  On Windows OSs
00138   //            is must return the same result as 
00139   //            Windows's UuidFromString().
00140   //
00141 
00142   // string has format like "85A08515-F383-11d3-BFE7-0010830122F0"
00143   // or like "{85A08515-F383-11d3-BFE7-0010830122F0}".  Brackets
00144   // and hyphens are optional and ignored.
00145   //
00146   // Windows users can use "guidgen" to create UUID strings.
00147 
00148   /*
00149 #if defined(ON_DEBUG) && defined(ON_OS_WINDOWS)
00150   RPC_STATUS st;
00151   union 
00152   {
00153     ON_UUID uuid;
00154     unsigned char b[16];
00155   } u1;
00156   st = UuidFromString( (unsigned char*)sUUID, &u1.uuid );
00157 #endif
00158 */
00159 
00160   static const int* rho = ( ON::big_endian == ON::Endian() ) 
00161                         ? big_endian_rho 
00162                         : little_endian_rho;
00163 
00164   union 
00165   {
00166     ON_UUID uuid;
00167     unsigned char b[16];
00168   } u;
00169   ON_BOOL32 bFailed;
00170   int bi, ci;
00171   unsigned char c;
00172   unsigned char byte_value[2];
00173 
00174   memset(&u,0,sizeof(u));
00175   //for ( bi = 0; bi < 16; bi++ ) 
00176   //  u.b[bi] = 0;
00177 
00178   bFailed = sUUID ? false : true;
00179 
00180   if ( !bFailed ) {
00181     while ( *sUUID && *sUUID <= ' ' ) // skip leading white space
00182       sUUID++;
00183     if ( *sUUID == '{' )
00184       sUUID++;
00185     for ( bi = 0; bi < 16; bi++ ) {
00186       ci = 0;
00187       byte_value[0] = 0;
00188       byte_value[1] = 0;
00189       while ( ci < 2 ) {
00190         c = *sUUID++;
00191         if ( !c ) {
00192           bFailed = true;
00193           break;
00194         }
00195         if ( c >= 'A' && c <= 'F' ) {
00196           byte_value[ci++] = (c-'A'+10);
00197         }
00198         else if ( c >= '0' && c <='9' ) {
00199           byte_value[ci++] = (c-'0');
00200         }
00201         else if ( c >= 'a' && c <= 'f' ) {
00202           byte_value[ci++] = (c-'a'+10);
00203         }
00204         else if ( c != '-' ) {
00205           bFailed = true;
00206           break;
00207         }
00208       }
00209       if ( bFailed )
00210         break;
00211       u.b[rho[bi]] = 16*byte_value[0] + byte_value[1];
00212     }
00213   }
00214 
00215   if ( bFailed ) {
00216     // 09 August 2006 John Morse
00217     // There are times when Rhino is looking for a plug-in but the SDK or command
00218     // allows the plug-in to be specified by name or UUID.  Rhino calls ON_UuidFromString()
00219     // to see if the string is a plug-in UUID so it knows if it should be comparing the string
00220     // or plug-in name when looking for a plug-in.  The ON_ERROR line makes the Rhino commands
00221     // generate an OpenNURBS message box (in DEBUG builds) when the command completes and is
00222     // a pain so I commented it out per Dale Lear.
00223     //ON_ERROR("ON_UuidFromString(): bad string passed in");
00224     u.uuid = ON_nil_uuid;
00225   }
00226 
00227 /*
00228 #if defined(ON_DEBUG) && defined(ON_OS_WINDOWS)
00229   if ( memcmp( &u.uuid, &u1.uuid, 16 ) ) {
00230     ON_ERROR("ON_UuidFromString() failed");
00231   }
00232   if ( UuidCompare( &u.uuid, &u1.uuid, &st ) ) {
00233     ON_ERROR("ON_UuidFromString() failed");
00234   }
00235   if ( ON_UuidCompare( &u.uuid, &u1.uuid ) ) {
00236     ON_ERROR("ON_UuidCompare() failed");
00237   }
00238 #endif
00239 */
00240   return u.uuid;
00241 }
00242 
00243 
00244 ON_UUID ON_UuidFromString( const wchar_t* sUUID )
00245 {
00246   wchar_t w;
00247   char s[64];
00248   int i;
00249   if( NULL == sUUID )
00250     return ON_nil_uuid;
00251   while ( *sUUID && *sUUID <= ' ' ) // skip leading white space
00252     sUUID++;
00253   if ( *sUUID == '{' )
00254     sUUID++;
00255   i = 0;
00256   while (i < 63 )
00257   {
00258     w = *sUUID++;
00259     if ( w >= 'A' && w <= 'F' )
00260       s[i++] = (char)w;
00261     else if ( w >= '0' && w <='9' )
00262       s[i++] = (char)w;
00263     else if ( w >= 'a' && w <= 'f' )
00264       s[i++] = (char)w;
00265     else if ( w != '-' ) 
00266       break;
00267   }
00268   s[i] = 0;
00269 
00270   return ON_UuidFromString(s);
00271 
00272 }
00273  
00274 ON_UuidIndex::ON_UuidIndex()
00275 {
00276   memset(this,0,sizeof(*this));
00277 }
00278 
00279 int ON_UuidIndex::CompareIdAndIndex( const ON_UuidIndex* a, const ON_UuidIndex* b )
00280 {
00281   int i;
00282   if ( !a )
00283     return (b ? -1 : 0 );
00284   if ( !b )
00285     return 1;
00286 
00287   // compare id first
00288   if ( 0 == (i = ON_UuidCompare(&a->m_id,&b->m_id)) )
00289     i = a->m_i - b->m_i;
00290 
00291   return i;
00292 }
00293 
00294 int ON_UuidIndex::CompareIndexAndId( const ON_UuidIndex* a, const ON_UuidIndex* b )
00295 {
00296   int i;
00297   if ( !a )
00298     return (b ? -1 : 0 );
00299   if ( !b )
00300     return 1;
00301 
00302   // compare index first
00303   if ( 0 == (i = a->m_i - b->m_i) )
00304     i = ON_UuidCompare(&a->m_id,&b->m_id);
00305 
00306   return i;
00307 }
00308 
00309 int ON_UuidIndex::CompareId( const ON_UuidIndex* a, const ON_UuidIndex* b )
00310 {
00311   if ( !a )
00312     return (b ? -1 : 0 );
00313   if ( !b )
00314     return 1;
00315   return ON_UuidCompare(&a->m_id,&b->m_id);
00316 }
00317 
00318 int ON_UuidIndex::CompareIndex( const ON_UuidIndex* a, const ON_UuidIndex* b )
00319 {
00320   if ( !a )
00321     return (b ? -1 : 0 );
00322   if ( !b )
00323     return 1;
00324   return a->m_i - b->m_i;
00325 }
00326 
00327 // Test code for ON_UuidCompare
00357 
00358 int ON_UuidCompare( const ON_UUID* a, const ON_UUID* b )
00359 {
00360   // NOTE WELL: This code has to work the same way
00361   //            on Windows and non-Windows OSs and on
00362   //            both big and little endian CPUs
00363   //            taking into account the way ON_UUIDs
00364   //            are read/written by ON_BinaryArchive.
00365   //
00366   //            On Windows, ::UuidCompare() must agree 
00367   //            with this function.
00368 
00369   if ( !a ) 
00370   {
00371     return b ? -1 : 0;
00372   }
00373   if ( !b )
00374     return 1;
00375 
00376   if ( a->Data1 < b->Data1 ) return -1;
00377   if ( a->Data1 > b->Data1 ) return  1;
00378 
00379   if ( a->Data2 < b->Data2 ) return -1;
00380   if ( a->Data2 > b->Data2 ) return  1;
00381 
00382   if ( a->Data3 < b->Data3 ) return -1;
00383   if ( a->Data3 > b->Data3 ) return  1;
00384   return memcmp(a->Data4,b->Data4,sizeof(a->Data4));
00385 }
00386  
00387 int ON_UuidCompare( const ON_UUID& a, const ON_UUID& b)
00388 {
00389   return ON_UuidCompare(&a,&b);
00390 }
00391 
00392 bool ON_UuidIsNil( 
00393         const ON_UUID& uuid 
00394         )
00395 {
00396   const ON__INT32* p = (const ON__INT32*)&uuid;
00397   return ( p[0] || p[1] || p[2] || p[3] ) ? false : true;
00398 }
00399 
00400 
00401 bool ON_UuidIsNotNil( 
00402         const ON_UUID& uuid 
00403         )
00404 {
00405   const ON__INT32* p = (const ON__INT32*)&uuid;
00406   return ( p[0] || p[1] || p[2] || p[3] ) ? true : false;
00407 }
00408 
00409 
00410 char* ON_UuidToString( const ON_UUID& uuid, char* s)
00411 {
00412   // s - [out]  The s[] char array must have length >= 37.  
00413   //            The returned char array will have a 36 
00414   //            character uuid in s[0..35] and a null in s[36].
00415 
00416   // NOTE WELL: 
00417   //   This code has to work on non-Windows OSs and on both big and
00418   //   little endian CPUs.  The result must satisfy
00419   //   uuid == ON_UuidFromString(ON_UuidToString(uuid,s))
00420 
00421   // 31 August 2005 Dale Lear
00422   //     Changed upper case to lower case so result is
00423   //     identical to the string returned by Windows' ::UuidToString().
00424   //static const char x[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
00425   static const char x[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
00426   static const int addhyphen[16] = {0,0,0,1, 0,1, 0,1, 0,1,  0, 0, 0, 0, 0, 0};
00427   const unsigned char* b = (const unsigned char*)&uuid;
00428   char* p;
00429   int i;
00430   
00431   static const int* rho = ( ON::big_endian == ON::Endian() ) 
00432                         ? big_endian_rho 
00433                         : little_endian_rho;
00434 
00435   // 5 December 2002 Dale Lear:
00436   //   There is either a bug in Purify (likely) or perhaps a bug in the 
00437   //   way Microsoft compiles  c>>4 when c is an unsigned char.  In any
00438   //   case, changing c to an unsigned int makes purify happy and should
00439   //   work just as well.
00440   //
00441   //unsigned char c;
00442 
00443   unsigned int c;
00444 
00445   if ( !s )
00446     return 0;
00447   p = s;
00448   for ( i = 0; i < 16; i++ ) {
00449     c = b[rho[i]];
00450     *p++ = x[c>>4];  // purify gripes here if c is an unsigned char - the code runs fine.
00451     *p++ = x[c&0x0F];
00452     if ( addhyphen[i] )
00453       *p++ = '-';
00454   }
00455   *p = 0;
00456 
00457 #if defined(ON_DEBUG)
00458   {
00459     ON_UUID u = ON_UuidFromString(s);
00460     if ( ON_UuidCompare(&u,&uuid) ) {
00461       ON_ERROR("ON_UuidToString() bug"); // <- breakpoint here
00462     }
00463   }
00464 #endif
00465 
00466   return s;
00467 }
00468 
00469 wchar_t* ON_UuidToString( const ON_UUID& uuid, wchar_t* s)
00470 {
00471   // s - [out]  The s[] char array must have length >= 37.  
00472   //            The returned char array will have a 36 
00473   //            character uuid in s[0..35] and a null in s[36].
00474 
00475   // NOTE WELL: 
00476   //   This code has to work on non-Windows OSs and on both big and
00477   //   little endian CPUs.  The result must satisfy
00478   //   uuid == ON_UuidFromString(ON_UuidToString(uuid,s))
00479   char x[37];
00480   if ( s && ON_UuidToString(uuid,x) )
00481   {
00482     int i;
00483     for (i = 0; i < 37; i++ )
00484     {
00485       s[i] = (wchar_t)x[i];
00486     }
00487   }
00488   else
00489   {
00490     s = 0;
00491   }
00492   return s;
00493 }
00494 
00495  
00496 const char* ON_UuidToString( const ON_UUID& uuid, ON_String& s )
00497 {
00498   char x[37];
00499   s = ON_UuidToString( uuid, x );
00500   return s.Array();
00501 }
00502 
00503  
00504 const wchar_t* ON_UuidToString( const ON_UUID& uuid, ON_wString& s )
00505 {
00506   wchar_t x[37];
00507   s = ON_UuidToString( uuid, x );
00508   return s.Array();
00509 }


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:27:03