72#define FULL_RATIO 0.75
102#define GENHASH_ITER(p) ((struct genhash_iter *) (p))
111 unsigned long result = 0;
113 for (; *vkey !=
'\0'; vkey++) {
117 result &= 0xFFFFFFFF;
126 return 0 == strcmp(vkey1, vkey2);
134 return fc_strdup(NULL != vkey ? vkey :
"");
161#define MIN_BUCKETS 29
166 static const size_t sizes[] = {
168 389, 769, 1543, 3079, 6151,
169 12289, 24593, 49157, 98317, 196613,
170 393241, 786433, 1572869, 3145739, 6291469,
171 12582917, 25165843, 50331653, 100663319, 201326611,
172 402653189, 805306457, 1610612741, 3221225473ul, 4294967291ul
174 const size_t *pframe = sizes, *pmid;
181 pmid = pframe + lpart;
182 if (*pmid < num_entries) {
184 fsize = fsize - lpart - 1;
212 log_debug(
"New genhash table with %lu buckets",
258 NULL, NULL, NULL, NULL,
317 for (; bucket < end; bucket++) {
318 for (iter = *bucket; NULL != iter; iter =
next) {
319 slot = new_buckets + (iter->
hash_val % new_nbuckets);
327 pgenhash->
buckets = new_buckets;
338#define genhash_maybe_expand(htab) genhash_maybe_resize((htab), TRUE)
339#define genhash_maybe_shrink(htab) genhash_maybe_resize((htab), FALSE)
342 size_t limit, new_nbuckets;
344 if (!expandingp && pgenhash->
no_shrink) {
364 log_debug(
"%s genhash (entries = %lu, buckets = %lu, new = %lu, "
366 (new_nbuckets < pgenhash->num_buckets ?
"Shrinking"
368 ?
"Expanding" :
"Rehashing")),
371 (
long unsigned) new_nbuckets,
372 expandingp ?
"up":
"down", (
long unsigned) limit);
387 return ((intptr_t)
key);
404 if (NULL != key_comp_func) {
405 for (; NULL != *slot; slot = &(*slot)->
next) {
407 && key_comp_func((*slot)->key,
key)) {
412 for (; NULL != *slot; slot = &(*slot)->
next) {
413 if (
key == (*slot)->key) {
438 void **pkey,
void **
data)
455 const void *
key,
const void *
data,
492 const void *
key,
const void *
data)
552 new_genhash =
fc_malloc(
sizeof(*new_genhash));
555 *new_genhash = *pgenhash;
559 sizeof(*new_genhash->
buckets));
562 src_bucket = pgenhash->
buckets;
564 dest_bucket = new_genhash->
buckets;
566 for (; src_bucket < end; src_bucket++, dest_bucket++) {
567 dest_slot = dest_bucket;
568 for (src_iter = *src_bucket; NULL != src_iter;
569 src_iter = src_iter->
next) {
572 dest_slot = &(*dest_slot)->
next;
590 for (; bucket < end; bucket++) {
591 while (NULL != *bucket) {
648 const void *
data,
void **old_pkey,
715 void **deleted_pkey,
void **deleted_pdata)
742 const struct genhash *pgenhash2)
751 const struct genhash *pgenhash2,
754 struct genhash_entry *
const *bucket1, *
const *max1, *
const *slot2;
758 if (pgenhash1 == pgenhash2) {
760 }
else if (NULL == pgenhash1 || NULL == pgenhash2) {
776 for (; bucket1 < max1; bucket1++) {
777 for (iter1 = *bucket1; NULL != iter1; iter1 = iter1->
next) {
780 || (iter1->
data != (*slot2)->data
781 && (NULL == data_comp_func
782 || !data_comp_func(iter1->
data, (*slot2)->data)))) {
831 if (NULL != *iter->
bucket) {
862 const struct genhash *pgenhash,
865 if (NULL == pgenhash) {
877 if (NULL != *iter->
bucket) {
892 const struct genhash *pgenhash)
901 const struct genhash *pgenhash)
910 const struct genhash *pgenhash)
static struct iterator * genhash_iter_init_common(struct genhash_iter *iter, const struct genhash *pgenhash, void *(*get)(const struct iterator *))
#define genhash_maybe_expand(htab)
struct iterator * genhash_iter_init(struct genhash_iter *iter, const struct genhash *pgenhash)
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)
static void genhash_iter_next(struct iterator *genhash_iter)
bool genhash_insert(struct genhash *pgenhash, const void *key, const void *data)
static void * genhash_iter_get(const struct iterator *genhash_iter)
bool genhash_str_comp_func(const char *vkey1, const char *vkey2)
bool genhashes_are_equal(const struct genhash *pgenhash1, const struct genhash *pgenhash2)
#define genhash_maybe_shrink(htab)
static void genhash_slot_free(struct genhash *pgenhash, struct genhash_entry **slot)
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)
static struct genhash_entry ** genhash_slot_lookup(const struct genhash *pgenhash, const void *key, genhash_val_t hash_val)
size_t genhash_size(const struct genhash *pgenhash)
static bool genhash_iter_valid(const struct iterator *genhash_iter)
void genhash_destroy(struct genhash *pgenhash)
static void genhash_slot_get(struct genhash_entry *const *slot, void **pkey, void **data)
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)
size_t genhash_capacity(const struct genhash *pgenhash)
void genhash_clear(struct genhash *pgenhash)
struct iterator * genhash_value_iter_init(struct genhash_iter *iter, const struct genhash *pgenhash)
size_t genhash_iter_sizeof(void)
static void genhash_default_get(void **pkey, void **data)
bool genhash_lookup(const struct genhash *pgenhash, const void *key, void **pdata)
bool genhashes_are_equal_full(const struct genhash *pgenhash1, const struct genhash *pgenhash2, genhash_comp_fn_t data_comp_func)
static genhash_val_t genhash_val_calc(const struct genhash *pgenhash, const void *key)
static void genhash_slot_create(struct genhash *pgenhash, struct genhash_entry **slot, const void *key, const void *data, genhash_val_t hash_val)
bool genhash_remove(struct genhash *pgenhash, const void *key)
static void genhash_slot_set(struct genhash *pgenhash, struct genhash_entry **slot, const void *key, const void *data)
bool genhash_replace_full(struct genhash *pgenhash, const void *key, const void *data, void **old_pkey, void **old_pdata)
struct genhash * genhash_new(genhash_val_fn_t key_val_func, genhash_comp_fn_t key_comp_func)
struct iterator * genhash_key_iter_init(struct genhash_iter *iter, const struct genhash *pgenhash)
struct genhash * genhash_new_nentries(genhash_val_fn_t key_val_func, genhash_comp_fn_t key_comp_func, size_t nentries)
void * genhash_iter_key(const struct iterator *genhash_iter)
static void genhash_resize_table(struct genhash *pgenhash, size_t new_nbuckets)
void genhash_str_free_func(char *vkey)
char * genhash_str_copy_func(const char *vkey)
bool genhash_replace(struct genhash *pgenhash, const void *key, const void *data)
struct genhash * genhash_copy(const struct genhash *pgenhash)
genhash_val_t genhash_str_val_func(const char *vkey)
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)
bool genhash_remove_full(struct genhash *pgenhash, const void *key, void **deleted_pkey, void **deleted_pdata)
void * genhash_iter_value(const struct iterator *genhash_iter)
genhash_val_t(* genhash_val_fn_t)(const void *)
bool(* genhash_comp_fn_t)(const void *, const void *)
void(* genhash_free_fn_t)(void *)
void *(* genhash_copy_fn_t)(const void *)
unsigned int genhash_val_t
struct iterator * invalid_iter_init(struct iterator *it)
#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,...)
#define fc_calloc(n, esz)
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)