32#define __INCLUDED_FROM_HTBL_C__
52H(
const void *p,
size_t l)
61 "Invalid hash table operation with key_sz %x, whereas the "
62 "hash table was created with key_sz %x. This most likely "
63 "indicates a data type error.",
64 (
unsigned)key_sz, (
unsigned)htbl->h.key_sz);
68htbl2_check_value_type(
size_t htbl_value_sz,
size_t value_sz)
71 "Invalid hash table operation with value_sz %x, whereas "
72 "the hash table was created with value_sz %x. This most "
73 "likely indicates a data type error.",
74 (
unsigned)value_sz, (
unsigned)htbl_value_sz);
78htbl2_check_types(
const htbl2_t REQ_PTR(htbl),
size_t key_sz,
size_t value_sz)
80 htbl2_check_key_type(htbl, key_sz);
81 htbl2_check_value_type(htbl->value_sz, value_sz);
85htbl_create_impl(
htbl_t *htbl,
size_t tbl_sz,
size_t key_sz,
bool multi_value)
90 ASSERT(tbl_sz <= ((
size_t)1 << ((
sizeof(
size_t) * 8) - 1)));
92 memset(htbl, 0,
sizeof (*htbl));
95 htbl->buckets =
safe_malloc(
sizeof (*htbl->buckets) * htbl->tbl_sz);
96 ASSERT(htbl->buckets != NULL);
97 for (
size_t i = 0; i < htbl->tbl_sz; i++) {
101 htbl->key_sz = key_sz;
102 htbl->multi_value = multi_value;
130 htbl_create_impl(htbl, tbl_sz, key_sz, multi_value);
135 size_t value_sz,
bool multi_value)
137 htbl_create_impl(&htbl->h, tbl_sz, key_sz, multi_value);
138 htbl->value_sz = value_sz;
157 ASSERT(htbl->num_values == 0);
158 ASSERT(htbl->buckets != NULL);
159 for (
size_t i = 0; i < htbl->tbl_sz; i++)
174 for (htbl_multi_value_t *mv =
list_head(&item->multi); mv;
177 func(mv->value, arg);
206 if (htbl->num_values == 0)
208 for (
size_t i = 0; i < htbl->tbl_sz; i++) {
210 item; item =
list_head(&htbl->buckets[i])) {
211 if (htbl->multi_value)
212 htbl_empty_multi_item(item, func, userinfo);
213 else if (func != NULL)
214 func(item->value, userinfo);
219 htbl->num_values = 0;
224 void (*func)(
void *value,
void *userinfo),
void *userinfo)
226 htbl2_check_value_type(htbl->value_sz, value_sz);
237 return (htbl->num_values);
241htbl2_count(
const htbl2_t *htbl)
244 return (htbl->h.num_values);
250 htbl_multi_value_t *mv =
safe_malloc(
sizeof (*mv));
251 ASSERT(htbl->multi_value);
259htbl_set_impl(
htbl_t REQ_PTR(htbl),
const void *key,
void *value,
264 list_t *bucket = &htbl->buckets[H(key, htbl->key_sz) &
271 if (memcmp(item->key, key, htbl->key_sz) == 0) {
272 if (htbl->multi_value)
273 htbl_multi_value_add(htbl, item, value);
279 item =
safe_calloc(
sizeof (*item) + htbl->key_sz - 1, 1);
280 item->value_sz = value_sz;
281 memcpy(item->key, key, htbl->key_sz);
282 if (htbl->multi_value) {
283 list_create(&item->multi, sizeof (htbl_multi_value_t),
284 offsetof(htbl_multi_value_t, node));
285 htbl_multi_value_add(htbl, item, value);
315 htbl_set_impl(htbl, key, value, SIZE_MAX);
320 void *value,
size_t value_sz)
322 htbl2_check_types(htbl, key_sz, value_sz);
323 htbl_set_impl(&htbl->h, key, value, value_sz);
346 list_t *bucket = &htbl->buckets[H(key, htbl->key_sz) &
351 if (memcmp(item->key, key, htbl->key_sz) == 0) {
353 if (htbl->multi_value) {
354 htbl_empty_multi_item(item, NULL, NULL);
360 ASSERT(htbl->num_values != 0);
370htbl2_remove(
htbl2_t REQ_PTR(htbl),
const void *key,
size_t key_sz,
373 htbl2_check_key_type(htbl, key_sz);
403 htbl_multi_value_t *list_item)
406 ASSERT(htbl->multi_value);
407 ASSERT(htbl->num_values != 0);
408 ASSERT(list_item != NULL);
419 &htbl->buckets[H(key, htbl->key_sz) & (htbl->tbl_sz - 1)];
427htbl2_remove_multi(
htbl2_t REQ_PTR(htbl),
const void *key,
size_t key_sz,
428 htbl2_multi_value_t *list_item)
430 htbl2_check_key_type(htbl, key_sz);
435htbl_lookup_common(
const htbl_t *htbl,
const void *key)
440 list_t *bucket = &htbl->buckets[H(key, htbl->key_sz) &
445 if (memcmp(item->key, key, htbl->key_sz) == 0)
465 ASSERT(!htbl->multi_value);
466 item = htbl_lookup_common(htbl, key);
467 return (item != NULL ? item->value : NULL);
472 size_t key_sz,
size_t value_sz)
474 htbl2_check_types(htbl, key_sz, value_sz);
495 ASSERT(htbl->multi_value);
496 item = htbl_lookup_common(htbl, key);
497 return (item != NULL ? &item->multi : NULL);
504 htbl2_check_key_type(htbl, key_sz);
522 void (*func)(
const void *key,
void *value,
void *userinfo),
void *userinfo)
526 for (
size_t i = 0; i < htbl->tbl_sz; i++) {
527 list_t *bucket = &htbl->buckets[i];
529 *next_item = NULL; item; item = next_item) {
535 if (htbl->multi_value) {
536 const list_t *ml = &item->multi;
537 for (htbl_multi_value_t *mv =
list_head(ml),
538 *mv_next = NULL; mv != NULL; mv = mv_next) {
540 func(item->key, mv->value, userinfo);
543 func(item->key, item->value, userinfo);
551 size_t key_sz,
size_t value_sz,
552 void (*func)(
const void *key,
void *value,
void *userinfo),
void *userinfo)
554 htbl2_check_types(htbl, key_sz, value_sz);
582 htbl2_check_value_type(mv->item->value_sz, SIZE_MAX);
587htbl2_value_multi(
const htbl2_multi_value_t *mv,
size_t value_sz)
590 htbl2_check_value_type(mv->item->value_sz, value_sz);
605 size_t result_sz = 0;
608 (
long unsigned)htbl->num_values);
609 for (
size_t i = 0; i < htbl->tbl_sz; i++) {
610 list_t *bucket = &htbl->buckets[i];
617 if (printable_keys) {
#define ASSERT_MSG(x, fmt,...)
#define ASSERT3U(x, op, y)
API_EXPORT uint64_t crc64(const void *input, size_t sz)
void append_format(char **str, size_t *sz, const char *format,...)
void htbl_foreach(const htbl_t *htbl, void(*func)(const void *key, void *value, void *userinfo), void *userinfo)
void htbl_empty(htbl_t *htbl, void(*func)(void *value, void *userinfo), void *userinfo)
void htbl_remove_multi(htbl_t *htbl, const void *key, htbl_multi_value_t *list_item)
void htbl_set(htbl_t *htbl, const void *key, void *value)
const list_t * htbl_lookup_multi(const htbl_t *htbl, const void *key)
void htbl_create(htbl_t *htbl, size_t tbl_sz, size_t key_sz, bool_t multi_value)
size_t htbl_count(const htbl_t *htbl)
void htbl_remove(htbl_t *htbl, const void *key, bool_t nil_ok)
void * htbl_value_multi(const htbl_multi_value_t *mv)
char * htbl_dump(const htbl_t *htbl, bool_t printable_keys)
void * htbl_lookup(const htbl_t *htbl, const void *key)
void htbl_destroy(htbl_t *htbl)
void list_destroy(list_t *)
void * list_head(const list_t *)
void list_create(list_t *, size_t, size_t)
void list_insert_head(list_t *, void *)
void * list_next(const list_t *, const void *)
size_t list_count(const list_t *)
void list_remove(list_t *, void *)
void * list_remove_head(list_t *)
static void * safe_calloc(size_t nmemb, size_t size)
static void * safe_malloc(size_t size)