00001
00032 #ifndef LL_LLUUIDHASHMAP_H
00033 #define LL_LLUUIDHASHMAP_H
00034
00035 #include "stdtypes.h"
00036 #include "llerror.h"
00037 #include "lluuid.h"
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 template <class DATA, int SIZE>
00117 class LLUUIDHashNode
00118 {
00119 public:
00120 LLUUIDHashNode();
00121
00122 public:
00123 S32 mCount;
00124 U8 mKey[SIZE];
00125 DATA mData[SIZE];
00126 LLUUIDHashNode<DATA, SIZE> *mNextNodep;
00127 };
00128
00129
00130
00131
00132
00133 template <class DATA, int SIZE>
00134 LLUUIDHashNode<DATA, SIZE>::LLUUIDHashNode()
00135 {
00136 mCount = 0;
00137 mNextNodep = NULL;
00138 }
00139
00140
00141 template <class DATA_TYPE, int SIZE>
00142 class LLUUIDHashMap
00143 {
00144 public:
00145
00146 LLUUIDHashMap(BOOL (*equals)(const LLUUID &uuid, const DATA_TYPE &data),
00147 const DATA_TYPE &null_data);
00148 ~LLUUIDHashMap();
00149
00150 inline DATA_TYPE &get(const LLUUID &uuid);
00151 inline BOOL check(const LLUUID &uuid) const;
00152 inline DATA_TYPE &set(const LLUUID &uuid, const DATA_TYPE &type);
00153 inline BOOL remove(const LLUUID &uuid);
00154 void removeAll();
00155
00156 inline S32 getLength() const;
00157 public:
00158 BOOL (*mEquals)(const LLUUID &uuid, const DATA_TYPE &data);
00159 LLUUIDHashNode<DATA_TYPE, SIZE> mNodes[256];
00160
00161 S32 mIterCount;
00162 protected:
00163 DATA_TYPE mNull;
00164 };
00165
00166
00167
00168
00169
00170
00171 template <class DATA_TYPE, int SIZE>
00172 LLUUIDHashMap<DATA_TYPE, SIZE>::LLUUIDHashMap(BOOL (*equals)(const LLUUID &uuid, const DATA_TYPE &data),
00173 const DATA_TYPE &null_data)
00174 : mEquals(equals),
00175 mIterCount(0),
00176 mNull(null_data)
00177 { }
00178
00179 template <class DATA_TYPE, int SIZE>
00180 LLUUIDHashMap<DATA_TYPE, SIZE>::~LLUUIDHashMap()
00181 {
00182 removeAll();
00183 }
00184
00185 template <class DATA_TYPE, int SIZE>
00186 void LLUUIDHashMap<DATA_TYPE, SIZE>::removeAll()
00187 {
00188 S32 bin;
00189 for (bin = 0; bin < 256; bin++)
00190 {
00191 LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin];
00192
00193 BOOL first = TRUE;
00194 while (nodep)
00195 {
00196 S32 i;
00197 const S32 count = nodep->mCount;
00198
00199
00200 for (i = 0; i < count; i++)
00201 {
00202 nodep->mData[i] = mNull;
00203 }
00204
00205 nodep->mCount = 0;
00206
00207
00208 LLUUIDHashNode<DATA_TYPE, SIZE>* curp = nodep;
00209 nodep = nodep->mNextNodep;
00210
00211
00212 if (first)
00213 {
00214 first = FALSE;
00215 curp->mNextNodep = NULL;
00216 }
00217 else
00218 {
00219 delete curp;
00220 }
00221 }
00222 }
00223 }
00224
00225 template <class DATA_TYPE, int SIZE>
00226 inline S32 LLUUIDHashMap<DATA_TYPE, SIZE>::getLength() const
00227 {
00228 S32 count = 0;
00229 S32 bin;
00230 for (bin = 0; bin < 256; bin++)
00231 {
00232 LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = (LLUUIDHashNode<DATA_TYPE, SIZE>*) &mNodes[bin];
00233 while (nodep)
00234 {
00235 count += nodep->mCount;
00236 nodep = nodep->mNextNodep;
00237 }
00238 }
00239 return count;
00240 }
00241
00242 template <class DATA_TYPE, int SIZE>
00243 inline DATA_TYPE &LLUUIDHashMap<DATA_TYPE, SIZE>::get(const LLUUID &uuid)
00244 {
00245 LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[uuid.mData[0]];
00246
00247
00248 const S32 second_byte = uuid.mData[1];
00249 while (nodep)
00250 {
00251 S32 i;
00252 const S32 count = nodep->mCount;
00253
00254
00255 for (i = 0; i < count; i++)
00256 {
00257 if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i]))
00258 {
00259
00260
00261 return nodep->mData[i];
00262 }
00263 }
00264
00265
00266 nodep = nodep->mNextNodep;
00267 }
00268 return mNull;
00269 }
00270
00271
00272 template <class DATA_TYPE, int SIZE>
00273 inline BOOL LLUUIDHashMap<DATA_TYPE, SIZE>::check(const LLUUID &uuid) const
00274 {
00275 const LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[uuid.mData[0]];
00276
00277
00278 const S32 second_byte = uuid.mData[1];
00279 while (nodep)
00280 {
00281 S32 i;
00282 const S32 count = nodep->mCount;
00283
00284
00285 for (i = 0; i < count; i++)
00286 {
00287 if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i]))
00288 {
00289
00290
00291 return TRUE;
00292 }
00293 }
00294
00295
00296 nodep = nodep->mNextNodep;
00297 }
00298
00299
00300 return FALSE;
00301 }
00302
00303
00304 template <class DATA_TYPE, int SIZE>
00305 inline DATA_TYPE &LLUUIDHashMap<DATA_TYPE, SIZE>::set(const LLUUID &uuid, const DATA_TYPE &data)
00306 {
00307
00308
00309
00310
00311 LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[uuid.mData[0]];
00312
00313 const S32 second_byte = uuid.mData[1];
00314 while (1)
00315 {
00316 const S32 count = nodep->mCount;
00317
00318 S32 i;
00319 for (i = 0; i < count; i++)
00320 {
00321 if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i]))
00322 {
00323
00324
00325 nodep->mData[i] = data;
00326 return nodep->mData[i];
00327 }
00328 }
00329 if (!nodep->mNextNodep)
00330 {
00331
00332 if (i < SIZE)
00333 {
00334
00335
00336 nodep->mKey[i] = second_byte;
00337 nodep->mData[i] = data;
00338 nodep->mCount++;
00339
00340 return nodep->mData[i];
00341 }
00342 else
00343 {
00344
00345 nodep->mNextNodep = new LLUUIDHashNode<DATA_TYPE, SIZE>;
00346 nodep->mNextNodep->mKey[0] = second_byte;
00347 nodep->mNextNodep->mData[0] = data;
00348 nodep->mNextNodep->mCount = 1;
00349
00350 return nodep->mNextNodep->mData[0];
00351 }
00352 }
00353
00354
00355 nodep = nodep->mNextNodep;
00356 }
00357 }
00358
00359
00360 template <class DATA_TYPE, int SIZE>
00361 inline BOOL LLUUIDHashMap<DATA_TYPE, SIZE>::remove(const LLUUID &uuid)
00362 {
00363 if (mIterCount)
00364 {
00365
00366 llerrs << "Attempted remove while an outstanding iterator in LLUUIDHashMap!" << llendl;
00367 }
00368
00369
00370
00371
00372
00373
00374 LLUUIDHashNode<DATA_TYPE, SIZE> *nodep = &mNodes[uuid.mData[0]];
00375
00376
00377 const S32 second_byte = uuid.mData[1];
00378
00379
00380 while (nodep)
00381 {
00382 const S32 count = nodep->mCount;
00383
00384 S32 i;
00385 for (i = 0; i < count; i++)
00386 {
00387 if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i]))
00388 {
00389
00390
00391
00392
00393
00394 LLUUIDHashNode<DATA_TYPE, SIZE> *prevp = &mNodes[uuid.mData[0]];
00395 LLUUIDHashNode<DATA_TYPE, SIZE> *lastp = prevp;
00396
00397
00398 while (lastp->mNextNodep)
00399 {
00400 prevp = lastp;
00401 lastp = lastp->mNextNodep;
00402 }
00403
00404
00405 nodep->mKey[i] = lastp->mKey[lastp->mCount - 1];
00406 nodep->mData[i] = lastp->mData[lastp->mCount - 1];
00407
00408
00409 lastp->mCount--;
00410 lastp->mData[lastp->mCount] = mNull;
00411
00412 if (!lastp->mCount)
00413 {
00414
00415 if (lastp != &mNodes[uuid.mData[0]])
00416 {
00417
00418
00419
00420 prevp->mNextNodep = NULL;
00421 delete lastp;
00422 }
00423 }
00424 return TRUE;
00425 }
00426 }
00427
00428
00429 nodep = nodep->mNextNodep;
00430 }
00431 return FALSE;
00432 }
00433
00434
00435
00436
00437
00438
00439 template <class DATA_TYPE, int SIZE>
00440 class LLUUIDHashMapIter
00441 {
00442 public:
00443 LLUUIDHashMapIter(LLUUIDHashMap<DATA_TYPE, SIZE> *hash_mapp);
00444 ~LLUUIDHashMapIter();
00445
00446
00447 inline void reset();
00448 inline void first();
00449 inline void next();
00450 inline BOOL done() const;
00451
00452 DATA_TYPE& operator*() const
00453 {
00454 return mCurHashNodep->mData[mCurHashNodeKey];
00455 }
00456 DATA_TYPE* operator->() const
00457 {
00458 return &(operator*());
00459 }
00460
00461 protected:
00462 LLUUIDHashMap<DATA_TYPE, SIZE> *mHashMapp;
00463 LLUUIDHashNode<DATA_TYPE, SIZE> *mCurHashNodep;
00464
00465 S32 mCurHashMapNodeNum;
00466 S32 mCurHashNodeKey;
00467
00468 DATA_TYPE mNull;
00469 };
00470
00471
00472
00473
00474
00475 template <class DATA_TYPE, int SIZE>
00476 LLUUIDHashMapIter<DATA_TYPE, SIZE>::LLUUIDHashMapIter(LLUUIDHashMap<DATA_TYPE, SIZE> *hash_mapp)
00477 {
00478 mHashMapp = hash_mapp;
00479 mCurHashNodep = NULL;
00480 mCurHashMapNodeNum = 0;
00481 mCurHashNodeKey = 0;
00482 }
00483
00484 template <class DATA_TYPE, int SIZE>
00485 LLUUIDHashMapIter<DATA_TYPE, SIZE>::~LLUUIDHashMapIter()
00486 {
00487 reset();
00488 }
00489
00490 template <class DATA_TYPE, int SIZE>
00491 inline void LLUUIDHashMapIter<DATA_TYPE, SIZE>::reset()
00492 {
00493 if (mCurHashNodep)
00494 {
00495
00496 mHashMapp->mIterCount--;
00497 mCurHashNodep = NULL;
00498 }
00499 }
00500
00501 template <class DATA_TYPE, int SIZE>
00502 inline void LLUUIDHashMapIter<DATA_TYPE, SIZE>::first()
00503 {
00504
00505 S32 i;
00506 for (i = 0; i < 256; i++)
00507 {
00508 if (mHashMapp->mNodes[i].mCount)
00509 {
00510 if (!mCurHashNodep)
00511 {
00512
00513 mHashMapp->mIterCount++;
00514 }
00515
00516 mCurHashNodep = &mHashMapp->mNodes[i];
00517 mCurHashMapNodeNum = i;
00518 mCurHashNodeKey = 0;
00519
00520 return;
00521 }
00522 }
00523
00524
00525 mCurHashNodep = NULL;
00526
00527 return;
00528 }
00529
00530 template <class DATA_TYPE, int SIZE>
00531 inline BOOL LLUUIDHashMapIter<DATA_TYPE, SIZE>::done() const
00532 {
00533 return mCurHashNodep ? FALSE : TRUE;
00534 }
00535
00536 template <class DATA_TYPE, int SIZE>
00537 inline void LLUUIDHashMapIter<DATA_TYPE, SIZE>::next()
00538 {
00539
00540 if (!mCurHashNodep)
00541 {
00542
00543 return;
00544 }
00545
00546
00547 mCurHashNodeKey++;
00548 if (mCurHashNodeKey < mCurHashNodep->mCount)
00549 {
00550
00551
00552 return;
00553 }
00554
00555
00556 mCurHashNodep = mCurHashNodep->mNextNodep;
00557 if (mCurHashNodep)
00558 {
00559
00560 mCurHashNodeKey = 0;
00561
00562 return;
00563 }
00564
00565
00566 mCurHashMapNodeNum++;
00567
00568 S32 i;
00569 for (i = mCurHashMapNodeNum; i < 256; i++)
00570 {
00571 if (mHashMapp->mNodes[i].mCount)
00572 {
00573
00574 mCurHashNodep = &mHashMapp->mNodes[i];
00575 mCurHashMapNodeNum = i;
00576 mCurHashNodeKey = 0;
00577
00578 return;
00579 }
00580 }
00581
00582
00583 mCurHashNodep = NULL;
00584 mHashMapp->mIterCount--;
00585
00586 }
00587
00588 #endif // LL_LLUUIDHASHMAP_H