00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00026 #ifndef HASHTABLE_H
00027 # define HASHTABLE_H
00028
00029
00030 #include <cstring>
00031
00032 #include "defs.h"
00033 #include "collection.h"
00034 #include "debug.h"
00035 #include "xmldefs.h"
00036 #include "xmlchar.h"
00037
00038
00039
00040
00041
00050 static inline unsigned long hashXmlString(const XmlChar *s)
00051 {
00052 unsigned long h = 0;
00053
00054 for ( ; *s; ++s)
00055 h = 5 * h + *s;
00056
00057 return h;
00058 }
00059
00060
00061
00068 template<unsigned long size_> struct HashTableHash
00069 {
00071
00072
00074 unsigned long operator()(const XmlChar *s) const { return hashXmlString(s) % size_; }
00075
00077 unsigned long operator()(char x) const { return x % size_; }
00078
00080 unsigned long operator()(unsigned char x) const { return x % size_; }
00081
00083
00084
00086
00087
00089 unsigned long operator()(int x) const { return x % size_; }
00090
00092 unsigned long operator()(unsigned int x) const { return x % size_; }
00093
00095 unsigned long operator()(long x) const { return x % size_; }
00096
00098 unsigned long operator()(unsigned long x) const { return x % size_; }
00099 };
00100
00101
00102
00103
00104
00111 struct HashTableComparator
00112 {
00114 bool compare(XmlChar x, XmlChar y) { return x == y; }
00115
00117 bool compare(unsigned char x, unsigned char y) { return x == y; }
00118
00119
00120
00122 bool compare(int x, int y) { return x == y; }
00123
00125 bool compare(unsigned int x, unsigned int y) { return x == y; }
00126
00128 bool compare(long x, long y) { return x == y; }
00129
00131 bool compare(unsigned long x, unsigned long y) { return x == y; }
00132
00134 bool compare(XmlChar *x, XmlChar *y) { return !xmlchar_strcmp(x, y); }
00135 };
00136
00137
00138
00145 template<class Key_, class T_> struct HashTableItem
00146 {
00148 Key_ key_;
00149
00151 T_ *data_;
00152 };
00153
00154
00155
00163 template<class Key_, class T_, template<class T_>
00164 class HashTableBucketContainer_> class HashTableBucket
00165 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00166 : public HashTableBucketContainer_< HashTableItem<Key_, T_> >
00167 #endif
00168 {
00169 public:
00171 HashTableComparator comparator_;
00172
00178 virtual void insertItem(HashTableItem<Key_, T_> *item)
00179 {
00180 prepend(item);
00181 }
00182
00183
00190 virtual T_ *find(Key_ key)
00191 {
00192 HashTableItem<Key_, T_> *pom;
00193
00194 for (pom = first(); pom; pom = next())
00195 {
00196 if (comparator_.compare(pom->key_, key))
00197 return pom->data_;
00198 }
00199
00200 return 0;
00201 }
00202
00203
00204
00214 virtual bool removeItem(Key_ key)
00215 {
00216 HashTableItem<Key_, T_> *pom;
00217
00218 pom = first();
00219
00220 while (pom)
00221 {
00222 if (comparator_.compare(pom->key_, key))
00223 {
00224 if (autoDelete_)
00225
00226 DELETE(pom->data_);
00227
00228
00229 return remove();
00230 }
00231
00232 pom = next();
00233 }
00234
00235 return false;
00236 }
00237 };
00238
00239
00240
00262 template<class Key_, class T_, template<class T_> class HashTableBucketContainer_, unsigned long size_> class HashTable : public Collection<T_>
00263 {
00264 public:
00265
00269 HashTable(void) : Collection<T_>()
00270 {
00271 NEW(table_, (HashTableBucket<Key_, T_, HashTableBucketContainer_> *[size_]));
00272
00273 for (unsigned long i = 0; i < size_; i++)
00274 table_[i] = 0;
00275 }
00276
00282 virtual ~HashTable(void)
00283 {
00284 clear();
00285 DELETE_ARRAY(table_);
00286 }
00287
00288
00298 virtual T_ *find(Key_ key)
00299 {
00300 unsigned long pos = hash_(key);
00301
00302 if (!table_[pos])
00303 return 0;
00304 else
00305 return table_[pos]->find(key);
00306 }
00307
00308
00317 virtual void insert(Key_ key, T_ *item)
00318 {
00319 unsigned long pos = hash_(key);
00320
00321 if (!table_[pos])
00322 {
00323 NEW(table_[pos], (HashTableBucket<Key_, T_, HashTableBucketContainer_>));
00324 }
00325
00326 if (!contains(key))
00327 {
00328 HashTableItem<Key_, T_> *tableItem;
00329
00330 NEW(tableItem, (HashTableItem<Key_, T_>));
00331
00332 tableItem->key_ = key;
00333 tableItem->data_ = item;
00334 table_[pos]->insertItem(tableItem);
00335 cnt_++;
00336 }
00337 }
00338
00339
00350 virtual bool remove(Key_ key)
00351 {
00352 unsigned long pos = hash_(key);
00353
00354 if (!table_[pos])
00355 return false;
00356 else
00357 {
00358 if (table_[pos]->removeItem(key))
00359 {
00360 cnt_--;
00361 return true;
00362 }
00363 else
00364 return false;
00365 }
00366 }
00367
00368
00377 virtual bool contains(Key_ key)
00378 {
00379 unsigned long pos = hash_(key);
00380
00381 if (!table_[pos])
00382 return false;
00383 else
00384 return (table_[pos]->find(key) != 0);
00385 }
00386
00387
00393 virtual void clear(void)
00394 {
00395 for (unsigned long i = 0; i < size_; i++)
00396 {
00397 if (autoDelete_)
00398 {
00399 if (table_[i])
00400 {
00401
00402
00403
00404
00405 }
00406 }
00407
00408 if (table_[i])
00409 {
00410 DELETE(table_[i]);
00411
00412 }
00413 }
00414 }
00415
00416
00424 virtual void setAutoDelete(bool ad)
00425 {
00426 for (unsigned long i = 0; i < size_; i++)
00427 {
00428 if (table_[i])
00429 table_[i]->setAutoDelete(ad);
00430 }
00431
00432 autoDelete_ = ad;
00433 }
00434
00435 protected:
00437 HashTableBucket<Key_, T_, HashTableBucketContainer_> **table_;
00438
00440 HashTableHash<size_> hash_;
00441 };
00442
00443 #endif //HASHTABLE_H
00444