Isle
Loading...
Searching...
No Matches
mxhashtable.h
Go to the documentation of this file.
1#ifndef MXHASHTABLE_H
2#define MXHASHTABLE_H
3
4#include "mxcollection.h"
5#include "mxcore.h"
6#include "mxtypes.h"
7
8#define HASH_TABLE_INIT_SIZE 128
9
16template <class T>
18
19template <class T>
21public:
29 MxHashTableNode<T>(T p_obj, MxU32 p_hash, MxHashTableNode* p_prev, MxHashTableNode* p_next)
30 {
31 m_obj = p_obj;
32 m_hash = p_hash;
33 m_prev = p_prev;
34 m_next = p_next;
35 }
36
37 // DECOMP: Should use getter and setter methods here per the style guide.
38 // However, LEGO1D (with no functions inlined) does not use them.
39
48};
49
56template <class T>
57class MxHashTable : protected MxCollection<T> {
58public:
62 enum Option {
66 };
67
72 {
74 MxU32 unused = 0;
76 memset(m_slots, 0, sizeof(MxHashTableNode<T>*) * m_numSlots);
78 }
79
83 ~MxHashTable() override;
84
89 void Resize();
90
95 void Add(T);
96
100 void DeleteAll();
101
107 virtual MxU32 Hash(T) { return 0; } // [AI] To be overridden by subclasses.
108
109 friend class MxHashTableCursor<T>;
110
111protected:
117
120
123
126
129
136 union {
138 double m_increaseFactor; // 0x20
139 };
140};
141
148template <class T>
149class MxHashTableCursor : public MxCore {
150public:
156 {
157 m_table = p_table;
158 m_match = NULL;
159 }
160
167 MxBool Find(T p_obj);
168
174 MxBool Current(T& p_obj);
175
179 void DeleteMatch();
180
181private:
183 MxHashTable<T>* m_table;
184
186 MxHashTableNode<T>* m_match;
187};
188
189template <class T>
191{
192 MxU32 hash = m_table->Hash(p_obj);
193
194 for (MxHashTableNode<T>* t = m_table->m_slots[hash % m_table->m_numSlots]; t; t = t->m_next) {
195 if (t->m_hash == hash && !m_table->Compare(t->m_obj, p_obj)) {
196 m_match = t;
197 }
198 }
199
200 return m_match != NULL;
201}
202
203template <class T>
205{
206 if (m_match) {
207 p_obj = m_match->m_obj;
208 }
209
210 return m_match != NULL;
211}
212
213template <class T>
215{
216 // Cut the matching node out of the linked list
217 // by updating pointer references.
218 if (m_match) {
219 if (m_match->m_prev) {
220 m_match->m_prev->m_next = m_match->m_next;
221 }
222 else {
223 // No "prev" node, so move "next" to the head of the list.
224 m_table->m_slots[m_match->m_hash % m_table->m_numSlots] = m_match->m_next;
225 }
226
227 if (m_match->m_next) {
228 m_match->m_next->m_prev = m_match->m_prev;
229 }
230
231 m_table->m_customDestructor(m_match->m_obj);
232 delete m_match;
233 m_table->m_count--;
234 }
235}
236
237template <class T>
239{
240 DeleteAll();
241 delete[] m_slots;
242}
243
244template <class T>
246{
247 for (MxS32 i = 0; i < m_numSlots; i++) {
248 MxHashTableNode<T>* next;
249 for (MxHashTableNode<T>* t = m_slots[i]; t != NULL; t = next) {
250 next = t->m_next;
251 this->m_customDestructor(t->m_obj);
252 delete t;
253 }
254 }
255
256 this->m_count = 0;
257 memset(m_slots, 0, sizeof(MxHashTableNode<T>*) * m_numSlots);
258}
259
260template <class T>
262{
263 // Save a reference to the current table
264 // so we can walk nodes and re-insert
265 MxU32 oldSize = m_numSlots;
266 MxHashTableNode<T>** oldTable = m_slots;
267
268 switch (m_resizeOption) {
269 case e_expandAll:
270 m_numSlots += m_increaseAmount;
271 break;
272 case e_expandMultiply:
273 m_numSlots *= m_increaseFactor;
274 break;
275 }
276
277 MxU32 unused = 0;
278 m_slots = new MxHashTableNode<T>*[m_numSlots];
279 memset(m_slots, 0, sizeof(MxHashTableNode<T>*) * m_numSlots);
280 this->m_count = 0;
281
282 for (MxS32 i = 0; i < oldSize; i++) {
283 MxHashTableNode<T>* next;
284 for (MxHashTableNode<T>* t = oldTable[i]; t != NULL; t = next) {
285 next = t->m_next;
286 NodeInsert(t);
287 }
288 }
289
290 delete[] oldTable;
291}
292
293template <class T>
295{
296 MxS32 bucket = p_node->m_hash % m_numSlots;
297
298 p_node->m_next = m_slots[bucket];
299
300 if (m_slots[bucket]) {
301 m_slots[bucket]->m_prev = p_node;
302 }
303
304 m_slots[bucket] = p_node;
305 this->m_count++;
306}
307
308template <class T>
309inline void MxHashTable<T>::Add(T p_newobj)
310{
311 if (m_resizeOption && ((this->m_count + 1) / m_numSlots) > m_autoResizeRatio) {
313 }
314
315 MxU32 hash = Hash(p_newobj);
316 MxU32 unused = 0;
317
318 MxHashTableNode<T>* node = new MxHashTableNode<T>(p_newobj, hash, NULL, NULL);
319
321}
322
323#undef HASH_TABLE_INIT_SIZE
324
325#endif // MXHASHTABLE_H
[AI] Template class for a generic collection, providing fundamental storage and comparison facilities...
Definition: mxcollection.h:10
[AI] Base virtual class for all Mindscape engine (Mx) objects.
Definition: mxcore.h:15
[AI] Non-intrusive search-and-edit cursor for navigating, querying, or deleting a specific entry in a...
Definition: mxhashtable.h:149
MxBool Find(T p_obj)
[AI] Finds and focuses the cursor on the first node matching the given object by hash and value; supp...
Definition: mxhashtable.h:190
MxHashTableCursor(MxHashTable< T > *p_table)
[AI] Constructs a cursor operating on the supplied table; initially not referencing any match.
Definition: mxhashtable.h:155
void DeleteMatch()
[AI] If the cursor points to a match, removes it from table and destroys the node.
Definition: mxhashtable.h:214
MxBool Current(T &p_obj)
[AI] Retrieves the object at the current match position, if valid.
Definition: mxhashtable.h:204
[AI] Node used within the MxHashTable to store an individual object and associated hash,...
Definition: mxhashtable.h:20
MxU32 m_hash
[AI] The hash value for m_obj, used for placement/search in the table.
Definition: mxhashtable.h:43
T m_obj
[AI] The actual object value this node represents.
Definition: mxhashtable.h:41
MxHashTableNode * m_prev
[AI] Previous node in the linked list chain within the current bucket.
Definition: mxhashtable.h:45
MxHashTableNode * m_next
[AI] Next node in the linked list chain within the current bucket.
Definition: mxhashtable.h:47
[AI] Generic hash table collection implementing chained (bucketed) hashing, used for efficient lookup...
Definition: mxhashtable.h:57
MxU32 m_increaseAmount
Definition: mxhashtable.h:137
void NodeInsert(MxHashTableNode< T > *)
[AI] Inserts a given node into the relevant hash bucket according to the node's hash value.
Definition: mxhashtable.h:294
MxU32 m_autoResizeRatio
[AI] Ratio at which the table will auto-resize (load factor denominator).
Definition: mxhashtable.h:125
Option m_resizeOption
[AI] Strategy currently in use for resizing the table when needed.
Definition: mxhashtable.h:128
MxHashTableNode< T > ** m_slots
[AI] Array of pointers to bucket heads; each slot is a chain of nodes (linked list) holding objects w...
Definition: mxhashtable.h:119
~MxHashTable() override
[AI] Destructor.
Definition: mxhashtable.h:238
void Add(T)
[AI] Inserts a new item into the hash table, possibly resizing if automatic resize is enabled and loa...
Definition: mxhashtable.h:309
MxHashTable()
[AI] Default constructor.
Definition: mxhashtable.h:71
MxU32 m_numSlots
[AI] Number of hash buckets in the table; controls how hash values are mapped to buckets.
Definition: mxhashtable.h:122
double m_increaseFactor
Definition: mxhashtable.h:138
void DeleteAll()
[AI] Removes and destructs all nodes in all hash buckets, clearing the table.
Definition: mxhashtable.h:245
Option
[AI] Enum describing the strategy for resizing the hash table when load increases.
Definition: mxhashtable.h:62
@ e_expandAll
[AI] Fixed amount of slots added on resize.
Definition: mxhashtable.h:64
@ e_noExpand
[AI] Never resize (table will not expand regardless of load).
Definition: mxhashtable.h:63
@ e_expandMultiply
[AI] Table size is multiplied by a factor on resize.
Definition: mxhashtable.h:65
void Resize()
[AI] Expand/recreates the hash table according to the current resizing policy.
Definition: mxhashtable.h:261
virtual MxU32 Hash(T)
[AI] Computes the hash of the given object.
Definition: mxhashtable.h:107
#define NULL
[AI] Null pointer value (C/C++ semantics).
Definition: legotypes.h:26
#define HASH_TABLE_INIT_SIZE
Definition: mxhashtable.h:8
MxU8 MxBool
[AI]
Definition: mxtypes.h:124
signed int MxS32
[AI]
Definition: mxtypes.h:38
unsigned int MxU32
[AI]
Definition: mxtypes.h:32