00001 #ifndef MMANN_FCINTERNAL_HASH_H
00002 #define MMANN_FCINTERNAL_HASH_H
00003
00011
00012 #include <assert.h>
00013 #include "AGenericHash.h"
00014
00019 template <class Key>
00020 class FCHashItem
00021 {
00022 public:
00023
00025 FCHashItem(Key* key, int value, FCHashItem<Key>* Next = NULL);
00026
00028 Key* m_Key;
00029
00031 int m_Value;
00032
00034 FCHashItem<Key>* m_Next;
00035 };
00036
00037 template <class Key>
00038 FCHashItem<Key>::FCHashItem(Key* key, int value, FCHashItem<Key>* Next)
00039 {
00040 m_Key = key;
00041 m_Value = value;
00042 m_Next = Next;
00043 }
00044
00049 template <class Key, class ConfigData>
00050 class FCInternalHash : public AGenericHash<Key, ConfigData>
00051 {
00052
00053 public:
00055 FCInternalHash(int SizeWanted, ACompareNodesAlgorithm<Key, ConfigData>* CompareAlgorithm,
00056 AHashAlgorithm<Key>* Hash,
00057 DeleteHashDataEnum DeleteHashData = NO_DELETE_HASH_ITEM);
00058
00060 virtual ~FCInternalHash();
00061
00067 Key* Insert(Key* key, bool OptimizeForCaching);
00068
00070 virtual void DeleteItems();
00071
00072 protected:
00076 void Rehash(FCInternalHash<Key, ConfigData>* Hash);
00077
00081 virtual void Copy(AGenericHash<Key, ConfigData>* Hash);
00082
00083 private:
00085 FCHashItem<Key>** m_Entries;
00086 };
00087
00088 template <class Key, class ConfigData>
00089 FCInternalHash<Key, ConfigData>::FCInternalHash(int SizeWanted, ACompareNodesAlgorithm<Key, ConfigData>* CompareAlgorithm,
00090 AHashAlgorithm<Key>* Hash,
00091 DeleteHashDataEnum DeleteHashData) : AGenericHash<Key, ConfigData>(SizeWanted, CompareAlgorithm, Hash, DeleteHashData)
00092 {
00093
00094 m_Size = FindClosestPrime(SizeWanted);
00095
00096
00097 m_Entries = new FCHashItem<Key>*[m_Size];
00098
00099
00100
00101 memset(m_Entries, 0, sizeof(FCHashItem<Key>*)*m_Size);
00102 }
00103
00104 template <class Key, class ConfigData>
00105 FCInternalHash<Key, ConfigData>::~FCInternalHash()
00106 {
00107 }
00108
00109 template <class Key, class ConfigData>
00110 void FCInternalHash<Key, ConfigData>::DeleteItems()
00111 {
00112 FCHashItem<Key> *Item, *NextItem;
00113
00114 for(int i=0;i<m_Size;i++)
00115 {
00116 Item = m_Entries[i];
00117 while (Item != NULL)
00118 {
00119 NextItem = Item->m_Next;
00120 switch(m_DeleteHashData)
00121 {
00122 case NO_DELETE_HASH_ITEM:
00123 break;
00124 case DELETE_HASH_ITEM:
00125 delete Item->m_Key;
00126 break;
00127 case DELETE_HASH_ITEM_ARRAY:
00128 delete [] Item->m_Key;
00129 break;
00130 default:
00131
00132 assert(false);
00133 }
00134 delete Item;
00135 Item = NextItem;
00136 }
00137 }
00138
00139 delete [] m_Entries;
00140 }
00141
00142
00143 template <class Key, class ConfigData>
00144 Key* FCInternalHash<Key, ConfigData>::Insert(Key* key, bool OptimizeForCaching)
00145 {
00146 FCHashItem<Key> *Item, *LastItem;
00147 int Value = m_Hash->Hash(key);
00148
00149
00150 FCHashItem<Key> **List = &m_Entries[Value % m_Size];
00151
00152
00153 if ((*List) == NULL)
00154 {
00155
00156 Item = (*List) = new FCHashItem<Key>(key, Value);
00157 goto RehashCheck;
00158 }
00159
00160
00161 Item = (*List);
00162 LastItem = NULL;
00163
00164 while (Item != NULL)
00165 {
00166
00167
00168
00169
00170 if ( (Item->m_Value == Value) && (m_Compare->Compare(Item->m_Key, key, NULL) == 0) )
00171 {
00172 if (OptimizeForCaching)
00173 {
00174
00175
00176
00177 if (LastItem != NULL)
00178 {
00179 LastItem->m_Next = Item->m_Next;
00180 Item->m_Next = (*List);
00181 (*List) = Item;
00182 }
00183 }
00184
00185 return Item->m_Key;
00186 }
00187
00188
00189 LastItem = Item;
00190
00191 Item = Item->m_Next;
00192 }
00193
00194 if (OptimizeForCaching)
00195 {
00196
00197 Item = new FCHashItem<Key>(key, Value, (*List));
00198 (*List) = Item;
00199 }
00200 else
00201 {
00202
00203 Item = LastItem->m_Next = new FCHashItem<Key>(key, Value);
00204 }
00205
00206 RehashCheck:
00207 m_NumberOfElements++;
00208
00209 if (m_NumberOfElements > ((m_Size*3)>>2))
00210 Rehash(this);
00211
00212 return NULL;
00213 }
00214
00215 template <class Key, class ConfigData>
00216 void FCInternalHash<Key, ConfigData>::Rehash(FCInternalHash<Key, ConfigData>* Hash)
00217 {
00218 FCInternalHash<Key, ConfigData>* NewHash;
00219 FCHashItem<Key> *Item, *NextItem;
00220 int Place;
00221
00222
00223 NewHash = new FCInternalHash<Key, ConfigData>(Hash->m_Size*2, Hash->m_Compare, Hash->m_Hash, m_DeleteHashData);
00224 NewHash->m_NumberOfElements = Hash->m_NumberOfElements;
00225
00226
00227 for(int i=0;i<Hash->m_Size;i++)
00228 {
00229 Item = Hash->m_Entries[i];
00230
00231 while(Item != NULL)
00232 {
00233
00234 Place = Item->m_Value % NewHash->m_Size;
00235
00236
00237
00238 NextItem = Item->m_Next;
00239
00240
00241
00242 Item->m_Next = NewHash->m_Entries[Place];
00243
00244
00245 NewHash->m_Entries[Place] = Item;
00246
00247
00248 Item = NextItem;
00249 }
00250 }
00251
00252
00253 delete [] Hash->m_Entries;
00254
00255
00256 Hash->Copy(NewHash);
00257
00258 delete NewHash;
00259 }
00260
00261 template <class Key, class ConfigData>
00262 void FCInternalHash<Key, ConfigData>::Copy(AGenericHash<Key, ConfigData>* Hash)
00263 {
00264
00265 AGenericHash<Key, ConfigData>::Copy(Hash);
00266
00267 m_Entries = ((FCInternalHash<Key, ConfigData>*)Hash)->m_Entries;
00268 }
00269
00270 #endif