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