csutil/hash.h
00001 /* 00002 Copyright (C) 2003 by Mat Sutcliffe <oktal@gmx.co.uk> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Lesser General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public 00015 License along with this library; if not, write to the Free 00016 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00017 */ 00018 00019 #ifndef __CS_UTIL_HASH_H__ 00020 #define __CS_UTIL_HASH_H__ 00021 00022 #include "csextern.h" 00023 #include "array.h" 00024 00031 CS_CSUTIL_EXPORT unsigned int csHashCompute (char const*); 00032 00039 CS_CSUTIL_EXPORT unsigned int csHashCompute (char const*, int length); 00040 00044 template <class T> 00045 class csIntegralHashKeyHandler 00046 { 00047 public: 00048 static unsigned int ComputeHash (const T& key) 00049 { 00050 return (unsigned int)key; 00051 } 00052 00053 static bool CompareKeys (const T& key1, const T& key2) 00054 { 00055 return (key1 == key2); 00056 } 00057 }; 00058 00063 template <class T, class K = unsigned int, 00064 class KeyHandler = csIntegralHashKeyHandler<K> > 00065 class csHash 00066 { 00067 protected: 00068 struct Element 00069 { 00070 const K key; 00071 T value; 00072 00073 Element (const K& key0, const T &value0) : key (key0), value (value0) {} 00074 Element (const Element &other) : key (other.key), value (other.value) {} 00075 }; 00076 csArray< csArray<Element> > Elements; 00077 00078 int Modulo; 00079 00080 private: 00081 int InitModulo; 00082 int GrowRate; 00083 int MaxSize; 00084 int Size; 00085 00086 void Grow () 00087 { 00088 static const int Primes[] = 00089 { 00090 53, 97, 193, 389, 769, 00091 1543, 3079, 6151, 12289, 24593, 00092 49157, 98317, 196613, 393241, 786433, 00093 1572869, 3145739, 6291469, 12582917, 25165843, 00094 50331653, 100663319, 201326611, 402653189, 805306457, 00095 1610612741, 0 00096 }; 00097 00098 const int *p; 00099 int elen = Elements.Length (); 00100 for (p = Primes; *p && *p <= elen; p++) ; 00101 Modulo = *p; 00102 CS_ASSERT (Modulo); 00103 00104 Elements.SetLength (Modulo); 00105 00106 for (int i = 0; i < elen; i++) 00107 { 00108 csArray<Element>& src = Elements[i]; 00109 int slen = src.Length (); 00110 for (int j = slen - 1; j >= 0; j--) 00111 { 00112 const Element& srcElem = src[j]; 00113 csArray<Element>& dst = 00114 Elements.Get (KeyHandler::ComputeHash (srcElem.key) % Modulo); 00115 if (&src != &dst) 00116 { 00117 dst.Push (srcElem); 00118 src.DeleteIndex (j); 00119 } 00120 } 00121 } 00122 } 00123 00124 public: 00138 csHash (int size = 257, int grow_rate = 64, int max_size = 20000) 00139 : Elements (size), Modulo (size), InitModulo (size), 00140 GrowRate (grow_rate), MaxSize (max_size), Size (0) 00141 { 00142 Elements.SetLength (size, csArray<Element> (0, 8)); 00143 } 00144 00146 csHash (const csHash<T> &o) : Elements (o.Elements), 00147 Modulo (o.Modulo), InitModulo (o.InitModulo), 00148 GrowRate (o.GrowRate), MaxSize (o.MaxSize), Size (o.Size) {} 00149 00151 void Put (const K& key, const T &value) 00152 { 00153 csArray<Element> &values = 00154 Elements[KeyHandler::ComputeHash (key) % Modulo]; 00155 values.Push (Element (key, value)); 00156 Size++; 00157 if (values.Length () > Elements.Length () / GrowRate 00158 && Elements.Length () < MaxSize) Grow (); 00159 } 00160 00162 csArray<T> GetAll (const K& key) const 00163 { 00164 const csArray<Element> &values = 00165 Elements[KeyHandler::ComputeHash (key) % Modulo]; 00166 csArray<T> ret (values.Length () / 2); 00167 const int len = values.Length (); 00168 for (int i = 0; i < len; ++i) 00169 { 00170 const Element& v = values[i]; 00171 if (KeyHandler::CompareKeys (v.key, key)) 00172 ret.Push (v.value); 00173 } 00174 return ret; 00175 } 00176 00178 void PutFirst (const K& key, const T &value) 00179 { 00180 csArray<Element> &values = 00181 Elements[KeyHandler::ComputeHash (key) % Modulo]; 00182 const int len = values.Length (); 00183 for (int i = 0; i < len; ++i) 00184 { 00185 Element& v = values[i]; 00186 if (KeyHandler::CompareKeys (v.key, key)) 00187 { 00188 v.value = value; 00189 return; 00190 } 00191 } 00192 00193 values.Push (Element (key, value)); 00194 Size++; 00195 if (values.Length () > Elements.Length () / GrowRate 00196 && Elements.Length () < MaxSize) Grow (); 00197 } 00198 00200 bool In (const K& key) const 00201 { 00202 const csArray<Element> &values = 00203 Elements[KeyHandler::ComputeHash (key) % Modulo]; 00204 const int len = values.Length (); 00205 for (int i = 0; i < len; ++i) 00206 if (KeyHandler::CompareKeys (values[i].key, key)) 00207 return true; 00208 00209 return false; 00210 } 00211 00216 const T* GetElementPointer (const K& key) const 00217 { 00218 const csArray<Element> &values = 00219 Elements[KeyHandler::ComputeHash (key) % Modulo]; 00220 const int len = values.Length (); 00221 for (int i = 0; i < len; ++i) 00222 { 00223 const Element& v = values[i]; 00224 if (KeyHandler::CompareKeys (v.key, key)) 00225 return &v.value; 00226 } 00227 00228 return 0; 00229 } 00230 00235 T* GetElementPointer (const K& key) 00236 { 00237 csArray<Element> &values = 00238 Elements[KeyHandler::ComputeHash (key) % Modulo]; 00239 const int len = values.Length (); 00240 for (int i = 0; i < len; ++i) 00241 { 00242 Element& v = values[i]; 00243 if (KeyHandler::CompareKeys (v.key, key)) 00244 return &v.value; 00245 } 00246 00247 return 0; 00248 } 00249 00254 const T& Get (const K& key, const T& fallback) const 00255 { 00256 const csArray<Element> &values = 00257 Elements[KeyHandler::ComputeHash (key) % Modulo]; 00258 const int len = values.Length (); 00259 for (int i = 0; i < len; ++i) 00260 { 00261 const Element& v = values[i]; 00262 if (KeyHandler::CompareKeys (v.key, key)) 00263 return v.value; 00264 } 00265 00266 return fallback; 00267 } 00268 00273 T& Get (const K& key, T& fallback) 00274 { 00275 csArray<Element> &values = 00276 Elements[KeyHandler::ComputeHash (key) % Modulo]; 00277 const int len = values.Length (); 00278 for (int i = 0; i < len; ++i) 00279 { 00280 Element& v = values[i]; 00281 if (KeyHandler::CompareKeys (v.key, key)) 00282 return v.value; 00283 } 00284 00285 return fallback; 00286 } 00287 00289 void DeleteAll () 00290 { 00291 Elements.SetLength (Modulo = InitModulo); 00292 int elen = Elements.Length (); 00293 for (int i = 0; i < elen; i++) 00294 Elements[i].Empty (); 00295 Size = 0; 00296 } 00297 00299 bool DeleteAll (const K& key) 00300 { 00301 bool ret = false; 00302 csArray<Element> &values = 00303 Elements[KeyHandler::ComputeHash (key) % Modulo]; 00304 for (int i = values.Length () - 1; i >= 0; i--) 00305 if (KeyHandler::CompareKeys (values[i].key, key)) 00306 { 00307 values.DeleteIndex (i); 00308 ret = true; 00309 Size--; 00310 } 00311 return ret; 00312 } 00313 00315 bool Delete (const K& key, const T &value) 00316 { 00317 bool ret = false; 00318 csArray<Element> &values = 00319 Elements[KeyHandler::ComputeHash (key) % Modulo]; 00320 for (int i = values.Length () - 1; i >= 0; i--) 00321 if (KeyHandler::CompareKeys (values[i].key, key) && 00322 (values[i].value == value)) 00323 { 00324 values.DeleteIndex (i); 00325 ret = true; 00326 Size--; 00327 } 00328 return ret; 00329 } 00330 00332 int GetSize () const 00333 { 00334 return Size; 00335 } 00336 00338 class Iterator 00339 { 00340 private: 00341 const csHash<T, K, KeyHandler>* hash; 00342 const K key; 00343 int bucket, size, element; 00344 00345 void Seek () 00346 { 00347 while ((element < size) && 00348 ! KeyHandler::CompareKeys (hash->Elements[bucket][element].key, key)) 00349 element++; 00350 } 00351 00352 protected: 00353 Iterator (const csHash<T, K, KeyHandler>* hash0, const K& key0) : 00354 hash(hash0), 00355 key(key0), 00356 bucket(KeyHandler::ComputeHash(key) % hash->Modulo), 00357 size(hash->Elements[bucket].Length ()) 00358 { Reset (); } 00359 00360 friend class csHash; 00361 public: 00363 Iterator (const Iterator &o) : 00364 hash (o.hash), 00365 key(o.key), 00366 bucket(o.bucket), 00367 size(o.size), 00368 element(o.element) {} 00369 00371 Iterator& operator=(const Iterator& o) 00372 { 00373 hash = o.hash; 00374 key = o.key; 00375 bucket = o.bucket; 00376 size = o.size; 00377 element = o.element; 00378 return *this; 00379 } 00380 00382 bool HasNext () const 00383 { 00384 return element < size; 00385 } 00386 00388 const T& Next () 00389 { 00390 const T &ret = hash->Elements[bucket][element].value; 00391 element++; 00392 Seek (); 00393 return ret; 00394 } 00395 00397 void Reset () { element = 0; Seek (); } 00398 }; 00399 friend class Iterator; 00400 00402 class GlobalIterator 00403 { 00404 private: 00405 const csHash<T, K, KeyHandler> *hash; 00406 int bucket, size, element; 00407 00408 void Zero () { bucket = element = 0; } 00409 void Init () { size = hash->Elements[bucket].Length (); } 00410 00411 void FindItem () 00412 { 00413 if (element >= size) 00414 { 00415 while (++bucket < hash->Elements.Length ()) 00416 { 00417 Init (); 00418 if (size != 0) 00419 { 00420 element = 0; 00421 break; 00422 } 00423 } 00424 } 00425 } 00426 00427 protected: 00428 GlobalIterator (const csHash<T, K, KeyHandler> *hash0) : hash (hash0) 00429 { 00430 Zero (); 00431 Init (); 00432 FindItem (); 00433 } 00434 00435 friend class csHash; 00436 public: 00438 GlobalIterator (const Iterator &o) : 00439 hash (o.hash), 00440 bucket (o.bucket), 00441 size (o.size), 00442 element (o.element) {} 00443 00445 GlobalIterator& operator=(const GlobalIterator& o) 00446 { 00447 hash = o.hash; 00448 bucket = o.bucket; 00449 size = o.size; 00450 element = o.element; 00451 return *this; 00452 } 00453 00455 bool HasNext () const 00456 { 00457 if (hash->Elements.Length () == 0) return false; 00458 return element < size || bucket < hash->Elements.Length (); 00459 } 00460 00462 void Advance () 00463 { 00464 element++; 00465 FindItem (); 00466 } 00467 00469 const T& NextNoAdvance () 00470 { 00471 return hash->Elements[bucket][element].value; 00472 } 00473 00475 const T& Next () 00476 { 00477 const T &ret = NextNoAdvance (); 00478 Advance (); 00479 return ret; 00480 } 00481 00482 const T& NextNoAdvance (K &key) 00483 { 00484 key = hash->Elements[bucket][element].key; 00485 return NextNoAdvance (); 00486 } 00487 00489 const T& Next (K &key) 00490 { 00491 key = hash->Elements[bucket][element].key; 00492 return Next (); 00493 } 00494 00496 void Reset () { Zero (); Init (); FindItem (); } 00497 }; 00498 friend class GlobalIterator; 00499 00502 void DeleteElement (GlobalIterator iterator) 00503 { 00504 Elements[iterator.bucket].DeleteIndex(iterator.element); 00505 Size--; 00506 iterator.size--; 00507 iterator.FindItem (); 00508 } 00509 00516 Iterator GetIterator (const K& key) const 00517 { 00518 return Iterator (this, key); 00519 } 00520 00526 GlobalIterator GetIterator () const 00527 { 00528 return GlobalIterator (this); 00529 } 00530 }; 00531 00537 template <class T, class KeyHandler = csIntegralHashKeyHandler<T> > 00538 class csSet 00539 { 00540 private: 00541 csHash<T, T, KeyHandler> map; 00542 00543 public: 00545 class Iterator : public csHash<T, T, KeyHandler>::Iterator 00546 { 00547 protected: 00548 Iterator () {} 00549 public: 00550 }; 00552 class GlobalIterator : public csHash<T, T, KeyHandler>::GlobalIterator 00553 { 00554 protected: 00555 GlobalIterator () {} 00556 GlobalIterator (const csSet<T, KeyHandler> *set0) : 00557 csHash<T, T, KeyHandler>::GlobalIterator(&set0->map) 00558 { } 00559 00560 public: 00561 friend class csSet; 00562 }; 00563 friend class GlobalIterator; 00564 00569 csSet (int size = 257, int grow_rate = 64, int max_size = 20000) 00570 : map (size, grow_rate, max_size) 00571 { 00572 } 00573 00578 void Add (const T& object) 00579 { 00580 if (In (object)) return; 00581 AddNoTest (object); 00582 } 00583 00590 void AddNoTest (const T& object) 00591 { 00592 map.Put (object, object); 00593 } 00594 00598 bool In (const T& object) const 00599 { 00600 return map.In (object); 00601 } 00602 00606 void DeleteAll () 00607 { 00608 map.DeleteAll (); 00609 } 00610 00616 bool Delete (const T& object) 00617 { 00618 return map.Delete (object, object); 00619 } 00620 00622 int GetSize () const 00623 { 00624 return map.GetSize (); 00625 } 00626 00628 csHash<T, T, KeyHandler>* GetHash () { return ↦ } 00629 00635 GlobalIterator GetIterator () const 00636 { 00637 return GlobalIterator(this); 00638 } 00639 }; 00640 00641 00642 #endif
Generated for Crystal Space by doxygen 1.2.18