True Axis Physics SDK 1.2.0.1 Beta Documentation
www.trueaxis.com

HashTable.h

00001 //---------------------------------------------------------------------------------
00002 // File Name: HashTable.h
00003 // Description: I'm sure any body could write a better hash table if they
00004 //              wanted to.
00005 //
00006 // Copyright (C) 2004 - 2005 True Axis Pty Ltd, Australia. 
00007 // All Rights Reserved.
00008 //
00009 // History:
00010 //      Created File.
00011 //---------------------------------------------------------------------------------
00012 
00013 #ifndef TA_HASHTABLE_H
00014 #define TA_HASHTABLE_H
00015 
00016 #ifndef TA_TYPES_H
00017 #include "Types.h"
00018 #endif // TA_TYPES_H
00019 
00020 #ifndef TA_STRING_H
00021 #include "String.h"
00022 #endif // TA_STRING_H
00023 
00024 #ifndef TA_LIST_H
00025 #include "List.h"
00026 #endif // TA_LIST_H
00027 
00028 namespace TA
00029 {
00030 
00031 template <class Type>
00032 class TACOMMON_CLASS HashTable
00033 {
00034 public:
00035     class Item
00036     {
00037     public:
00038         Item() { m_pData = 0; }
00039         ~Item() {}
00040 
00041         Type* GetData() { return m_pData; }
00042         const Type* GetData() const { return m_pData; }
00043         void SetData(Type* pData) { m_pData = pData; }
00044 
00045     private:
00046         friend HashTable;
00047         Type* m_pData;
00048         String m_strString;
00049     };  
00050 /*  // Seem to have trouble getting this to compile
00051     class Iterator
00052     {
00053     public:
00054         ~Iterator() { Finalise(); }
00055         void operator ++()
00056         {
00057             if (m_nEntry != -1)
00058             {
00059                 if (m_itList.AtEnd())
00060                 {
00061                     m_nEntry++;
00062                     if (m_nEntry < m_nHashSize)
00063                         m_itList = pHashTable[m_nEntry];
00064                     else
00065                         m_nEntry = -1;
00066                 }
00067                 else
00068                 {
00069                     ++m_itList;
00070                 }
00071             }
00072         }
00073         Item& operator *() { return *m_itList; }
00074         bool AtEnd() { return m_nEntry == -1; }
00075     private:
00076         friend HashTable;
00077         Iterator() 
00078         { 
00079             m_nEntry = -1; 
00080             m_pHashTable = 0; 
00081         }
00082         void Initialise(List<Item>* pHashTable, int nHashSize) 
00083         {       
00084             m_nEntry = 0;
00085             m_pHashTable = pHashTable;
00086             m_itList = pHashTable[m_nEntry];
00087             m_nHashSize = nHashSize;
00088         }
00089         void Finalise() 
00090         { 
00091             m_nEntry = -1; 
00092             m_pHashTable = 0; 
00093         }
00094         int m_nHashSize;
00095         int m_nEntry;
00096         List<Item>::Iterator m_itList;
00097         List<Item>* m_pHashTable;
00098     };
00099     */
00100 
00101     HashTable();
00102     ~HashTable();
00103 
00104     void Initialise(int nHashSize); // nHashSize should be a prime number
00105     void Finalise();
00106 
00107     Item& CreateItem(const Char* szString);
00108     Item* GetItemIfExists(const Char* szString);
00109     void RemoveItem(const Char* szString);
00110 
00111     //---------------------------------------------------------------------------------
00112     // Traverse the hash table and return a callback for each item.
00113     //---------------------------------------------------------------------------------
00114     void Traverse(void (TAC_CALL *pCallBack)(Item& item, void* pCallBackData), void* pCallBackData);
00115 
00116     //---------------------------------------------------------------------------------
00117     // This is a reasonably chunky iterator
00118     //---------------------------------------------------------------------------------
00119     //Iterator GetIterator()
00120 
00121 
00122 private:
00123 
00124     int m_nHashSize;
00125     List<Item>* m_pHashTable;
00126 
00127     int CalculateHashValue(const Char * szString);
00128 
00129 };
00130 
00131 //---------------------------------------------------------------------------------
00132 //---------------------------------------------------------------------------------
00133 template <class Type>
00134 HashTable<Type>::HashTable() 
00135 {
00136     m_pHashTable = 0;
00137 }
00138 
00139 //---------------------------------------------------------------------------------
00140 //---------------------------------------------------------------------------------
00141 template <class Type>
00142 HashTable<Type>::~HashTable()
00143 {
00144     Finalise();
00145 }
00146 
00147 //---------------------------------------------------------------------------------
00148 //---------------------------------------------------------------------------------
00149 template <class Type>
00150 void HashTable<Type>::Initialise(int nHashSize)
00151 {
00152     m_nHashSize = nHashSize;
00153     if (m_pHashTable != 0)
00154     {
00155         TA_ASSERT(0);
00156         Finalise();
00157     }
00158     TA_MEMORY_MGR_NEW_ARRAY(m_pHashTable, List<Item>, m_nHashSize);
00159 }
00160 
00161 //---------------------------------------------------------------------------------
00162 //---------------------------------------------------------------------------------
00163 template <class Type>
00164 void HashTable<Type>::Finalise()
00165 {   
00166     if (m_pHashTable)
00167     {       
00168         TA_MEMORY_MGR_DELETE_ARRAY(m_pHashTable, List<Item>);
00169         m_pHashTable = 0;
00170     }
00171     m_nHashSize = 0;
00172 }
00173 
00174 //---------------------------------------------------------------------------------
00175 //---------------------------------------------------------------------------------
00176 template <class Type>
00177 typename HashTable<Type>::Item& HashTable<Type>::CreateItem(const Char* szString)
00178 {
00179     // todo: use a better searching method
00180     int nHashValue = CalculateHashValue(szString);  
00181     List<Item>& list = m_pHashTable[nHashValue];
00182     for (List<Item>::Iterator it = list.GetIterator(); !it.AtEnd(); ++it)
00183     {
00184         Item& item = *it;
00185         if (item.m_strString == szString)
00186             return item;
00187     }
00188     Item& item = list.Append();
00189     item.m_strString = szString;
00190     return item;
00191 }
00192 
00193 //---------------------------------------------------------------------------------
00194 //---------------------------------------------------------------------------------
00195 template <class Type>
00196 typename HashTable<Type>::Item* HashTable<Type>::GetItemIfExists(const Char* szString)
00197 {
00198     // todo: use a better searching method
00199     int nHashValue = CalculateHashValue(szString);  
00200     List<Item>& list = m_pHashTable[nHashValue];
00201     for (List<Item>::Iterator it = list.GetIterator(); !it.AtEnd(); ++it)
00202     {
00203         Item& item = *it;
00204         if (item.m_strString == szString)
00205             return &item;
00206     }
00207     return 0;
00208 }
00209 
00210 //---------------------------------------------------------------------------------
00211 //---------------------------------------------------------------------------------
00212 template <class Type>
00213 void HashTable<Type>::RemoveItem(const Char* szString)
00214 {
00215     int nHashValue = CalculateHashValue(szString);  
00216     List<Item>& list = m_pHashTable[nHashValue];
00217     for (List<Item>::Iterator it = list.GetIterator(); !it.AtEnd(); ++it)
00218     {
00219         Item& item = *it;
00220         if (item.m_strString == szString)
00221         {
00222             list.Remove(&item);
00223             return;
00224         }
00225     }
00226 }
00227 
00228 //---------------------------------------------------------------------------------
00229 //---------------------------------------------------------------------------------
00230 /*template <class Type>
00231 HashTable<Type>::Iterator HashTable<Type>::GetIterator()
00232 {
00233     Iterator it;
00234     it.Initialise(m_pHashTable, m_nHashSize);
00235     return it;
00236 }*/
00237 
00238 //---------------------------------------------------------------------------------
00239 //---------------------------------------------------------------------------------
00240 template <class Type>
00241 void HashTable<Type>::Traverse(void (TAC_CALL *pCallBack)(Item& item, void* pCallBackData), void* pCallBackData)
00242 {
00243     if (!pCallBack)
00244         return;
00245     for (int nIndex = 0; nIndex < m_nHashSize; nIndex++)
00246     {   
00247         List<Item>& list = m_pHashTable[nIndex];
00248         for (List<Item>::Iterator it = list.GetIterator(); !it.AtEnd(); ++it)
00249         {
00250             Item& item = *it;
00251             pCallBack(item, pCallBackData);
00252         }
00253     }
00254 }
00255 
00256 //---------------------------------------------------------------------------------
00257 //---------------------------------------------------------------------------------
00258 template <class Type>
00259 int HashTable<Type>::CalculateHashValue(const Char * szString)
00260 {
00261     // calculate hash function
00262     for (int nHashValue = 0; *szString != '\0'; szString++)
00263         nHashValue = ((nHashValue << 8) + *szString) % m_nHashSize;
00264     return nHashValue;
00265 }
00266 
00267 };
00268 
00269 #endif // TA_HASHTABLE_H


© Copyright 2004-2006 TRUE AXIS PTY LTD Australia. All rights reserved.