CrystalSpace

Public API Reference

Main Page   Modules   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

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 &map; }
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