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