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 #include <assert.h>
00039 #include <stdlib.h>
00040
00041 #include "systemc/kernel/sc_cmnhdr.h"
00042 #include "systemc/utils/sc_hash.h"
00043 #include "systemc/utils/sc_mempool.h"
00044
00045
00046 const double PHASH_DEFAULT_GROW_FACTOR = 2.0;
00047
00048 class sc_phash_elem {
00049 friend class sc_phash_base;
00050 friend class sc_phash_base_iter;
00051
00052 private:
00053 void* key;
00054 void* contents;
00055 sc_phash_elem* next;
00056
00057 sc_phash_elem( void* k, void* c, sc_phash_elem* n )
00058 : key(k), contents(c), next(n) { }
00059 sc_phash_elem() { }
00060 ~sc_phash_elem() { }
00061
00062 static void* operator new(size_t sz) { return sc_mempool::allocate(sz); }
00063 static void operator delete(void* p, size_t sz) { sc_mempool::release(p, sz); }
00064 };
00065
00066
00067 sc_phash_base::sc_phash_base(
00068 void* def,
00069 int size,
00070 int density,
00071 double grow,
00072 bool reorder,
00073 unsigned (*hash_fn)(const void*),
00074 int (*cmp_fn)(const void*, const void*)
00075 )
00076 {
00077 default_value = def;
00078 hash = hash_fn;
00079 num_entries = 0;
00080 max_density = density;
00081 grow_factor = grow;
00082 reorder_flag = reorder;
00083
00084 if (size <= 0)
00085 size = PHASH_DEFAULT_INIT_TABLE_SIZE;
00086 else if ((size % 2) == 0)
00087 size += 1;
00088 num_bins = size;
00089 bins = new sc_phash_elem*[size];
00090 for (int i = 0; i < size; ++i)
00091 bins[i] = 0;
00092
00093 set_cmpr_fn(cmp_fn);
00094 }
00095
00096 void
00097 sc_phash_base::set_cmpr_fn(cmpr_fn_t c)
00098 {
00099 cmpr = c;
00100 }
00101
00102 void
00103 sc_phash_base::set_hash_fn(hash_fn_t h)
00104 {
00105 hash = h;
00106 }
00107
00108 sc_phash_base::~sc_phash_base()
00109 {
00110 sc_phash_elem* ptr;
00111 sc_phash_elem* next;
00112
00113 for (int i = 0; i < num_bins; ++i) {
00114 ptr = bins[i];
00115 while (ptr != 0) {
00116 next = ptr->next;
00117 delete ptr;
00118 ptr = next;
00119 }
00120 }
00121 delete[] bins;
00122 }
00123
00124 void
00125 sc_phash_base::rehash()
00126 {
00127 sc_phash_elem* ptr;
00128 sc_phash_elem* next;
00129 sc_phash_elem** old_bins = bins;
00130
00131 int old_num_bins = num_bins;
00132 unsigned hash_val;
00133
00134 num_bins = (int) (grow_factor * old_num_bins);
00135 if (num_bins % 2 == 0)
00136 ++num_bins;
00137
00138 num_entries = 0;
00139 bins = new sc_phash_elem*[num_bins];
00140 memset( bins, 0, sizeof(sc_phash_elem*) * num_bins );
00141
00142 for (int i = 0; i < old_num_bins; ++i) {
00143 ptr = old_bins[i];
00144 while (ptr != 0) {
00145 next = ptr->next;
00146 hash_val = do_hash(ptr->key);
00147 ptr->next = bins[hash_val];
00148 bins[hash_val] = ptr;
00149 ++num_entries;
00150 ptr = next;
00151 }
00152 }
00153 delete[] old_bins;
00154 }
00155
00156 sc_phash_elem*
00157 sc_phash_base::find_entry_q( unsigned hash_val, const void* key, sc_phash_elem*** plast )
00158 {
00159 sc_phash_elem** last = &(bins[hash_val]);
00160 sc_phash_elem* ptr = *last;
00161
00162
00163 while ((ptr != 0) && (ptr->key != key)) {
00164
00165 last = &(ptr->next);
00166 ptr = *last;
00167 }
00168 if ((ptr != 0) && reorder_flag) {
00169 *last = ptr->next;
00170 ptr->next = bins[hash_val];
00171 bins[hash_val] = ptr;
00172 last = &(bins[hash_val]);
00173 }
00174 if (plast) *plast = last;
00175 return ptr;
00176 }
00177
00178 sc_phash_elem*
00179 sc_phash_base::find_entry_c( unsigned hash_val, const void* key, sc_phash_elem*** plast )
00180 {
00181 sc_phash_elem** last = &(bins[hash_val]);
00182 sc_phash_elem* ptr = *last;
00183
00184 while ((ptr != 0) && ((*cmpr)(ptr->key, key) != 0)) {
00185 last = &(ptr->next);
00186 ptr = *last;
00187 }
00188
00189 if ((ptr != 0) && reorder_flag) {
00190 *last = ptr->next;
00191 ptr->next = bins[hash_val];
00192 bins[hash_val] = ptr;
00193 last = &(bins[hash_val]);
00194 }
00195 if (plast) *plast = last;
00196 return ptr;
00197 }
00198
00199 sc_phash_elem*
00200 sc_phash_base::add_direct( void* key, void* contents, unsigned hash_val )
00201 {
00202 if (num_entries / num_bins >= max_density) {
00203 rehash();
00204 hash_val = do_hash(key);
00205 }
00206
00207 sc_phash_elem* new_entry = new sc_phash_elem(key, contents, bins[hash_val]);
00208 bins[hash_val] = new_entry;
00209 ++num_entries;
00210 return new_entry;
00211 }
00212
00213 void
00214 sc_phash_base::erase()
00215 {
00216 for (int i = 0; i < num_bins; ++i) {
00217 sc_phash_elem* ptr = bins[i];
00218 while (ptr != 0) {
00219 sc_phash_elem* next = ptr->next;
00220 delete ptr;
00221 ptr = next;
00222 --num_entries;
00223 }
00224 bins[i] = 0;
00225 }
00226 assert(num_entries == 0);
00227 }
00228
00229 void
00230 sc_phash_base::erase(void (*kfree)(void*))
00231 {
00232 for (int i = 0; i < num_bins; ++i) {
00233 sc_phash_elem* ptr = bins[i];
00234 while (ptr != 0) {
00235 sc_phash_elem* next = ptr->next;
00236 (*kfree)(ptr->key);
00237 delete ptr;
00238 ptr = next;
00239 --num_entries;
00240 }
00241 bins[i] = 0;
00242 }
00243 assert(num_entries == 0);
00244 }
00245
00246 void
00247 sc_phash_base::copy( const sc_phash_base* b )
00248 {
00249 erase();
00250 iterator iter((sc_phash_base*) b);
00251 for ( ; ! iter.empty(); iter++)
00252 insert( iter.key(), iter.contents() );
00253 }
00254
00255 void
00256 sc_phash_base::copy(const sc_phash_base& b, void* (*kdup)(const void*), void (*kfree)(void*))
00257 {
00258 erase(kfree);
00259 iterator iter((sc_phash_base&) b);
00260 for ( ; ! iter.empty(); iter++)
00261 insert( (*kdup)(iter.key()), iter.contents() );
00262 }
00263
00264 int
00265 sc_phash_base::insert( void* k, void* c )
00266 {
00267 unsigned hash_val = do_hash(k);
00268 sc_phash_elem* ptr = find_entry( hash_val, k );
00269 if (ptr == 0) {
00270 (void) add_direct(k, c, hash_val);
00271 return 0;
00272 }
00273 else {
00274 ptr->contents = c;
00275 return 1;
00276 }
00277 }
00278
00279 int
00280 sc_phash_base::insert( void* k, void* c, void* (*kdup)(const void*) )
00281 {
00282 unsigned hash_val = do_hash(k);
00283 sc_phash_elem* ptr = find_entry( hash_val, k );
00284 if (ptr == 0) {
00285 (void) add_direct((*kdup)(k), c, hash_val);
00286 return 0;
00287 }
00288 else {
00289 ptr->contents = c;
00290 return 1;
00291 }
00292 }
00293
00294 int
00295 sc_phash_base::insert_if_not_exists( void* k, void* c )
00296 {
00297 unsigned hash_val = do_hash(k);
00298 sc_phash_elem* ptr = find_entry( hash_val, k );
00299 if (ptr == 0) {
00300 (void) add_direct( k, c, hash_val );
00301 return 0;
00302 }
00303 else
00304 return 1;
00305 }
00306
00307 int
00308 sc_phash_base::insert_if_not_exists( void* k, void* c, void* (*kdup)(const void*) )
00309 {
00310 unsigned hash_val = do_hash(k);
00311 sc_phash_elem* ptr = find_entry( hash_val, k );
00312 if (ptr == 0) {
00313 (void) add_direct( (*kdup)(k), c, hash_val );
00314 return 0;
00315 }
00316 else
00317 return 1;
00318 }
00319
00320 int
00321 sc_phash_base::remove( const void* k )
00322 {
00323 unsigned hash_val = do_hash(k);
00324 sc_phash_elem** last;
00325 sc_phash_elem* ptr = find_entry( hash_val, k, &last );
00326
00327 if (ptr == 0)
00328 return 0;
00329
00330 assert(*last == ptr);
00331 *last = ptr->next;
00332 delete ptr;
00333 --num_entries;
00334 return 1;
00335 }
00336
00337 int
00338 sc_phash_base::remove( const void* k, void** pk, void** pc )
00339 {
00340 unsigned hash_val = do_hash(k);
00341 sc_phash_elem** last;
00342 sc_phash_elem* ptr = find_entry( hash_val, k, &last );
00343
00344 if (ptr == 0) {
00345 *pk = 0;
00346 *pc = 0;
00347 return 0;
00348 }
00349 else {
00350 *pk = ptr->key;
00351 *pc = ptr->contents;
00352 }
00353
00354 assert(*last == ptr);
00355 *last = ptr->next;
00356 delete ptr;
00357 --num_entries;
00358 return 1;
00359 }
00360
00361 int
00362 sc_phash_base::remove(const void* k, void (*kfree)(void*))
00363 {
00364 void* rk;
00365 void* rc;
00366 if (remove(k, &rk, &rc)) {
00367 (*kfree)(rk);
00368 return 1;
00369 }
00370 else
00371 return 0;
00372 }
00373
00374 int
00375 sc_phash_base::remove_by_contents( const void* c )
00376 {
00377 sc_phash_elem** last;
00378 sc_phash_elem* ptr;
00379
00380 int num_removed = 0;
00381 for (int i = 0; i < num_bins; ++i) {
00382 last = &(bins[i]);
00383 ptr = *last;
00384 while (ptr != 0) {
00385 if (ptr->contents != c) {
00386 last = &(ptr->next);
00387 ptr = *last;
00388 }
00389 else {
00390 *last = ptr->next;
00391 delete ptr;
00392 ptr = *last;
00393 --num_entries;
00394 ++num_removed;
00395 }
00396 }
00397 }
00398 return num_removed;
00399 }
00400
00401 int
00402 sc_phash_base::remove_by_contents( bool (*predicate)(const void* c, void* arg), void* arg )
00403 {
00404 sc_phash_elem** last;
00405 sc_phash_elem* ptr;
00406
00407 int num_removed = 0;
00408 for (int i = 0; i < num_bins; ++i) {
00409 last = &(bins[i]);
00410 ptr = *last;
00411 while (ptr != 0) {
00412 if (! (*predicate)(ptr->contents, arg)) {
00413 last = &(ptr->next);
00414 ptr = *last;
00415 }
00416 else {
00417 *last = ptr->next;
00418 delete ptr;
00419 ptr = *last;
00420 --num_entries;
00421 ++num_removed;
00422 }
00423 }
00424 }
00425 return num_removed;
00426 }
00427
00428 int
00429 sc_phash_base::remove_by_contents( const void* c, void (*kfree)(void*) )
00430 {
00431 sc_phash_elem** last;
00432 sc_phash_elem* ptr;
00433
00434 int num_removed = 0;
00435 for (int i = 0; i < num_bins; ++i) {
00436 last = &(bins[i]);
00437 ptr = *last;
00438 while (ptr != 0) {
00439 if (ptr->contents != c) {
00440 last = &(ptr->next);
00441 ptr = *last;
00442 }
00443 else {
00444 *last = ptr->next;
00445 (*kfree)(ptr->key);
00446 delete ptr;
00447 ptr = *last;
00448 --num_entries;
00449 ++num_removed;
00450 }
00451 }
00452 }
00453 return num_removed;
00454 }
00455
00456 int
00457 sc_phash_base::remove_by_contents( bool (*predicate)(const void*, void*), void* arg, void (*kfree)(void*))
00458 {
00459 sc_phash_elem** last;
00460 sc_phash_elem* ptr;
00461
00462 int num_removed = 0;
00463 for (int i = 0; i < num_bins; ++i) {
00464 last = &(bins[i]);
00465 ptr = *last;
00466 while (ptr != 0) {
00467 if (! (*predicate)(ptr->contents, arg)) {
00468 last = &(ptr->next);
00469 ptr = *last;
00470 }
00471 else {
00472 *last = ptr->next;
00473 (*kfree)(ptr->key);
00474 delete ptr;
00475 ptr = *last;
00476 --num_entries;
00477 ++num_removed;
00478 }
00479 }
00480 }
00481 return num_removed;
00482 }
00483
00484 int
00485 sc_phash_base::lookup( const void* k, void** c_ptr ) const
00486 {
00487 unsigned hash_val = do_hash(k);
00488 sc_phash_elem* ptr = find_entry( hash_val, k );
00489 if (ptr == 0) {
00490 if (c_ptr != 0) *c_ptr = default_value;
00491 return 0;
00492 }
00493 else {
00494 if (c_ptr != 0) *c_ptr = ptr->contents;
00495 return 1;
00496 }
00497 }
00498
00499 void*
00500 sc_phash_base::operator[]( const void* key ) const
00501 {
00502 void* contents;
00503 lookup( key, &contents );
00504 return contents;
00505 }
00506
00507
00508
00509 void
00510 sc_phash_base_iter::reset( sc_phash_base* t )
00511 {
00512 table = t;
00513 index = 0;
00514 entry = 0;
00515 next = 0;
00516
00517 for (int i = index; i < table->num_bins; ++i) {
00518 if (table->bins[i] != 0) {
00519 index = i + 1;
00520 last = &(table->bins[i]);
00521 entry = *last;
00522 next = entry->next;
00523 break;
00524 }
00525 }
00526 }
00527
00528 bool
00529 sc_phash_base_iter::empty() const
00530 {
00531 return (entry == 0);
00532 }
00533
00534 void
00535 sc_phash_base_iter::step()
00536 {
00537 if (entry) {
00538 last = &(entry->next);
00539 }
00540 entry = next;
00541 if (! entry) {
00542 for (int i = index; i < table->num_bins; ++i) {
00543 if (table->bins[i] != 0) {
00544 index = i + 1;
00545 last = &(table->bins[i]);
00546 entry = *last;
00547 next = entry->next;
00548 break;
00549 }
00550 }
00551 }
00552 else {
00553 next = entry->next;
00554 }
00555 }
00556
00557 void
00558 sc_phash_base_iter::remove()
00559 {
00560 delete entry;
00561 *last = next;
00562 entry = 0;
00563 --table->num_entries;
00564 step();
00565 }
00566
00567 void
00568 sc_phash_base_iter::remove(void (*kfree)(void*))
00569 {
00570 (*kfree)(entry->key);
00571 delete entry;
00572 *last = next;
00573 entry = 0;
00574 --table->num_entries;
00575 step();
00576 }
00577
00578 void*
00579 sc_phash_base_iter::key() const
00580 {
00581 return entry->key;
00582 }
00583
00584 void*
00585 sc_phash_base_iter::contents() const
00586 {
00587 return entry->contents;
00588 }
00589
00590 void*
00591 sc_phash_base_iter::set_contents( void* c )
00592 {
00593 return entry->contents = c;
00594 }
00595
00596
00597
00598 unsigned
00599 default_ptr_hash_fn(const void* p)
00600 {
00601 return ((unsigned)(p) >> 2) * 2654435789U;
00602
00603 }
00604
00605 unsigned
00606 default_int_hash_fn(const void* p)
00607 {
00608 return (unsigned)(p) * 3141592661U;
00609 }
00610
00611
00612 unsigned
00613 default_str_hash_fn(const void* p)
00614 {
00615 if (!p) return 0;
00616
00617 const char* x = (const char*) p;
00618 unsigned int h = 0;
00619 unsigned int g;
00620
00621 while (*x != 0) {
00622 h = (h << 4) + *x++;
00623 if ((g = h & 0xf0000000) != 0)
00624 h = (h ^ (g >> 24)) ^ g;
00625 }
00626 return h;
00627 }
00628
00629 int
00630 sc_strhash_cmp( const void* a, const void* b )
00631 {
00632 return strcmp( (const char*) a, (const char*) b );
00633 }
00634
00635 void*
00636 sc_strhash_kdup(const void* k)
00637 {
00638 return strdup((const char*) k);
00639 }
00640
00641 void
00642 sc_strhash_kfree(void* k)
00643 {
00644 if (k) free((char*) k);
00645 }