00001 00031 #ifndef LL_LLSIMPLEHASH_H 00032 #define LL_LLSIMPLEHASH_H 00033 00034 #include "llstl.h" 00035 00036 template <typename HASH_KEY_TYPE> 00037 class LLSimpleHashEntry 00038 { 00039 protected: 00040 HASH_KEY_TYPE mHashKey; 00041 LLSimpleHashEntry<HASH_KEY_TYPE>* mNextEntry; 00042 public: 00043 LLSimpleHashEntry(HASH_KEY_TYPE key) : 00044 mHashKey(key), 00045 mNextEntry(0) 00046 { 00047 } 00048 virtual ~LLSimpleHashEntry() 00049 { 00050 } 00051 HASH_KEY_TYPE getHashKey() const 00052 { 00053 return mHashKey; 00054 } 00055 LLSimpleHashEntry<HASH_KEY_TYPE>* getNextEntry() const 00056 { 00057 return mNextEntry; 00058 } 00059 void setNextEntry(LLSimpleHashEntry<HASH_KEY_TYPE>* next) 00060 { 00061 mNextEntry = next; 00062 } 00063 }; 00064 00065 template <typename HASH_KEY_TYPE, int TABLE_SIZE> 00066 class LLSimpleHash 00067 { 00068 public: 00069 LLSimpleHash() 00070 { 00071 llassert(TABLE_SIZE); 00072 llassert((TABLE_SIZE ^ (TABLE_SIZE-1)) == (TABLE_SIZE | (TABLE_SIZE-1))); // power of 2 00073 memset(mEntryTable, 0, sizeof(mEntryTable)); 00074 } 00075 virtual ~LLSimpleHash() 00076 { 00077 } 00078 00079 virtual int getIndex(HASH_KEY_TYPE key) 00080 { 00081 return key & (TABLE_SIZE-1); 00082 } 00083 00084 bool insert(LLSimpleHashEntry<HASH_KEY_TYPE>* entry) 00085 { 00086 llassert(entry->getNextEntry() == 0); 00087 int index = getIndex(entry->getHashKey()); 00088 entry->setNextEntry(mEntryTable[index]); 00089 mEntryTable[index] = entry; 00090 return true; 00091 } 00092 LLSimpleHashEntry<HASH_KEY_TYPE>* find(HASH_KEY_TYPE key) 00093 { 00094 int index = getIndex(key); 00095 LLSimpleHashEntry<HASH_KEY_TYPE>* res = mEntryTable[index]; 00096 while(res && (res->getHashKey() != key)) 00097 { 00098 res = res->getNextEntry(); 00099 } 00100 return res; 00101 } 00102 bool erase(LLSimpleHashEntry<HASH_KEY_TYPE>* entry) 00103 { 00104 return erase(entry->getHashKey()); 00105 } 00106 bool erase(HASH_KEY_TYPE key) 00107 { 00108 int index = getIndex(key); 00109 LLSimpleHashEntry<HASH_KEY_TYPE>* prev = 0; 00110 LLSimpleHashEntry<HASH_KEY_TYPE>* res = mEntryTable[index]; 00111 while(res && (res->getHashKey() != key)) 00112 { 00113 prev = res; 00114 res = res->getNextEntry(); 00115 } 00116 if (res) 00117 { 00118 LLSimpleHashEntry<HASH_KEY_TYPE>* next = res->getNextEntry(); 00119 if (prev) 00120 { 00121 prev->setNextEntry(next); 00122 } 00123 else 00124 { 00125 mEntryTable[index] = next; 00126 } 00127 return true; 00128 } 00129 else 00130 { 00131 return false; 00132 } 00133 } 00134 // Removes and returns an arbitrary ("first") element from the table 00135 // Used for deleting the entire table. 00136 LLSimpleHashEntry<HASH_KEY_TYPE>* pop_element() 00137 { 00138 for (int i=0; i<TABLE_SIZE; i++) 00139 { 00140 LLSimpleHashEntry<HASH_KEY_TYPE>* entry = mEntryTable[i]; 00141 if (entry) 00142 { 00143 mEntryTable[i] = entry->getNextEntry(); 00144 return entry; 00145 } 00146 } 00147 return 0; 00148 } 00149 // debugging 00150 LLSimpleHashEntry<HASH_KEY_TYPE>* get_element_at_index(S32 index) const 00151 { 00152 return mEntryTable[index]; 00153 } 00154 00155 00156 private: 00157 LLSimpleHashEntry<HASH_KEY_TYPE>* mEntryTable[TABLE_SIZE]; 00158 }; 00159 00160 #endif // LL_LLSIMPLEHASH_H