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
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 #ifndef cxx_hash_INCLUDED
00211 #define cxx_hash_INCLUDED "cxx_hash.h"
00212
00213 #ifdef _KEEP_RCS_ID
00214 static char *cxx_hash_rcs_id = cxx_hash_INCLUDED "$Revision: 1.2 $";
00215 #endif
00216
00217 #ifndef CXX_MEMORY_INCLUDED
00218 #include "cxx_memory.h"
00219 #endif
00220 #include "erglob.h"
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 template <class SIG_TYPE, class DATA_TYPE>
00239 class HASH_ELEMENT
00240 {
00241 public:
00242 DATA_TYPE _data;
00243 SIG_TYPE _signature;
00244 HASH_ELEMENT *_next;
00245
00246
00247 HASH_ELEMENT(const SIG_TYPE& signature, const DATA_TYPE& data) :
00248 _signature(signature), _data(data), _next(NULL) {}
00249 void Add_To_List(HASH_ELEMENT *e) { e->_next = _next; _next = e; }
00250 };
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 template <class SIG_TYPE, class DATA_TYPE>
00263 class HASH_TABLE {
00264 private:
00265 MEM_POOL *_pool;
00266 HASH_ELEMENT<SIG_TYPE,DATA_TYPE> * *_data;
00267 UINT _num_elements;
00268 UINT _num_entries;
00269 public:
00270 HASH_TABLE<SIG_TYPE,DATA_TYPE>(UINT num_elements, MEM_POOL *pool);
00271 UINT Num_Elements() const { return _num_elements; };
00272 UINT Num_Entries() const { return _num_entries; };
00273 HASH_ELEMENT<SIG_TYPE,DATA_TYPE> *Data(UINT i) const { return _data[i]; };
00274
00275 void Enter(SIG_TYPE signature,DATA_TYPE data) {
00276 typedef HASH_ELEMENT<SIG_TYPE,DATA_TYPE> THIS_HASH_ELEMENT;
00277 typedef HASH_ELEMENT<SIG_TYPE,DATA_TYPE> *HASH_ELEMENTP;
00278 HASH_ELEMENTP element =
00279 CXX_NEW(THIS_HASH_ELEMENT(signature,data),_pool);
00280 UINT location = abs((INT)(INTPS)signature) % _num_elements;
00281 if (_data[location]) {
00282 _data[location]->Add_To_List(element);
00283 } else {
00284 _data[location] = element;
00285 }
00286 _num_entries++;
00287 }
00288
00289 void Enter_If_Unique(SIG_TYPE signature,DATA_TYPE data);
00290 DATA_TYPE Find(SIG_TYPE signature) const;
00291 void Remove(SIG_TYPE signature);
00292
00293
00294 ~HASH_TABLE() {
00295 typedef HASH_ELEMENT<SIG_TYPE,DATA_TYPE> *HASH_ELEMENTP;
00296 for (UINT loc = 0; loc < _num_elements; loc++) {
00297 HASH_ELEMENTP element = _data[loc];
00298 HASH_ELEMENTP next_element;
00299 while (element) {
00300 next_element = element->_next;
00301 CXX_DELETE(element, _pool);
00302 element = next_element;
00303 }
00304 }
00305 CXX_DELETE_ARRAY(_data, _pool);
00306 };
00307
00308 };
00309
00310 template <class SIG_TYPE, class DATA_TYPE>
00311 class HASH_TABLE_ITER {
00312 private:
00313 INT _loc;
00314 HASH_ELEMENT<SIG_TYPE,DATA_TYPE> *_he;
00315 const HASH_TABLE<SIG_TYPE,DATA_TYPE> *_hash;
00316 public:
00317 BOOL Step(SIG_TYPE* sig, DATA_TYPE* data);
00318 HASH_TABLE_ITER(const HASH_TABLE<SIG_TYPE,DATA_TYPE> * h) :
00319 _hash(h), _loc(-1), _he(NULL) {}
00320 ~HASH_TABLE_ITER() {}
00321 };
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 typedef UINT32 HASH;
00336
00337
00338 struct String_Hash
00339 {
00340 HASH operator() ( const char * k ) const;
00341 };
00342
00343
00344 struct String_Equal
00345 {
00346 BOOL operator() ( const char *a, const char *b ) const
00347 { return ! strcmp ( a, b ); }
00348 };
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 #define TEMPLATE_USER_HASH_TABLE template \
00364 < class KEY_TYPE, class DATA_TYPE, class HASH_FUNC, class KEY_EQ >
00365 #define CLASS_USER_HASH_TABLE \
00366 USER_HASH_TABLE < KEY_TYPE, DATA_TYPE, HASH_FUNC, KEY_EQ >
00367
00368 TEMPLATE_USER_HASH_TABLE
00369 class USER_HASH_TABLE {
00370 private:
00371 MEM_POOL *_pool;
00372 HASH_ELEMENT<KEY_TYPE,DATA_TYPE> * *_data;
00373 UINT32 _num_elements;
00374 UINT _num_entries;
00375 HASH_FUNC _hash;
00376 KEY_EQ _equal;
00377
00378 public:
00379
00380 USER_HASH_TABLE ( UINT32 num_elements, MEM_POOL *pool );
00381
00382
00383 void Print ( FILE *f );
00384
00385
00386 UINT32 Num_Elements ( void ) const { return _num_elements; };
00387 UINT Num_Entries( void ) const { return _num_entries; };
00388 HASH_ELEMENT < KEY_TYPE, DATA_TYPE > *Data ( UINT32 i) const
00389 { return _data[i]; }
00390
00391
00392 void Enter ( KEY_TYPE key, DATA_TYPE data ) {
00393 typedef HASH_ELEMENT<KEY_TYPE,DATA_TYPE> THIS_HASH_ELEMENT;
00394 typedef HASH_ELEMENT<KEY_TYPE,DATA_TYPE> *HASH_ELEMENTP;
00395 HASH_ELEMENTP element =
00396 CXX_NEW ( THIS_HASH_ELEMENT(key,data), _pool );
00397 UINT32 location = _hash(key) % _num_elements;
00398
00399 element->_next = _data[location];
00400 _data[location] = element;
00401 _num_entries++;
00402 }
00403
00404
00405 void Enter_If_Unique ( KEY_TYPE key, DATA_TYPE data );
00406
00407
00408 DATA_TYPE Find(KEY_TYPE key) const;
00409
00410
00411 ~USER_HASH_TABLE() {
00412 typedef HASH_ELEMENT<KEY_TYPE,DATA_TYPE> *HASH_ELEMENTP;
00413 for (UINT loc = 0; loc < _num_elements; loc++) {
00414 HASH_ELEMENTP element = _data[loc];
00415 HASH_ELEMENTP next_element;
00416 while (element) {
00417 next_element = element->_next;
00418 CXX_DELETE(element, _pool);
00419 element = next_element;
00420 }
00421 }
00422 CXX_DELETE_ARRAY(_data, _pool);
00423 };
00424 };
00425
00426 TEMPLATE_USER_HASH_TABLE
00427 class USER_HASH_TABLE_ITER {
00428 private:
00429 INT _loc;
00430 HASH_ELEMENT<KEY_TYPE,DATA_TYPE> *_he;
00431 const USER_HASH_TABLE < KEY_TYPE, DATA_TYPE, HASH_FUNC, KEY_EQ > *_hash;
00432
00433 public:
00434 BOOL Step ( KEY_TYPE* key, DATA_TYPE* data );
00435 USER_HASH_TABLE_ITER (
00436 const USER_HASH_TABLE < KEY_TYPE, DATA_TYPE, HASH_FUNC, KEY_EQ > * h ) :
00437 _hash(h), _loc(-1), _he(NULL) {}
00438 ~USER_HASH_TABLE_ITER ( void ) {}
00439 };
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 template <class SIG_TYPE, class DATA_TYPE>
00468 HASH_TABLE<SIG_TYPE,DATA_TYPE> :: HASH_TABLE (
00469 UINT num_elements,
00470 MEM_POOL *pool )
00471 {
00472 typedef HASH_ELEMENT<SIG_TYPE,DATA_TYPE> *HASH_ELEMENTP;
00473 _pool = pool;
00474 _num_elements = num_elements;
00475 _num_entries = 0;
00476 _data = CXX_NEW_ARRAY(HASH_ELEMENTP ,num_elements,pool);
00477 for (INT i=0; i<num_elements; i++) {
00478 _data[i] = (HASH_ELEMENTP) 0;
00479 }
00480 }
00481
00482 template <class SIG_TYPE, class DATA_TYPE>
00483 void
00484 HASH_TABLE<SIG_TYPE,DATA_TYPE> :: Enter_If_Unique(SIG_TYPE signature,
00485 DATA_TYPE data)
00486 {
00487 typedef HASH_ELEMENT<SIG_TYPE,DATA_TYPE> THIS_HASH_ELEMENT;
00488 typedef HASH_ELEMENT<SIG_TYPE,DATA_TYPE> *HASH_ELEMENTP;
00489 HASH_ELEMENTP element =
00490 CXX_NEW(THIS_HASH_ELEMENT(signature,data),_pool);
00491 UINT location = abs((INT)(INTPS)signature) % _num_elements;
00492
00493 if (_data[location]) {
00494 HASH_ELEMENTP iter = _data[location];
00495 for (; iter != NULL ; iter = iter->_next) {
00496 if (iter->_signature == signature) {
00497 return;
00498 }
00499 }
00500 _data[location]->Add_To_List(element);
00501 } else {
00502 _data[location] = element;
00503 }
00504 _num_entries++;
00505 }
00506
00507 template <class SIG_TYPE, class DATA_TYPE>
00508 DATA_TYPE
00509 HASH_TABLE<SIG_TYPE,DATA_TYPE> :: Find (
00510 SIG_TYPE signature ) const
00511 {
00512 typedef HASH_ELEMENT<SIG_TYPE,DATA_TYPE> *HASH_ELEMENTP;
00513 HASH_ELEMENTP hash_element = _data[abs((INT)(INTPS)signature) % _num_elements];
00514
00515 for (; hash_element != NULL; hash_element = hash_element->_next) {
00516 if (hash_element->_signature == signature) {
00517 return(hash_element->_data);
00518 }
00519 }
00520 return((DATA_TYPE)0);
00521 }
00522
00523 template <class SIG_TYPE, class DATA_TYPE>
00524 void HASH_TABLE<SIG_TYPE,DATA_TYPE> :: Remove (
00525 SIG_TYPE signature )
00526 {
00527 typedef HASH_ELEMENT<SIG_TYPE,DATA_TYPE> *HASH_ELEMENTP;
00528 HASH_ELEMENTP hash_element = _data[abs((INT)(INTPTR)signature) % _num_elements];
00529
00530 if (hash_element->_signature == signature) {
00531 _data[abs((INT)(INTPS)signature) % _num_elements] = hash_element->_next;
00532 CXX_DELETE(hash_element,_pool);
00533 _num_entries--;
00534 return;
00535 }
00536
00537 HASH_ELEMENTP prev = hash_element;
00538 for (hash_element = hash_element->_next; hash_element;
00539 hash_element = hash_element->_next) {
00540 if (hash_element->_signature == signature) {
00541 prev->_next = hash_element->_next;
00542 CXX_DELETE(hash_element,_pool);
00543 _num_entries--;
00544 return;
00545 }
00546 prev = hash_element;
00547 }
00548 }
00549
00550 template <class SIG_TYPE, class DATA_TYPE>
00551 BOOL
00552 HASH_TABLE_ITER<SIG_TYPE,DATA_TYPE> :: Step (
00553 SIG_TYPE* sig,
00554 DATA_TYPE* data )
00555 {
00556 if (_he && _he->_next) {
00557 _he = _he->_next;
00558 *sig = _he->_signature;
00559 *data = _he->_data;
00560 return TRUE;
00561 }
00562
00563 for (_loc++; _loc < _hash->Num_Elements(); _loc++) {
00564 if (_hash->Data(_loc)) {
00565 _he = _hash->Data(_loc);
00566 *sig = _he->_signature;
00567 *data = _he->_data;
00568 return TRUE;
00569 }
00570 }
00571
00572 return FALSE;
00573 }
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 TEMPLATE_USER_HASH_TABLE
00598 CLASS_USER_HASH_TABLE :: USER_HASH_TABLE
00599 ( UINT32 num_elements, MEM_POOL *pool )
00600 {
00601 typedef HASH_ELEMENT < KEY_TYPE, DATA_TYPE > *pHASH_ELEMENT;
00602
00603 _pool = pool;
00604 _num_elements = num_elements;
00605 _num_entries = 0;
00606 _data = CXX_NEW_ARRAY ( pHASH_ELEMENT, num_elements, pool );
00607 if ( _data == NULL ) {
00608 ErrMsg ( EC_No_Mem, "USER_HASH_TABLE::USER_HASH_TABLE" );
00609 }
00610 for ( INT i=0; i<num_elements; i++ ) {
00611 _data[i] = (pHASH_ELEMENT) NULL;
00612 }
00613 }
00614
00615 TEMPLATE_USER_HASH_TABLE
00616 void
00617 CLASS_USER_HASH_TABLE :: Print ( FILE *f )
00618 {
00619 HASH_ELEMENT < KEY_TYPE, DATA_TYPE > *elt;
00620
00621 for ( INT32 i = 0; i < _num_elements; i++ ) {
00622 if ( _data[i] != NULL ) {
00623 fprintf ( f, "%2d:", i );
00624 elt = _data[i];
00625 while ( elt != NULL ) {
00626 fprintf ( f, " k%2d:%s:d%d:n0x%06lx",
00627 _hash(elt->_signature) % _num_elements,
00628 elt->_signature, elt->_data, elt->_next );
00629 elt = elt->_next;
00630 }
00631 fprintf ( f, "\n" );
00632 }
00633 }
00634 }
00635
00636 TEMPLATE_USER_HASH_TABLE
00637 void
00638 CLASS_USER_HASH_TABLE :: Enter_If_Unique(KEY_TYPE key, DATA_TYPE data)
00639 {
00640 typedef HASH_ELEMENT<KEY_TYPE,DATA_TYPE> THIS_HASH_ELEMENT;
00641 typedef HASH_ELEMENT<KEY_TYPE,DATA_TYPE> *pHASH_ELEMENT;
00642 pHASH_ELEMENT element =
00643 CXX_NEW ( THIS_HASH_ELEMENT(key,data), _pool );
00644 UINT32 location = _hash ( key ) % _num_elements;
00645
00646 if ( element == NULL ) {
00647 ErrMsg ( EC_No_Mem, "USER_HASH_TABLE::Enter_If_Unique" );
00648 }
00649
00650 if ( _data[location] ) {
00651 pHASH_ELEMENT iter = _data[location];
00652
00653 for ( ; iter != NULL ; iter = iter->_next ) {
00654 if ( _equal ( iter->_signature, key ) ) {
00655 return;
00656 }
00657 }
00658 element->_next = _data[location];
00659 }
00660 _data[location] = element;
00661 _num_entries++;
00662 }
00663
00664 TEMPLATE_USER_HASH_TABLE
00665 DATA_TYPE
00666 CLASS_USER_HASH_TABLE :: Find ( KEY_TYPE key ) const
00667 {
00668 typedef HASH_ELEMENT < KEY_TYPE, DATA_TYPE > *pHASH_ELEMENT;
00669 HASH hash = _hash(key) % _num_elements;
00670 pHASH_ELEMENT hash_element = _data[hash];
00671
00672
00673
00674
00675
00676 for ( ; hash_element != NULL; hash_element = hash_element->_next ) {
00677 if ( _equal ( hash_element->_signature, key ) ) {
00678 return ( hash_element->_data );
00679 }
00680 }
00681
00682 return((DATA_TYPE)0);
00683 }
00684
00685 TEMPLATE_USER_HASH_TABLE
00686 BOOL
00687 USER_HASH_TABLE_ITER < KEY_TYPE, DATA_TYPE, HASH_FUNC, KEY_EQ > :: Step
00688 ( KEY_TYPE* key, DATA_TYPE* data )
00689 {
00690 if ( _he && _he->_next ) {
00691 _he = _he->_next;
00692 *key = _he->_signature;
00693 *data = _he->_data;
00694 return TRUE;
00695 }
00696
00697 for ( _loc++; _loc < _hash->Num_Elements(); _loc++ ) {
00698 if ( _hash->Data(_loc) ) {
00699 _he = _hash->Data(_loc);
00700 *key = _he->_signature;
00701 *data = _he->_data;
00702 return TRUE;
00703 }
00704 }
00705
00706 return FALSE;
00707 }
00708 #endif
00709