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