annotate PrivateHash.c @ 23:ac99f4a8ce22

First working version
author Sean Halle <seanhalle@yahoo.com>
date Wed, 06 Jun 2012 18:00:58 -0700
parents 4b5abed39ab9
children b032601956bb
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