OpenMoHAA 0.82.0
Loading...
Searching...
No Matches
umap.h
1/*
2===========================================================================
3Copyright (C) 2024 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// umap.h: Hash table based map class template. Maps text based keys to previously
24// stored data.
25//
26
27#pragma once
28
29#include "str.h"
30#include <stdlib.h>
31
32template< class Type >
33class UMap : public Class
34 {
35 private:
36 struct hashnode_s
37 {
38 str key;
39 Type value;
40 hashnode_s *next;
41
42 hashnode_s( const char *k, Type v, hashnode_s *n ) : key( k ), value( v ), next( n ) {};
43 hashnode_s( const str &k, Type v, hashnode_s *n ) : key( k.c_str() ), value( v ), next( n ) {};
44 };
45
46 hashnode_s **m_heads;
47 Type m_defaultvalue;
48
49 unsigned m_tablesize;
50 unsigned m_numentries;
51 unsigned m_tablesizemask;
52
53 unsigned getHash( const char *key );
54
55 public:
56 void Clear( void );
57 unsigned getNumEntries( void ) const;
58 void DeleteDefaultValues ( void );
59
60 Type& operator[]( const char *key );
61 Type& operator[]( const str &key );
62
63 const char *getKeyByIndex ( int index ) const;
64 Type& getValueByIndex ( unsigned index );
65
66 ~UMap<Type>();
67
68 UMap( Type defaultvalue, unsigned tablesize = 64 ) : m_defaultvalue( defaultvalue ), m_tablesize( tablesize )
69 {
70 int i;
71 int bits;
72
73 assert( m_tablesize > 0 );
74
75 m_heads = new hashnode_s *[ m_tablesize ];
76 memset( m_heads, 0, sizeof( *m_heads ) * m_tablesize );
77
78 m_numentries = 0;
79 m_tablesizemask = 0;
80
81 bits = 0;
82 for( i = 0; i < 32; i++ )
83 {
84 if ( m_tablesize & ( 1 << i ) )
85 {
86 bits++;
87 }
88 }
89
90 if ( bits == 1 )
91 {
92 m_tablesizemask = m_tablesize - 1;
93 }
94 };
95
96 UMap( UMap<Type> &map ) : m_defaultvalue( map.m_defaultvalue ), m_tablesize( map.m_tablesize )
97 {
98 unsigned i;
99 hashnode_s *node;
100 hashnode_s **prev;
101
102 assert( m_tablesize > 0 );
103
104 m_heads = new hashnode_s *[ m_tablesize ];
105 m_numentries = map.m_numentries;
106 m_tablesizemask = map.m_tablesizemask;
107
108 for( i = 0; i < m_tablesize; i++ )
109 {
110 if ( !map.m_heads[ i ] )
111 {
112 m_heads[ i ] = NULL;
113 continue;
114 }
115
116 prev = &m_heads[ i ];
117 for( node = map.m_heads[ i ]; node != NULL; node = node->next )
118 {
119 *prev = new hashnode_s( node->key, node->value, NULL );
120 prev = &( *prev )->next;
121 }
122 }
123 };
124 };
125
126template< class Type >
127UMap<Type>::~UMap<Type>()
128 {
129 Clear();
130 delete m_heads;
131 }
132
133template< class Type >
134unsigned UMap<Type>::getHash
135 (
136 const char *key
137 )
138
139 {
140 unsigned h;
141 const char *v;
142
143 if ( m_tablesizemask )
144 {
145 h = 0;
146 for( v = key; *v != '\0'; v++ )
147 {
148 h = ( 64 * h + unsigned( *v ) ) & m_tablesizemask;
149 }
150 }
151 else
152 {
153 h = 0;
154 for( v = key; *v != '\0'; v++ )
155 {
156 h = ( 64 * h + unsigned( *v ) ) % m_tablesize;
157 }
158 }
159
160 return h;
161 }
162
163template< class Type >
165 (
166 const char *key
167 )
168
169 {
170 hashnode_s **head;
171 hashnode_s *node;
172 unsigned hash;
173
174 // FIXME
175 // if list was always sorted, could just insert new node as soon as we get
176 // node whose key is greater than the search key
177 hash = getHash( key );
178 head = &m_heads[ hash ];
179 if ( *head )
180 {
181 for( node = *head; node != NULL; node = node->next )
182 {
183 if ( node->key == key )
184 {
185 return node->value;
186 }
187 }
188 }
189
190 m_numentries++;
191
192 *head = new hashnode_s( key, m_defaultvalue, *head );
193
194 return ( *head )->value;
195 }
196
197template< class Type >
198const char * UMap<Type>::getKeyByIndex
199 (
200 int index
201 ) const
202
203 {
204 unsigned head;
205
206 for ( head = 0; head < m_tablesize; head++ )
207 {
208 hashnode_s *node;
209
210 for ( node = m_heads[head]; node; node = node->next )
211 {
212 if ( !index )
213 return node->key.c_str ();
214
215 index--;
216 }
217 }
218
219 return NULL;
220 }
221
222template <class Type>
223Type &UMap<Type>::getValueByIndex
224 (
225 unsigned index
226 )
227
228 {
229 unsigned head;
230
231 ASSERT ( index < getNumEntries () );
232
233 for ( head = 0; head < m_tablesize; head++ )
234 {
235 hashnode_s *node;
236
237 for ( node = m_heads[head]; node; node = node->next )
238 {
239 if ( !index )
240 return node->value;
241
242 index--;
243 }
244 }
245
246 // Should never, EVER get here.
247 ASSERT ( 0 );
248 return m_defaultvalue;
249 }
250
251template <class Type>
252inline void UMap<Type>::DeleteDefaultValues
253 (
254 void
255 )
256
257 {
258 unsigned head;
259
260 for ( head = 0; head < m_tablesize; head++ )
261 {
262 hashnode_s *node;
263
264 while ( m_heads[head] && m_heads[head]->value == m_defaultvalue )
265 {
266 node = m_heads[head];
267 m_heads[head] = node->next;
268 delete node;
269 m_numentries--;
270 }
271
272 if ( !m_heads[head] )
273 continue;
274
275 for ( node = m_heads[head]; node->next; )
276 {
277 hashnode_s *next = node->next;
278
279 if ( next->value == m_defaultvalue )
280 {
281 node->next = next->next;
282 delete next;
283 m_numentries--;
284 }
285 else
286 node = node->next;
287 }
288 }
289 }
290
291template< class Type >
292inline Type& UMap<Type>::operator[]
293 (
294 const str &key
295 )
296
297 {
298 return this->[ key.c_str() ];
299 }
300
301template< class Type >
302void UMap<Type>::Clear
303 (
304 void
305 )
306
307 {
308 unsigned i;
309 hashnode_s *node;
310 hashnode_s *next;
311
312 for( i = 0; i < m_tablesize; i++ )
313 {
314 next = m_heads[ i ];
315 while( next != NULL )
316 {
317 node = next;
318 next = next->next;
319 delete node;
320 }
321
322 m_heads[ i ] = NULL;
323 }
324
325 m_numentries = 0;
326 }
327
328template< class Type >
329inline unsigned UMap<Type>::getNumEntries
330 (
331 void
332 ) const
333
334 {
335 return m_numentries;
336 }
Definition umap.h:34
Definition str.h:77