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 #ifndef SC_HASH_H
00038 #define SC_HASH_H
00039
00040
00041 #include "systemc/utils/sc_iostream.h"
00042
00043
00044 extern unsigned default_int_hash_fn(const void*);
00045 extern unsigned default_ptr_hash_fn(const void*);
00046 extern unsigned default_str_hash_fn(const void*);
00047
00048 class sc_phash_elem;
00049 class sc_phash_base_iter;
00050 template<class K, class C>
00051 class sc_pdhash_iter;
00052
00053 const int PHASH_DEFAULT_MAX_DENSITY = 5;
00054 const int PHASH_DEFAULT_INIT_TABLE_SIZE = 11;
00055 extern const double PHASH_DEFAULT_GROW_FACTOR;
00056 const bool PHASH_DEFAULT_REORDER_FLAG = true;
00057
00058 class sc_phash_base {
00059 friend class sc_phash_base_iter;
00060
00061 typedef sc_phash_base_iter iterator;
00062
00063 public:
00064 typedef unsigned (*hash_fn_t)(const void*);
00065 typedef int (*cmpr_fn_t)(const void*, const void*);
00066
00067 protected:
00068 void* default_value;
00069 int num_bins;
00070 int num_entries;
00071 int max_density;
00072 int reorder_flag;
00073 double grow_factor;
00074
00075 sc_phash_elem** bins;
00076
00077 hash_fn_t hash;
00078 cmpr_fn_t cmpr;
00079
00080 void rehash();
00081 unsigned do_hash(const void* key) const { return (*hash)(key) % num_bins; }
00082
00083 sc_phash_elem* add_direct(void* key, void* contents, unsigned hash_val);
00084 sc_phash_elem* find_entry_c(unsigned hv, const void* k, sc_phash_elem*** plast);
00085 sc_phash_elem* find_entry_q(unsigned hv, const void* k, sc_phash_elem*** plast);
00086 sc_phash_elem* find_entry(unsigned hv, const void* k, sc_phash_elem*** plast=0) const
00087 {
00088
00089
00090 if( cmpr == 0 )
00091 return ((sc_phash_base*)this)->find_entry_q( hv, k, plast );
00092 else
00093 return ((sc_phash_base*)this)->find_entry_c( hv, k, plast );
00094 }
00095
00096 public:
00097 sc_phash_base( void* def = 0,
00098 int size = PHASH_DEFAULT_INIT_TABLE_SIZE,
00099 int density = PHASH_DEFAULT_MAX_DENSITY,
00100 double grow = PHASH_DEFAULT_GROW_FACTOR,
00101 bool reorder = PHASH_DEFAULT_REORDER_FLAG,
00102 hash_fn_t hash_fn = default_ptr_hash_fn,
00103 cmpr_fn_t cmpr_fn = 0 );
00104 ~sc_phash_base();
00105
00106 void set_cmpr_fn(cmpr_fn_t);
00107 void set_hash_fn(hash_fn_t);
00108
00109 bool empty() const { return (num_entries == 0); }
00110 unsigned count() const { return num_entries; }
00111
00112 void erase();
00113 void erase(void (*kfree)(void*));
00114 void copy( const sc_phash_base* );
00115 void copy( const sc_phash_base& b ) { copy(&b); }
00116 void copy( const sc_phash_base& b, void* (*kdup)(const void*), void (*kfree)(void*));
00117 int insert( void* k, void* c );
00118 int insert( void* k ) { return insert(k, default_value); }
00119 int insert( void* k, void* c, void* (*kdup)(const void*) );
00120 int insert_if_not_exists(void* k, void* c);
00121 int insert_if_not_exists(void* k) { return insert_if_not_exists(k, default_value); }
00122 int insert_if_not_exists(void* k, void* c, void* (*kdup)(const void*));
00123 int remove(const void* k);
00124 int remove(const void* k, void** pk, void** pc);
00125 int remove(const void* k, void (*kfree)(void*));
00126 int remove_by_contents(const void* c);
00127 int remove_by_contents(bool (*predicate)(const void*, void*), void* arg);
00128 int remove_by_contents(const void* c, void (*kfree)(void*));
00129 int remove_by_contents(bool (*predicate)(const void*, void*), void* arg, void (*kfree)(void*));
00130 int lookup(const void* k, void** pc) const;
00131 bool contains(const void* k) const { return (lookup(k, 0) != 0); }
00132 void* operator[](const void* key) const;
00133 };
00134
00135 class sc_phash_base_iter {
00136 protected:
00137 sc_phash_base* table;
00138 sc_phash_elem* entry;
00139 sc_phash_elem* next;
00140 sc_phash_elem** last;
00141 int index;
00142
00143 public:
00144 void reset(sc_phash_base* t);
00145 void reset(sc_phash_base& t) { reset(&t); }
00146
00147 sc_phash_base_iter(sc_phash_base* t) { reset(t); }
00148 sc_phash_base_iter(sc_phash_base& t) { reset(t); }
00149 ~sc_phash_base_iter() { }
00150
00151 bool empty() const;
00152 void step();
00153 void operator++(int) { step(); }
00154 void remove();
00155 void remove(void (*kfree)(void*));
00156 void* key() const;
00157 void* contents() const;
00158 void* set_contents(void* c);
00159 };
00160
00161 template< class K, class C >
00162 class sc_phash_iter;
00163
00164 template< class K, class C >
00165 class sc_phash : public sc_phash_base {
00166 friend class sc_phash_iter<K,C>;
00167
00168 public:
00169 typedef sc_phash_iter<K,C> iterator;
00170
00171 sc_phash( C def = (C) 0,
00172 int size = PHASH_DEFAULT_INIT_TABLE_SIZE,
00173 int density = PHASH_DEFAULT_MAX_DENSITY,
00174 double grow = PHASH_DEFAULT_GROW_FACTOR,
00175 bool reorder = PHASH_DEFAULT_REORDER_FLAG,
00176 hash_fn_t hash_fn = default_ptr_hash_fn,
00177 cmpr_fn_t cmpr_fn = 0 )
00178 : sc_phash_base((void*) def, size, density, grow, reorder, hash_fn, cmpr_fn) { }
00179 ~sc_phash() { }
00180
00181 void copy(const sc_phash<K,C>* b) { sc_phash_base::copy(b); }
00182 void copy(const sc_phash<K,C>& b) { sc_phash_base::copy(b); }
00183 void copy(const sc_phash<K,C>& b, void* (*kdup)(const void*), void (*kfree)(void*)) { sc_phash_base::copy(b, kdup, kfree); }
00184
00185 int insert(K k, C c) { return sc_phash_base::insert((void*) k, (void*) c); }
00186 int insert(K k) { return sc_phash_base::insert((void*) k, default_value); }
00187 int insert(K k, C c, void* (*kdup)(const void*)) { return sc_phash_base::insert((void*) k, (void*) c, kdup); }
00188 int insert_if_not_exists(K k, C c)
00189 {
00190 return sc_phash_base::insert_if_not_exists((void*) k, (void*) c);
00191 }
00192 int insert_if_not_exists(K k)
00193 {
00194 return sc_phash_base::insert_if_not_exists((void*) k, default_value);
00195 }
00196 int insert_if_not_exists(K k, C c, void* (*kdup)(const void*))
00197 {
00198 return sc_phash_base::insert_if_not_exists((void*) k, (void*) c, kdup);
00199 }
00200 int remove(K k) { return sc_phash_base::remove((const void*) k); }
00201 int remove(K k, K* pk, C* pc)
00202 {
00203 return sc_phash_base::remove((const void*) k, (void**) pk, (void**) pc);
00204 }
00205 int remove(K k, void (*kfree)(void*))
00206 {
00207 return sc_phash_base::remove((const void*) k, kfree);
00208 }
00209 int remove_by_contents(C c)
00210 {
00211 return sc_phash_base::remove_by_contents((const void*) c);
00212 }
00213 int remove_by_contents(bool (*predicate)(const void*, void*), void* arg)
00214 {
00215 return sc_phash_base::remove_by_contents(predicate, arg);
00216 }
00217 int remove_by_contents(const void* c, void (*kfree)(void*))
00218 {
00219 return sc_phash_base::remove_by_contents(c, kfree);
00220 }
00221 int remove_by_contents(bool (*predicate)(const void*, void*), void* arg, void (*kfree)(void*))
00222 {
00223 return sc_phash_base::remove_by_contents(predicate, arg, kfree);
00224 }
00225 int lookup(K k, C* pc) const
00226 {
00227 return sc_phash_base::lookup((const void*) k, (void**) pc);
00228 }
00229 bool contains(K k) const
00230 {
00231 return sc_phash_base::contains((const void*) k);
00232 }
00233 C operator[](K k) const
00234 {
00235 return (C) sc_phash_base::operator[]((const void*) k);
00236 }
00237 };
00238
00239
00240 template< class K, class C >
00241 class sc_phash_iter : public sc_phash_base_iter {
00242 public:
00243 sc_phash_iter(sc_phash<K,C>* t) : sc_phash_base_iter(t) { }
00244 sc_phash_iter(sc_phash<K,C>& t) : sc_phash_base_iter(t) { }
00245 ~sc_phash_iter() { }
00246
00247 void reset(sc_phash<K,C>* t) { sc_phash_base_iter::reset(t); }
00248 void reset(sc_phash<K,C>& t) { sc_phash_base_iter::reset(t); }
00249
00250 K key() const { return (K) sc_phash_base_iter::key(); }
00251 C contents() const { return (C) sc_phash_base_iter::contents(); }
00252 C set_contents(C c)
00253 {
00254 return (C) sc_phash_base_iter::set_contents((void*) c);
00255 }
00256 };
00257
00258
00259
00260
00261
00262 template< class K, class C >
00263 class sc_pdhash : public sc_phash_base {
00264 friend class sc_pdhash_iter<K,C>;
00265
00266 private:
00267 void* (*kdup)(const void*);
00268 void (*kfree)(void*);
00269
00270 public:
00271 typedef sc_pdhash_iter<K,C> iterator;
00272 sc_pdhash( C def = (C) 0,
00273 int size = PHASH_DEFAULT_INIT_TABLE_SIZE,
00274 int density = PHASH_DEFAULT_MAX_DENSITY,
00275 double grow = PHASH_DEFAULT_GROW_FACTOR,
00276 bool reorder = PHASH_DEFAULT_REORDER_FLAG,
00277 hash_fn_t hash_fn = (hash_fn_t) 0,
00278 cmpr_fn_t cmpr_fn = (cmpr_fn_t) 0,
00279 void* (*kdup_fn)(const void*) = 0,
00280 void (*kfree_fn)(void*) = 0 )
00281 : sc_phash_base((void*) def, size, density, grow, reorder, hash_fn, cmpr_fn)
00282 {
00283 kdup = kdup_fn;
00284 kfree = kfree_fn;
00285 }
00286 ~sc_pdhash()
00287 {
00288 erase();
00289 }
00290 void erase()
00291 {
00292 sc_phash_base::erase(kfree);
00293 }
00294 void copy(const sc_pdhash<K,C>& b) { sc_phash_base::copy(b, kdup, kfree); }
00295 int insert(K k, C c) { return sc_phash_base::insert((void*) k, (void*) c, kdup); }
00296 int insert(K k) { return sc_phash_base::insert((void*) k, default_value, kdup); }
00297 int insert_if_not_exists(K k, C c)
00298 {
00299 return sc_phash_base::insert_if_not_exists((void*) k, (void*) c, kdup);
00300 }
00301 int insert_if_not_exists(K k)
00302 {
00303 return sc_phash_base::insert_if_not_exists((void*) k, default_value, kdup);
00304 }
00305 int remove(K k) { return sc_phash_base::remove((const void*) k, kfree); }
00306 int remove(K k, K* pk, C* pc)
00307 {
00308 return sc_phash_base::remove((const void*) k, (void**) pk, (void**) pc);
00309 }
00310 int remove_by_contents(C c)
00311 {
00312 return sc_phash_base::remove_by_contents((const void*) c, kfree);
00313 }
00314 int remove_by_contents(bool (*predicate)(const void*, void*), void* arg)
00315 {
00316 return sc_phash_base::remove_by_contents(predicate, arg, kfree);
00317 }
00318 int lookup(K k, C* pc) const
00319 {
00320 return sc_phash_base::lookup((const void*) k, (void**) pc);
00321 }
00322 bool contains(K k) const
00323 {
00324 return sc_phash_base::contains((const void*) k);
00325 }
00326 C operator[](K k) const
00327 {
00328 return (C) sc_phash_base::operator[]((const void*) k);
00329 }
00330 };
00331
00332 template< class K, class C >
00333 class sc_pdhash_iter : public sc_phash_base_iter {
00334 public:
00335 sc_pdhash_iter(sc_pdhash<K,C>* t) : sc_phash_base_iter(t) { }
00336 sc_pdhash_iter(sc_pdhash<K,C>& t) : sc_phash_base_iter(t) { }
00337 ~sc_pdhash_iter() { }
00338
00339 void reset(sc_pdhash<K,C>* t) { sc_phash_base_iter::reset(t); }
00340 void reset(sc_pdhash<K,C>& t) { sc_phash_base_iter::reset(t); }
00341
00342 void remove() { sc_phash_base_iter::remove(((sc_pdhash<K,C>*) table)->kfree); }
00343 K key() const { return (K) sc_phash_base_iter::key(); }
00344 C contents() const { return (C) sc_phash_base_iter::contents(); }
00345 C set_contents(C c)
00346 {
00347 return (C) sc_phash_base_iter::set_contents((void*) c);
00348 }
00349 };
00350
00351 extern int sc_strhash_cmp( const void*, const void* );
00352 extern void sc_strhash_kfree(void*);
00353 extern void* sc_strhash_kdup(const void*);
00354
00355 template< class C >
00356 class sc_strhash_iter;
00357
00358 template< class C >
00359 class sc_strhash : public sc_phash_base {
00360 friend class sc_strhash_iter<C>;
00361
00362 public:
00363 typedef sc_strhash_iter<C> iterator;
00364
00365 sc_strhash( C def = (C) 0,
00366 int size = PHASH_DEFAULT_INIT_TABLE_SIZE,
00367 int density = PHASH_DEFAULT_MAX_DENSITY,
00368 double grow = PHASH_DEFAULT_GROW_FACTOR,
00369 bool reorder = PHASH_DEFAULT_REORDER_FLAG,
00370 unsigned (*hash_fn)(const void*) = default_str_hash_fn,
00371 int (*cmpr_fn)(const void*, const void*) = sc_strhash_cmp )
00372 : sc_phash_base((void*) def, size, density, grow, reorder, hash_fn, cmpr_fn)
00373 {
00374
00375 }
00376 ~sc_strhash()
00377 {
00378 erase();
00379 }
00380
00381 void erase() { sc_phash_base::erase(sc_strhash_kfree); }
00382 void copy(const sc_strhash<C>* b) { sc_phash_base::copy(*b, sc_strhash_kdup, sc_strhash_kfree); }
00383 void copy(const sc_strhash<C>& b) { sc_phash_base::copy(b, sc_strhash_kdup, sc_strhash_kfree); }
00384
00385 int insert(char* k, C c) { return sc_phash_base::insert((void*) k, (void*) c, sc_strhash_kdup); }
00386 int insert(char* k) { return sc_phash_base::insert((void*) k, default_value, sc_strhash_kdup); }
00387 int insert_if_not_exists(char* k, C c)
00388 {
00389 return sc_phash_base::insert_if_not_exists((void*) k, (void*) c, sc_strhash_kdup);
00390 }
00391 int insert_if_not_exists(char* k)
00392 {
00393 return sc_phash_base::insert_if_not_exists((void*) k, default_value, sc_strhash_kdup);
00394 }
00395 int remove(const char* k) { return sc_phash_base::remove((const void*) k, sc_strhash_kfree); }
00396 int remove(const char* k, char** pk, C* pc)
00397 {
00398 return sc_phash_base::remove((const void*) k, (void**) pk, (void**) pc);
00399 }
00400 int remove_by_contents(C c)
00401 {
00402 return sc_phash_base::remove_by_contents((const void*) c, sc_strhash_kfree);
00403 }
00404 int remove_by_contents(bool (*predicate)(const void*, void*), void* arg)
00405 {
00406 return sc_phash_base::remove_by_contents(predicate, arg, sc_strhash_kfree);
00407 }
00408 int lookup(const char* k, C* pc) const
00409 {
00410 return sc_phash_base::lookup((const void*) k, (void** )pc);
00411 }
00412 bool contains(const char* k) const
00413 {
00414 return sc_phash_base::contains((const void*) k);
00415 }
00416 C operator[](const char* k) const
00417 {
00418 return (C) sc_phash_base::operator[]((const void*) k);
00419 }
00420 };
00421
00422 template<class C>
00423 class sc_strhash_iter : public sc_phash_base_iter {
00424 public:
00425 sc_strhash_iter ( sc_strhash<C>* t ) : sc_phash_base_iter(t) { }
00426 sc_strhash_iter ( sc_strhash<C>& t ) : sc_phash_base_iter(t) { }
00427 ~sc_strhash_iter() { }
00428
00429 void reset ( sc_strhash<C>* t ) { sc_phash_base_iter::reset(t); }
00430 void reset ( sc_strhash<C>& t ) { sc_phash_base_iter::reset(t); }
00431
00432 void remove() { sc_phash_base_iter::remove(sc_strhash_kfree); }
00433 const char* key() { return (const char*) sc_phash_base_iter::key(); }
00434 C contents() { return (C) sc_phash_base_iter::contents(); }
00435 C set_contents(C c)
00436 {
00437 return (C) sc_phash_base_iter::set_contents((void*) c);
00438 }
00439 };
00440
00441 #endif