00001 #ifndef __CHM_REF_HASH_TABLE__
00002 #define __CHM_REF_HASH_TABLE__
00003 #include <CHM/CHMvector.h>
00004 #include <CHM/CHMstring.h>
00005
00006 template<class PKey, class PValue>
00007 class CHMpair : public CHMinstanceHeap
00008 {
00009 public:
00010 CHMpair() {}
00011 CHMpair(const PKey& nKey, const PValue& nValue)
00012 : Key(nKey), Value(nValue) {}
00013 ~CHMpair() {}
00014 PKey Key;
00015 PValue Value;
00016 };
00017
00018 size_t CHMhashFunc(size_t Item);
00019
00020 template<class PKey, class PValue> class CHMrefHashTableIterator;
00021
00022 template<class PKey, class PValue>
00023 class CHMrefHashTable : public CHMinstanceHeap
00024 {
00025 public:
00026 CHMrefHashTable(size_t CountOfBucket=10);
00027 virtual ~CHMrefHashTable();
00028
00029
00030
00031 PValue& operator[](const PKey& Key);
00032 const PValue& operator[](const PKey& Key) const;
00033
00034 CHMpair<PKey,PValue>* findPair(const PKey& Key) const;
00035 CHMboolean has(const PKey& Key) const;
00036
00037 PValue* getValue(const PKey& Key) const;
00038 void clear();
00039
00040 void remove(const PKey& Key);
00041
00042 void insert(const PKey& Key, const PValue& Value);
00043
00044 size_t size() const { return m_Size; }
00045
00046 friend class CHMrefHashTableIterator<PKey, PValue>;
00047 typedef CHMrefHashTableIterator<PKey, PValue> Iterator;
00048 private:
00049 void removeAll();
00050 void init(size_t CountOfBucket);
00051
00052 typedef CHMvector< CHMpair<PKey, PValue>* > CHMbucket;
00053
00054 CHMvector<CHMbucket*> m_Bucket;
00055
00056 void findIndex(const PKey& Key, size_t& BucketIndex, size_t& ItemIndex) const;
00057 size_t m_Size;
00058
00059 CHMrefHashTable(const CHMrefHashTable<PKey,PValue>& Original) {}
00060 CHMrefHashTable<PKey,PValue>& operator=(const CHMrefHashTable<PKey,PValue>& Original) { return *this;}
00061 };
00062
00063 template<class PKey, class PValue>
00064 class CHMrefHashTableIterator
00065 {
00066 public:
00067 CHMrefHashTableIterator(const CHMrefHashTable<PKey, PValue>& Table);
00068 ~CHMrefHashTableIterator() {}
00069
00070 void resetIterator();
00071 CHMboolean iterateNext(PKey& Key, PValue& Value);
00072 private:
00073 size_t m_IterBucketIndex;
00074 size_t m_IterItemIndex;
00075 const CHMrefHashTable<PKey, PValue>* m_pTable;
00076 };
00077
00078 template<class PKey, class PValue>
00079 CHMrefHashTableIterator<PKey, PValue>::CHMrefHashTableIterator
00080 (
00081 const CHMrefHashTable<PKey, PValue>& Table
00082 )
00083 {
00084 m_pTable = &Table;
00085 resetIterator();
00086 }
00087
00088 template<class PKey, class PValue>
00089 void CHMrefHashTableIterator<PKey, PValue>::resetIterator()
00090 {
00091 m_IterBucketIndex=npos;
00092 m_IterItemIndex=0;
00093 }
00094
00095 template<class PKey, class PValue>
00096 CHMboolean CHMrefHashTableIterator<PKey,PValue>::iterateNext
00097 (
00098 PKey& Key,
00099 PValue& Value
00100 )
00101 {
00102 if (m_IterBucketIndex == npos)
00103 {
00104 m_IterBucketIndex = 0;
00105 }
00106 while (m_IterBucketIndex < m_pTable->m_Bucket.size() &&
00107 m_pTable->m_Bucket[m_IterBucketIndex]->size() <= m_IterItemIndex )
00108 {
00109 m_IterBucketIndex++;
00110 m_IterItemIndex = 0;
00111 }
00112 if (m_IterBucketIndex == m_pTable->m_Bucket.size())
00113 {
00114 return false;
00115 }
00116 else
00117 {
00118 Key = m_pTable->m_Bucket[m_IterBucketIndex]->operator[](m_IterItemIndex)->Key;
00119 Value = m_pTable->m_Bucket[m_IterBucketIndex]->operator[](m_IterItemIndex)->Value;
00120 m_IterItemIndex++;
00121 return true;
00122 }
00123 }
00124
00125 size_t CHMhashFunc(const CHMstring& String);
00126
00127 template<class PKey, class PValue>
00128 CHMrefHashTable<PKey, PValue>::CHMrefHashTable
00129 (
00130 size_t CountOfBucket
00131 ) : m_Bucket(CountOfBucket)
00132 {
00133 init(CountOfBucket);
00134 }
00135
00136 template<class PKey, class PValue>
00137 void CHMrefHashTable<PKey, PValue>::init(size_t CountOfBucket)
00138 {
00139 removeAll();
00140 m_Size = 0;
00141 m_Bucket.resize(CountOfBucket);
00142 for(size_t BucketIndex=0; BucketIndex < m_Bucket.size(); ++BucketIndex)
00143 {
00144 m_Bucket[BucketIndex] = new CHMvector< CHMpair<PKey,PValue>* >(2, 0, true);
00145
00146 }
00147 }
00148
00149 template<class PKey, class PValue>
00150 CHMrefHashTable<PKey, PValue>::~CHMrefHashTable()
00151 {
00152 removeAll();
00153 }
00154
00155 template<class PKey, class PValue>
00156 void CHMrefHashTable<PKey, PValue>::removeAll()
00157 {
00158 for(size_t BucketIndex = 0;
00159 BucketIndex < m_Bucket.size();
00160 ++BucketIndex)
00161 {
00162 for(size_t ItemIndex = 0; ItemIndex < m_Bucket[BucketIndex]->size();
00163 ++ItemIndex)
00164 {
00165 delete m_Bucket[BucketIndex]->operator[](ItemIndex);
00166 }
00167 delete m_Bucket[BucketIndex];
00168 }
00169 m_Size = 0;
00170 }
00171
00172 template<class PKey, class PValue>
00173 CHMpair<PKey,PValue>* CHMrefHashTable<PKey, PValue>::findPair(const PKey& Key) const
00174 {
00175 size_t BucketIndex;
00176 size_t ItemIndex;
00177 findIndex(Key, BucketIndex, ItemIndex);
00178
00179 if (ItemIndex == npos)
00180 {
00181 return NULL;
00182 }
00183 else
00184 {
00185 return m_Bucket[BucketIndex]->operator[](ItemIndex);
00186 }
00187 }
00188
00189 template<class PKey, class PValue>
00190 PValue& CHMrefHashTable<PKey, PValue>::operator[](const PKey& Key)
00191 {
00192 CHMpair<PKey, PValue>* pPair = findPair(Key);
00193
00194 if (!pPair)
00195 {
00196 insert(Key, PValue());
00197 pPair = findPair(Key);
00198 }
00199 CHMPRECONDITION(pPair != NULL)
00200 return pPair->Value;
00201 }
00202
00203 template<class PKey, class PValue>
00204 const PValue& CHMrefHashTable<PKey, PValue>::operator[](const PKey& Key) const
00205 {
00206 CHMpair<PKey, PValue>* pPair = findPair(Key);
00207
00208 if (!pPair)
00209 {
00210 throw CHMerror(CHM_TEXT("Key does not exist."),0);
00211 }
00212
00213 return pPair->Value;
00214 }
00215
00216
00217 template<class PKey, class PValue>
00218 CHMboolean CHMrefHashTable<PKey, PValue>::has(const PKey& Key) const
00219 {
00220 CHMpair<PKey, PValue>* pPair = findPair(Key);
00221 if (!pPair)
00222 return false;
00223 else
00224 return true;
00225 }
00226
00227 template<class PKey, class PValue>
00228 PValue* CHMrefHashTable<PKey, PValue>::getValue(const PKey& Key) const
00229 {
00230 CHMpair<PKey, PValue>* pPair = findPair(Key);
00231 if (pPair)
00232 return &pPair->Value;
00233 else
00234 return NULL;
00235 }
00236
00237 template<class PKey, class PValue>
00238 void CHMrefHashTable<PKey, PValue>::clear()
00239 {
00240 size_t CountOfBucket = m_Bucket.size();
00241 init(CountOfBucket);
00242 }
00243
00244 template<class PKey, class PValue>
00245 void CHMrefHashTable<PKey, PValue>::findIndex
00246 (
00247 const PKey& Key,
00248 size_t& BucketIndex,
00249 size_t& ItemIndex
00250 ) const
00251 {
00252 BucketIndex = CHMhashFunc(Key) % m_Bucket.size();
00253 ItemIndex = 0;
00254 while (ItemIndex < m_Bucket[BucketIndex]->size()
00255 && Key != m_Bucket[BucketIndex]->operator[](ItemIndex)->Key)
00256 {
00257 ItemIndex++;
00258 }
00259 if (m_Bucket[BucketIndex]->size() == ItemIndex)
00260 {
00261 ItemIndex = npos;
00262 }
00263 }
00264
00265 template<class PKey, class PValue>
00266 void CHMrefHashTable<PKey, PValue>::remove(const PKey& Key)
00267 {
00268 size_t BucketIndex;
00269 size_t ItemIndex;
00270 findIndex(Key, BucketIndex, ItemIndex);
00271
00272 if (ItemIndex == npos)
00273 {
00274 return;
00275 }
00276 else
00277 {
00278 delete m_Bucket[BucketIndex]->operator[](ItemIndex);
00279 m_Bucket[BucketIndex]->remove(ItemIndex);
00280 m_Size--;
00281 }
00282 }
00283
00284 template<class PKey, class PValue>
00285 void CHMrefHashTable<PKey,PValue>::insert(const PKey& Key, const PValue& Value)
00286 {
00287 size_t BucketIndex;
00288 size_t ItemIndex;
00289 findIndex(Key, BucketIndex, ItemIndex);
00290 if (ItemIndex != npos)
00291 {
00292
00293 m_Bucket[BucketIndex]->operator[](ItemIndex)->Value = Value;
00294 }
00295 else
00296 {
00297 m_Size +=1;
00298 m_Bucket[BucketIndex]->push_back(new CHMpair<PKey,PValue>(Key,Value));
00299 }
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 #endif // end of defensive include