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