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