annotate PrivateHash.c @ 37:c21c30e45a17

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