267
298
entry->key = key;\
268
299
entry->record = value;\
269
300
entry->next = table->bins[bin_pos];\
301
if ((head = table->head) != 0) {\
303
(entry->back = head->back)->fore = entry;\
307
table->head = entry->fore = entry->back = entry;\
270
309
table->bins[bin_pos] = entry;\
271
310
table->num_entries++;\
314
unpack_entries(register st_table *table)
317
struct st_table_entry *packed_bins[MAX_PACKED_NUMHASH*2];
318
int num_entries = table->num_entries;
320
memcpy(packed_bins, table->bins, sizeof(struct st_table_entry *) * num_entries*2);
321
table->entries_packed = 0;
322
table->num_entries = 0;
323
memset(table->bins, 0, sizeof(struct st_table_entry *) * table->num_bins);
324
for (i = 0; i < num_entries; i++) {
325
st_insert(table, (st_data_t)packed_bins[i*2], (st_data_t)packed_bins[i*2+1]);
275
330
st_insert(register st_table *table, register st_data_t key, st_data_t value)
277
332
unsigned int hash_val, bin_pos;
278
333
register st_table_entry *ptr;
335
if (table->entries_packed) {
337
for (i = 0; i < table->num_entries; i++) {
338
if ((st_data_t)table->bins[i*2] == key) {
339
table->bins[i*2+1] = (struct st_table_entry*)value;
343
if ((table->num_entries+1) * 2 <= table->num_bins && table->num_entries+1 <= MAX_PACKED_NUMHASH) {
344
i = table->num_entries++;
345
table->bins[i*2] = (struct st_table_entry*)key;
346
table->bins[i*2+1] = (struct st_table_entry*)value;
350
unpack_entries(table);
280
354
hash_val = do_hash(key, table);
281
355
FIND_ENTRY(table, ptr, hash_val, bin_pos);
304
391
rehash(register st_table *table)
306
register st_table_entry *ptr, *next, **new_bins;
307
int i, old_num_bins = table->num_bins, new_num_bins;
393
register st_table_entry *ptr, **new_bins;
308
395
unsigned int hash_val;
310
new_num_bins = new_size(old_num_bins+1);
311
new_bins = (st_table_entry**)Calloc(new_num_bins, sizeof(st_table_entry*));
397
new_num_bins = new_size(table->num_bins+1);
398
new_bins = (st_table_entry**)
399
xrealloc(table->bins, new_num_bins * sizeof(st_table_entry*));
400
for (i = 0; i < new_num_bins; ++i) new_bins[i] = 0;
401
table->num_bins = new_num_bins;
402
table->bins = new_bins;
313
for(i = 0; i < old_num_bins; i++) {
314
ptr = table->bins[i];
404
if ((ptr = table->head) != 0) {
317
406
hash_val = ptr->hash % new_num_bins;
318
407
ptr->next = new_bins[hash_val];
319
408
new_bins[hash_val] = ptr;
409
} while ((ptr = ptr->fore) != table->head);
324
table->num_bins = new_num_bins;
325
table->bins = new_bins;
329
414
st_copy(st_table *old_table)
331
416
st_table *new_table;
332
st_table_entry *ptr, *entry;
333
int i, num_bins = old_table->num_bins;
417
st_table_entry *ptr, *entry, *prev, **tail;
418
int num_bins = old_table->num_bins;
419
unsigned int hash_val;
335
421
new_table = alloc(st_table);
336
422
if (new_table == 0) {
349
for(i = 0; i < num_bins; i++) {
350
new_table->bins[i] = 0;
351
ptr = old_table->bins[i];
435
if (old_table->entries_packed) {
436
memcpy(new_table->bins, old_table->bins, sizeof(struct st_table_entry *) * old_table->num_bins);
440
if ((ptr = old_table->head) != 0) {
442
tail = &new_table->head;
353
444
entry = alloc(st_table_entry);
354
445
if (entry == 0) {
355
free(new_table->bins);
446
st_free_table(new_table);
360
entry->next = new_table->bins[i];
361
new_table->bins[i] = entry;
450
hash_val = entry->hash % num_bins;
451
entry->next = new_table->bins[hash_val];
452
new_table->bins[hash_val] = entry;
454
*tail = prev = entry;
456
} while ((ptr = ptr->fore) != old_table->head);
457
entry = new_table->head;
365
462
return new_table;
465
#define REMOVE_ENTRY(table, ptr) do \
467
if (ptr == ptr->fore) { \
471
st_table_entry *fore = ptr->fore, *back = ptr->back; \
474
if (ptr == table->head) table->head = fore; \
476
table->num_entries--; \
369
480
st_delete(register st_table *table, register st_data_t *key, st_data_t *value)
371
482
unsigned int hash_val;
483
st_table_entry **prev;
373
484
register st_table_entry *ptr;
486
if (table->entries_packed) {
488
for (i = 0; i < table->num_entries; i++) {
489
if ((st_data_t)table->bins[i*2] == *key) {
490
if (value != 0) *value = (st_data_t)table->bins[i*2+1];
491
table->num_entries--;
492
memmove(&table->bins[i*2], &table->bins[(i+1)*2],
493
sizeof(struct st_table_entry*) * 2*(table->num_entries-i));
497
if (value != 0) *value = 0;
375
501
hash_val = do_hash_bin(*key, table);
376
ptr = table->bins[hash_val];
379
if (value != 0) *value = 0;
383
if (EQUAL(table, *key, ptr->key)) {
384
table->bins[hash_val] = ptr->next;
385
table->num_entries--;
386
if (value != 0) *value = ptr->record;
392
for(; ptr->next != 0; ptr = ptr->next) {
393
if (EQUAL(table, ptr->next->key, *key)) {
395
ptr->next = ptr->next->next;
396
table->num_entries--;
397
if (value != 0) *value = tmp->record;
503
for (prev = &table->bins[hash_val]; (ptr = *prev) != 0; prev = &ptr->next) {
504
if (EQUAL(table, *key, ptr->key)) {
506
REMOVE_ENTRY(table, ptr);
507
if (value != 0) *value = ptr->record;
514
if (value != 0) *value = 0;
537
if (value != 0) *value = 0;
435
delete_never(st_data_t key, st_data_t value, st_data_t never)
437
if (value == never) return ST_DELETE;
442
542
st_cleanup_safe(st_table *table, st_data_t never)
444
int num_entries = table->num_entries;
544
st_table_entry *ptr, **last, *tmp;
446
st_foreach(table, delete_never, never);
447
table->num_entries = num_entries;
547
for (i = 0; i < table->num_bins; i++) {
548
ptr = *(last = &table->bins[i]);
550
if (ptr->key == never) {
552
*last = ptr = ptr->next;
556
ptr = *(last = &ptr->next);
451
563
st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg)
453
st_table_entry *ptr, *last, *tmp;
565
st_table_entry *ptr, **last, *tmp;
454
566
enum st_retval retval;
457
for(i = 0; i < table->num_bins; i++) {
459
for(ptr = table->bins[i]; ptr != 0;) {
569
if (table->entries_packed) {
570
for (i = 0; i < table->num_entries; i++) {
573
key = (st_data_t)table->bins[i*2];
574
val = (st_data_t)table->bins[i*2+1];
575
retval = (*func)(key, val, arg);
577
case ST_CHECK: /* check if hash is modified during iteration */
578
for (j = 0; j < table->num_entries; j++) {
579
if ((st_data_t)table->bins[j*2] == key)
582
if (j == table->num_entries) {
583
/* call func with error notice */
584
retval = (*func)(0, 0, arg, 1);
593
table->num_entries--;
594
memmove(&table->bins[i*2], &table->bins[(i+1)*2],
595
sizeof(struct st_table_entry*) * 2*(table->num_entries-i));
603
if ((ptr = table->head) != 0) {
605
end = ptr->fore == table->head;
460
606
retval = (*func)(ptr->key, ptr->record, arg);
461
607
switch (retval) {
462
case ST_CHECK: /* check if hash is modified during iteration */
464
if (i < table->num_bins) {
465
for (tmp = table->bins[i]; tmp; tmp=tmp->next) {
466
if (tmp == ptr) break;
470
/* call func with error notice */
483
table->bins[i] = ptr->next;
486
last->next = ptr->next;
608
case ST_CHECK: /* check if hash is modified during iteration */
609
i = ptr->hash % table->num_bins;
610
for (tmp = table->bins[i]; tmp != ptr; tmp = tmp->next) {
612
/* call func with error notice */
613
retval = (*func)(0, 0, arg, 1);
624
last = &table->bins[ptr->hash % table->num_bins];
625
for (; (tmp = *last) != 0; last = &tmp->next) {
629
REMOVE_ENTRY(table, ptr);
631
if (ptr == tmp) return 0;
637
} while (!end && table->head);
643
st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg)
645
st_table_entry *ptr, **last, *tmp;
646
enum st_retval retval;
649
if (table->entries_packed) {
650
for (i = table->num_entries-1; 0 <= i; i--) {
653
key = (st_data_t)table->bins[i*2];
654
val = (st_data_t)table->bins[i*2+1];
655
retval = (*func)(key, val, arg);
657
case ST_CHECK: /* check if hash is modified during iteration */
658
for (j = 0; j < table->num_entries; j++) {
659
if ((st_data_t)table->bins[j*2] == key)
662
if (j == table->num_entries) {
663
/* call func with error notice */
664
retval = (*func)(0, 0, arg, 1);
673
table->num_entries--;
674
memmove(&table->bins[i*2], &table->bins[(i+1)*2],
675
sizeof(struct st_table_entry*) * 2*(table->num_entries-i));
682
if ((ptr = table->head) != 0) {
685
end = ptr == table->head;
686
retval = (*func)(ptr->key, ptr->record, arg, 0);
688
case ST_CHECK: /* check if hash is modified during iteration */
689
i = ptr->hash % table->num_bins;
690
for (tmp = table->bins[i]; tmp != ptr; tmp = tmp->next) {
692
/* call func with error notice */
693
retval = (*func)(0, 0, arg, 1);
704
last = &table->bins[ptr->hash % table->num_bins];
705
for (; (tmp = *last) != 0; last = &tmp->next) {
709
REMOVE_ENTRY(table, ptr);
490
717
table->num_entries--;
719
} while (!end && table->head);