| rev |
line source |
|
Me@14
|
1 /*
|
|
Me@14
|
2 * Copyright 2009 OpenSourceStewardshipFoundation.org
|
|
Me@14
|
3 * Licensed under GNU General Public License version 2
|
|
Me@14
|
4 *
|
|
Me@14
|
5 *
|
|
Me@14
|
6 * Author: seanhalle@yahoo.com
|
|
Me@14
|
7 */
|
|
Me@14
|
8
|
|
Me@14
|
9 #include "PrivateHash.h"
|
|
Me@14
|
10
|
|
Me@14
|
11
|
|
seanhalle@23
|
12 HashTable *
|
|
Me@14
|
13 makeHashTable( int numHashSlots, FreeEntryContentFnPtr freeFn )
|
|
Me@14
|
14 { HashTable * retTable;
|
|
Me@17
|
15 retTable = VMS_int__malloc( sizeof( HashTable ) );
|
|
Me@14
|
16
|
|
Me@14
|
17 retTable->freeEntryContentFn = freeFn;
|
|
Me@14
|
18
|
|
Me@17
|
19 retTable->entries = VMS_int__malloc( numHashSlots * sizeof(HashEntry *) );
|
|
Me@14
|
20 retTable->numEntries = 0;
|
|
Me@14
|
21 retTable->tableSz = numHashSlots;
|
|
Me@14
|
22
|
|
Me@14
|
23 nullOutTablesArray( retTable );
|
|
Me@14
|
24
|
|
Me@14
|
25 return retTable;
|
|
Me@14
|
26 }
|
|
Me@14
|
27
|
|
seanhalle@23
|
28 HashTable *
|
|
seanhalle@23
|
29 makeHashTable_WL( int numHashSlots, FreeEntryContentFnPtr freeFn )
|
|
seanhalle@23
|
30 { HashTable * retTable;
|
|
seanhalle@23
|
31 retTable = VMS_WL__malloc( sizeof( HashTable ) );
|
|
seanhalle@23
|
32
|
|
seanhalle@23
|
33 retTable->freeEntryContentFn = freeFn;
|
|
seanhalle@23
|
34
|
|
seanhalle@23
|
35 retTable->entries = VMS_int__malloc( numHashSlots * sizeof(HashEntry *) );
|
|
seanhalle@23
|
36 retTable->numEntries = 0;
|
|
seanhalle@23
|
37 retTable->tableSz = numHashSlots;
|
|
seanhalle@23
|
38
|
|
seanhalle@23
|
39 nullOutTablesArray( retTable );
|
|
seanhalle@23
|
40
|
|
seanhalle@23
|
41 return retTable;
|
|
seanhalle@23
|
42 }
|
|
seanhalle@23
|
43
|
|
seanhalle@23
|
44 void
|
|
Me@14
|
45 doubleTableSize( HashTable *table )
|
|
Me@14
|
46 { int i, oldTableSz, newTableSz;
|
|
Me@14
|
47 HashEntry *entry, *nextEntry, **oldEntries, **newEntries;
|
|
Me@14
|
48
|
|
Me@14
|
49 oldTableSz = table->tableSz;
|
|
Me@14
|
50 oldEntries = table->entries;
|
|
Me@14
|
51
|
|
seanhalle@23
|
52 newTableSz = 2 * oldTableSz;
|
|
Me@17
|
53 newEntries = VMS_int__malloc( newTableSz * sizeof(HashEntry *) );
|
|
Me@14
|
54
|
|
Me@14
|
55 table->tableSz = newTableSz;
|
|
Me@14
|
56 table->entries = newEntries;
|
|
Me@14
|
57 table->numEntries = 0; //about to add them all back!
|
|
Me@14
|
58
|
|
Me@14
|
59 // move all the entries from old to new
|
|
Me@14
|
60 for( i=0; i < oldTableSz; i++ )
|
|
Me@14
|
61 { if( oldEntries[i] != NULL )
|
|
Me@14
|
62 { entry = oldEntries[i];
|
|
Me@14
|
63 while( entry != NULL )
|
|
seanhalle@23
|
64 { nextEntry = entry->next; //save for later
|
|
Me@14
|
65 entry->next = NULL;
|
|
Me@14
|
66 putEntryIntoTable( entry, table ); //does not allocate anything
|
|
Me@14
|
67 entry = nextEntry;
|
|
Me@14
|
68 }
|
|
Me@14
|
69 }
|
|
Me@14
|
70 }
|
|
Me@14
|
71 }
|
|
Me@14
|
72
|
|
Me@14
|
73 void
|
|
Me@14
|
74 nullOutTablesArray( HashTable *table )
|
|
Me@14
|
75 { int i, tableSz;
|
|
Me@14
|
76 tableSz = table->tableSz;
|
|
Me@14
|
77 HashEntry ** entries = table->entries;
|
|
Me@14
|
78 for( i = 0; i < tableSz; i++ )
|
|
Me@14
|
79 entries[ i ] = NULL;
|
|
Me@14
|
80 }
|
|
Me@14
|
81
|
|
Me@14
|
82 unsigned int
|
|
Me@14
|
83 hashThisKey( char* s, int hashSz )
|
|
Me@14
|
84 { unsigned int h = 0;
|
|
Me@14
|
85 unsigned int i;
|
|
Me@14
|
86 hashkey_t* key = (hashkey_t*)s;
|
|
Me@14
|
87
|
|
Me@14
|
88 for(i=0 ; i<sizeof(hashkey_t); i++ )
|
|
Me@14
|
89 h = key->hashable[i] + h*31;
|
|
Me@14
|
90 return h % hashSz;
|
|
Me@14
|
91 }
|
|
Me@14
|
92
|
|
seanhalle@23
|
93 /*Copies the string that is the key*/
|
|
seanhalle@23
|
94 inline HashEntry *
|
|
seanhalle@23
|
95 makeHashEntry( char * key )
|
|
seanhalle@23
|
96 { HashEntry *hashEntry;
|
|
seanhalle@23
|
97
|
|
seanhalle@23
|
98 int32 len = strlen(key);
|
|
seanhalle@23
|
99
|
|
seanhalle@23
|
100 hashEntry = (HashEntry*) VMS_int__malloc( sizeof( HashEntry ) );
|
|
seanhalle@23
|
101 if( hashEntry == NULL ) return NULL;
|
|
seanhalle@23
|
102
|
|
seanhalle@23
|
103 hashEntry->key = VMS_int__malloc( len + 1 );
|
|
seanhalle@23
|
104 if( hashEntry->key == NULL ) return NULL;
|
|
seanhalle@23
|
105 memcpy( hashEntry->key, key, len + 1 );
|
|
seanhalle@23
|
106 hashEntry->next = NULL;
|
|
seanhalle@23
|
107
|
|
seanhalle@23
|
108 return hashEntry;
|
|
seanhalle@23
|
109 }
|
|
seanhalle@23
|
110
|
|
seanhalle@23
|
111
|
|
Me@14
|
112 /*Need this to be separated out, for use in both getParam and putParam
|
|
Me@14
|
113 */
|
|
Me@14
|
114 HashEntry *
|
|
Me@14
|
115 getEntryFromTable( char *key, HashTable * table )
|
|
seanhalle@23
|
116 { uint32
|
|
Me@14
|
117 hashIndex = hashThisKey( key, table->tableSz );
|
|
Me@14
|
118 HashEntry*
|
|
Me@14
|
119 hashEntry = table->entries[ hashIndex ];
|
|
Me@14
|
120 for( ; hashEntry != NULL; hashEntry = hashEntry->next )
|
|
Me@14
|
121 {
|
|
seanhalle@23
|
122 if( strcmp( hashEntry->key, key ) == 0 )
|
|
Me@14
|
123 return hashEntry;
|
|
Me@14
|
124 }
|
|
Me@14
|
125 return NULL;
|
|
Me@14
|
126 }
|
|
Me@14
|
127
|
|
Me@14
|
128 void *
|
|
Me@14
|
129 getValueFromTable( char *key, HashTable * table )
|
|
Me@14
|
130 { HashEntry *entry;
|
|
Me@14
|
131 entry = getEntryFromTable( key, table );
|
|
Me@14
|
132 if( entry == NULL ) return NULL;
|
|
Me@14
|
133
|
|
Me@14
|
134 return entry->content;
|
|
Me@14
|
135 }
|
|
Me@14
|
136
|
|
Me@14
|
137 /*If key already has a value, clobber the old one and replace it
|
|
Me@14
|
138 */
|
|
Me@14
|
139 int
|
|
Me@14
|
140 addValueIntoTable( char* key, void *content, HashTable *table )
|
|
Me@14
|
141 { unsigned int hashIdx;
|
|
Me@14
|
142 HashEntry* hashEntry;
|
|
Me@14
|
143
|
|
Me@14
|
144 hashEntry = getEntryFromTable( key, table );
|
|
Me@14
|
145 if( hashEntry == NULL )
|
|
Me@14
|
146 { hashIdx = hashThisKey( key, table->tableSz );
|
|
seanhalle@23
|
147 hashEntry = makeHashEntry( key );
|
|
Me@14
|
148 hashEntry->next = (table->entries)[hashIdx];
|
|
Me@14
|
149 (table->entries)[hashIdx] = hashEntry;
|
|
Me@14
|
150 table->numEntries += 1;
|
|
Me@14
|
151 if( table->tableSz < table->numEntries ) doubleTableSize( table );
|
|
Me@14
|
152 }
|
|
Me@14
|
153 else
|
|
Me@14
|
154 { (*(table->freeEntryContentFn))( hashEntry->content );
|
|
Me@14
|
155 }
|
|
Me@14
|
156 hashEntry->content = content;
|
|
Me@14
|
157 return 1;
|
|
Me@14
|
158 }
|
|
Me@14
|
159
|
|
seanhalle@23
|
160
|
|
Me@14
|
161 int
|
|
Me@14
|
162 putEntryIntoTable( HashEntry *entry, HashTable *table )
|
|
Me@14
|
163 { unsigned int hashIdx;
|
|
Me@14
|
164 HashEntry* testEntry;
|
|
Me@14
|
165
|
|
Me@14
|
166 testEntry = getEntryFromTable( entry->key, table );
|
|
Me@14
|
167 if( testEntry == NULL )
|
|
Me@14
|
168 { hashIdx = hashThisKey( entry->key, table->tableSz );
|
|
Me@14
|
169 entry->next = (table->entries)[hashIdx];
|
|
Me@14
|
170 (table->entries)[hashIdx] = entry;
|
|
Me@14
|
171 table->numEntries += 1;
|
|
Me@14
|
172 if( table->tableSz < table->numEntries ) doubleTableSize( table );
|
|
Me@14
|
173 }
|
|
Me@14
|
174 else
|
|
Me@14
|
175 { (*(table->freeEntryContentFn))( testEntry->content );
|
|
seanhalle@23
|
176 //being lazy -- will create bug in code that relies on having ptr
|
|
seanhalle@23
|
177 // to elem given to insert into table!
|
|
Me@14
|
178 testEntry->content = entry->content;
|
|
Me@14
|
179 entry->content = NULL;
|
|
Me@14
|
180 freeHashEntryButNotContent( entry );
|
|
Me@14
|
181 }
|
|
Me@14
|
182 return 1;
|
|
Me@14
|
183 }
|
|
Me@14
|
184
|
|
Me@14
|
185 /*Better version
|
|
Me@14
|
186 */
|
|
Me@14
|
187 void
|
|
Me@14
|
188 untested_putEntryIntoTable( HashEntry *entry, HashTable * table )
|
|
Me@14
|
189 { HashEntry *testEntry, *prevEntry = NULL;
|
|
Me@14
|
190 unsigned int
|
|
Me@14
|
191 hashIndex = hashThisKey( entry->key, table->tableSz );
|
|
Me@14
|
192
|
|
Me@14
|
193 testEntry = table->entries[ hashIndex ];
|
|
Me@14
|
194 for( ; testEntry != NULL; testEntry = testEntry->next )
|
|
seanhalle@23
|
195 { if( strcmp( testEntry->key, entry->key ) == 0 )
|
|
Me@14
|
196 { if( prevEntry == NULL )
|
|
Me@14
|
197 { table->entries[hashIndex] = entry;
|
|
Me@14
|
198 entry->next = testEntry->next;
|
|
Me@14
|
199 }
|
|
Me@14
|
200 else
|
|
Me@14
|
201 { prevEntry->next = entry;
|
|
Me@14
|
202 entry->next = testEntry->next;
|
|
Me@14
|
203 }
|
|
Me@14
|
204 freeHashEntryUsing( testEntry, table ); //frees content too!
|
|
Me@14
|
205 return;
|
|
Me@14
|
206 }
|
|
Me@14
|
207 }
|
|
Me@14
|
208 //wasn't found, so insert
|
|
Me@14
|
209 entry->next = table->entries[hashIndex];
|
|
Me@14
|
210 table->entries[hashIndex] = entry;
|
|
Me@14
|
211 }
|
|
Me@14
|
212
|
|
Me@14
|
213
|
|
seanhalle@23
|
214 bool8
|
|
Me@14
|
215 deleteEntryFromTable( char *key, HashTable *table )
|
|
Me@14
|
216 { HashEntry *hashEntry;
|
|
seanhalle@23
|
217 HashEntry **addrOfPrevPtr;
|
|
Me@14
|
218 unsigned int hashIndex;
|
|
Me@14
|
219
|
|
Me@14
|
220 hashIndex = hashThisKey( key, table->tableSz );
|
|
seanhalle@23
|
221 addrOfPrevPtr = &( table->entries[ hashIndex ] );//for removing node
|
|
seanhalle@23
|
222 hashEntry = *addrOfPrevPtr; //already did work, might as well use it
|
|
Me@14
|
223 while( hashEntry != NULL )
|
|
seanhalle@23
|
224 { if( strcmp( hashEntry->key, key ) == 0 )
|
|
Me@14
|
225 {
|
|
seanhalle@23
|
226 *addrOfPrevPtr = hashEntry->next; //remove node from list
|
|
Me@14
|
227 //TODO: Free the contents of entry?
|
|
Me@14
|
228 freeHashEntryButNotContent( hashEntry );
|
|
Me@14
|
229 table->numEntries -= 1;
|
|
Me@14
|
230 return TRUE;
|
|
Me@14
|
231 }
|
|
seanhalle@23
|
232 addrOfPrevPtr = &( hashEntry->next );
|
|
seanhalle@23
|
233 hashEntry = *addrOfPrevPtr;
|
|
Me@14
|
234 }
|
|
Me@14
|
235 return FALSE;
|
|
Me@14
|
236 }
|
|
Me@14
|
237
|
|
Me@14
|
238 void
|
|
Me@14
|
239 freeHashTable( HashTable *table )
|
|
Me@14
|
240 { int i;
|
|
Me@14
|
241 HashEntry *hashEntry, *temp, **entries;
|
|
Me@14
|
242
|
|
Me@14
|
243 entries = table->entries;
|
|
Me@14
|
244 for( i=0; i < table->tableSz; i++ )
|
|
Me@14
|
245 { if( entries[i] != NULL )
|
|
Me@14
|
246 { hashEntry = entries[i];
|
|
Me@14
|
247 while( hashEntry != NULL )
|
|
Me@14
|
248 {
|
|
Me@14
|
249 temp = hashEntry->next;
|
|
Me@14
|
250 freeHashEntryUsing( hashEntry, table );
|
|
Me@14
|
251 hashEntry = temp;
|
|
Me@14
|
252 }
|
|
Me@14
|
253 }
|
|
Me@14
|
254 }
|
|
Me@14
|
255 }
|
|
Me@14
|
256
|
|
Me@14
|
257 void
|
|
Me@14
|
258 freeHashEntryUsing( HashEntry *entry, HashTable *table )
|
|
Me@14
|
259 {
|
|
Me@14
|
260 if( entry->content != NULL )
|
|
Me@14
|
261 (*(table->freeEntryContentFn))( entry->content );
|
|
seanhalle@21
|
262 VMS_int__free( entry->key ); //was VMS_int__malloc'd above, so free it
|
|
Me@17
|
263 VMS_int__free( entry );
|
|
Me@14
|
264 }
|
|
Me@14
|
265
|
|
Me@14
|
266 void
|
|
seanhalle@23
|
267 freeHashEntryUsing_WL( HashEntry *entry, HashTable *table )
|
|
seanhalle@23
|
268 {
|
|
seanhalle@23
|
269 if( entry->content != NULL )
|
|
seanhalle@23
|
270 (*(table->freeEntryContentFn))( entry->content );
|
|
seanhalle@23
|
271 VMS_WL__free( entry->key ); //was VMS_int__malloc'd above, so free it
|
|
seanhalle@23
|
272 VMS_WL__free( entry );
|
|
seanhalle@23
|
273 }
|
|
seanhalle@23
|
274
|
|
seanhalle@23
|
275 void
|
|
seanhalle@23
|
276 freeHashTable_WL( HashTable *table )
|
|
seanhalle@23
|
277 { int i;
|
|
seanhalle@23
|
278 HashEntry *hashEntry, *temp, **entries;
|
|
seanhalle@23
|
279
|
|
seanhalle@23
|
280 entries = table->entries;
|
|
seanhalle@23
|
281 for( i=0; i < table->tableSz; i++ )
|
|
seanhalle@23
|
282 { if( entries[i] != NULL )
|
|
seanhalle@23
|
283 { hashEntry = entries[i];
|
|
seanhalle@23
|
284 while( hashEntry != NULL )
|
|
seanhalle@23
|
285 {
|
|
seanhalle@23
|
286 temp = hashEntry->next;
|
|
seanhalle@23
|
287 freeHashEntryUsing_WL( hashEntry, table );
|
|
seanhalle@23
|
288 hashEntry = temp;
|
|
seanhalle@23
|
289 }
|
|
seanhalle@23
|
290 }
|
|
seanhalle@23
|
291 }
|
|
seanhalle@23
|
292 }
|
|
seanhalle@23
|
293
|
|
seanhalle@23
|
294
|
|
seanhalle@23
|
295 void
|
|
Me@14
|
296 freeHashEntryButNotContent( HashEntry *entry )
|
|
Me@14
|
297 {
|
|
seanhalle@21
|
298 VMS_int__free( entry->key ); //was VMS_int__malloc'd above, so free it
|
|
Me@17
|
299 VMS_int__free( entry );
|
|
Me@14
|
300 }
|
|
Me@14
|
301
|
|
seanhalle@23
|
302 void
|
|
seanhalle@23
|
303 freeHashEntryButNotContent_WL( HashEntry *entry )
|
|
seanhalle@23
|
304 {
|
|
seanhalle@23
|
305 VMS_WL__free( entry->key ); //was VMS_int__malloc'd above, so free it
|
|
seanhalle@23
|
306 VMS_WL__free( entry );
|
|
seanhalle@23
|
307 }
|
|
seanhalle@23
|
308
|
|
seanhalle@23
|
309
|
|
seanhalle@23
|
310
|
|
seanhalle@23
|
311
|
|
seanhalle@23
|
312 //======================= 32 bit integer key version ======================
|
|
seanhalle@23
|
313
|
|
seanhalle@23
|
314 /*key is array of uint32, with first entry being the num ints in key.
|
|
seanhalle@23
|
315 * that means size of key is content of first entry times 4, plus the
|
|
seanhalle@23
|
316 * size of first entry itself, which is another 4*/
|
|
seanhalle@23
|
317 #define sizeOfKey(key) key[0]*4 + 4
|
|
seanhalle@23
|
318
|
|
seanhalle@23
|
319
|
|
seanhalle@23
|
320 HashTable *
|
|
seanhalle@23
|
321 makeHashTable32( int powerOf2OfSz, FreeEntryContentFnPtr freeFn )
|
|
seanhalle@23
|
322 { HashTable * retTable;
|
|
seanhalle@23
|
323 int32 numHashSlots;
|
|
seanhalle@23
|
324
|
|
seanhalle@23
|
325 retTable = VMS_int__malloc( sizeof( HashTable ) );
|
|
seanhalle@23
|
326
|
|
seanhalle@23
|
327 numHashSlots = 1 << powerOf2OfSz;
|
|
seanhalle@23
|
328 retTable->hashMask = 0xffffffff >> 32 - powerOf2OfSz;
|
|
seanhalle@23
|
329 retTable->prevHash = (int32)rand();
|
|
seanhalle@23
|
330
|
|
seanhalle@23
|
331 retTable->freeEntryContentFn = freeFn;
|
|
seanhalle@23
|
332
|
|
seanhalle@23
|
333 retTable->entries = VMS_int__malloc( numHashSlots * sizeof(HashEntry *));
|
|
seanhalle@23
|
334 retTable->numEntries = 0;
|
|
seanhalle@23
|
335 retTable->tableSz = numHashSlots;
|
|
seanhalle@23
|
336
|
|
seanhalle@23
|
337 nullOutTablesArray( retTable );
|
|
seanhalle@23
|
338
|
|
seanhalle@23
|
339 return retTable;
|
|
seanhalle@23
|
340 }
|
|
seanhalle@23
|
341
|
|
seanhalle@23
|
342 HashTable *
|
|
seanhalle@23
|
343 makeDefaultSizeHashTable32( FreeEntryContentFnPtr freeFn )
|
|
seanhalle@23
|
344 {
|
|
seanhalle@23
|
345 return makeHashTable32( DEFAULT_POWER_OF_2_TABLE_SIZE, freeFn );
|
|
seanhalle@23
|
346 }
|
|
seanhalle@23
|
347
|
|
seanhalle@23
|
348 HashEntry *
|
|
seanhalle@23
|
349 makeHashEntry32( uint32 * key )
|
|
seanhalle@23
|
350 { HashEntry *hashEntry;
|
|
seanhalle@23
|
351
|
|
seanhalle@23
|
352 hashEntry = (HashEntry*) VMS_int__malloc( sizeof( HashEntry ) );
|
|
seanhalle@23
|
353 if( hashEntry == NULL ) return NULL;
|
|
seanhalle@23
|
354 hashEntry->key = VMS_int__malloc( sizeOfKey(key) );
|
|
seanhalle@23
|
355 if( hashEntry->key == NULL ) return NULL;
|
|
seanhalle@23
|
356 memcpy( hashEntry->key, key, sizeOfKey(key) );
|
|
seanhalle@23
|
357 hashEntry->next = NULL;
|
|
seanhalle@23
|
358
|
|
seanhalle@23
|
359 return hashEntry;
|
|
seanhalle@23
|
360 }
|
|
seanhalle@23
|
361
|
|
seanhalle@23
|
362
|
|
seanhalle@23
|
363
|
|
seanhalle@23
|
364 int32
|
|
seanhalle@23
|
365 putEntryIntoTable32( HashEntry *entry, HashTable *table )
|
|
seanhalle@23
|
366 { unsigned int hashIdx;
|
|
seanhalle@23
|
367 HashEntry* testEntry;
|
|
seanhalle@23
|
368
|
|
seanhalle@23
|
369 testEntry = getEntryFromTable32( (uint32 *)entry->key, table );
|
|
seanhalle@23
|
370 if( testEntry == NULL ) //no entry w/key, so add passed-in as list-head
|
|
seanhalle@23
|
371 { hashIdx = hashThisKey32( entry->key, table->tableSz );
|
|
seanhalle@23
|
372 entry->next = (table->entries)[hashIdx];
|
|
seanhalle@23
|
373 (table->entries)[hashIdx] = entry;
|
|
seanhalle@23
|
374 table->numEntries += 1;
|
|
seanhalle@23
|
375 //keep num entries less than half the num indexes in table
|
|
seanhalle@23
|
376 if( table->numEntries > (table->tableSz >>1) ) doubleTableSize(table);
|
|
seanhalle@23
|
377 }
|
|
seanhalle@23
|
378 else //entry w/key already exists, so free content, then replace then
|
|
seanhalle@23
|
379 // free the passed-in entry, leaving the entry already in table
|
|
seanhalle@23
|
380 { (*(table->freeEntryContentFn))( testEntry->content );
|
|
seanhalle@23
|
381 //being lazy -- will create bug in code that relies on having ptr
|
|
seanhalle@23
|
382 // to elem given to insert into table!
|
|
seanhalle@23
|
383 testEntry->content = entry->content;
|
|
seanhalle@23
|
384 entry->content = NULL;
|
|
seanhalle@23
|
385 freeHashEntryButNotContent( entry );
|
|
seanhalle@23
|
386 }
|
|
seanhalle@23
|
387 return 1;
|
|
seanhalle@23
|
388 }
|
|
seanhalle@23
|
389
|
|
seanhalle@23
|
390
|
|
seanhalle@23
|
391 void
|
|
seanhalle@23
|
392 doubleTableSize32( HashTable *table )
|
|
seanhalle@23
|
393 { int i, oldTableSz, newTableSz;
|
|
seanhalle@23
|
394 HashEntry *entry, *nextEntry, **oldEntries, **newEntries;
|
|
seanhalle@23
|
395
|
|
seanhalle@23
|
396 oldTableSz = table->tableSz;
|
|
seanhalle@23
|
397 oldEntries = table->entries;
|
|
seanhalle@23
|
398
|
|
seanhalle@23
|
399 newTableSz = 2 * oldTableSz;
|
|
seanhalle@23
|
400 newEntries = VMS_int__malloc( newTableSz * sizeof(HashEntry *) );
|
|
seanhalle@23
|
401
|
|
seanhalle@23
|
402 table->tableSz = newTableSz;
|
|
seanhalle@23
|
403 table->entries = newEntries;
|
|
seanhalle@23
|
404 table->numEntries = 0; //about to add them all back!
|
|
seanhalle@23
|
405
|
|
seanhalle@23
|
406 // move all the entries from old to new
|
|
seanhalle@23
|
407 for( i=0; i < oldTableSz; i++ )
|
|
seanhalle@23
|
408 { if( oldEntries[i] != NULL )
|
|
seanhalle@23
|
409 { entry = oldEntries[i];
|
|
seanhalle@23
|
410 while( entry != NULL )
|
|
seanhalle@23
|
411 { nextEntry = entry->next; //save for later
|
|
seanhalle@23
|
412 entry->next = NULL; //null before, so can chain in new
|
|
seanhalle@23
|
413 putEntryIntoTable32( entry, table ); //doesn't allocate anything
|
|
seanhalle@23
|
414 entry = nextEntry;
|
|
seanhalle@23
|
415 }
|
|
seanhalle@23
|
416 }
|
|
seanhalle@23
|
417 }
|
|
seanhalle@23
|
418 }
|
|
seanhalle@23
|
419
|
|
seanhalle@23
|
420 /*The key is a self-sized array of 32 bit unsigned ints, with the first
|
|
seanhalle@23
|
421 * entry being the number of ints in the key, which makes up the rest of
|
|
seanhalle@23
|
422 * the array.*/
|
|
seanhalle@23
|
423 int32
|
|
seanhalle@23
|
424 hashThisKey32( uint32 *key, HashTable *hashTable )
|
|
seanhalle@23
|
425 { int32 hashOfKey;
|
|
seanhalle@23
|
426
|
|
seanhalle@23
|
427 //the hash function takes addr of start of key array, plus num int32s,
|
|
seanhalle@23
|
428 hashOfKey = jenkHash32( &key[1], *key );
|
|
seanhalle@23
|
429 hashTable->prevHash = hashOfKey;
|
|
seanhalle@23
|
430
|
|
seanhalle@23
|
431 /*The hash is a full 32 bits, but only want hashes that fall within
|
|
seanhalle@23
|
432 * the size of the table. So, mask off the higher bits. */
|
|
seanhalle@23
|
433 return ( hashTable->hashMask & hashOfKey ); //reduce to size of table
|
|
seanhalle@23
|
434 }
|
|
seanhalle@23
|
435
|
|
seanhalle@23
|
436
|
|
seanhalle@23
|
437 /*The first entry of key says the size of the key, while key itself is the
|
|
seanhalle@23
|
438 * rest of the integers in the array
|
|
seanhalle@23
|
439 */
|
|
seanhalle@23
|
440 HashEntry *
|
|
seanhalle@23
|
441 getEntryFromTable32( uint32 *key, HashTable * table )
|
|
seanhalle@23
|
442 { unsigned int
|
|
seanhalle@23
|
443 hashIndex = hashThisKey32( key, table );
|
|
seanhalle@23
|
444 HashEntry*
|
|
seanhalle@23
|
445 hashEntry = table->entries[ hashIndex ];
|
|
seanhalle@23
|
446 for( ; hashEntry != NULL; hashEntry = hashEntry->next )
|
|
seanhalle@23
|
447 {
|
|
seanhalle@23
|
448 if( memcmp( hashEntry->key, key, sizeOfKey(key) ) == 0 )
|
|
seanhalle@23
|
449 return hashEntry;
|
|
seanhalle@23
|
450 }
|
|
seanhalle@23
|
451 return NULL;
|
|
seanhalle@23
|
452 }
|
|
seanhalle@23
|
453
|
|
seanhalle@23
|
454 void *
|
|
seanhalle@23
|
455 getValueFromTable32( uint32 *key, HashTable * table )
|
|
seanhalle@23
|
456 { HashEntry *entry;
|
|
seanhalle@23
|
457 entry = getEntryFromTable32( key, table );
|
|
seanhalle@23
|
458 if( entry == NULL ) return NULL;
|
|
seanhalle@23
|
459
|
|
seanhalle@23
|
460 return entry->content;
|
|
seanhalle@23
|
461 }
|
|
seanhalle@23
|
462
|
|
seanhalle@23
|
463 /*Returns NULL if failed to insert, else returns ptr to hash entry */
|
|
seanhalle@23
|
464 HashEntry *
|
|
seanhalle@23
|
465 addValueIntoTable32( uint32* key, void *content, HashTable *table )
|
|
seanhalle@23
|
466 { unsigned int hashIdx;
|
|
seanhalle@23
|
467 HashEntry* hashEntry;
|
|
seanhalle@23
|
468
|
|
seanhalle@23
|
469 hashEntry = getEntryFromTable32( key, table );
|
|
seanhalle@23
|
470 if( hashEntry == NULL )
|
|
seanhalle@23
|
471 { hashIdx = hashThisKey32( key, table );
|
|
seanhalle@23
|
472 hashEntry = makeHashEntry32( key );
|
|
seanhalle@23
|
473 hashEntry->next = (table->entries)[hashIdx];
|
|
seanhalle@23
|
474 (table->entries)[hashIdx] = hashEntry;
|
|
seanhalle@23
|
475 table->numEntries += 1;
|
|
seanhalle@23
|
476 //Check if need to make bigger -- keep half-full (hence ">> 1")
|
|
seanhalle@23
|
477 if( table->numEntries > table->tableSz >>1 ) doubleTableSize( table );
|
|
seanhalle@23
|
478 }
|
|
seanhalle@23
|
479 else
|
|
seanhalle@23
|
480 { (*(table->freeEntryContentFn))( hashEntry->content );
|
|
seanhalle@23
|
481 }
|
|
seanhalle@23
|
482 hashEntry->content = content;
|
|
seanhalle@23
|
483 return hashEntry;
|
|
seanhalle@23
|
484 }
|
|
seanhalle@23
|
485
|
|
seanhalle@23
|
486
|
|
seanhalle@23
|
487 bool32
|
|
seanhalle@23
|
488 deleteEntryFromTable32( uint32 *key, HashTable *table )
|
|
seanhalle@23
|
489 { HashEntry *hashEntry;
|
|
seanhalle@23
|
490 HashEntry **addrOfPrevPtr;
|
|
seanhalle@23
|
491 unsigned int hashIndex;
|
|
seanhalle@23
|
492
|
|
seanhalle@23
|
493 hashIndex = hashThisKey32( key, table );
|
|
seanhalle@23
|
494 hashEntry = table->entries[ hashIndex ];
|
|
seanhalle@23
|
495 //go down the chained list, checking all with this hash value
|
|
seanhalle@23
|
496 addrOfPrevPtr = &( table->entries[hashIndex] ); //for removing a node
|
|
seanhalle@23
|
497 hashEntry = *addrOfPrevPtr; //did ptr chasing, might as well use it
|
|
seanhalle@23
|
498 while( hashEntry != NULL )
|
|
seanhalle@23
|
499 { if( memcmp( hashEntry->key, key, sizeOfKey(key) ) == 0 )
|
|
seanhalle@23
|
500 { *addrOfPrevPtr = hashEntry->next; //remove node from list
|
|
seanhalle@23
|
501 freeHashEntryButNotContent( hashEntry );
|
|
seanhalle@23
|
502 table->numEntries -= 1;
|
|
seanhalle@23
|
503 return TRUE;
|
|
seanhalle@23
|
504 }
|
|
seanhalle@23
|
505 addrOfPrevPtr = &(hashEntry->next); //chg content of *this* to remove
|
|
seanhalle@23
|
506 hashEntry = *addrOfPrevPtr; //cheaper than hashEntry->next
|
|
seanhalle@23
|
507 }
|
|
seanhalle@23
|
508 return FALSE;
|
|
seanhalle@23
|
509 }
|
|
seanhalle@23
|
510
|