68 #define FULL_RATIO 0.75
69 #define MIN_RATIO 0.24
98 #define GENHASH_ITER(p) ((struct genhash_iter *) (p))
106 unsigned long result = 0;
108 for (; *vkey !=
'\0'; vkey++) {
112 result &= 0xFFFFFFFF;
121 return 0 == strcmp(vkey1, vkey2);
129 return fc_strdup(
nullptr != vkey ? vkey :
"");
156 #define MIN_BUCKETS 29
161 static const size_t sizes[] = {
163 769, 1543, 3079, 6151, 12289,
164 24593, 49157, 98317, 196613, 393241,
165 786433, 1572869, 3145739, 6291469, 12582917,
166 25165843, 50331653, 100663319, 201326611, 402653189,
167 805306457, 1610612741, 3221225473ul, 4294967291ul};
168 const size_t *pframe = sizes, *pmid;
175 pmid = pframe + lpart;
176 if (*pmid < num_entries) {
178 fsize = fsize - lpart - 1;
205 log_debug(
"New genhash table with %lu buckets",
308 for (; bucket < end; bucket++) {
309 for (iter = *bucket;
nullptr != iter; iter =
next) {
310 slot = new_buckets + (iter->
hash_val % new_nbuckets);
318 pgenhash->
buckets = new_buckets;
329 #define genhash_maybe_expand(htab) genhash_maybe_resize((htab), true)
330 #define genhash_maybe_shrink(htab) genhash_maybe_resize((htab), false)
333 size_t limit, new_nbuckets;
335 if (!expandingp && pgenhash->
no_shrink) {
355 log_debug(
"%s genhash (entries = %lu, buckets = %lu, new = %lu, "
357 (new_nbuckets < pgenhash->num_buckets
359 : (new_nbuckets > pgenhash->
num_buckets ?
"Expanding"
363 (
long unsigned) new_nbuckets, expandingp ?
"up" :
"down",
364 (
long unsigned) limit);
378 return ((intptr_t)
key);
394 if (
nullptr != key_comp_func) {
395 for (;
nullptr != *slot; slot = &(*slot)->
next) {
397 && key_comp_func((*slot)->key,
key)) {
402 for (;
nullptr != *slot; slot = &(*slot)->
next) {
403 if (
key == (*slot)->key) {
416 if (
nullptr != pkey) {
419 if (
nullptr !=
data) {
428 void **pkey,
void **
data)
432 if (
nullptr != pkey) {
435 if (
nullptr !=
data) {
445 const void *
key,
const void *
data,
452 :
const_cast<void *
>(
key));
455 :
const_cast<void *
>(
data));
470 ::operator
delete[](
entry->key);
473 ::operator
delete(
entry->data);
484 const void *
key,
const void *
data)
496 :
const_cast<void *
>(
key));
499 :
const_cast<void *
>(
data));
549 *new_genhash = *pgenhash;
555 src_bucket = pgenhash->
buckets;
557 dest_bucket = new_genhash->
buckets;
559 for (; src_bucket < end; src_bucket++, dest_bucket++) {
560 dest_slot = dest_bucket;
561 for (src_iter = *src_bucket;
nullptr != src_iter;
562 src_iter = src_iter->
next) {
565 dest_slot = &(*dest_slot)->
next;
583 for (; bucket < end; bucket++) {
584 while (
nullptr != *bucket) {
607 if (
nullptr != *slot) {
641 const void *
data,
void **old_pkey,
653 if (
nullptr != *slot) {
684 if (
nullptr != *slot) {
709 void **deleted_pkey,
void **deleted_pdata)
718 if (
nullptr != *slot) {
735 const struct genhash *pgenhash2)
744 const struct genhash *pgenhash2,
747 struct genhash_entry *
const *bucket1, *
const *max1, *
const *slot2;
751 if (pgenhash1 == pgenhash2) {
753 }
else if (
nullptr == pgenhash1 ||
nullptr == pgenhash2) {
769 for (; bucket1 < max1; bucket1++) {
770 for (iter1 = *bucket1;
nullptr != iter1; iter1 = iter1->
next) {
772 if (
nullptr == *slot2
773 || (iter1->
data != (*slot2)->data
774 && (
nullptr == data_comp_func
775 || !data_comp_func(iter1->
data, (*slot2)->data)))) {
820 if (
nullptr != *iter->
bucket) {
851 const struct genhash *pgenhash,
854 if (
nullptr == pgenhash) {
866 if (
nullptr != *iter->
bucket) {
881 const struct genhash *pgenhash)
890 const struct genhash *pgenhash)
899 const struct genhash *pgenhash)
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)
Internal constructor, specifying exact number of buckets.
#define genhash_maybe_expand(htab)
Call this when an entry might be added or deleted: resizes the genhash table if seems like a good ide...
size_t genhash_iter_sizeof()
"Sizeof" function implementation for generic_iterate genhash iterators.
static void genhash_iter_next(struct iterator *genhash_iter)
Iterator interface 'next' function implementation.
bool genhashs_are_equal(const struct genhash *pgenhash1, const struct genhash *pgenhash2)
Returns TRUE iff the hash tables contains the same pairs of key/data.
bool genhash_insert(struct genhash *pgenhash, const void *key, const void *data)
Insert entry: returns TRUE if inserted, or FALSE if there was already an entry with the same key,...
bool genhash_str_comp_func(const char *vkey1, const char *vkey2)
A supplied function for comparison of nul-terminated strings:
bool genhashs_are_equal_full(const struct genhash *pgenhash1, const struct genhash *pgenhash2, genhash_comp_fn_t data_comp_func)
Returns TRUE iff the hash tables contains the same pairs of key/data.
#define genhash_maybe_shrink(htab)
static void genhash_slot_free(struct genhash *pgenhash, struct genhash_entry **slot)
Free the entry slot and call the free callbacks.
static size_t genhash_calc_num_buckets(size_t num_entries)
static bool genhash_maybe_resize(struct genhash *pgenhash, bool expandingp)
bool genhash_set_no_shrink(struct genhash *pgenhash, bool no_shrink)
Prevent or allow the genhash table automatically shrinking.
static struct iterator * genhash_iter_init_common(struct genhash_iter *iter, const struct genhash *pgenhash, void *(*get)(const struct iterator *))
Common genhash iterator initializer.
size_t genhash_size(const struct genhash *pgenhash)
Returns the number of entries in the genhash table.
static bool genhash_iter_valid(const struct iterator *genhash_iter)
Iterator interface 'valid' function implementation.
static struct genhash_entry ** genhash_slot_lookup(const struct genhash *pgenhash, const void *key, genhash_val_t hash_val)
Return slot (entry pointer) in genhash table where key resides, or where it should go if it is to be ...
struct genhash * genhash_copy(const struct genhash *pgenhash)
Returns a newly allocated mostly deep copy of the given genhash table.
void genhash_destroy(struct genhash *pgenhash)
Destructor: free internal memory.
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)
Constructor with unspecified number of entries.
static void genhash_slot_get(struct genhash_entry *const *slot, void **pkey, void **data)
Function to store data.
size_t genhash_capacity(const struct genhash *pgenhash)
Returns the number of buckets in the genhash table.
void genhash_clear(struct genhash *pgenhash)
Remove all entries of the genhash table.
struct genhash * genhash_new(genhash_val_fn_t key_val_func, genhash_comp_fn_t key_comp_func)
Constructor with unspecified number of entries.
static void genhash_default_get(void **pkey, void **data)
Function to store from invalid data.
bool genhash_lookup(const struct genhash *pgenhash, const void *key, void **pdata)
Lookup data.
static genhash_val_t genhash_val_calc(const struct genhash *pgenhash, const void *key)
Calculate genhash value given hash table and key.
static void genhash_slot_create(struct genhash *pgenhash, struct genhash_entry **slot, const void *key, const void *data, genhash_val_t hash_val)
Create the entry and call the copy callbacks.
void * genhash_iter_key(const struct iterator *genhash_iter)
Helper function for genhash (key, value) pair iteration.
struct iterator * genhash_key_iter_init(struct genhash_iter *iter, const struct genhash *pgenhash)
Returns an iterator over the genhash table's k genhashgenhashenhashys.
bool genhash_remove(struct genhash *pgenhash, const void *key)
Delete an entry from the genhash table.
#define MIN_BUCKETS
Calculate a "reasonable" number of buckets for a given number of entries.
static void genhash_slot_set(struct genhash *pgenhash, struct genhash_entry **slot, const void *key, const void *data)
Clear previous values (with free callback) and call the copy callbacks.
bool genhash_replace_full(struct genhash *pgenhash, const void *key, const void *data, void **old_pkey, void **old_pdata)
Insert entry, replacing any existing entry which has the same key.
char * genhash_str_copy_func(const char *vkey)
Copy function for string allocation.
struct genhash * genhash_new_nentries(genhash_val_fn_t key_val_func, genhash_comp_fn_t key_comp_func, size_t nentries)
Constructor specifying number of entries.
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)
Constructor specifying number of entries.
void * genhash_iter_value(const struct iterator *genhash_iter)
Helper function for genhash (key, value) pair iteration.
struct iterator * genhash_iter_init(struct genhash_iter *iter, const struct genhash *pgenhash)
Returns an iterator that iterates over both keys and values of the genhash table.
static void genhash_resize_table(struct genhash *pgenhash, size_t new_nbuckets)
Resize the genhash table: relink entries.
void genhash_str_free_func(char *vkey)
Free function for string allocation.
bool genhash_replace(struct genhash *pgenhash, const void *key, const void *data)
Insert entry, replacing any existing entry which has the same key.
genhash_val_t genhash_str_val_func(const char *vkey)
A supplied genhash function appropriate to nul-terminated strings.
static void * genhash_iter_get(const struct iterator *genhash_iter)
Iterator interface 'get' function implementation.
struct iterator * genhash_value_iter_init(struct genhash_iter *iter, const struct genhash *pgenhash)
Returns an iterator over the hash table's values.
bool genhash_remove_full(struct genhash *pgenhash, const void *key, void **deleted_pkey, void **deleted_pdata)
Delete an entry from the genhash table.
genhash_val_t(* genhash_val_fn_t)(const void *)
void *(* genhash_copy_fn_t)(const void *)
bool(* genhash_comp_fn_t)(const void *, const void *)
void(* genhash_free_fn_t)(void *)
unsigned int genhash_val_t
struct iterator * invalid_iter_init(struct iterator *it)
Initializes the iterator vtable so that generic_iterate assumes that the iterator is invalid.
#define fc_assert_ret(condition)
#define fc_assert(condition)
#define fc_assert_ret_val(condition, val)
#define fc_assert_action(condition, action)
#define log_debug(message,...)
struct genhash_entry * next
const struct genhash_entry * iterator
struct genhash_entry *const *const * end
struct genhash_entry *const * bucket
struct genhash_entry ** buckets
genhash_comp_fn_t key_comp_func
genhash_val_fn_t key_val_func
genhash_free_fn_t key_free_func
genhash_copy_fn_t data_copy_func
genhash_free_fn_t data_free_func
genhash_copy_fn_t key_copy_func
bool(* valid)(const struct iterator *it)
void *(* get)(const struct iterator *it)
void(* next)(struct iterator *it)