OpenMoHAA 0.82.0
Loading...
Searching...
No Matches
con_arrayset.h
1/*
2===========================================================================
3Copyright (C) 2015 the OpenMoHAA team
4
5This file is part of OpenMoHAA source code.
6
7OpenMoHAA source code is free software; you can redistribute it
8and/or modify it under the terms of the GNU General Public License as
9published by the Free Software Foundation; either version 2 of the License,
10or (at your option) any later version.
11
12OpenMoHAA source code is distributed in the hope that it will be
13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with OpenMoHAA source code; if not, write to the Free Software
19Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20===========================================================================
21*/
22
23// con_arrayset.h: con_set with an index table
24
25#pragma once
26
27#include "mem_blockalloc.h"
28
29#if defined(GAME_DLL)
30# include "../fgame/g_local.h"
31
32# define ARRAYSET_Alloc gi.Malloc
33# define ARRAYSET_Free gi.Free
34
35#elif defined(CGAME_DLL)
36# include "../cgame/cg_local.h"
37
38# define ARRAYSET_Alloc cgi.Malloc
39# define ARRAYSET_Free cgi.Free
40
41#elif defined(REF_DLL)
42# include "../renderercommon/tr_common.h"
43
44# define ARRAYSET_Alloc ri.Malloc
45# define ARRAYSET_Free ri.Free
46
47#else
48# include "qcommon.h"
49
50# define ARRAYSET_Alloc Z_Malloc
51# define ARRAYSET_Free Z_Free
52#endif
53
54template<typename k, typename v>
55class con_arrayset;
56
57template<typename k, typename v>
59
60template<typename k, typename v>
61class con_arrayset_Entry
62{
63 friend con_arrayset<k, v>;
65
66public:
67 k key;
68 v value;
69 unsigned int index;
70
71 con_arrayset_Entry *next;
72
73public:
74 void *operator new(size_t size) { return con_arrayset<k, v>::NewEntry(size); }
75
76 void operator delete(void *ptr) { con_arrayset<k, v>::DeleteEntry(ptr); }
77
78 con_arrayset_Entry()
79 {
80 this->key = k();
81 this->value = v();
82
83 index = 0;
84 next = NULL;
85 }
86
87#ifdef ARCHIVE_SUPPORTED
88 void Archive(Archiver& arc);
89#endif
90};
91
92template<typename k, typename v>
93class con_arrayset
94{
95 friend class con_arrayset_enum<k, v>;
96
97public:
98 using Entry = con_arrayset_Entry<k, v>;
99
100public:
101 static MEM_BlockAlloc<Entry> Entry_allocator;
102
103private:
104 Entry **table; // hashtable
105 unsigned int tableLength;
106 unsigned int threshold;
107 unsigned int count; // num of entries
108 short unsigned int tableLengthIndex;
109 Entry *defaultEntry;
110 Entry **reverseTable; // the index table
111
112protected:
113 Entry *findKeyEntry(const k& key) const;
114 Entry *addKeyEntry(const k& key);
115 Entry *addNewKeyEntry(const k& key);
116
117public:
118 static void *NewEntry(size_t size);
119 static void DeleteEntry(void *entry);
120 static void *NewTable(size_t count);
121 static void DeleteTable(void *table);
122
123public:
124 con_arrayset();
125 ~con_arrayset();
126
127#ifdef ARCHIVE_SUPPORTED
128 void Archive(Archiver& arc);
129#endif
130
131 void clear();
132 void resize(int count = 0);
133 unsigned int size() const;
134
135 unsigned int findKeyIndex(const k& key);
136 unsigned int addKeyIndex(const k& key);
137 unsigned int addNewKeyIndex(const k& key);
138 bool remove(const k& key);
139
140 v& operator[](unsigned int index);
141};
142
143template<typename k, typename v>
144MEM_BlockAlloc<typename con_arrayset<k, v>::Entry> con_arrayset<k, v>::Entry_allocator;
145
146template<typename k, typename v>
147void *con_arrayset<k, v>::NewEntry(size_t size)
148{
149 return Entry_allocator.Alloc();
150}
151
152template<typename k, typename v>
153void con_arrayset<k, v>::DeleteEntry(void *entry)
154{
155 Entry_allocator.Free(entry);
156}
157
158template<typename k, typename v>
159void *con_arrayset<k, v>::NewTable(size_t count)
160{
161 return ARRAYSET_Alloc(sizeof(Entry *) * (int)count);
162}
163
164template<typename k, typename v>
165void con_arrayset<k, v>::DeleteTable(void *table)
166{
167 ARRAYSET_Free(table);
168}
169
170template<typename key, typename value>
171con_arrayset<key, value>::con_arrayset()
172{
173 tableLength = 1;
174 table = &defaultEntry;
175
176 threshold = 1;
177 count = 0;
178 tableLengthIndex = 0;
179
180 defaultEntry = NULL;
181 reverseTable = &this->defaultEntry;
182}
183
184template<typename key, typename value>
185con_arrayset<key, value>::~con_arrayset()
186{
187 clear();
188}
189
190template<typename key, typename value>
191void con_arrayset<key, value>::resize(int count)
192{
193 Entry **oldReverseTable = reverseTable;
194 Entry **oldTable = table;
195 Entry *e, *old;
196 unsigned int index;
197 unsigned int oldTableLength = tableLength;
198 unsigned int i;
199
200 if (count > 0) {
201 tableLength += count;
202 threshold = tableLength;
203 } else {
204 //threshold = ( unsigned int )( ( float )tableLength * 0.75f );
205 threshold = (unsigned int)((float)tableLength * 0.75);
206 if (threshold < 1) {
207 threshold = 1;
208 }
209
210 tableLength += threshold;
211 }
212
213 // allocate a new table
214 table = new (NewTable(tableLength)) Entry *[tableLength]();
215
216 // rehash the table
217 for (i = oldTableLength; i > 0; i--) {
218 // rehash all entries from the old table
219 for (e = oldTable[i - 1]; e != NULL; e = old) {
220 old = e->next;
221
222 // insert the old entry to the table hashindex
223 index = HashCode<key>(e->key) % tableLength;
224
225 e->next = table[index];
226 table[index] = e;
227 }
228 }
229
230 if (oldTableLength > 1) {
231 // delete the previous table
232 DeleteTable(oldTable);
233 }
234
235 // allocate a bigger reverse table
236 reverseTable = new (NewTable(tableLength)) Entry *[this->tableLength]();
237
238 for (i = 0; i < oldTableLength; i++) {
239 reverseTable[i] = oldReverseTable[i];
240 }
241
242 if (oldTableLength > 1) {
243 DeleteTable(oldReverseTable);
244 }
245}
246
247template<typename k, typename v>
248unsigned int con_arrayset<k, v>::size() const
249{
250 return count;
251}
252
253template<typename key, typename value>
254void con_arrayset<key, value>::clear()
255{
256 Entry *entry = NULL;
257 Entry *next = NULL;
258 unsigned int i;
259
260 if (tableLength > 1) {
261 DeleteTable(reverseTable);
262 reverseTable = &defaultEntry;
263 }
264
265 for (i = 0; i < tableLength; i++) {
266 for (entry = table[i]; entry != NULL; entry = next) {
267 next = entry->next;
268 delete entry;
269 }
270 }
271
272 if (tableLength > 1) {
273 DeleteTable(table);
274 }
275
276 tableLength = 1;
277 table = &defaultEntry;
278
279 threshold = 1;
280 count = 0;
281 tableLengthIndex = 0;
282
283 defaultEntry = NULL;
284}
285
286template<typename k, typename v>
287typename con_arrayset<k, v>::Entry *con_arrayset<k, v>::findKeyEntry(const k& key) const
288{
289 Entry *entry;
290
291 entry = table[HashCode<k>(key) % tableLength];
292
293 for (; entry != NULL; entry = entry->next) {
294 if (entry->key == key) {
295 return entry;
296 }
297 }
298
299 return NULL;
300}
301
302template<typename k, typename v>
303typename con_arrayset<k, v>::Entry *con_arrayset<k, v>::addKeyEntry(const k& key)
304{
305 Entry *entry;
306
307 entry = findKeyEntry(key);
308
309 if (entry != NULL) {
310 return entry;
311 } else {
312 return addNewKeyEntry(key);
313 }
314}
315
316template<typename k, typename v>
317typename con_arrayset<k, v>::Entry *con_arrayset<k, v>::addNewKeyEntry(const k& key)
318{
319 Entry *entry;
320 int index;
321
322 if (count >= threshold) {
323 resize();
324 }
325
326 index = HashCode<k>(key) % tableLength;
327
328 entry = new Entry;
329
330 if (defaultEntry == NULL) {
331 defaultEntry = entry;
332 entry->next = NULL;
333 } else {
334 entry->next = table[index];
335 }
336
337 reverseTable[count] = entry;
338 count++;
339
340 entry->key = key;
341 entry->index = count;
342 table[index] = entry;
343
344 return entry;
345}
346
347template<typename k, typename v>
348unsigned int con_arrayset<k, v>::addKeyIndex(const k& key)
349{
350 Entry *entry = this->addKeyEntry(key);
351
352 return entry->index;
353}
354
355template<typename k, typename v>
356unsigned int con_arrayset<k, v>::addNewKeyIndex(const k& key)
357{
358 Entry *entry = this->addNewKeyEntry(key);
359
360 return entry->index;
361}
362
363template<typename k, typename v>
364unsigned int con_arrayset<k, v>::findKeyIndex(const k& key)
365{
366 Entry *entry = this->findKeyEntry(key);
367
368 if (entry != NULL) {
369 return entry->index;
370 } else {
371 return 0;
372 }
373}
374
375template<typename k, typename v>
376bool con_arrayset<k, v>::remove(const k& key)
377{
378 int i;
379
380 for (i = 0; i < tableLength; i++) {
381 if (reverseTable[i] && reverseTable[i]->key == key) {
382 reverseTable[i] = NULL;
383 }
384 }
385
386 return con_set<k, v>::remove(key);
387}
388
389template<typename key, typename value>
390value& con_arrayset<key, value>::operator[](unsigned int index)
391{
392 return reverseTable[index - 1]->key;
393}
394
395template<typename key, typename value>
396class con_arrayset_enum
397{
398 friend class con_map_enum<key, value>;
399
400public:
401 using Entry = typename con_arrayset<key, value>::Entry;
402
403protected:
405 unsigned int m_Index;
406 Entry *m_CurrentEntry;
407 Entry *m_NextEntry;
408
409public:
410 con_arrayset_enum();
411 con_arrayset_enum(con_arrayset<key, value>& set);
412
413 bool operator=(con_arrayset<key, value>& set);
414
415 Entry *NextElement(void);
416 Entry *CurrentElement(void);
417};
418
419template<typename key, typename value>
420con_arrayset_enum<key, value>::con_arrayset_enum()
421{
422 m_Set = NULL;
423 m_Index = 0;
424 m_CurrentEntry = NULL;
425 m_NextEntry = NULL;
426}
427
428template<typename key, typename value>
429con_arrayset_enum<key, value>::con_arrayset_enum(con_arrayset<key, value>& set)
430{
431 *this = set;
432}
433
434template<typename key, typename value>
435bool con_arrayset_enum<key, value>::operator=(con_arrayset<key, value>& set)
436{
437 m_Set = &set;
438 m_Index = m_Set->tableLength;
439 m_CurrentEntry = NULL;
440 m_NextEntry = NULL;
441
442 return true;
443}
444
445template<typename key, typename value>
446typename con_arrayset_enum<key, value>::Entry *con_arrayset_enum<key, value>::CurrentElement(void)
447{
448 return m_CurrentEntry;
449}
450
451template<typename key, typename value>
452typename con_arrayset_enum<key, value>::Entry *con_arrayset_enum<key, value>::NextElement(void)
453{
454 if (!m_NextEntry) {
455 while (1) {
456 if (!m_Index) {
457 break;
458 }
459
460 m_Index--;
461 m_NextEntry = m_Set->table[m_Index];
462
463 if (m_NextEntry) {
464 break;
465 }
466 }
467
468 if (!m_NextEntry) {
469 m_CurrentEntry = NULL;
470 return NULL;
471 }
472 }
473
474 m_CurrentEntry = m_NextEntry;
475 m_NextEntry = m_NextEntry->next;
476
477 return m_CurrentEntry;
478}
Definition archive.h:86
Definition mem_blockalloc.h:172
Definition con_arrayset.h:62
Definition con_arrayset.h:397
Definition con_arrayset.h:94
Definition con_set.h:607