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