Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
hashtemplate.h
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/***********************************************************************************************
20 *** Confidential - Westwood Studios ***
21 ***********************************************************************************************
22 * *
23 * Project Name : Commando *
24 * *
25 * $Archive:: /Commando/Code/wwlib/hashtemplate.h $*
26 * *
27 * Author:: Greg_h *
28 * *
29 * $Modtime:: 11/19/01 12:16p $*
30 * *
31 * $Revision:: 7 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
36
37
38#if defined(_MSC_VER)
39#pragma once
40#endif
41
42#ifndef HASH_TEMPLATE_H
43#define HASH_TEMPLATE_H
44
45#include "always.h"
46#include "wwstring.h"
47
48// Class for providing hash values
49
50template <class Key> class HashTemplateKeyClass
51{
52public:
53 static inline unsigned int Get_Hash_Value (const Key& k);
54};
55
56// Default hash function for data types that can be cast into an unsigned int
57template <class Key> inline unsigned int HashTemplateKeyClass<Key>::Get_Hash_Value (const Key& k)
58{
59 unsigned int hval = *((const unsigned int*)(&k));
60 hval = hval + (hval>>5) + (hval>>10) + (hval >> 20);
61 return hval;
62}
63
64// Specialization for floating point hash values (as the default dword-
65// casting yields a very bad hash function)
66template <> inline unsigned int HashTemplateKeyClass<float>::Get_Hash_Value (const float& s)
67{
68 unsigned int z = *((const unsigned int*)(&s));
69 return ((z>>22)+(z>>12)+(z));
70}
71
72// Hash class
73template <class KeyType, class ValueType>
75{
76 struct Entry;
77public:
78
79 enum
80 {
81 NIL = -1 // internal enumeration for representing a NULL link
82 };
83
86
87 void Insert(const KeyType& s, const ValueType& d);
88 void Set_Value(const KeyType& s, const ValueType& d);
89 void Remove(const KeyType& s);
90 void Remove(const KeyType& s, const ValueType& d);
91 ValueType Get(const KeyType& s) const;
92 bool Get(const KeyType& s, ValueType& d) const;
93 bool Exists(const KeyType& s) const;
94 bool Exists(const KeyType& s, const ValueType& d) const;
95 void Remove_All(void);
96 unsigned int Get_Size(void) const;
97
98 int* Get_Hash() { return Hash; }
99 Entry* Get_Table() { return Table; }
100
101private:
102 HashTemplateClass (const HashTemplateClass&); // not allowed
103 HashTemplateClass& operator= (const HashTemplateClass&); // not allowed
104 static unsigned int Get_Hash_Val(const KeyType& s, const unsigned int hash_array_size);
105 void Re_Hash(void);
106
107 int Alloc_Entry(void);
108
109 struct Entry
110 {
111 int Next; // next pointer in linked list
112 KeyType Key; // key
113 ValueType Value; // value
114 };
115
116 int* Hash; // hash pointers
117 Entry* Table; // allocation table
118 int First; // handle of first free entry
119 unsigned int Size; // size of hash table
120};
121
122template <class KeyType, class ValueType>
124{
125 int HashIndex; // index to hash pointer table
126 int Handle;
128
129public:
131 :
132 HashTable(hash_table)
133 {
134 First();
135 }
136
137 void First()
138 {
140 int size=HashTable.Get_Size();
141 for (HashIndex=0;HashIndex<size;++HashIndex) {
142 Handle = HashTable.Get_Hash()[HashIndex];
144 }
145 }
146
147 void Next()
148 {
149 Handle=HashTable.Get_Table()[Handle].Next;
151 int size=HashTable.Get_Size();
152 for (++HashIndex;HashIndex<size;++HashIndex) {
153 Handle = HashTable.Get_Hash()[HashIndex];
155 }
156 }
157 }
158
159 bool Is_Done() const
160 {
161 return HashIndex==int(HashTable.Get_Size());
162 }
163
164 ValueType& Peek_Value()
165 {
166 return HashTable.Get_Table()[Handle].Value;
167 }
168
169 const KeyType& Peek_Key()
170 {
171 return HashTable.Get_Table()[Handle].Key;
172 }
173
174};
175
176//------------------------------------------------------------------------
177// Implementation
178//------------------------------------------------------------------------
179
180template <class KeyType, class ValueType> inline void HashTemplateClass<KeyType,ValueType>::Insert(const KeyType& s, const ValueType& d)
181{
182 int h;
183 h = Alloc_Entry();
184 unsigned int hval = Get_Hash_Val(s,Size);
185 Table[h].Key = s;
186 Table[h].Value = d;
187 Table[h].Next = Hash[hval];
188 Hash[hval] = h;
189}
190
191template <class KeyType, class ValueType> inline unsigned int HashTemplateClass<KeyType,ValueType>::Get_Size (void) const
192{
193 return Size;
194}
195
196template <class KeyType, class ValueType> inline void HashTemplateClass<KeyType,ValueType>::Remove_All (void)
197{
198 for (unsigned int i = 0; i < Size; i++)
199 {
200 int f = Hash[i];
201 if (f!=NIL)
202 {
203 int h = f;
204 while (Table[h].Next != NIL)
205 h = Table[h].Next;
206 Table[h].Next = First; // link to first free
207 First = f; // link to beginning
208 Hash[i] = NIL; // kill entry in hash
209 }
210 }
211}
212
213template <class KeyType, class ValueType> inline void HashTemplateClass<KeyType,ValueType>::Remove (const KeyType& s)
214{
215 if (!Hash) return;
216 unsigned int hval = Get_Hash_Val(s,Size);
217 int prev = NIL;
218 int h = Hash[hval];
219
220 while (h != NIL)
221 {
222 if (Table[h].Key == s)
223 {
224 if (prev!=NIL)
225 Table[prev].Next = Table[h].Next;
226 else
227 Hash[hval] = Table[h].Next;
228 Table[h].Next = First;
229 First = h;
230 return;
231 }
232 prev = h;
233 h = Table[h].Next;
234 }
235}
236
237template <class KeyType, class ValueType> inline void HashTemplateClass<KeyType,ValueType>::Remove (const KeyType& s, const ValueType& d)
238{
239 if (!Hash) return;
240 unsigned int hval = Get_Hash_Val(s,Size);
241 int prev = NIL;
242 int h = Hash[hval];
243
244 while (h != NIL)
245 {
246 if (Table[h].Key == s && Table[h].Value == d)
247 {
248 if (prev!=NIL)
249 Table[prev].Next = Table[h].Next;
250 else
251 Hash[hval] = Table[h].Next;
252 Table[h].Next = First;
253 First = h;
254 return;
255 }
256 prev = h;
257 h = Table[h].Next;
258 }
259}
260
261// Set the value at existing key, or if not found insert a new value
262template <class KeyType, class ValueType> inline void HashTemplateClass<KeyType,ValueType>::Set_Value (const KeyType& s, const ValueType& v)
263{
264 if (Hash) {
265 int h = Hash[Get_Hash_Val(s,Size)];
266 while (h!=NIL) {
267 if (Table[h].Key == s) {
268 Table[h].Value=v;
269 return;
270 }
271 h = Table[h].Next;
272 }
273 }
274 Insert(s,v);
275}
276
277template <class KeyType, class ValueType> inline ValueType HashTemplateClass<KeyType,ValueType>::Get (const KeyType& s) const
278{
279 if (Hash) {
280 int h = Hash[Get_Hash_Val(s,Size)];
281 while (h!=NIL)
282 {
283 if (Table[h].Key == s)
284 return Table[h].Value;
285 h = Table[h].Next;
286 }
287 }
288 return ValueType(0);
289}
290
291template <class KeyType, class ValueType> inline bool HashTemplateClass<KeyType,ValueType>::Get(const KeyType& s, ValueType& d) const
292{
293 if (Hash) {
294 int h = Hash[Get_Hash_Val(s,Size)];
295 while (h!=NIL)
296 {
297 if (Table[h].Key == s)
298 {
299 d = Table[h].Value;
300 return true;
301 }
302 h = Table[h].Next;
303 }
304 }
305 return false;
306}
307
308template <class KeyType, class ValueType> inline bool HashTemplateClass<KeyType,ValueType>::Exists(const KeyType& s) const
309{
310 if (Hash) {
311 int h = Hash[Get_Hash_Val(s,Size)];
312 while (h!=NIL)
313 {
314 if (Table[h].Key == s)
315 return true;
316 h = Table[h].Next;
317 }
318 }
319 return false;
320}
321
322template <class KeyType, class ValueType> inline bool HashTemplateClass<KeyType,ValueType>::Exists(const KeyType& s, const ValueType& d) const
323{
324 if (Hash) {
325 int h = Hash[Get_Hash_Val(s,Size)];
326 while (h!=NIL)
327 {
328 if (Table[h].Key == s && Table[h].Value == d)
329 return true;
330 h = Table[h].Next;
331 }
332 }
333 return false;
334}
335
336template <class KeyType, class ValueType> inline unsigned int HashTemplateClass<KeyType,ValueType>::Get_Hash_Val(const KeyType& s, const unsigned int hash_array_size)
337{
338 return HashTemplateKeyClass<KeyType>::Get_Hash_Value (s) & (hash_array_size-1);
339}
340
341template <class KeyType, class ValueType> inline void HashTemplateClass<KeyType,ValueType>::Re_Hash()
342{
343 unsigned int new_size = Size*2;
344 if (new_size < 4)
345 new_size = 4;
346
347 Entry *new_table = W3DNEWARRAY Entry[new_size];
348 int *new_hash = W3DNEWARRAY int[new_size];
349
350 int cnt = 0;
351 int i;
352
353 for (i = 0; i < (int)new_size; i++)
354 {
355 new_table[i].Next = NIL;
356 new_hash[i] = NIL;
357 }
358
359 if (Size) // if we have existing data, it needs to be rehashed
360 {
361 for (i = 0; i < (int)Size; i++) // step through each old hash set
362 {
363 int h = Hash[i];
364 while (h != NIL)
365 {
366 unsigned int hVal = Get_Hash_Val(Table[h].Key, new_size);
367 new_table[cnt].Key = Table[h].Key;
368 new_table[cnt].Value = Table[h].Value;
369 new_table[cnt].Next = new_hash[hVal];
370 new_hash[hVal] = cnt;
371 cnt++;
372 h = Table[h].Next;
373 }
374 }
375 delete[] Hash;
376 delete[] Table;
377 }
378
379 for (i = cnt; i < (int)new_size; i++)
380 new_table[i].Next = i+1;
381 new_table[new_size-1].Next = NIL;
382
383 First = cnt;
384 Hash = new_hash;
385 Table = new_table;
386 Size = new_size;
387}
388
389template <class KeyType, class ValueType> inline int HashTemplateClass<KeyType,ValueType>::Alloc_Entry()
390{
391 if (First == NIL) // need to re-alloc and re-hash tables
392 Re_Hash();
393 int h = First;
394 First = Table[First].Next;
395 return h;
396}
397
398template <class KeyType, class ValueType> inline HashTemplateClass<KeyType,ValueType>::HashTemplateClass() : Hash(0),Table(0),First(NIL),Size(0)
399{
400// Re_Hash();
401}
402
403template <class KeyType, class ValueType> inline HashTemplateClass<KeyType,ValueType>::~HashTemplateClass()
404{
405 if (Hash)
406 delete[] Hash;
407 if (Table)
408 delete[] Table;
409}
410
411// Get_Hash_Value specialization for StringClass. This is intended to be used
412// for filenames, so it takes into account the four characters that come before
413// the file extension (.xxx - extension expected to be 4 characters).
414
415template <> inline unsigned int HashTemplateKeyClass<StringClass>::Get_Hash_Value(const StringClass& s)
416{
417 unsigned int len=s.Get_Length();
418 unsigned char* buffer=(unsigned char*)s.Peek_Buffer();
419 if (len<8) {
420 unsigned int hval=0;
421 for (unsigned int a=0;a<len;++a) {
422 hval+=37*hval+buffer[a];
423 }
424 return hval;
425 }
426 unsigned int hval = *((const unsigned int*)(buffer+len-8));
427 hval = hval + (hval>>5) + (hval>>10) + (hval >> 20);
428 return hval;
429}
430
431
432
433#endif
#define W3DNEWARRAY
Definition always.h:110
void Remove(const KeyType &s, const ValueType &d)
bool Exists(const KeyType &s, const ValueType &d) const
bool Exists(const KeyType &s) const
void Remove_All(void)
Entry * Get_Table()
bool Get(const KeyType &s, ValueType &d) const
void Set_Value(const KeyType &s, const ValueType &d)
unsigned int Get_Size(void) const
ValueType Get(const KeyType &s) const
void Remove(const KeyType &s)
void Insert(const KeyType &s, const ValueType &d)
HashTemplateIterator(HashTemplateClass< KeyType, ValueType > &hash_table)
ValueType & Peek_Value()
const KeyType & Peek_Key()
static unsigned int Get_Hash_Value(const Key &k)
int Get_Length(void) const
Definition wwstring.h:664
TCHAR * Peek_Buffer(void)
Definition wwstring.h:560