Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifndef HASHTABLE_HPP
00013 #define HASHTABLE_HPP
00014
00015 #include "../core/math_func.hpp"
00016
00017 template <class Titem_>
00018 struct CHashTableSlotT
00019 {
00020 typedef typename Titem_::Key Key;
00021
00022 Titem_ *m_pFirst;
00023
00024 inline CHashTableSlotT() : m_pFirst(NULL) {}
00025
00027 inline void Clear() {m_pFirst = NULL;}
00028
00030 inline const Titem_ *Find(const Key& key) const
00031 {
00032 for (const Titem_ *pItem = m_pFirst; pItem != NULL; pItem = pItem->GetHashNext()) {
00033 if (pItem->GetKey() == key) {
00034
00035 return pItem;
00036 }
00037 }
00038 return NULL;
00039 }
00040
00042 inline Titem_ *Find(const Key& key)
00043 {
00044 for (Titem_ *pItem = m_pFirst; pItem != NULL; pItem = pItem->GetHashNext()) {
00045 if (pItem->GetKey() == key) {
00046
00047 return pItem;
00048 }
00049 }
00050 return NULL;
00051 }
00052
00054 inline void Attach(Titem_& new_item)
00055 {
00056 assert(new_item.GetHashNext() == NULL);
00057 new_item.SetHashNext(m_pFirst);
00058 m_pFirst = &new_item;
00059 }
00060
00062 inline bool Detach(Titem_& item_to_remove)
00063 {
00064 if (m_pFirst == &item_to_remove) {
00065 m_pFirst = item_to_remove.GetHashNext();
00066 item_to_remove.SetHashNext(NULL);
00067 return true;
00068 }
00069 Titem_ *pItem = m_pFirst;
00070 for (;;) {
00071 if (pItem == NULL) {
00072 return false;
00073 }
00074 Titem_ *pNextItem = pItem->GetHashNext();
00075 if (pNextItem == &item_to_remove) break;
00076 pItem = pNextItem;
00077 }
00078 pItem->SetHashNext(item_to_remove.GetHashNext());
00079 item_to_remove.SetHashNext(NULL);
00080 return true;
00081 }
00082
00084 inline Titem_ *Detach(const Key& key)
00085 {
00086
00087 if (m_pFirst == NULL) {
00088 return NULL;
00089 }
00090
00091 if (m_pFirst->GetKey() == key) {
00092 Titem_& ret_item = *m_pFirst;
00093 m_pFirst = m_pFirst->GetHashNext();
00094 ret_item.SetHashNext(NULL);
00095 return &ret_item;
00096 }
00097
00098 Titem_ *pPrev = m_pFirst;
00099 for (Titem_ *pItem = m_pFirst->GetHashNext(); pItem != NULL; pPrev = pItem, pItem = pItem->GetHashNext()) {
00100 if (pItem->GetKey() == key) {
00101
00102 pPrev->SetHashNext(pItem->GetHashNext());
00103 pItem->SetHashNext(NULL);
00104 return pItem;
00105 }
00106 }
00107 return NULL;
00108 }
00109 };
00110
00133 template <class Titem_, int Thash_bits_>
00134 class CHashTableT {
00135 public:
00136 typedef Titem_ Titem;
00137 typedef typename Titem_::Key Tkey;
00138 static const int Thash_bits = Thash_bits_;
00139 static const int Tcapacity = 1 << Thash_bits;
00140
00141 protected:
00146 typedef CHashTableSlotT<Titem_> Slot;
00147
00148 Slot m_slots[Tcapacity];
00149 int m_num_items;
00150
00151 public:
00152
00153 inline CHashTableT() : m_num_items(0)
00154 {
00155 }
00156
00157 protected:
00159 inline static int CalcHash(const Tkey& key)
00160 {
00161 int32 hash = key.CalcHash();
00162 if ((8 * Thash_bits) < 32) hash ^= hash >> (min(8 * Thash_bits, 31));
00163 if ((4 * Thash_bits) < 32) hash ^= hash >> (min(4 * Thash_bits, 31));
00164 if ((2 * Thash_bits) < 32) hash ^= hash >> (min(2 * Thash_bits, 31));
00165 if ((1 * Thash_bits) < 32) hash ^= hash >> (min(1 * Thash_bits, 31));
00166 hash &= (1 << Thash_bits) - 1;
00167 return hash;
00168 }
00169
00171 inline static int CalcHash(const Titem_& item) {return CalcHash(item.GetKey());}
00172
00173 public:
00175 inline int Count() const {return m_num_items;}
00176
00178 inline void Clear() {for (int i = 0; i < Tcapacity; i++) m_slots[i].Clear();}
00179
00181 const Titem_ *Find(const Tkey& key) const
00182 {
00183 int hash = CalcHash(key);
00184 const Slot& slot = m_slots[hash];
00185 const Titem_ *item = slot.Find(key);
00186 return item;
00187 }
00188
00190 Titem_ *Find(const Tkey& key)
00191 {
00192 int hash = CalcHash(key);
00193 Slot& slot = m_slots[hash];
00194 Titem_ *item = slot.Find(key);
00195 return item;
00196 }
00197
00199 Titem_ *TryPop(const Tkey& key)
00200 {
00201 int hash = CalcHash(key);
00202 Slot& slot = m_slots[hash];
00203 Titem_ *item = slot.Detach(key);
00204 if (item != NULL) {
00205 m_num_items--;
00206 }
00207 return item;
00208 }
00209
00211 Titem_& Pop(const Tkey& key)
00212 {
00213 Titem_ *item = TryPop(key);
00214 assert(item != NULL);
00215 return *item;
00216 }
00217
00219 bool TryPop(Titem_& item)
00220 {
00221 const Tkey& key = item.GetKey();
00222 int hash = CalcHash(key);
00223 Slot& slot = m_slots[hash];
00224 bool ret = slot.Detach(item);
00225 if (ret) {
00226 m_num_items--;
00227 }
00228 return ret;
00229 }
00230
00232 void Pop(Titem_& item)
00233 {
00234 bool ret = TryPop(item);
00235 assert(ret);
00236 }
00237
00239 void Push(Titem_& new_item)
00240 {
00241 int hash = CalcHash(new_item);
00242 Slot& slot = m_slots[hash];
00243 assert(slot.Find(new_item.GetKey()) == NULL);
00244 slot.Attach(new_item);
00245 m_num_items++;
00246 }
00247 };
00248
00249 #endif