Changeset 3d5c1b18b9912541a77e63bdb908db34f068b328
- Timestamp:
- 04/23/08 10:02:37 (9 months ago)
- Parents:
- 399100f1271aa3320cae55afa2d8364875291971
- Children:
- b39568e8202274e6aed953a924659cef1f971d55, aee5f1150b23fd9469c1afe18187627c2320550d
- git-committer:
- David Balmain <dbalmain@gmail.com> / 2008-04-23T10:02:37Z+1000
- Location:
- c
- Files:
-
- 6 modified
-
Rakefile (modified) (1 diff)
-
include/hash.h (modified) (2 diffs)
-
include/internal.h (modified) (1 diff)
-
src/hash.c (modified) (17 diffs)
-
src/index.c (modified) (1 diff)
-
test/test_term_vectors.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
c/Rakefile
r553474 r3d5c1b 386 386 end 387 387 388 task :valgrind => 'testall' do 389 sh "valgrind --suppressions=valgrind.supp " + 390 "--leak-check=yes " + 391 "--show-reachable=yes " + 392 "--workaround-gcc296-bugs=yes -v ./testall -q" 393 end 394 395 task :gen_valgrind => 'build:testall' do 396 sh "valgrind --suppressions=valgrind.supp " + 397 "--leak-check=yes " + 398 "--show-reachable=yes " + 399 "--gen-suppressions=yes " + 400 "--workaround-gcc296-bugs=yes -v ./testall -q" 388 task :valgrind do 389 check_coptions 390 Rake::Task[:testall].invoke 391 sh "valgrind --suppressions=valgrind.supp " + 392 "--leak-check=yes " + 393 "--show-reachable=yes " + 394 "--workaround-gcc296-bugs=yes -v ./testall -q" 395 end 396 397 task :gen_valgrind do 398 check_coptions 399 Rake::Task[:testall].invoke 400 sh "valgrind --suppressions=valgrind.supp " + 401 "--leak-check=yes " + 402 "--show-reachable=yes " + 403 "--gen-suppressions=yes " + 404 "--workaround-gcc296-bugs=yes -v ./testall -q" 401 405 end 402 406 -
c/include/hash.h
r553474 r3d5c1b 61 61 * used outside of the Hash methods */ 62 62 FrtHashEntry *(*lookup_i)(struct FrtHash *self, 63 register const void *key);63 register const void *key); 64 64 unsigned long (*hash_i)(const void *key); 65 65 int (*eq_i)(const void *key1, const void *key2); … … 275 275 * @param self the Hash to add the value to 276 276 * @param key the key to use to reference the value 277 * @ returnHashEntry a pointer to the hash entry object now reserved for this277 * @param he HashEntry a pointer to the hash entry object now reserved for this 278 278 * value. Be sure to set both the *key* and the *value* 279 */ 280 extern FrtHashEntry *frt_h_set_ext(FrtHash *ht, const void *key); 279 * @return true if the key was empty, false otherwise 280 */ 281 extern FRT_INLINE bool h_set_ext(FrtHash *self, 282 const void *key, 283 FrtHashEntry **he); 281 284 282 285 /** -
c/include/internal.h
r4ba05f r3d5c1b 528 528 #define h_rem_int frt_h_rem_int 529 529 #define h_set frt_h_set 530 #define h_set_ext frt_h_set_ext531 530 #define h_set_int frt_h_set_int 532 531 #define h_set_safe frt_h_set_safe -
c/src/hash.c
r48290f r3d5c1b 13 13 14 14 static char *dummy_key = ""; 15 static char *dummy_int_key = "i"; 16 15 17 16 18 #define PERTURB_SHIFT 5 … … 47 49 } 48 50 49 static int int_eq(const void *q1, const void *q2) 50 { 51 (void)q1; 52 (void)q2; 53 return true; 54 } 55 56 static unsigned long int_hash(const void *i) 57 { 58 return *((unsigned long *)i); 59 } 60 61 typedef HashEntry *(*lookup_ft)(struct Hash *ht, register const void *key); 51 typedef HashEntry *(*lookup_ft)(struct Hash *self, register const void *key); 62 52 63 53 /** … … 65 55 * deletes to worry about. 66 56 * 67 * @param htthe Hash to do the fast lookup in57 * @param self the Hash to do the fast lookup in 68 58 * @param the hashkey we are looking for 69 59 */ 70 static INLINE HashEntry *h_resize_lookup(Hash * ht,60 static INLINE HashEntry *h_resize_lookup(Hash *self, 71 61 register const unsigned long hash) 72 62 { 73 63 register unsigned long perturb; 74 register int mask = ht->mask;75 register HashEntry *he0 = ht->table;64 register int mask = self->mask; 65 register HashEntry *he0 = self->table; 76 66 register int i = hash & mask; 77 67 register HashEntry *he = &he0[i]; … … 92 82 } 93 83 94 static HashEntry *h_lookup_ int(Hash *ht, const void *key)95 { 96 register const unsigned long hash = *((int *)key);84 static HashEntry *h_lookup_ptr(Hash *self, const void *key) 85 { 86 register const unsigned long hash = (long)key; 97 87 register unsigned long perturb; 98 register int mask = ht->mask;99 register HashEntry *he0 = ht->table;88 register int mask = self->mask; 89 register HashEntry *he0 = self->table; 100 90 register int i = hash & mask; 101 91 register HashEntry *he = &he0[i]; … … 129 119 } 130 120 131 HashEntry *h_lookup(Hash * ht, register const void *key)132 { 133 register const unsigned long hash = ht->hash_i(key);121 HashEntry *h_lookup(Hash *self, register const void *key) 122 { 123 register const unsigned long hash = self->hash_i(key); 134 124 register unsigned long perturb; 135 register int mask = ht->mask;136 register HashEntry *he0 = ht->table;125 register int mask = self->mask; 126 register HashEntry *he0 = self->table; 137 127 register int i = hash & mask; 138 128 register HashEntry *he = &he0[i]; 139 129 register HashEntry *freeslot = NULL; 140 eq_ft eq = ht->eq_i;130 eq_ft eq = self->eq_i; 141 131 142 132 if (he->key == NULL || he->key == key) { … … 176 166 Hash *h_new_str(free_ft free_key, free_ft free_value) 177 167 { 178 Hash * ht;168 Hash *self; 179 169 if (num_free_hts > 0) { 180 ht= free_hts[--num_free_hts];170 self = free_hts[--num_free_hts]; 181 171 } 182 172 else { 183 ht= ALLOC(Hash);184 } 185 ht->fill = 0;186 ht->size = 0;187 ht->mask = HASH_MINSIZE - 1;188 ht->table = ht->smalltable;189 memset( ht->smalltable, 0, sizeof(ht->smalltable));190 ht->lookup_i = (lookup_ft)&h_lookup;191 ht->eq_i = str_eq;192 ht->hash_i = (hash_ft)str_hash;193 194 ht->free_key_i = free_key != NULL ? free_key : &dummy_free;195 ht->free_value_i = free_value != NULL ? free_value : &dummy_free;196 ht->ref_cnt = 1;197 return ht;173 self = ALLOC(Hash); 174 } 175 self->fill = 0; 176 self->size = 0; 177 self->mask = HASH_MINSIZE - 1; 178 self->table = self->smalltable; 179 memset(self->smalltable, 0, sizeof(self->smalltable)); 180 self->lookup_i = (lookup_ft)&h_lookup; 181 self->eq_i = str_eq; 182 self->hash_i = (hash_ft)str_hash; 183 184 self->free_key_i = free_key != NULL ? free_key : &dummy_free; 185 self->free_value_i = free_value != NULL ? free_value : &dummy_free; 186 self->ref_cnt = 1; 187 return self; 198 188 } 199 189 200 190 Hash *h_new_int(free_ft free_value) 201 191 { 202 Hash *ht = h_new_str(NULL, free_value); 203 ht->lookup_i = &h_lookup_int; 204 ht->eq_i = int_eq; 205 ht->hash_i = int_hash; 206 return ht; 192 Hash *self = h_new_str(NULL, free_value); 193 194 self->lookup_i = &h_lookup_ptr; 195 self->eq_i = NULL; 196 self->hash_i = NULL; 197 198 return self; 199 } 200 201 Hash *h_new_ptr(free_ft free_key, free_ft free_value) 202 { 203 Hash *self = h_new_str(free_key, free_value); 204 205 self->lookup_i = &h_lookup_ptr; 206 self->eq_i = NULL; 207 self->hash_i = NULL; 208 209 return self; 207 210 } 208 211 209 212 Hash *h_new(hash_ft hash, eq_ft eq, free_ft free_key, free_ft free_value) 210 213 { 211 Hash *ht = h_new_str(free_key, free_value); 212 213 ht->lookup_i = &h_lookup; 214 ht->eq_i = eq; 215 ht->hash_i = hash; 216 return ht; 217 } 218 219 void h_clear(Hash *ht) 214 Hash *self = h_new_str(free_key, free_value); 215 216 self->lookup_i = &h_lookup; 217 self->eq_i = eq; 218 self->hash_i = hash; 219 220 return self; 221 } 222 223 void h_clear(Hash *self) 220 224 { 221 225 int i; 222 226 HashEntry *he; 223 free_ft free_key = ht->free_key_i;224 free_ft free_value = ht->free_value_i;227 free_ft free_key = self->free_key_i; 228 free_ft free_value = self->free_value_i; 225 229 226 230 /* Clear all the hash values and keys as necessary */ 227 231 if (free_key != dummy_free || free_value != dummy_free) { 228 for (i = 0; i <= ht->mask; i++) {229 he = & ht->table[i];232 for (i = 0; i <= self->mask; i++) { 233 he = &self->table[i]; 230 234 if (he->key != NULL && he->key != dummy_key) { 231 235 free_value(he->value); … … 235 239 } 236 240 } 237 ZEROSET_N( ht->table, HashEntry, ht->mask + 1);238 ht->size = 0;239 ht->fill = 0;240 } 241 242 void h_destroy(Hash * ht)243 { 244 if (--( ht->ref_cnt) <= 0) {245 h_clear( ht);241 ZEROSET_N(self->table, HashEntry, self->mask + 1); 242 self->size = 0; 243 self->fill = 0; 244 } 245 246 void h_destroy(Hash *self) 247 { 248 if (--(self->ref_cnt) <= 0) { 249 h_clear(self); 246 250 247 251 /* if a new table was created, be sure to free it */ 248 if ( ht->table != ht->smalltable) {249 free( ht->table);252 if (self->table != self->smalltable) { 253 free(self->table); 250 254 } 251 255 252 256 #ifdef DEBUG 253 free( ht);257 free(self); 254 258 #else 255 259 if (num_free_hts < MAX_FREE_HASH_TABLES) { 256 free_hts[num_free_hts++] = ht;260 free_hts[num_free_hts++] = self; 257 261 } 258 262 else { 259 free( ht);263 free(self); 260 264 } 261 265 #endif … … 263 267 } 264 268 265 void *h_get(Hash * ht, const void *key)269 void *h_get(Hash *self, const void *key) 266 270 { 267 271 /* Note: lookup_i will never return NULL. */ 268 return ht->lookup_i(ht, key)->value;269 } 270 271 int h_del(Hash * ht, const void *key)272 { 273 HashEntry *he = ht->lookup_i(ht, key);272 return self->lookup_i(self, key)->value; 273 } 274 275 int h_del(Hash *self, const void *key) 276 { 277 HashEntry *he = self->lookup_i(self, key); 274 278 275 279 if (he->key != NULL && he->key != dummy_key) { 276 ht->free_key_i(he->key);277 ht->free_value_i(he->value);280 self->free_key_i(he->key); 281 self->free_value_i(he->value); 278 282 he->key = dummy_key; 279 283 he->value = NULL; 280 ht->size--;284 self->size--; 281 285 return true; 282 286 } … … 286 290 } 287 291 288 void *h_rem(Hash * ht, const void *key, bool destroy_key)292 void *h_rem(Hash *self, const void *key, bool destroy_key) 289 293 { 290 294 void *val; 291 HashEntry *he = ht->lookup_i(ht, key);295 HashEntry *he = self->lookup_i(self, key); 292 296 293 297 if (he->key != NULL && he->key != dummy_key) { 294 298 if (destroy_key) { 295 ht->free_key_i(he->key);299 self->free_key_i(he->key); 296 300 } 297 301 … … 299 303 val = he->value; 300 304 he->value = NULL; 301 ht->size--;305 self->size--; 302 306 return val; 303 307 } … … 307 311 } 308 312 309 static int h_resize(Hash * ht, int min_newsize)313 static int h_resize(Hash *self, int min_newsize) 310 314 { 311 315 HashEntry smallcopy[HASH_MINSIZE]; … … 318 322 } 319 323 320 oldtable = ht->table;324 oldtable = self->table; 321 325 if (newsize == HASH_MINSIZE) { 322 if ( ht->table == ht->smalltable) {323 /* need to copy the d *(int *)ata out so we can rebuild the table into326 if (self->table == self->smalltable) { 327 /* need to copy the data out so we can rebuild the table into 324 328 * the same space */ 325 memcpy(smallcopy, ht->smalltable, sizeof(smallcopy));329 memcpy(smallcopy, self->smalltable, sizeof(smallcopy)); 326 330 oldtable = smallcopy; 327 331 } 328 332 else { 329 ht->table = ht->smalltable;333 self->table = self->smalltable; 330 334 } 331 335 } 332 336 else { 333 ht->table = ALLOC_N(HashEntry, newsize);334 } 335 memset( ht->table, 0, sizeof(HashEntry) * newsize);336 ht->fill = ht->size;337 ht->mask = newsize - 1;338 339 for (num_active = ht->size, he_old = oldtable; num_active > 0; he_old++) {337 self->table = ALLOC_N(HashEntry, newsize); 338 } 339 memset(self->table, 0, sizeof(HashEntry) * newsize); 340 self->fill = self->size; 341 self->mask = newsize - 1; 342 343 for (num_active = self->size, he_old = oldtable; num_active > 0; he_old++) { 340 344 if (he_old->key && he_old->key != dummy_key) { /* active entry */ 341 /*he_new = ht->lookup_i(ht, he_old->key); */342 he_new = h_resize_lookup( ht, he_old->hash);345 /*he_new = self->lookup_i(self, he_old->key); */ 346 he_new = h_resize_lookup(self, he_old->hash); 343 347 he_new->key = he_old->key; 344 348 he_new->value = he_old->value; … … 346 350 } /* else empty entry so nothing to do */ 347 351 } 348 if (oldtable != smallcopy && oldtable != ht->smalltable) {352 if (oldtable != smallcopy && oldtable != self->smalltable) { 349 353 free(oldtable); 350 354 } … … 352 356 } 353 357 354 HashKeyStatus h_set(Hash *ht, const void *key, void *value) 358 INLINE bool h_set_ext(Hash *self, const void *key, HashEntry **he) 359 { 360 *he = self->lookup_i(self, key); 361 if ((*he)->key == NULL) { 362 if (self->fill * 3 > self->mask * 2) { 363 h_resize(self, self->size * ((self->size > SLOW_DOWN) ? 4 : 2)); 364 *he = self->lookup_i(self, key); 365 } 366 self->fill++; 367 self->size++; 368 return true; 369 } 370 else if ((*he)->key == dummy_key) { 371 self->size++; 372 return true; 373 } 374 375 return false; 376 } 377 378 HashKeyStatus h_set(Hash *self, const void *key, void *value) 355 379 { 356 380 HashKeyStatus ret_val = HASH_KEY_DOES_NOT_EXIST; 357 HashEntry *he = ht->lookup_i(ht, key); 358 if (he->key == NULL) { 359 if (ht->fill * 3 > ht->mask * 2) { 360 h_resize(ht, ht->size * ((ht->size > SLOW_DOWN) ? 4 : 2)); 361 he = ht->lookup_i(ht, key); 362 } 363 ht->fill++; 364 ht->size++; 365 } 366 else if (he->key == dummy_key) { 367 ht->size++; 368 } 369 else if (he->key != key) { 370 ht->free_key_i(he->key); 371 if (he->value != value) { 372 ht->free_value_i(he->value); 373 } 374 ret_val = HASH_KEY_EQUAL; 375 } 376 else { 377 /* safety check. Only free old value if it isn't the new value */ 378 if (he->value != value) { 379 ht->free_value_i(he->value); 380 } 381 ret_val = HASH_KEY_SAME; 381 HashEntry *he; 382 if (!h_set_ext(self, key, &he)) { 383 if (he->key != key) { 384 self->free_key_i(he->key); 385 if (he->value != value) { 386 self->free_value_i(he->value); 387 } 388 ret_val = HASH_KEY_EQUAL; 389 } 390 else { 391 /* Only free old value if it isn't the new value */ 392 if (he->value != value) { 393 self->free_value_i(he->value); 394 } 395 ret_val = HASH_KEY_SAME; 396 } 382 397 } 383 398 he->key = (void *)key; 384 399 he->value = value; 385 400 386 /*387 if ((ht->fill > fill) && (ht->fill * 3 > ht->mask * 2)) {388 h_resize(ht, ht->size * ((ht->size > SLOW_DOWN) ? 4 : 2));389 }390 */391 401 return ret_val; 392 402 } 393 403 394 HashEntry *h_set_ext(Hash *ht, const void *key) 395 { 396 HashEntry *he = ht->lookup_i(ht, key); 397 if (he->key == NULL) { 398 if (ht->fill * 3 > ht->mask * 2) { 399 h_resize(ht, ht->size * ((ht->size > SLOW_DOWN) ? 4 : 2)); 400 he = ht->lookup_i(ht, key); 401 } 402 ht->fill++; 403 ht->size++; 404 } 405 else if (he->key == dummy_key) { 406 ht->size++; 407 } 408 409 return he; 410 } 411 412 int h_set_safe(Hash *ht, const void *key, void *value) 413 { 414 HashEntry *he = ht->lookup_i(ht, key); 415 int fill = ht->fill; 416 if (he->key == NULL) { 417 ht->fill++; 418 ht->size++; 419 } 420 else if (he->key == dummy_key) { 421 ht->size++; 404 int h_set_safe(Hash *self, const void *key, void *value) 405 { 406 HashEntry *he; 407 if (h_set_ext(self, key, &he)) { 408 he->key = (void *)key; 409 he->value = value; 410 return true; 422 411 } 423 412 else { 424 413 return false; 425 414 } 426 he->key = (void *)key; 427 he->value = value; 428 429 if ((ht->fill > fill) && (ht->fill * 3 > ht->mask * 2)) { 430 h_resize(ht, ht->size * ((ht->size > SLOW_DOWN) ? 4 : 2)); 431 } 432 return true; 433 } 434 435 HashKeyStatus h_has_key(Hash *ht, const void *key) 436 { 437 HashEntry *he = ht->lookup_i(ht, key); 415 } 416 417 HashKeyStatus h_has_key(Hash *self, const void *key) 418 { 419 HashEntry *he = self->lookup_i(self, key); 438 420 if (he->key == NULL || he->key == dummy_key) { 439 421 return HASH_KEY_DOES_NOT_EXIST; … … 445 427 } 446 428 447 void *h_get_int(Hash *self, const unsigned long key) 448 { 449 return h_get(self, &key); 450 } 451 452 int h_del_int(Hash *self, const unsigned long key) 453 { 454 return h_del(self, &key); 455 } 456 457 void *h_rem_int(Hash *self, const unsigned long key) 458 { 459 return h_rem(self, &key, false); 460 } 461 462 HashKeyStatus h_set_int(Hash *self, 463 const unsigned long key, 464 void *value) 465 { 466 return h_set(self, &key, value); 467 } 468 469 int h_set_safe_int(Hash *self, const unsigned long key, void *value) 470 { 471 return h_set_safe(self, &key, value); 472 } 473 474 int h_has_key_int(Hash *self, const unsigned long key) 475 { 476 return h_has_key(self, &key); 477 } 478 479 void h_each(Hash *ht, 429 INLINE void *h_get_int(Hash *self, const unsigned long key) 430 { 431 return h_get(self, (const void *)key); 432 } 433 434 INLINE int h_del_int(Hash *self, const unsigned long key) 435 { 436 return h_del(self, (const void *)key); 437 } 438 439 INLINE void *h_rem_int(Hash *self, const unsigned long key) 440 { 441 return h_rem(self, (const void *)key, false); 442 } 443 444 INLINE HashKeyStatus h_set_int(Hash *self, 445 const unsigned long key, 446 void *value) 447 { 448 HashKeyStatus ret_val = HASH_KEY_DOES_NOT_EXIST; 449 HashEntry *he; 450 if (!h_set_ext(self, (const void *)key, &he)) { 451 /* Only free old value if it isn't the new value */ 452 if (he->value != value) { 453 self->free_value_i(he->value); 454 } 455 ret_val = HASH_KEY_EQUAL; 456 } 457 he->key = dummy_int_key; 458 he->value = value; 459 460 return ret_val; 461 } 462 463 INLINE int h_set_safe_int(Hash *self, const unsigned long key, void *value) 464 { 465 HashEntry *he; 466 if (h_set_ext(self, (const void *)key, &he)) { 467 he->key = dummy_int_key; 468 he->value = value; 469 return true; 470 } 471 return false; 472 } 473 474 INLINE int h_has_key_int(Hash *self, const unsigned long key) 475 { 476 return h_has_key(self, (const void *)key); 477 } 478 479 void h_each(Hash *self, 480 480 void (*each_kv) (void *key, void *value, void *arg), void *arg) 481 481 { 482 482 HashEntry *he; 483 int i = ht->size;484 for (he = ht->table; i > 0; he++) {483 int i = self->size; 484 for (he = self->table; i > 0; he++) { 485 485 if (he->key && he->key != dummy_key) { /* active entry */ 486 486 each_kv(he->key, he->value, arg); … … 490 490 } 491 491 492 Hash *h_clone(Hash *ht, 493 h_clone_ft clone_key, h_clone_ft clone_value) 492 Hash *h_clone(Hash *self, h_clone_ft clone_key, h_clone_ft clone_value) 494 493 { 495 494 void *key, *value; 496 495 HashEntry *he; 497 int i = ht->size;496 int i = self->size; 498 497 Hash *ht_clone; 499 498 500 &n
