hashtable.hpp
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 template <class Titem_>
00016 struct CHashTableSlotT
00017 {
00018 typedef typename Titem_::Key Key;
00019
00020 Titem_ *m_pFirst;
00021
00022 FORCEINLINE CHashTableSlotT() : m_pFirst(NULL) {}
00023
00025 FORCEINLINE void Clear() {m_pFirst = NULL;}
00026
00028 FORCEINLINE const Titem_ *Find(const Key& key) const
00029 {
00030 for (const Titem_ *pItem = m_pFirst; pItem != NULL; pItem = pItem->GetHashNext()) {
00031 if (pItem->GetKey() == key) {
00032
00033 return pItem;
00034 }
00035 }
00036 return NULL;
00037 }
00038
00040 FORCEINLINE Titem_ *Find(const Key& key)
00041 {
00042 for (Titem_ *pItem = m_pFirst; pItem != NULL; pItem = pItem->GetHashNext()) {
00043 if (pItem->GetKey() == key) {
00044
00045 return pItem;
00046 }
00047 }
00048 return NULL;
00049 }
00050
00052 FORCEINLINE void Attach(Titem_& new_item)
00053 {
00054 assert(new_item.GetHashNext() == NULL);
00055 new_item.SetHashNext(m_pFirst);
00056 m_pFirst = &new_item;
00057 }
00058
00060 FORCEINLINE bool Detach(Titem_& item_to_remove)
00061 {
00062 if (m_pFirst == &item_to_remove) {
00063 m_pFirst = item_to_remove.GetHashNext();
00064 item_to_remove.SetHashNext(NULL);
00065 return true;
00066 }
00067 Titem_ *pItem = m_pFirst;
00068 while (true) {
00069 if (pItem == NULL) {
00070 return false;
00071 }
00072 Titem_ *pNextItem = pItem->GetHashNext();
00073 if (pNextItem == &item_to_remove) break;
00074 pItem = pNextItem;
00075 }
00076 pItem->SetHashNext(item_to_remove.GetHashNext());
00077 item_to_remove.SetHashNext(NULL);
00078 return true;
00079 }
00080
00082 FORCEINLINE Titem_ *Detach(const Key& key)
00083 {
00084
00085 if (m_pFirst == NULL) {
00086 return NULL;
00087 }
00088
00089 if (m_pFirst->GetKey() == key) {
00090 Titem_& ret_item = *m_pFirst;
00091 m_pFirst = m_pFirst->GetHashNext();
00092 ret_item.SetHashNext(NULL);
00093 return &ret_item;
00094 }
00095
00096 Titem_ *pPrev = m_pFirst;
00097 for (Titem_ *pItem = m_pFirst->GetHashNext(); pItem != NULL; pPrev = pItem, pItem = pItem->GetHashNext()) {
00098 if (pItem->GetKey() == key) {
00099
00100 pPrev->SetHashNext(pItem->GetHashNext());
00101 pItem->SetHashNext(NULL);
00102 return pItem;
00103 }
00104 }
00105 return NULL;
00106 }
00107 };
00108
00130 template <class Titem_, int Thash_bits_>
00131 class CHashTableT {
00132 public:
00133 typedef Titem_ Titem;
00134 typedef typename Titem_::Key Tkey;
00135 static const int Thash_bits = Thash_bits_;
00136 static const int Tcapacity = 1 << Thash_bits;
00137
00138 protected:
00141 typedef CHashTableSlotT<Titem_> Slot;
00142
00143 Slot *m_slots;
00144 int m_num_items;
00145
00146 public:
00147
00148 FORCEINLINE CHashTableT()
00149 {
00150
00151 m_slots = new Slot[Tcapacity];
00152 m_num_items = 0;
00153 }
00154
00155 ~CHashTableT() {delete [] m_slots; m_num_items = 0; m_slots = NULL;}
00156
00157 protected:
00159 FORCEINLINE 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 FORCEINLINE static int CalcHash(const Titem_& item) {return CalcHash(item.GetKey());}
00172
00173 public:
00175 FORCEINLINE int Count() const {return m_num_items;}
00176
00178 FORCEINLINE void Clear() const {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