00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
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
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 #ifndef id_map_INCLUDED
00145 #define id_map_INCLUDED "id_map.h"
00146
00147 #include <math.h>
00148 #include "defs.h"
00149 #include "cxx_template.h"
00150 #include "tracing.h"
00151 #include "opt_defs.h"
00152 #include "erglob.h"
00153
00154 #define MIN_TABLE_SIZE 16
00155
00156 #define CAPACITY_FACTOR 0.75
00157
00158
00159
00160 #define GROWTH_FACTOR 2.0
00161
00162 template <class NODE_TYPE, class KEY_TYPE> class ID_MAP;
00163
00164 template <class NODE_TYPE, class KEY_TYPE>
00165 class ID_MAP_HASH_ENTRY {
00166 friend class ID_MAP<NODE_TYPE, KEY_TYPE>;
00167 NODE_TYPE _node;
00168 union {
00169 KEY_TYPE _key;
00170 mINT32 _prev;
00171 };
00172 mINT32 _next;
00173
00174 #ifdef DEBUG_ID_MAP
00175 enum {
00176 IMHE_UNKNOWN,
00177 IMHE_FREE,
00178 IMHE_USED
00179 } _state;
00180 #endif // DEBUG_ID_MAP
00181 };
00182
00183 template <class NODE_TYPE, class KEY_TYPE>
00184 class ID_MAP {
00185 private:
00186 NODE_TYPE _not_found_value;
00187 BOOL _constructed;
00188 const BOOL _tracing;
00189 const BOOL _verbose;
00190 MEM_POOL *const _pool;
00191 ID_MAP_HASH_ENTRY<NODE_TYPE, KEY_TYPE> * _table;
00192
00193
00194
00195
00196
00197
00198 UINT32 _table_size;
00199 UINT32 _num_entries;
00200 mINT32 _free_list;
00201
00202
00203
00204 static UINT32 Capacity(UINT32 size)
00205 {
00206 return (UINT32) floor((double) size * CAPACITY_FACTOR);
00207 }
00208
00209
00210
00211 static UINT32 Size(UINT32 capacity)
00212 {
00213 return (UINT32) ceil((double) capacity / CAPACITY_FACTOR);
00214 }
00215
00216 void Alloc_table_space(UINT32 table_size);
00217 void Initialize_table(void);
00218
00219 mINT32 Hash(const KEY_TYPE key, const UINT32 tbl_size) const
00220 {
00221
00222 UINT32 key_uint32;
00223 if (sizeof(key) == sizeof(UINT32)) {
00224 key_uint32 = *((const UINT32 *) &key);
00225 }
00226 else if (sizeof(key) < sizeof(UINT32)) {
00227 key_uint32 = (*((const UINT32 *) &key) &
00228 ((1 << ((sizeof(key) & (sizeof(UINT32)-1)) * 8)) - 1));
00229
00230
00231
00232
00233 }
00234 else {
00235 const UINT32 *p = (const UINT32 *) &key;
00236 INT i;
00237 key_uint32 = 0;
00238 for (i = 0; i < (sizeof(key) / sizeof(UINT32)); i++) {
00239 key_uint32 = (key_uint32 << 19) + (key_uint32 >> 13);
00240 key_uint32 ^= *p++;
00241 }
00242 }
00243
00244
00245 const UINT64 multiplier = 2654435769LL;
00246
00247 mINT32 retval = (tbl_size * ((key_uint32 * multiplier) %
00248 0x100000000LL)) >> 32;
00249 return retval;
00250 }
00251
00252 void Add_to_free_list(const mINT32 idx)
00253 {
00254 Is_Trace(_tracing && _verbose,
00255 (TFile, "ID_MAP::Add_to_free_list(%d)\n", idx));
00256
00257 if (_free_list != -1) {
00258 _table[_free_list]._prev = idx;
00259 }
00260
00261 _table[idx]._next = _free_list;
00262 _table[idx]._node = _not_found_value;
00263
00264 Is_True(Check(_free_list != idx),
00265 ("ID_MAP::Add_to_free_list: Must not introduce loop"));
00266
00267 _free_list = idx;
00268
00269 }
00270
00271 void Enlarge(void);
00272
00273 void Remove_from_free_list(const mINT32 idx)
00274 {
00275 Is_Trace(_tracing && _verbose,
00276 (TFile, "ID_MAP::Remove_from_free_list(%d)\n", idx));
00277 Is_True(Check(_table[idx]._node == _not_found_value),
00278 ("ID_MAP::Remove_from_free_list: Node must be free: %ld", idx));
00279
00280 if (_free_list == idx) {
00281 _free_list = _table[idx]._next;
00282 Is_True(Check(_free_list != idx),
00283 ("ID_MAP::Remove_from_free_list: Inconsistent free list: %lu",
00284 _free_list));
00285 Is_True(Check(_table[idx]._node == _not_found_value),
00286 ("ID_MAP::Remove_from_free_list: Node must be free: %ld", idx));
00287 }
00288 else {
00289 Is_True(Check(_table[idx]._prev != -1),
00290 ("ID_MAP::Remove_from_free_list: Inconsistent free list"));
00291 Is_True(Check(_table[idx]._next != idx),
00292 ("ID_MAP::Remove_from_free_list: Loop in free list : %ld",
00293 idx));
00294 _table[_table[idx]._prev]._next = _table[idx]._next;
00295 }
00296 if (_table[idx]._next != -1) {
00297 _table[_table[idx]._next]._prev = _table[idx]._prev;
00298 _table[idx]._next = -1;
00299 }
00300 }
00301
00302 mINT32 Alloc_from_free_list(void)
00303 {
00304 Is_Trace(_tracing && _verbose,
00305 (TFile, "ID_MAP::Alloc_from_free_list()..."));
00306 Is_True(_free_list != -1,
00307 ("ID_MAP::Displace: free list must be nonempty; %lu / %lu",
00308 _num_entries, _table_size));
00309 mINT32 idx = _free_list;
00310
00311 Is_True(_table[_free_list]._node == _not_found_value,
00312 ("ID_MAP::Alloc_from_free_list: free list inconsistency"));
00313
00314 _free_list = _table[_free_list]._next;
00315
00316 Is_True(Check(idx != _free_list),
00317 ("ID_MAP::Alloc_from_free_list: loop in free list"));
00318
00319 Is_True(_table[_free_list]._node == _not_found_value,
00320 ("ID_MAP:Alloc_from_free_list: free list inconsistency"));
00321
00322 Is_Trace(_tracing && _verbose,
00323 (TFile, " returning %d\n", idx));
00324 return idx;
00325 }
00326
00327 BOOL Check(BOOL cond) const
00328 {
00329 if (!cond)
00330 Print(TFile);
00331 return cond;
00332 }
00333
00334 void Verify(void) const
00335 {
00336 #ifdef DEBUG_ID_MAP
00337 for (mINT32 idx = 0; idx < _table_size; idx++) {
00338 _table[idx]._state =
00339 ID_MAP_HASH_ENTRY<NODE_TYPE, KEY_TYPE>::IMHE_UNKNOWN;
00340 }
00341 for (idx = _free_list; idx != -1; idx = _table[idx]._next) {
00342 Is_True(Check(_table[idx]._state ==
00343 ID_MAP_HASH_ENTRY<NODE_TYPE, KEY_TYPE>::IMHE_UNKNOWN),
00344 ("ID_MAP::Verify: Loop in free list"));
00345 _table[idx]._state =
00346 ID_MAP_HASH_ENTRY<NODE_TYPE, KEY_TYPE>::IMHE_FREE;
00347 }
00348 for (idx = 0; idx < _table_size; idx++) {
00349 if (_table[idx]._state !=
00350 ID_MAP_HASH_ENTRY<NODE_TYPE, KEY_TYPE>::IMHE_FREE) {
00351
00352
00353 Is_True(Check(idx == Entry_lookup(_table[idx]._key)),
00354 ("ID_MAP::Verify: Dangling node: idx == %ld", idx));
00355 _table[idx]._state =
00356 ID_MAP_HASH_ENTRY<NODE_TYPE, KEY_TYPE>::IMHE_USED;
00357 }
00358 }
00359 #endif // DEBUG_ID_MAP
00360 }
00361
00362 mINT32 Entry_lookup(const KEY_TYPE) const;
00363
00364 public:
00365 ID_MAP(const UINT32 initial_capacity,
00366 const NODE_TYPE not_found_value,
00367 MEM_POOL *const pool,
00368 const BOOL tracing);
00369 ~ID_MAP(void);
00370
00371 void Init(void);
00372 void Init(UINT32);
00373
00374 NODE_TYPE Lookup(const KEY_TYPE) const;
00375
00376 void Insert(const KEY_TYPE, const NODE_TYPE);
00377
00378 void Delete(const KEY_TYPE);
00379
00380 void Print(FILE *) const;
00381 };
00382
00383
00384
00385
00386 template <class KEY_TYPE>
00387 UINT64 Key_as_llu(const KEY_TYPE k)
00388 {
00389 UINT64 llu;
00390
00391 switch (sizeof(k))
00392 {
00393 case 1:
00394 llu = *(UINT8 *)&k;
00395 break;
00396 case 2:
00397 llu = *(UINT16 *)&k;
00398 break;
00399 case 4:
00400 llu = *(UINT32 *)&k;
00401 break;
00402 default:
00403 llu = *(UINT64 *)&k;
00404 break;
00405 }
00406 return llu;
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 template <class NODE_TYPE, class KEY_TYPE>
00418 ID_MAP<NODE_TYPE, KEY_TYPE>::ID_MAP(const UINT32 init_capacity,
00419 const NODE_TYPE not_found_value,
00420 MEM_POOL *const pool,
00421 const BOOL tracing) :
00422 _not_found_value(not_found_value),
00423 _pool(pool),
00424 _tracing(tracing),
00425 _verbose(FALSE),
00426 _num_entries(0),
00427 _constructed(FALSE)
00428 {
00429 _table = NULL;
00430 _table_size = Size(init_capacity);
00431 }
00432
00433 template <class NODE_TYPE, class KEY_TYPE> void
00434 ID_MAP<NODE_TYPE, KEY_TYPE>::Alloc_table_space(UINT32 table_size)
00435 {
00436 if (_table == NULL) {
00437 if (table_size < MIN_TABLE_SIZE) {
00438 table_size = MIN_TABLE_SIZE;
00439 }
00440 _table_size = table_size;
00441
00442 _table = (ID_MAP_HASH_ENTRY<NODE_TYPE, KEY_TYPE> *)
00443 MEM_POOL_Alloc(_pool,
00444 (table_size *
00445 sizeof(ID_MAP_HASH_ENTRY<NODE_TYPE, KEY_TYPE>)));
00446 }
00447 else {
00448
00449
00450 if (_table_size < table_size) {
00451 _table = (ID_MAP_HASH_ENTRY<NODE_TYPE, KEY_TYPE> *)
00452 MEM_POOL_Realloc(_pool,
00453 _table,
00454 _table_size *
00455 sizeof(ID_MAP_HASH_ENTRY<NODE_TYPE, KEY_TYPE>),
00456 table_size *
00457 sizeof(ID_MAP_HASH_ENTRY<NODE_TYPE, KEY_TYPE>));
00458 _table_size = table_size;
00459 }
00460 }
00461
00462 if (_table == NULL) ErrMsg(EC_No_Mem, "ID_MAP::ID_MAP");
00463
00464 Is_Trace(_tracing,
00465 (TFile, "ID_MAP::ID_MAP: allocated %u entries\n",
00466 _table_size));
00467 }
00468
00469 template <class NODE_TYPE, class KEY_TYPE> void
00470 ID_MAP<NODE_TYPE, KEY_TYPE>::Initialize_table(void)
00471 {
00472
00473 _free_list = 0;
00474 for (mINT32 i = 0; i < _table_size; i++) {
00475 _table[i]._node = _not_found_value;
00476 _table[i]._prev = i - 1;
00477 _table[i]._next = i + 1;
00478 }
00479 _table[_table_size - 1]._next = -1;
00480 }
00481
00482 template <class NODE_TYPE, class KEY_TYPE> void
00483 ID_MAP<NODE_TYPE, KEY_TYPE>::Init(UINT32 capacity)
00484 {
00485 Alloc_table_space(Size(capacity));
00486 Initialize_table();
00487 }
00488
00489 template <class NODE_TYPE, class KEY_TYPE> void
00490 ID_MAP<NODE_TYPE, KEY_TYPE>::Init(void)
00491 {
00492 _constructed = TRUE;
00493
00494 Alloc_table_space(_table_size);
00495 Initialize_table();
00496 }
00497
00498 template <class X>
00499 inline void Id_map_fprint(FILE *fp, X *x)
00500 {
00501 x->Print(fp);
00502 }
00503
00504 inline void Id_map_fprint(FILE *fp, IDTYPE *x)
00505 {
00506 fprintf(fp, "%d\n", *x);
00507 }
00508
00509 inline void Id_map_fprint(FILE *fp, INT x)
00510 {
00511 fprintf(fp, "%d\n", x);
00512 }
00513
00514 template <class NODE_TYPE, class KEY_TYPE> void
00515 ID_MAP<NODE_TYPE, KEY_TYPE>::Print(FILE *fp) const
00516 {
00517 fprintf(fp, "Number of entries: %u\n", _num_entries);
00518 fprintf(fp, "Free list --> %d\n", _free_list);
00519
00520 for (mINT32 i = 0; i < _table_size; i++) {
00521 fprintf(fp, "ID_MAP table[%d] : ", i);
00522 if (_table[i]._node != _not_found_value) {
00523 fprintf(fp, "[H(%llu)=%d; %d -->] ",
00524 Key_as_llu(_table[i]._key),
00525 Hash(_table[i]._key, _table_size),
00526 _table[i]._next);
00527 Id_map_fprint(fp, _table[i]._node);
00528 }
00529 else {
00530 fprintf(fp, "<-- %d, 0x%lx, %d -->\n",
00531 _table[i]._prev, (INTPTR) _table[i]._node, _table[i]._next);
00532 }
00533 }
00534 }
00535
00536 template <class NODE_TYPE, class KEY_TYPE>
00537 ID_MAP<NODE_TYPE, KEY_TYPE>::~ID_MAP(void)
00538 {
00539 if (_constructed) {
00540 Verify();
00541 if (_tracing) {
00542
00543 Is_Trace(TRUE, (TFile, "--- ID_MAP pre-destruct table dump:\n"));
00544 Print(TFile);
00545
00546
00547 }
00548 _constructed = FALSE;
00549 }
00550 }
00551
00552 template <class NODE_TYPE, class KEY_TYPE> void
00553 ID_MAP<NODE_TYPE, KEY_TYPE>::Enlarge(void)
00554 {
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570 mINT32 first_new_idx = _table_size;
00571 UINT32 save_num_entries = _num_entries;
00572
00573 mINT32 i;
00574
00575 Is_Trace(_tracing, (TFile, "ID_MAP enlarging from size %d\n",
00576 _table_size));
00577 Is_Trace_cmd(_tracing && _verbose, Print(TFile));
00578
00579 UINT32 new_table_size = (UINT32) ceil(GROWTH_FACTOR * (double) _table_size);
00580
00581 _table = (ID_MAP_HASH_ENTRY<NODE_TYPE, KEY_TYPE> *)
00582 MEM_POOL_Realloc(_pool,
00583 _table,
00584 _table_size *
00585 sizeof(ID_MAP_HASH_ENTRY<NODE_TYPE, KEY_TYPE>),
00586 new_table_size *
00587 sizeof(ID_MAP_HASH_ENTRY<NODE_TYPE, KEY_TYPE>));
00588
00589 if (_table == NULL) ErrMsg(EC_No_Mem, "ID_MAP::Enlarge");
00590
00591 _table_size = new_table_size;
00592
00593
00594
00595 for (i = _table_size - 1; i >= first_new_idx; i--) {
00596 _table[i]._next = -1;
00597 _table[i]._node = _not_found_value;
00598 }
00599
00600 for (; i >= 0; i--) {
00601 _table[i]._next = -1;
00602 }
00603
00604
00605
00606 for (i = 0; i < first_new_idx; i++) {
00607 if (_table[i]._node != _not_found_value) {
00608 mINT32 h = Hash(_table[i]._key, _table_size);
00609 if (_table[h]._next == -1) {
00610 Is_True(Check(save_num_entries != 0),
00611 ("ID_MAP::Enlarge: Bad save_num_entries logic"));
00612 --save_num_entries;
00613 _table[h]._next = 0;
00614 }
00615 }
00616 }
00617
00618
00619
00620
00621 for (i = 0; save_num_entries > 0; i++) {
00622 Is_True(i < _table_size,
00623 ("ID_MAP::Enlarge: Bad logic"));
00624 if (_table[i]._next == -1) {
00625 Is_True(Check(save_num_entries != 0),
00626 ("ID_MAP::Enlarge: Bad save_num_entries logic"));
00627 --save_num_entries;
00628 _table[i]._next = 0;
00629 }
00630 }
00631
00632
00633 i = _table_size;
00634 mINT32 unocc_head = -1;
00635
00636 while (TRUE) {
00637 --i;
00638 if (_table[i]._next == -1) {
00639 unocc_head = i;
00640 break;
00641 }
00642 Is_True(i > 0, ("ID_MAP::Enlarge: Bad logic"));
00643 }
00644
00645
00646
00647 while (i > 0) {
00648 --i;
00649 if (_table[i]._next == -1) {
00650 _table[i]._next = -unocc_head - 2;
00651 unocc_head = i;
00652 }
00653 }
00654
00655
00656
00657 mINT32 unocc = unocc_head;
00658 while (_table[unocc]._node != _not_found_value) {
00659 Is_True(0 <= unocc && unocc < _table_size,
00660 ("ID_MAP::Enlarge: Bad logic"));
00661 unocc = -_table[unocc]._next - 2;
00662 }
00663
00664 _free_list = -1;
00665
00666
00667
00668 for (i = _table_size - 1; i >= 0; i--) {
00669 if (_table[i]._next == 0) {
00670
00671 if (_table[i]._node != _not_found_value) {
00672 FmtAssert(unocc != -1,
00673 ("ID_MAP::Enlarge: Insufficient unoccupied entries.\n"
00674 " GROWTH_FACTOR too small WRT "
00675 "CAPACITY_FACTOR"));
00676 Is_True(Check(0 <= unocc && unocc < _table_size &&
00677 _table[unocc]._node == _not_found_value),
00678 ("ID_MAP::Enlarge: Bad logic"));
00679 _table[unocc]._node = _table[i]._node;
00680 _table[unocc]._key = _table[i]._key;
00681 do {
00682 Is_True(Check(0 <= unocc && unocc < _table_size),
00683 ("ID_MAP::Enlarge: Bad logic"));
00684 unocc = -_table[unocc]._next - 2;
00685 } while (_table[unocc]._node != _not_found_value);
00686 }
00687 Add_to_free_list(i);
00688 }
00689 }
00690
00691 save_num_entries = _num_entries;
00692
00693
00694
00695
00696 for (i = unocc_head; i != -1; i = unocc) {
00697 KEY_TYPE key = _table[i]._key;
00698 NODE_TYPE node = _table[i]._node;
00699
00700 unocc = -_table[i]._next - 2;
00701
00702
00703 Add_to_free_list(i);
00704
00705 if (node != _not_found_value) {
00706
00707 _num_entries = 0;
00708 Insert(key, node);
00709 }
00710 }
00711
00712 _num_entries = save_num_entries;
00713
00714 Is_Trace(_tracing, (TFile, "ID_MAP::Enlarge: Starting verification\n"));
00715 Verify();
00716 Is_Trace(_tracing, (TFile, "ID_MAP::Enlarge: Verification passed\n"));
00717 }
00718
00719 template <class NODE_TYPE, class KEY_TYPE> void
00720 ID_MAP<NODE_TYPE, KEY_TYPE>::Insert(const KEY_TYPE key,
00721 const NODE_TYPE node)
00722 {
00723 Is_Trace(_tracing && _verbose,
00724 (TFile, "ID_MAP::Insert(%llu, ...) ...\n", Key_as_llu(key)));
00725
00726 if (_num_entries + 1 > Capacity(_table_size)) {
00727 Is_Trace(_tracing,
00728 (TFile, "Enlarging: will have %u entries\n"
00729 " table size: %u\n"
00730 " table capacity: %u\n",
00731 _num_entries + 1, _table_size,
00732 Capacity(_table_size)));
00733 Enlarge();
00734 Is_True(_num_entries <= Capacity(_table_size),
00735 ("ID_MAP::Insert: Enlarge didn't get enough capacity"));
00736 }
00737 else {
00738 Is_Trace(_tracing && _verbose,
00739 (TFile, "Not enlarging: Capacity(%u) = %u\n",
00740 _table_size, Capacity(_table_size)));
00741 }
00742
00743 mINT32 idx = Hash(key, _table_size);
00744
00745 Is_Trace(_tracing && _verbose,
00746 (TFile, " ID_MAP::Insert: inserting at %d\n", idx));
00747
00748 if (_table[idx]._node != _not_found_value) {
00749 Is_True(Check(_table[idx]._next != _free_list),
00750 ("ID_MAP::Insert: inconsistent relocation"));
00751
00752 mINT32 displaced = Alloc_from_free_list();
00753
00754 Is_Trace(_tracing && _verbose,
00755 (TFile, " displacing [H(%llu)=%d; %d] to %d\n",
00756 Key_as_llu(_table[idx]._key),
00757 Hash(_table[idx]._key, _table_size),
00758 _table[idx]._next, displaced));
00759
00760 _table[displaced]._node = _table[idx]._node;
00761 _table[displaced]._key = _table[idx]._key;
00762
00763 Is_True(Check(_table[idx]._next != displaced),
00764 ("ID_MAP::Insert: inconsistent relocation"));
00765
00766 _table[displaced]._next = _table[idx]._next;
00767
00768 Is_True(Check(idx != displaced),
00769 ("ID_MAP::Insert: inconsistent relocation"));
00770 Is_True(Check(displaced != _free_list),
00771 ("ID_MAP::Insert: Bug in Alloc_from_free_list"));
00772
00773 mINT32 temp_idx = Hash(_table[displaced]._key, _table_size);
00774 if (idx == temp_idx) {
00775
00776 _table[idx]._next = displaced;
00777 }
00778 else {
00779 _table[idx]._next = -1;
00780
00781
00782 while (temp_idx != -1 && _table[temp_idx]._next != idx) {
00783 temp_idx = _table[temp_idx]._next;
00784 }
00785
00786 #if Is_True_On
00787 if (temp_idx == -1 || _table[temp_idx]._next != idx) {
00788 fprintf(TFile, "Insert %llu at idx = %d (%d)\n",
00789 Key_as_llu(key), idx,
00790 Hash(key, _table_size));
00791 fprintf(TFile, " -> displaced = %d\n", displaced);
00792 fprintf(TFile, "start [H(%llu)=%d]\n",
00793 Key_as_llu(_table[displaced]._key),
00794 Hash(_table[displaced]._key, _table_size));
00795 }
00796 #endif
00797 Is_True(Check(temp_idx != -1 && _table[temp_idx]._next == idx),
00798 ("ID_MAP::Insert: displaced item not found in hash table."));
00799 FmtAssert(temp_idx != -1 && _table[temp_idx]._next == idx,
00800 ("ID_MAP::Insert: displaced item not found in hash table."));
00801
00802 _table[temp_idx]._next = displaced;
00803 }
00804 }
00805 else {
00806 Remove_from_free_list(idx);
00807 _table[idx]._next = -1;
00808 }
00809
00810 _table[idx]._node = node;
00811 _table[idx]._key = key;
00812 ++_num_entries;
00813 }
00814
00815
00816 template <class NODE_TYPE, class KEY_TYPE> void
00817 ID_MAP<NODE_TYPE, KEY_TYPE>::Delete(const KEY_TYPE key)
00818 {
00819 mINT32 idx = Hash(key, _table_size);
00820 mINT32 prev_idx = -1;
00821
00822 while (idx != -1 &&
00823 _table[idx]._node != _not_found_value &&
00824 _table[idx]._key != key) {
00825 prev_idx = idx;
00826 idx = _table[idx]._next;
00827 }
00828
00829 FmtAssert(idx != -1 && _table[idx]._node != _not_found_value,
00830 ("ID_MAP::Delete: item not found in hash table."));
00831
00832 if (prev_idx != -1) {
00833 _table[prev_idx]._next = _table[idx]._next;
00834 }
00835 else {
00836 mINT32 next_idx = _table[idx]._next;
00837 if (next_idx != -1) {
00838 _table[idx]._node = _table[next_idx]._node;
00839 _table[idx]._key = _table[next_idx]._key;
00840 _table[idx]._next = _table[next_idx]._next;
00841 idx = next_idx;
00842 }
00843 }
00844 Add_to_free_list(idx);
00845 --_num_entries;
00846 }
00847
00848
00849 template <class NODE_TYPE, class KEY_TYPE> NODE_TYPE
00850 ID_MAP<NODE_TYPE, KEY_TYPE>::Lookup(const KEY_TYPE key) const
00851 {
00852 mINT32 idx = Entry_lookup(key);
00853 if (idx == -1) {
00854 return _not_found_value;
00855 }
00856 else {
00857 return _table[idx]._node;
00858 }
00859 }
00860
00861 template <class NODE_TYPE, class KEY_TYPE> mINT32
00862 ID_MAP<NODE_TYPE, KEY_TYPE>::Entry_lookup(const KEY_TYPE key) const
00863 {
00864 mINT32 idx = Hash(key, _table_size);
00865
00866 #if Is_True_On
00867 mINT32 loopcheck = idx;
00868 #endif
00869
00870 while (idx != -1 &&
00871 _table[idx]._node != _not_found_value &&
00872 _table[idx]._key != key) {
00873 idx = _table[idx]._next;
00874
00875 #if Is_True_On
00876 if (loopcheck != -1) {
00877 loopcheck = _table[loopcheck]._next;
00878 }
00879 if (loopcheck != -1) {
00880 loopcheck = _table[loopcheck]._next;
00881 }
00882 if (loopcheck != -1) {
00883 Is_True(Check(loopcheck != idx),
00884 ("ID_MAP::Lookup: loop in hash bucket %lu", idx));
00885 }
00886 #endif
00887 }
00888 if (idx == -1 || _table[idx]._node == _not_found_value) {
00889 return -1;
00890 }
00891 else {
00892 return idx;
00893 }
00894 }
00895
00896 #endif