Freeciv-3.3
Loading...
Searching...
No Matches
genhash.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14/****************************************************************************
15 A general-purpose generic hash table implementation.
16
17 Based on implementation previous included in registry.c, but separated
18 out so that can be used more generally. Maybe we should just use glib?
19
20 Original author: David Pfitzner dwp@mso.anu.edu.au
21
22 A hash table maps keys to user data values, using a user-supplied hash
23 function to do this efficiently. Here both keys and values are general
24 data represented by (void*) pointers. Memory management of both keys
25 and data is the responsibility of the caller: that is, the caller must
26 ensure that the memory (especially for keys) remains valid (allocated)
27 for as long as required (typically, the life of the genhash table).
28 (Otherwise, to allocate keys internally would either have to restrict
29 key type (e.g., strings), or have user-supplied function to duplicate
30 a key type. See further comments below.)
31
32 User-supplied functions required are:
33 key_val_func: map key to bucket number given number of buckets; should
34 map keys fairly evenly to range 0 to (num_buckets - 1)
35 inclusive.
36
37 key_comp_func: compare keys for equality, necessary for lookups for keys
38 which map to the same genhash value. Keys which compare
39 equal should map to the same hash value. Returns 0 for
40 equality, so can use qsort-type comparison function (but
41 the hash table does not make use of the ordering
42 information if the return value is non-zero).
43
44 Some constructors also accept following functions to be registered:
45 key_copy_func: This is called when assigning a new value to a bucket.
46 key_free_func: This is called when genhash no longer needs key construct.
47 Note that one key construct gets freed even when it is
48 replaced with another that is considered identical by
49 key_comp_func().
50 data_copy_func: same as 'key_copy_func', but for data.
51 data_free_func: same as 'key_free_func', but for data.
52
53 Implementation uses open hashing. Collision resolution is done by
54 separate chaining with linked lists. Resize hash table when deemed
55 necessary by making and populating a new table.
56****************************************************************************/
57
58#ifdef HAVE_CONFIG_H
59#include <fc_config.h>
60#endif
61
62#include <string.h>
63
64/* utility */
65#include "log.h"
66#include "mem.h"
67#include "shared.h" /* ARRAY_SIZE */
68#include "support.h"
69
70#include "genhash.h"
71
72#define FULL_RATIO 0.75 /* consider expanding when above this */
73#define MIN_RATIO 0.24 /* shrink when below this */
74
81
82/* Contents of the opaque type: */
95
98 struct genhash_entry *const *bucket, *const *end;
99 const struct genhash_entry *iterator;
100};
101
102#define GENHASH_ITER(p) ((struct genhash_iter *) (p))
103
104
105/************************************************************************/
110{
111 unsigned long result = 0;
112
113 for (; *vkey != '\0'; vkey++) {
114 result *= 5;
115 result += *vkey;
116 }
117 result &= 0xFFFFFFFF; /* To make results independent of sizeof(long) */
118 return result;
119}
120
121/************************************************************************/
124bool genhash_str_comp_func(const char *vkey1, const char *vkey2)
125{
126 return 0 == strcmp(vkey1, vkey2);
127}
128
129/************************************************************************/
132char *genhash_str_copy_func(const char *vkey)
133{
134 return fc_strdup(vkey != nullptr ? vkey : "");
135}
136
137/************************************************************************/
141{
142 free(vkey);
143}
144
145/************************************************************************/
158#define MIN_BUCKETS 29 /* Historical purposes. */
159static size_t genhash_calc_num_buckets(size_t num_entries)
160{
161 /* A bunch of prime numbers close to successive elements of the sequence
162 * A_n = 3 * 2 ^ n; to be used for table sizes. */
163 static const size_t sizes[] = {
164 MIN_BUCKETS, 53, 97, 193,
165 389, 769, 1543, 3079, 6151,
166 12289, 24593, 49157, 98317, 196613,
167 393241, 786433, 1572869, 3145739, 6291469,
168 12582917, 25165843, 50331653, 100663319, 201326611,
169 402653189, 805306457, 1610612741, 3221225473ul, 4294967291ul
170 };
171 const size_t *pframe = sizes, *pmid;
172 int fsize = ARRAY_SIZE(sizes) - 1, lpart;
173
174 num_entries <<= 1; /* breathing room */
175
176 while (fsize > 0) {
177 lpart = fsize >> 1;
178 pmid = pframe + lpart;
179 if (*pmid < num_entries) {
180 pframe = pmid + 1;
181 fsize = fsize - lpart - 1;
182 } else {
183 fsize = lpart;
184 }
185 }
186 return *pframe;
187}
188
189/************************************************************************/
198static struct genhash *
205 size_t num_buckets)
206{
207 struct genhash *pgenhash = fc_malloc(sizeof(*pgenhash));
208
209 log_debug("New genhash table with %lu buckets",
210 (long unsigned) num_buckets);
211
212 pgenhash->buckets = fc_calloc(num_buckets, sizeof(*pgenhash->buckets));
213 pgenhash->key_val_func = key_val_func;
214 pgenhash->key_comp_func = key_comp_func;
215 pgenhash->key_copy_func = key_copy_func;
216 pgenhash->key_free_func = key_free_func;
217 pgenhash->data_copy_func = data_copy_func;
218 pgenhash->data_free_func = data_free_func;
219 pgenhash->num_buckets = num_buckets;
220 pgenhash->num_entries = 0;
221 pgenhash->no_shrink = FALSE;
222
223 return pgenhash;
224}
225
226/************************************************************************/
232struct genhash *
246
247/************************************************************************/
258
259/************************************************************************/
276
277/************************************************************************/
286
287/************************************************************************/
291{
292 pgenhash->no_shrink = TRUE;
294 free(pgenhash->buckets);
295 free(pgenhash);
296}
297
298/************************************************************************/
302 size_t new_nbuckets)
303{
304 struct genhash_entry **new_buckets, **bucket, **end, **slot;
305 struct genhash_entry *iter, *next;
306
307 fc_assert(new_nbuckets >= pgenhash->num_entries);
308
309 new_buckets = fc_calloc(new_nbuckets, sizeof(*pgenhash->buckets));
310
311 bucket = pgenhash->buckets;
312 end = bucket + pgenhash->num_buckets;
313 for (; bucket < end; bucket++) {
314 for (iter = *bucket; iter != nullptr; iter = next) {
315 slot = new_buckets + (iter->hash_val % new_nbuckets);
316 next = iter->next;
317 iter->next = *slot;
318 *slot = iter;
319 }
320 }
321
322 free(pgenhash->buckets);
323 pgenhash->buckets = new_buckets;
324 pgenhash->num_buckets = new_nbuckets;
325}
326
327/************************************************************************/
334#define genhash_maybe_expand(htab) genhash_maybe_resize((htab), TRUE)
335#define genhash_maybe_shrink(htab) genhash_maybe_resize((htab), FALSE)
337{
338 size_t limit, new_nbuckets;
339
340 if (!expandingp && pgenhash->no_shrink) {
341 return FALSE;
342 }
343 if (expandingp) {
344 limit = FULL_RATIO * pgenhash->num_buckets;
345 if (pgenhash->num_entries < limit) {
346 return FALSE;
347 }
348 } else {
349 if (pgenhash->num_buckets <= MIN_BUCKETS) {
350 return FALSE;
351 }
352 limit = MIN_RATIO * pgenhash->num_buckets;
353 if (pgenhash->num_entries > limit) {
354 return FALSE;
355 }
356 }
357
359
360 log_debug("%s genhash (entries = %lu, buckets = %lu, new = %lu, "
361 "%s limit = %lu)",
362 (new_nbuckets < pgenhash->num_buckets ? "Shrinking"
363 : (new_nbuckets > pgenhash->num_buckets
364 ? "Expanding" : "Rehashing")),
365 (long unsigned) pgenhash->num_entries,
366 (long unsigned) pgenhash->num_buckets,
367 (long unsigned) new_nbuckets,
368 expandingp ? "up": "down", (long unsigned) limit);
370 return TRUE;
371}
372
373
374/************************************************************************/
377static inline genhash_val_t genhash_val_calc(const struct genhash *pgenhash,
378 const void *key)
379{
380 if (pgenhash->key_val_func != nullptr) {
381 return pgenhash->key_val_func(key);
382 } else {
383 return ((intptr_t) key);
384 }
385}
386
387/************************************************************************/
391static inline struct genhash_entry **
393 const void *key,
395{
396 struct genhash_entry **slot;
397 genhash_comp_fn_t key_comp_func = pgenhash->key_comp_func;
398
399 slot = pgenhash->buckets + (hash_val % pgenhash->num_buckets);
400 if (key_comp_func != nullptr) {
401 for (; *slot != nullptr; slot = &(*slot)->next) {
402 if (hash_val == (*slot)->hash_val
403 && key_comp_func((*slot)->key, key)) {
404 return slot;
405 }
406 }
407 } else {
408 for (; *slot != nullptr; slot = &(*slot)->next) {
409 if (key == (*slot)->key) {
410 return slot;
411 }
412 }
413 }
414 return slot;
415}
416
417/************************************************************************/
420static inline void genhash_default_get(void **pkey, void **data)
421{
422 if (pkey != nullptr) {
423 *pkey = nullptr;
424 }
425 if (data != nullptr) {
426 *data = nullptr;
427 }
428}
429
430/************************************************************************/
433static inline void genhash_slot_get(struct genhash_entry *const *slot,
434 void **pkey, void **data)
435{
436 const struct genhash_entry *entry = *slot;
437
438 if (pkey != nullptr) {
439 *pkey = entry->key;
440 }
441 if (data != nullptr) {
442 *data = entry->data;
443 }
444}
445
446/************************************************************************/
449static inline void genhash_slot_create(struct genhash *pgenhash,
450 struct genhash_entry **slot,
451 const void *key, const void *data,
453{
454 struct genhash_entry *entry = fc_malloc(sizeof(*entry));
455
456 entry->key = (pgenhash->key_copy_func != nullptr
457 ? pgenhash->key_copy_func(key) : (void *) key);
458 entry->data = (pgenhash->data_copy_func != nullptr
459 ? pgenhash->data_copy_func(data) : (void *) data);
460 entry->hash_val = hash_val;
461 entry->next = *slot;
462 *slot = entry;
463}
464
465/************************************************************************/
468static inline void genhash_slot_free(struct genhash *pgenhash,
469 struct genhash_entry **slot)
470{
471 struct genhash_entry *entry = *slot;
472
473 if (pgenhash->key_free_func != nullptr) {
474 pgenhash->key_free_func(entry->key);
475 }
476 if (pgenhash->data_free_func != nullptr) {
477 pgenhash->data_free_func(entry->data);
478 }
479
480 *slot = entry->next;
481 free(entry);
482}
483
484/************************************************************************/
487static inline void genhash_slot_set(struct genhash *pgenhash,
488 struct genhash_entry **slot,
489 const void *key, const void *data)
490{
491 struct genhash_entry *entry = *slot;
492
493 if (pgenhash->key_free_func != nullptr) {
494 pgenhash->key_free_func(entry->key);
495 }
496 if (pgenhash->data_free_func != nullptr) {
497 pgenhash->data_free_func(entry->data);
498 }
499
500 entry->key = (pgenhash->key_copy_func != nullptr
501 ? pgenhash->key_copy_func(key) : (void *) key);
502 entry->data = (pgenhash->data_copy_func != nullptr
503 ? pgenhash->data_copy_func(data) : (void *) data);
504}
505
506/************************************************************************/
510bool genhash_set_no_shrink(struct genhash *pgenhash, bool no_shrink)
511{
512 bool old;
513
514 old = pgenhash->no_shrink;
515 pgenhash->no_shrink = no_shrink;
516
517 return old;
518}
519
520/************************************************************************/
523size_t genhash_size(const struct genhash *pgenhash)
524{
525 return pgenhash->num_entries;
526}
527
528/************************************************************************/
531size_t genhash_capacity(const struct genhash *pgenhash)
532{
533 return pgenhash->num_buckets;
534}
535
536/************************************************************************/
539struct genhash *genhash_copy(const struct genhash *pgenhash)
540{
541 struct genhash *new_genhash;
542 struct genhash_entry *const *src_bucket, *const *end;
543 const struct genhash_entry *src_iter;
545
547
548 /* Copy fields. */
550
551 /* But make fresh buckets. */
552 new_genhash->buckets = fc_calloc(new_genhash->num_buckets,
553 sizeof(*new_genhash->buckets));
554
555 /* Let's re-insert all data */
556 src_bucket = pgenhash->buckets;
557 end = src_bucket + pgenhash->num_buckets;
558 dest_bucket = new_genhash->buckets;
559
560 for (; src_bucket < end; src_bucket++, dest_bucket++) {
562 for (src_iter = *src_bucket; src_iter != nullptr;
563 src_iter = src_iter->next) {
565 src_iter->data, src_iter->hash_val);
566 dest_slot = &(*dest_slot)->next;
567 }
568 }
569
570 return new_genhash;
571}
572
573/************************************************************************/
577{
578 struct genhash_entry **bucket, **end;
579
580 bucket = pgenhash->buckets;
581 end = bucket + pgenhash->num_buckets;
582 for (; bucket < end; bucket++) {
583 while (*bucket != nullptr) {
585 }
586 }
587
588 pgenhash->num_entries = 0;
590}
591
592/************************************************************************/
596bool genhash_insert(struct genhash *pgenhash, const void *key,
597 const void *data)
598{
599 struct genhash_entry **slot;
601
604 if (*slot != nullptr) {
605 return FALSE;
606 } else {
608 /* Recalculate slot. */
609 slot = pgenhash->buckets + (hash_val % pgenhash->num_buckets);
610 }
612 pgenhash->num_entries++;
613 return TRUE;
614 }
615}
616
617/************************************************************************/
622bool genhash_replace(struct genhash *pgenhash, const void *key,
623 const void *data)
624{
625 return genhash_replace_full(pgenhash, key, data, nullptr, nullptr);
626}
627
628/************************************************************************/
637bool genhash_replace_full(struct genhash *pgenhash, const void *key,
638 const void *data, void **old_pkey,
639 void **old_pdata)
640{
641 struct genhash_entry **slot;
643
646 if (*slot != nullptr) {
647 /* Replace. */
650 return TRUE;
651 } else {
652 /* Insert. */
654 /* Recalculate slot. */
655 slot = pgenhash->buckets + (hash_val % pgenhash->num_buckets);
656 }
659 pgenhash->num_entries++;
660 return FALSE;
661 }
662}
663
664/************************************************************************/
668bool genhash_lookup(const struct genhash *pgenhash, const void *key,
669 void **pdata)
670{
671 struct genhash_entry **slot;
672
674 if (*slot != nullptr) {
675 genhash_slot_get(slot, nullptr, pdata);
676 return TRUE;
677 } else {
678 genhash_default_get(nullptr, pdata);
679 return FALSE;
680 }
681}
682
683/************************************************************************/
686bool genhash_remove(struct genhash *pgenhash, const void *key)
687{
688 return genhash_remove_full(pgenhash, key, nullptr, nullptr);
689}
690
691/************************************************************************/
698bool genhash_remove_full(struct genhash *pgenhash, const void *key,
699 void **deleted_pkey, void **deleted_pdata)
700{
701 struct genhash_entry **slot;
702
704 if (*slot != nullptr) {
708
709 fc_assert(0 < pgenhash->num_entries);
710
711 pgenhash->num_entries--;
712 return TRUE;
713 } else {
715 return FALSE;
716 }
717}
718
719
720/************************************************************************/
724 const struct genhash *pgenhash2)
725{
727}
728
729/************************************************************************/
733 const struct genhash *pgenhash2,
735{
736 struct genhash_entry *const *bucket1, *const *max1, *const *slot2;
737 const struct genhash_entry *iter1;
738
739 /* Check pointers. */
740 if (pgenhash1 == pgenhash2) {
741 return TRUE;
742 } else if (pgenhash1 == nullptr || pgenhash2 == nullptr) {
743 return FALSE;
744 }
745
746 /* General check. */
747 if (pgenhash1->num_entries != pgenhash2->num_entries
748 /* If the key functions is not the same, we cannot know if the
749 * keys are equals. */
750 || pgenhash1->key_val_func != pgenhash2->key_val_func
751 || pgenhash1->key_comp_func != pgenhash2->key_comp_func) {
752 return FALSE;
753 }
754
755 /* Compare buckets. */
756 bucket1 = pgenhash1->buckets;
757 max1 = bucket1 + pgenhash1->num_buckets;
758 for (; bucket1 < max1; bucket1++) {
759 for (iter1 = *bucket1; iter1 != nullptr; iter1 = iter1->next) {
760 slot2 = genhash_slot_lookup(pgenhash2, iter1->key, iter1->hash_val);
761 if (*slot2 == nullptr
762 || (iter1->data != (*slot2)->data
763 && (data_comp_func == nullptr
764 || !data_comp_func(iter1->data, (*slot2)->data)))) {
765 return FALSE;
766 }
767 }
768 }
769
770 return TRUE;
771}
772
773
774/************************************************************************/
778{
779 return sizeof(struct genhash_iter);
780}
781
782/************************************************************************/
786{
788 return (void *) iter->iterator->key;
789}
790
791/************************************************************************/
795{
797 return (void *) iter->iterator->data;
798}
799
800/************************************************************************/
804{
806
807 iter->iterator = iter->iterator->next;
808 if (iter->iterator != nullptr) {
809 return;
810 }
811
812 for (iter->bucket++; iter->bucket < iter->end; iter->bucket++) {
813 if (*iter->bucket != nullptr) {
814 iter->iterator = *iter->bucket;
815 return;
816 }
817 }
818}
819
820/************************************************************************/
825static void *genhash_iter_get(const struct iterator *genhash_iter)
826{
827 return (void *) genhash_iter;
828}
829
830/************************************************************************/
833static bool genhash_iter_valid(const struct iterator *genhash_iter)
834{
836 return iter->bucket < iter->end;
837}
838
839/************************************************************************/
842static inline struct iterator *
844 const struct genhash *pgenhash,
845 void * (*get) (const struct iterator *))
846{
847 if (pgenhash == nullptr) {
849 }
850
851 iter->vtable.next = genhash_iter_next;
852 iter->vtable.get = get;
853 iter->vtable.valid = genhash_iter_valid;
854 iter->bucket = pgenhash->buckets;
855 iter->end = pgenhash->buckets + pgenhash->num_buckets;
856
857 /* Seek to the first used bucket. */
858 for (; iter->bucket < iter->end; iter->bucket++) {
859 if (*iter->bucket != nullptr) {
860 iter->iterator = *iter->bucket;
861 break;
862 }
863 }
864
865 return ITERATOR(iter);
866}
867
868/************************************************************************/
878
879/************************************************************************/
887
888/************************************************************************/
char * incite_cost
Definition comments.c:76
static struct iterator * genhash_iter_init_common(struct genhash_iter *iter, const struct genhash *pgenhash, void *(*get)(const struct iterator *))
Definition genhash.c:843
#define genhash_maybe_expand(htab)
Definition genhash.c:334
struct iterator * genhash_iter_init(struct genhash_iter *iter, const struct genhash *pgenhash)
Definition genhash.c:873
struct genhash * genhash_new_full(genhash_val_fn_t key_val_func, genhash_comp_fn_t key_comp_func, genhash_copy_fn_t key_copy_func, genhash_free_fn_t key_free_func, genhash_copy_fn_t data_copy_func, genhash_free_fn_t data_free_func)
Definition genhash.c:265
static void genhash_iter_next(struct iterator *genhash_iter)
Definition genhash.c:803
bool genhash_insert(struct genhash *pgenhash, const void *key, const void *data)
Definition genhash.c:596
static void * genhash_iter_get(const struct iterator *genhash_iter)
Definition genhash.c:825
bool genhash_str_comp_func(const char *vkey1, const char *vkey2)
Definition genhash.c:124
bool genhashes_are_equal(const struct genhash *pgenhash1, const struct genhash *pgenhash2)
Definition genhash.c:723
#define genhash_maybe_shrink(htab)
Definition genhash.c:335
static void genhash_slot_free(struct genhash *pgenhash, struct genhash_entry **slot)
Definition genhash.c:468
static size_t genhash_calc_num_buckets(size_t num_entries)
Definition genhash.c:159
static bool genhash_maybe_resize(struct genhash *pgenhash, bool expandingp)
Definition genhash.c:336
bool genhash_set_no_shrink(struct genhash *pgenhash, bool no_shrink)
Definition genhash.c:510
static struct genhash_entry ** genhash_slot_lookup(const struct genhash *pgenhash, const void *key, genhash_val_t hash_val)
Definition genhash.c:392
size_t genhash_size(const struct genhash *pgenhash)
Definition genhash.c:523
static bool genhash_iter_valid(const struct iterator *genhash_iter)
Definition genhash.c:833
void genhash_destroy(struct genhash *pgenhash)
Definition genhash.c:290
static void genhash_slot_get(struct genhash_entry *const *slot, void **pkey, void **data)
Definition genhash.c:433
static struct genhash * genhash_new_nbuckets(genhash_val_fn_t key_val_func, genhash_comp_fn_t key_comp_func, genhash_copy_fn_t key_copy_func, genhash_free_fn_t key_free_func, genhash_copy_fn_t data_copy_func, genhash_free_fn_t data_free_func, size_t num_buckets)
Definition genhash.c:199
size_t genhash_capacity(const struct genhash *pgenhash)
Definition genhash.c:531
void genhash_clear(struct genhash *pgenhash)
Definition genhash.c:576
struct iterator * genhash_value_iter_init(struct genhash_iter *iter, const struct genhash *pgenhash)
Definition genhash.c:891
size_t genhash_iter_sizeof(void)
Definition genhash.c:777
#define MIN_RATIO
Definition genhash.c:73
static void genhash_default_get(void **pkey, void **data)
Definition genhash.c:420
bool genhash_lookup(const struct genhash *pgenhash, const void *key, void **pdata)
Definition genhash.c:668
bool genhashes_are_equal_full(const struct genhash *pgenhash1, const struct genhash *pgenhash2, genhash_comp_fn_t data_comp_func)
Definition genhash.c:732
static genhash_val_t genhash_val_calc(const struct genhash *pgenhash, const void *key)
Definition genhash.c:377
#define FULL_RATIO
Definition genhash.c:72
static void genhash_slot_create(struct genhash *pgenhash, struct genhash_entry **slot, const void *key, const void *data, genhash_val_t hash_val)
Definition genhash.c:449
bool genhash_remove(struct genhash *pgenhash, const void *key)
Definition genhash.c:686
#define MIN_BUCKETS
Definition genhash.c:158
static void genhash_slot_set(struct genhash *pgenhash, struct genhash_entry **slot, const void *key, const void *data)
Definition genhash.c:487
bool genhash_replace_full(struct genhash *pgenhash, const void *key, const void *data, void **old_pkey, void **old_pdata)
Definition genhash.c:637
struct genhash * genhash_new(genhash_val_fn_t key_val_func, genhash_comp_fn_t key_comp_func)
Definition genhash.c:280
struct iterator * genhash_key_iter_init(struct genhash_iter *iter, const struct genhash *pgenhash)
Definition genhash.c:882
struct genhash * genhash_new_nentries(genhash_val_fn_t key_val_func, genhash_comp_fn_t key_comp_func, size_t nentries)
Definition genhash.c:250
void * genhash_iter_key(const struct iterator *genhash_iter)
Definition genhash.c:785
static void genhash_resize_table(struct genhash *pgenhash, size_t new_nbuckets)
Definition genhash.c:301
void genhash_str_free_func(char *vkey)
Definition genhash.c:140
char * genhash_str_copy_func(const char *vkey)
Definition genhash.c:132
bool genhash_replace(struct genhash *pgenhash, const void *key, const void *data)
Definition genhash.c:622
struct genhash * genhash_copy(const struct genhash *pgenhash)
Definition genhash.c:539
genhash_val_t genhash_str_val_func(const char *vkey)
Definition genhash.c:109
struct genhash * genhash_new_nentries_full(genhash_val_fn_t key_val_func, genhash_comp_fn_t key_comp_func, genhash_copy_fn_t key_copy_func, genhash_free_fn_t key_free_func, genhash_copy_fn_t data_copy_func, genhash_free_fn_t data_free_func, size_t nentries)
Definition genhash.c:233
#define GENHASH_ITER(p)
Definition genhash.c:102
bool genhash_remove_full(struct genhash *pgenhash, const void *key, void **deleted_pkey, void **deleted_pdata)
Definition genhash.c:698
void * genhash_iter_value(const struct iterator *genhash_iter)
Definition genhash.c:794
genhash_val_t(* genhash_val_fn_t)(const void *)
Definition genhash.h:35
bool(* genhash_comp_fn_t)(const void *, const void *)
Definition genhash.h:36
void(* genhash_free_fn_t)(void *)
Definition genhash.h:38
void *(* genhash_copy_fn_t)(const void *)
Definition genhash.h:37
unsigned int genhash_val_t
Definition genhash.h:32
struct iterator * invalid_iter_init(struct iterator *it)
Definition iterator.c:51
#define ITERATOR(p)
Definition iterator.h:37
#define fc_assert(condition)
Definition log.h:177
#define log_debug(message,...)
Definition log.h:116
#define fc_calloc(n, esz)
Definition mem.h:38
#define fc_strdup(str)
Definition mem.h:43
#define fc_malloc(sz)
Definition mem.h:34
#define ARRAY_SIZE(x)
Definition shared.h:85
Definition genhash.c:75
genhash_val_t hash_val
Definition genhash.c:78
struct genhash_entry * next
Definition genhash.c:79
void * key
Definition genhash.c:76
void * data
Definition genhash.c:77
const struct genhash_entry * iterator
Definition genhash.c:99
struct genhash_entry *const *const * end
Definition genhash.c:98
struct genhash_entry *const * bucket
Definition genhash.c:98
struct iterator vtable
Definition genhash.c:97
struct genhash_entry ** buckets
Definition genhash.c:84
genhash_comp_fn_t key_comp_func
Definition genhash.c:86
genhash_val_fn_t key_val_func
Definition genhash.c:85
genhash_free_fn_t key_free_func
Definition genhash.c:88
bool no_shrink
Definition genhash.c:93
genhash_copy_fn_t data_copy_func
Definition genhash.c:89
size_t num_buckets
Definition genhash.c:91
size_t num_entries
Definition genhash.c:92
genhash_free_fn_t data_free_func
Definition genhash.c:90
genhash_copy_fn_t key_copy_func
Definition genhash.c:87
void *(* get)(const struct iterator *it)
Definition iterator.h:33
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47