00001
00002
00003
00004
00005 #ifndef dsHashTable_H
00006 #define dsHashTable_H
00007
00008 #ifdef HAVE_CONFIG_H
00009 # include <config.h>
00010 #endif
00011
00012
00013 #ifdef WITH_HASH_STAT
00014 #include <stdio.h>
00015 #endif
00016
00017 #include <dsSmartException.h>
00018 #include <dsDataAccessor.h>
00019
00020 #define HASH_INCREMENT 1024
00021 #define HASH_MAXSIZE 32576
00022
00023
00024 DECLARE_EXCEPTION2(dsHash, dsDataAccessor);
00025
00026
00027
00031 class dsHashTableItem : public dsDataAccessorItem
00032 {
00033 public:
00034 dsHashTableItem():
00035 dsDataAccessorItem(){}
00036
00037 dsHashTableItem(void *xval):
00038 dsDataAccessorItem(xval){ }
00039 };
00040
00054 typedef dsHashTableItem *dsHashTableItemPtr;
00055
00056 class dsHashTableGeneric : public dsDataAccessor
00057 {
00058 dsHashTableItem **_Table;
00059 int _HSize;
00060
00061 int GrowUp(void);
00062
00063 dsHashTableItem* _hi_seek(void *a, int *HIndex );
00064
00065 protected:
00066 virtual int cf(void * a, void *b) = 0;
00067 virtual int primary_hash_func( void *a) = 0;
00068 virtual int secondary_hash_func( void *a) = 0;
00069
00070 public:
00075 dsHashTableGeneric(int numEntries, DACleanupMode purge = cmPURGE);
00076 virtual ~dsHashTableGeneric();
00077
00078
00079
00080 virtual void *insert(void *a, bool replace = false );
00081 virtual void *remove(void *a);
00082 virtual void *seek(void *a);
00083
00087 void clear();
00091 void *walk(int i);
00092
00096 int HSize(void);
00097
00101 int NumEntries(void);
00102
00103
00104 #ifdef WITH_HASH_STAT
00105 long n_computation;
00106 long n_cmps;
00107 long n_grows;
00108 long n_repeats;
00109
00110 void print_stat()
00111 {
00112 printf("Table size: %ld\n",HSize());
00113 printf("Table entries: %ld\n",NumEntries() );
00114 printf("\nWarning! All Library should be compiled with -DWITH_HASH_STAT\n");
00115 printf("Hash computation: %ld\n",n_computation);
00116 printf("String comparisons: %ld\n",n_cmps);
00117 printf("String repeats: %ld\n",n_repeats);
00118 printf("Table resizing: %ld\n",n_grows);
00119 }
00120 #endif
00121
00122 };
00123
00124 inline int dsHashTableGeneric::HSize(void)
00125 {
00126 return _HSize;
00127 }
00128
00129 inline void *dsHashTableGeneric::walk(int i)
00130 {
00131 if (i > _HSize)
00132 throw dsHashException("Index out of bounds");
00133
00134 return (_Table[i]) ? _Table[i]->body : 0;
00135 }
00136
00137 inline int dsHashTableGeneric::NumEntries(void)
00138 {
00139 int total=0;
00140
00141 for (int i=0; i < _HSize; i++)
00142 {
00143 if (_Table[i]) total++;
00144 }
00145
00146 return total;
00147 }
00148
00149
00150
00151
00152 class dsHashTable : public dsHashTableGeneric
00153 {
00154
00155 int HFuncAddition( const char *key );
00156 int HFuncHorner( const char *key );
00157 const char *key(void *a) { return ((dsDataPair *)a)->key; }
00158
00159 protected:
00160 virtual int cf(void * a, void *b) { return strcmp(key(a), key(b)); }
00161 virtual int primary_hash_func( void *a) { return HFuncAddition( key(a) ); }
00162 virtual int secondary_hash_func( void *a) { return HFuncHorner( key(a) ); }
00163
00164 public:
00165 dsHashTable(int numEntries, DACleanupMode purge = cmPURGE):
00166 dsHashTableGeneric(numEntries,purge){}
00167
00168
00169 char * seek(const char *key, char *defval = 0);
00170
00171 dsDataPair *seek(dsDataPair *dp);
00172
00173 void *insert(const char *key, void *value, bool replace = false);
00174 void *insert(const char *key, const void *value, size_t size, bool replace = false);
00175
00176 char *insert(const char *key, const char * value, bool replace = false);
00177 long insert(const char *key, long value, bool replace = false);
00178
00179 dsDataPair *insert(dsDataPair *dp, bool replace = false);
00180 };
00181
00182
00183
00184 inline dsDataPair * dsHashTable::seek(dsDataPair *dp)
00185 {
00186 return (dsDataPair *) dsHashTableGeneric::seek((void *)dp);
00187 }
00188
00189 inline dsDataPair *dsHashTable::insert(dsDataPair *dp, bool replace)
00190 {
00191 return (dsDataPair *) dsHashTableGeneric::insert((void *)dp, replace);
00192 }
00193
00194 inline char * dsHashTable::seek(const char *xkey, char *defval)
00195 {
00196 dsDataPair dp(xkey);
00197 dsDataPair *tmp = seek(&dp);
00198 return (tmp) ? (char *) (tmp->val) : defval;
00199 }
00200
00201
00202 inline void *dsHashTable::insert(const char *key, void *value, bool replace)
00203 {
00204 dsDataPair *hi = new dsDataPair(key, value);
00205 dsDataPair *tmp = insert(hi, replace);
00206 if (tmp)
00207 { if (!replace)
00208 delete hi;
00209 return tmp->val;
00210 }
00211
00212 return 0;
00213 }
00214
00215 inline void *dsHashTable::insert(const char *key, const void *value, size_t size, bool replace)
00216 {
00217 dsDataPair *hi = new dsDataPair(key, value, size);
00218 dsDataPair *tmp = insert(hi, replace);
00219 if (tmp)
00220 { if (!replace)
00221 delete hi;
00222 return tmp->val;
00223 }
00224
00225 return 0;
00226 }
00227
00228
00229 inline char *dsHashTable::insert(const char *key, const char * value, bool replace)
00230 {
00231 dsDataPair *hi = new dsDataPair(key, value);
00232 dsDataPair *tmp = insert(hi, replace);
00233 if (tmp)
00234 { if (!replace)
00235 delete hi;
00236 return (char *)tmp->val;
00237 }
00238
00239 return 0;
00240 }
00241
00242 inline long dsHashTable::insert(const char *key, long value, bool replace)
00243 {
00244 dsDataPair *hi = new dsDataPair(key, &value, sizeof(value) );
00245 dsDataPair *tmp = insert(hi, replace);
00246 if (tmp)
00247 { if (!replace)
00248 delete hi;
00249 return *((long *)(tmp->val));
00250 }
00251
00252 return 0;
00253 }
00254
00255
00256
00257 #endif
00258