00001 00031 #ifndef LL_LLUUID_H 00032 #define LL_LLUUID_H 00033 00034 #include <iostream> 00035 #include <set> 00036 #include "stdtypes.h" 00037 00038 const S32 UUID_BYTES = 16; 00039 const S32 UUID_WORDS = 4; 00040 const S32 UUID_STR_LENGTH = 37; // actually wrong, should be 36 and use size below 00041 const S32 UUID_STR_SIZE = 37; 00042 const S32 UUID_BASE85_LENGTH = 21; // including the trailing NULL. 00043 00044 struct uuid_time_t { 00045 U32 high; 00046 U32 low; 00047 }; 00048 00049 class LLUUID 00050 { 00051 public: 00052 // 00053 // CREATORS 00054 // 00055 LLUUID(); 00056 explicit LLUUID(const char *in_string); // Convert from string. 00057 explicit LLUUID(const std::string& in_string); // Convert from string. 00058 LLUUID(const LLUUID &in); 00059 LLUUID &operator=(const LLUUID &rhs); 00060 00061 ~LLUUID(); 00062 00063 // 00064 // MANIPULATORS 00065 // 00066 void generate(); // Generate a new UUID 00067 BOOL set(const char *in_string, BOOL emit = TRUE); // Convert from string, if emit is FALSE, do not emit warnings 00068 BOOL set(const std::string& in_string, BOOL emit = TRUE); // Convert from string, if emit is FALSE, do not emit warnings 00069 void setNull(); // Faster than setting to LLUUID::null. 00070 00071 S32 cmpTime(uuid_time_t *t1, uuid_time_t *t2); 00072 static void getSystemTime(uuid_time_t *timestamp); 00073 void getCurrentTime(uuid_time_t *timestamp); 00074 00075 // 00076 // ACCESSORS 00077 // 00078 BOOL isNull() const; // Faster than comparing to LLUUID::null. 00079 BOOL notNull() const; // Faster than comparing to LLUUID::null. 00080 // JC: This is dangerous. It allows UUIDs to be cast automatically 00081 // to integers, among other things. Use isNull() or notNull(). 00082 // operator bool() const; 00083 00084 // JC: These must return real bool's (not BOOLs) or else use of the STL 00085 // will generate bool-to-int performance warnings. 00086 bool operator==(const LLUUID &rhs) const; 00087 bool operator!=(const LLUUID &rhs) const; 00088 bool operator<(const LLUUID &rhs) const; 00089 bool operator>(const LLUUID &rhs) const; 00090 00091 // xor functions. Useful since any two random uuids xored together 00092 // will yield a determinate third random unique id that can be 00093 // used as a key in a single uuid that represents 2. 00094 const LLUUID& operator^=(const LLUUID& rhs); 00095 LLUUID operator^(const LLUUID& rhs) const; 00096 00097 // similar to functions above, but not invertible 00098 // yields a third random UUID that can be reproduced from the two inputs 00099 // but which, given the result and one of the inputs can't be used to 00100 // deduce the other input 00101 LLUUID combine(const LLUUID& other) const; 00102 void combine(const LLUUID& other, LLUUID& result) const; 00103 00104 friend std::ostream& operator<<(std::ostream& s, const LLUUID &uuid); 00105 friend std::istream& operator>>(std::istream& s, LLUUID &uuid); 00106 00107 void toString(char *out) const; // Does not allocate memory, needs 36 characters (including \0) 00108 void toCompressedString(char *out) const; // Does not allocate memory, needs 17 characters (including \0) 00109 00110 std::string asString() const; 00111 std::string getString() const; 00112 00113 U16 getCRC16() const; 00114 U32 getCRC32() const; 00115 00116 static BOOL validate(const std::string& in_string); // Validate that the UUID string is legal. 00117 static BOOL validate(const char *in_string); // Validate that the UUID string is legal. 00118 00119 static const LLUUID null; 00120 00121 static U32 getRandomSeed(); 00122 static S32 getNodeID(unsigned char * node_id); 00123 00124 static BOOL parseUUID(const char* buf, LLUUID* value); 00125 00126 U8 mData[UUID_BYTES]; 00127 }; 00128 00129 00130 // Construct 00131 inline LLUUID::LLUUID() 00132 { 00133 setNull(); 00134 } 00135 00136 00137 // Faster than copying from memory 00138 inline void LLUUID::setNull() 00139 { 00140 U32 *word = (U32 *)mData; 00141 word[0] = 0; 00142 word[1] = 0; 00143 word[2] = 0; 00144 word[3] = 0; 00145 } 00146 00147 00148 // Compare 00149 inline bool LLUUID::operator==(const LLUUID& rhs) const 00150 { 00151 U32 *tmp = (U32 *)mData; 00152 U32 *rhstmp = (U32 *)rhs.mData; 00153 // Note: binary & to avoid branching 00154 return 00155 (tmp[0] == rhstmp[0]) & 00156 (tmp[1] == rhstmp[1]) & 00157 (tmp[2] == rhstmp[2]) & 00158 (tmp[3] == rhstmp[3]); 00159 } 00160 00161 00162 inline bool LLUUID::operator!=(const LLUUID& rhs) const 00163 { 00164 U32 *tmp = (U32 *)mData; 00165 U32 *rhstmp = (U32 *)rhs.mData; 00166 // Note: binary | to avoid branching 00167 return 00168 (tmp[0] != rhstmp[0]) | 00169 (tmp[1] != rhstmp[1]) | 00170 (tmp[2] != rhstmp[2]) | 00171 (tmp[3] != rhstmp[3]); 00172 } 00173 00174 /* 00175 // JC: This is dangerous. It allows UUIDs to be cast automatically 00176 // to integers, among other things. Use isNull() or notNull(). 00177 inline LLUUID::operator bool() const 00178 { 00179 U32 *word = (U32 *)mData; 00180 return (word[0] | word[1] | word[2] | word[3]) > 0; 00181 } 00182 */ 00183 00184 inline BOOL LLUUID::notNull() const 00185 { 00186 U32 *word = (U32 *)mData; 00187 return (word[0] | word[1] | word[2] | word[3]) > 0; 00188 } 00189 00190 // Faster than == LLUUID::null because doesn't require 00191 // as much memory access. 00192 inline BOOL LLUUID::isNull() const 00193 { 00194 U32 *word = (U32 *)mData; 00195 // If all bits are zero, return !0 == TRUE 00196 return !(word[0] | word[1] | word[2] | word[3]); 00197 } 00198 00199 // Copy constructor 00200 inline LLUUID::LLUUID(const LLUUID& rhs) 00201 { 00202 U32 *tmp = (U32 *)mData; 00203 U32 *rhstmp = (U32 *)rhs.mData; 00204 tmp[0] = rhstmp[0]; 00205 tmp[1] = rhstmp[1]; 00206 tmp[2] = rhstmp[2]; 00207 tmp[3] = rhstmp[3]; 00208 } 00209 00210 inline LLUUID::~LLUUID() 00211 { 00212 } 00213 00214 // Assignment 00215 inline LLUUID& LLUUID::operator=(const LLUUID& rhs) 00216 { 00217 // No need to check the case where this==&rhs. The branch is slower than the write. 00218 U32 *tmp = (U32 *)mData; 00219 U32 *rhstmp = (U32 *)rhs.mData; 00220 tmp[0] = rhstmp[0]; 00221 tmp[1] = rhstmp[1]; 00222 tmp[2] = rhstmp[2]; 00223 tmp[3] = rhstmp[3]; 00224 00225 return *this; 00226 } 00227 00228 00229 inline LLUUID::LLUUID(const char *in_string) 00230 { 00231 if (!in_string || in_string[0] == 0) 00232 { 00233 setNull(); 00234 return; 00235 } 00236 00237 set(in_string); 00238 } 00239 00240 inline LLUUID::LLUUID(const std::string& in_string) 00241 { 00242 if (in_string.empty()) 00243 { 00244 setNull(); 00245 return; 00246 } 00247 00248 set(in_string); 00249 } 00250 00251 // IW: DON'T "optimize" these w/ U32s or you'll scoogie the sort order 00252 // IW: this will make me very sad 00253 inline bool LLUUID::operator<(const LLUUID &rhs) const 00254 { 00255 U32 i; 00256 for( i = 0; i < (UUID_BYTES - 1); i++ ) 00257 { 00258 if( mData[i] != rhs.mData[i] ) 00259 { 00260 return (mData[i] < rhs.mData[i]); 00261 } 00262 } 00263 return (mData[UUID_BYTES - 1] < rhs.mData[UUID_BYTES - 1]); 00264 } 00265 00266 inline bool LLUUID::operator>(const LLUUID &rhs) const 00267 { 00268 U32 i; 00269 for( i = 0; i < (UUID_BYTES - 1); i++ ) 00270 { 00271 if( mData[i] != rhs.mData[i] ) 00272 { 00273 return (mData[i] > rhs.mData[i]); 00274 } 00275 } 00276 return (mData[UUID_BYTES - 1] > rhs.mData[UUID_BYTES - 1]); 00277 } 00278 00279 inline U16 LLUUID::getCRC16() const 00280 { 00281 // A UUID is 16 bytes, or 8 shorts. 00282 U16 *short_data = (U16*)mData; 00283 U16 out = 0; 00284 out += short_data[0]; 00285 out += short_data[1]; 00286 out += short_data[2]; 00287 out += short_data[3]; 00288 out += short_data[4]; 00289 out += short_data[5]; 00290 out += short_data[6]; 00291 out += short_data[7]; 00292 return out; 00293 } 00294 00295 inline U32 LLUUID::getCRC32() const 00296 { 00297 U32 *tmp = (U32*)mData; 00298 return tmp[0] + tmp[1] + tmp[2] + tmp[3]; 00299 } 00300 00301 00302 // Helper structure for ordering lluuids in stl containers. 00303 // eg: std::map<LLUUID, LLWidget*, lluuid_less> widget_map; 00304 struct lluuid_less 00305 { 00306 bool operator()(const LLUUID& lhs, const LLUUID& rhs) const 00307 { 00308 return (lhs < rhs) ? true : false; 00309 } 00310 }; 00311 00312 typedef std::set<LLUUID, lluuid_less> uuid_list_t; 00313 00314 /* 00315 * Sub-classes for keeping transaction IDs and asset IDs 00316 * straight. 00317 */ 00318 typedef LLUUID LLAssetID; 00319 00320 class LLTransactionID : public LLUUID 00321 { 00322 public: 00323 LLTransactionID() : LLUUID() { } 00324 00325 static const LLTransactionID tnull; 00326 LLAssetID makeAssetID(const LLUUID& session) const; 00327 }; 00328 00329 #endif