00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef _TABLE_H
00024 #define _TABLE_H
00025
00026 #include <Basics.H>
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 template <class K, class V>
00086 class Table {
00087 public:
00088
00089 class Iterator;
00090
00091
00092
00093 class T {
00094 public:
00095 bool Get(const K& k, V& v) const throw ();
00096
00097
00098
00099
00100 bool Put(const K& k, const V& v, bool resize = true) throw ();
00101
00102
00103
00104
00105 bool Delete(const K& k, V& v, bool resize = true) throw ();
00106
00107
00108
00109
00110 int Size() const throw ();
00111
00112 };
00113
00114
00115 class Default {
00116 public:
00117
00118 Default(int sizeHint = 0, bool useGC = false) throw ()
00119 : maxEntries(!useGC), buckets(NULL) { Init(sizeHint); }
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 Default(const Default *tbl, bool useGC = false) throw ()
00131 : maxEntries(!useGC), buckets(NULL)
00132 { Init(tbl->numEntries); Copy(tbl); }
00133
00134
00135
00136 ~Default() throw ();
00137
00138
00139 void Init(Bit32 sizeHint = 0U) throw ();
00140
00141
00142
00143
00144
00145 Default& operator = (const Default& tbl) throw ()
00146 { Init(tbl.numEntries); Copy(&tbl); return *this; }
00147
00148
00149
00150 int Size() const throw () { return numEntries; }
00151 bool Get(const K& k, V& v) const throw ();
00152 bool Put(const K& k, const V& v, bool resize = true) throw ();
00153 bool Delete(const K& k, V& v, bool resize = true) throw ();
00154
00155
00156
00157
00158
00159
00160
00161 void Resize() throw ();
00162
00163
00164
00165
00166 private:
00167
00168 class EntryList {
00169 public:
00170 EntryList(const K& k, const V& v, EntryList *next)
00171 : key(k), val(v), tail(next) { }
00172 EntryList *tail;
00173 K key;
00174 V val;
00175 };
00176 typedef EntryList *EntryListPtr;
00177
00178 Bit32 numEntries;
00179 Bit32 minEntries;
00180 Bit32 maxEntries;
00181 Bit16 logBuckets;
00182 Bit16 minLogBuckets;
00183 EntryListPtr *buckets;
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 void NewBuckets(bool allocBuckets) throw ();
00196
00197
00198
00199
00200
00201 void AllocBuckets(Bit32 numBuckets) throw ();
00202
00203
00204
00205 void EmptyBuckets(Bit32 numBuckets) throw ();
00206
00207
00208 void Rehash(Bit16 logBuckets) throw ();
00209
00210
00211
00212 inline Bit32 Bucket(const K &k) const throw ();
00213
00214
00215 void Copy(const Default* tbl) throw ();
00216
00217
00218
00219
00220
00221 friend class Iterator;
00222
00223
00224 Default(const Default&);
00225 };
00226
00227 class Iterator {
00228 public:
00229 Iterator(const Default* tbl) throw ()
00230 : tbl(tbl) { Reset(); }
00231
00232
00233
00234
00235
00236
00237 void Reset() throw ();
00238
00239
00240
00241
00242 bool Next( K& k, V& v) throw ();
00243
00244
00245
00246
00247 private:
00248
00249 const Default *tbl;
00250 typedef typename Default::EntryList EntryList;
00251 EntryList *curr;
00252 Bit32 bucket;
00253 bool done;
00254
00255
00256 Iterator(const Iterator&);
00257 };
00258 };
00259
00260
00261
00262 #include "TableUtils.H"
00263 #include "TableConsts.H"
00264
00265
00266
00267 template <class K, class V>
00268 void Table<K,V>::Default::Copy(const Default *tbl) throw ()
00269
00270
00271
00272 {
00273 Iterator iter(tbl);
00274 K key; V value;
00275 while (iter.Next( key, value)) {
00276
00277 (void) Put(key, value, false);
00278 }
00279 Resize();
00280 }
00281
00282 template <class K, class V>
00283 void Table<K,V>::Default::Init(Bit32 sizeHint) throw ()
00284 {
00285 Bit32 idealBuckets;
00286 float idealF = (float)sizeHint / TableConsts::IdealDensity;
00287 idealBuckets = (idealF > (float)TableConsts::MaxBuckets) ? TableConsts::MaxBuckets : Ceiling(idealF);
00288 idealBuckets = max(TableConsts::MinBuckets, idealBuckets);
00289 this->numEntries = 0U;
00290 if (this->buckets != NULL && idealBuckets < (TableConsts::One32U << this->logBuckets)) {
00291
00292 EmptyBuckets(TableConsts::One32U << this->logBuckets);
00293 } else {
00294
00295 this->logBuckets = this->minLogBuckets = Log_2(idealBuckets);
00296 NewBuckets(sizeHint > 0);
00297 }
00298 }
00299
00300 template <class K, class V>
00301 Table<K,V>::Default::~Default() throw ()
00302 {
00303 if (this->buckets != (EntryListPtr *)NULL) {
00304 if ((this->maxEntries & TableConsts::DoDeletions) != 0) {
00305 Bit32 numBuckets = (TableConsts::One32U << this->logBuckets);
00306 for (Bit32 i = 0U; i < numBuckets; i++) {
00307 EntryList *curr = this->buckets[i];
00308 while (curr != (EntryList *)NULL) {
00309 EntryList *prev = curr;
00310 curr = curr->tail;
00311 prev->tail = (EntryList *)NULL;
00312 delete prev;
00313 }
00314 }
00315 }
00316 delete[] this->buckets;
00317 this->buckets = (EntryListPtr *)NULL;
00318 }
00319 }
00320
00321 template <class K, class V>
00322 void Table<K,V>::Default::NewBuckets(bool allocBuckets) throw ()
00323 {
00324
00325 Bit32 numBuckets = (TableConsts::One32U << this->logBuckets);
00326 this->minEntries = Round(TableConsts::MinDensity * (float)numBuckets);
00327 Bit32 doDeletions = this->maxEntries & TableConsts::DoDeletions;
00328 this->maxEntries = TableConsts::DoDeletionsBar &
00329 Round(TableConsts::MaxDensity * (float)numBuckets);
00330 this->maxEntries |= doDeletions;
00331
00332
00333 if (allocBuckets) {
00334 AllocBuckets(numBuckets);
00335 } else {
00336 this->buckets = NULL;
00337 }
00338 }
00339
00340 template <class K, class V>
00341 void Table<K,V>::Default::AllocBuckets(Bit32 numBuckets) throw ()
00342 {
00343 this->buckets = NEW_ARRAY(EntryListPtr, numBuckets);
00344 assert(this->buckets != NULL);
00345 EmptyBuckets(numBuckets);
00346 }
00347
00348 template <class K, class V>
00349 void Table<K,V>::Default::EmptyBuckets(Bit32 numBuckets) throw ()
00350 {
00351 for (Bit32 i = 0U; i < numBuckets; i++) {
00352 this->buckets[i] = (EntryList *)NULL;
00353 }
00354 }
00355
00356 template <class K, class V>
00357 inline Bit32 Table<K,V>::Default::Bucket(const K& k) const throw ()
00358 {
00359 return ((TableConsts::Multiplier * k.Hash()) >> (TableConsts::BitsPerWd - this->logBuckets));
00360 }
00361
00362 template <class K, class V>
00363 void Table<K,V>::Default::Rehash(Bit16 logBuckets) throw ()
00364 {
00365 assert(logBuckets <= TableConsts::MaxLogBuckets);
00366 assert(logBuckets >= this->minLogBuckets);
00367
00368 EntryListPtr *ob = this->buckets;
00369 Bit16 oldLogBuckets = this->logBuckets;
00370 Bit32 oldNumBuckets = (TableConsts::One32U << oldLogBuckets);
00371
00372
00373 this->logBuckets = logBuckets;
00374 NewBuckets(ob != NULL);
00375
00376 if (ob != NULL) {
00377
00378 for (Bit32 i = 0U; i < oldNumBuckets; i++) {
00379 EntryList *curr = ob[i], *tail;
00380 ob[i] = (EntryList *)NULL;
00381 while (curr != (EntryList *)NULL) {
00382 int ix = Bucket(curr->key);
00383 tail = curr->tail;
00384 curr->tail = this->buckets[ix];
00385 this->buckets[ix] = curr;
00386 curr = tail;
00387 }
00388 }
00389
00390
00391 if (this->maxEntries & TableConsts::DoDeletions)
00392 delete[] ob;
00393 }
00394 }
00395
00396 template <class K, class V>
00397 void Table<K,V>::Default::Resize() throw ()
00398 {
00399 if (this->numEntries < this->minEntries
00400 && this->logBuckets > this->minLogBuckets) {
00401
00402 Rehash(this->logBuckets - 1);
00403 } else if (this->numEntries > this->maxEntries
00404 && this->logBuckets < TableConsts::MaxLogBuckets) {
00405
00406 Rehash(this->logBuckets + 1);
00407 }
00408 }
00409
00410 template <class K, class V>
00411 bool Table<K,V>::Default::Get(const K& k, V& v) const throw ()
00412 {
00413 if (this->buckets == NULL) return false;
00414 register EntryList *curr = this->buckets[Bucket(k)];
00415
00416 while (curr != (EntryList *)NULL && !(curr->key == k)) {
00417 curr = curr->tail;
00418 }
00419 if (curr != (EntryList *)NULL) {
00420 v = curr->val;
00421 return true;
00422 } else {
00423 return false;
00424 }
00425 }
00426
00427 template <class K, class V>
00428 bool Table<K,V>::Default::Put(const K& k, const V& v, bool resize) throw ()
00429 {
00430 Bit32 b = Bucket(k);
00431 if (this->buckets == NULL) AllocBuckets(TableConsts::One32U << this->logBuckets);
00432 register EntryList *curr = this->buckets[b];
00433
00434 while (curr != (EntryList *)NULL && !(curr->key == k)) {
00435 curr = curr->tail;
00436 }
00437 if (curr != (EntryList *)NULL) {
00438 curr->val = v;
00439 return true;
00440 } else {
00441 this->buckets[b] = NEW_CONSTR(EntryList, (k, v, this->buckets[b]));
00442 this->numEntries++;
00443 if (resize && this->numEntries > this->maxEntries
00444 && this->logBuckets < TableConsts::MaxLogBuckets) {
00445
00446 Rehash(this->logBuckets + 1);
00447 }
00448 return false;
00449 }
00450 }
00451
00452 template <class K, class V>
00453 bool Table<K,V>::Default::Delete(const K& k, V& v, bool resize)
00454 throw ()
00455 {
00456 if (this->buckets == NULL) return false;
00457 Bit32 b = Bucket(k);
00458 EntryList *curr = this->buckets[b];
00459 EntryList *prev = (EntryList *)NULL;
00460
00461 while (curr != (EntryList *)NULL && !(curr->key == k)) {
00462 prev = curr;
00463 curr = curr->tail;
00464 }
00465 if (curr != (EntryList *)NULL) {
00466 v = curr->val;
00467 if (prev == (EntryList *)NULL)
00468 this->buckets[b] = curr->tail;
00469 else
00470 prev->tail = curr->tail;
00471 this->numEntries--;
00472 if (this->maxEntries & TableConsts::DoDeletions) delete curr;
00473 if (resize && this->numEntries < this->minEntries
00474 && this->logBuckets > this->minLogBuckets) {
00475
00476 Rehash(this->logBuckets - 1);
00477 }
00478 return true;
00479 } else {
00480 return false;
00481 }
00482 }
00483
00484
00485
00486 template <class K, class V>
00487 void Table<K,V>::Iterator::Reset() throw ()
00488 {
00489 this->curr = (EntryList *)NULL;
00490 this->bucket = 0U;
00491 this->done = false;
00492 }
00493
00494 template <class K, class V>
00495 bool Table<K,V>::Iterator::Next( K& k, V& v) throw ()
00496 {
00497 if (this->tbl->buckets != NULL) {
00498 while (this->curr == (EntryList *)NULL
00499 && this->bucket < (TableConsts::One32U << tbl->logBuckets)) {
00500 this->curr = this->tbl->buckets[this->bucket];
00501 this->bucket++;
00502 }
00503 }
00504 if (this->curr != (EntryList *)NULL) {
00505 k = curr->key;
00506 v = curr->val;
00507 this->curr = this->curr->tail;
00508 return true;
00509 } else {
00510 assert(!(this->done));
00511 this->done = true;
00512 return false;
00513 }
00514 }
00515
00516 #endif // _TABLE_H