hash table FEATURE make hash table public
diff --git a/src/common.h b/src/common.h
index bb4e49d..82b0603 100644
--- a/src/common.h
+++ b/src/common.h
@@ -23,7 +23,7 @@
#include "compat.h"
#include "config.h"
#include "context.h"
-#include "hash_table.h"
+#include "hash_table_internal.h"
#include "log.h"
#include "schema_compile.h"
#include "set.h"
diff --git a/src/context.c b/src/context.c
index b0d8dcc..7a14203 100644
--- a/src/context.c
+++ b/src/context.c
@@ -680,25 +680,25 @@
while ((mod = ly_ctx_get_module_iter(ctx, &i))) {
/* name */
- hash = dict_hash_multi(hash, mod->name, strlen(mod->name));
+ hash = lyht_hash_multi(hash, mod->name, strlen(mod->name));
/* revision */
if (mod->revision) {
- hash = dict_hash_multi(hash, mod->revision, strlen(mod->revision));
+ hash = lyht_hash_multi(hash, mod->revision, strlen(mod->revision));
}
/* enabled features */
while ((f = lysp_feature_next(f, mod->parsed, &fi))) {
if (f->flags & LYS_FENABLED) {
- hash = dict_hash_multi(hash, f->name, strlen(f->name));
+ hash = lyht_hash_multi(hash, f->name, strlen(f->name));
}
}
/* imported/implemented */
- hash = dict_hash_multi(hash, (char *)&mod->implemented, sizeof mod->implemented);
+ hash = lyht_hash_multi(hash, (char *)&mod->implemented, sizeof mod->implemented);
}
- hash = dict_hash_multi(hash, NULL, 0);
+ hash = lyht_hash_multi(hash, NULL, 0);
return hash;
}
diff --git a/src/dict.c b/src/dict.c
new file mode 100644
index 0000000..07631f6
--- /dev/null
+++ b/src/dict.c
@@ -0,0 +1,265 @@
+/**
+ * @file dict.c
+ * @author Radek Krejci <rkrejci@cesnet.cz>
+ * @author Michal Vasko <mvasko@cesnet.cz>
+ * @brief libyang dictionary for storing strings
+ *
+ * Copyright (c) 2015 - 2023 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ */
+
+#include "dict.h"
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+#include "compat.h"
+#include "log.h"
+
+/* starting size of the dictionary */
+#define LYDICT_MIN_SIZE 1024
+
+/**
+ * @brief Comparison callback for dictionary's hash table
+ *
+ * Implementation of ::lyht_value_equal_cb.
+ */
+static ly_bool
+lydict_val_eq(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *cb_data)
+{
+ LY_CHECK_ARG_RET(NULL, val1_p, val2_p, cb_data, 0);
+
+ const char *str1 = ((struct ly_dict_rec *)val1_p)->value;
+ const char *str2 = ((struct ly_dict_rec *)val2_p)->value;
+
+ LY_CHECK_ERR_RET(!str1, LOGARG(NULL, val1_p), 0);
+ LY_CHECK_ERR_RET(!str2, LOGARG(NULL, val2_p), 0);
+
+ if (strncmp(str1, str2, *(size_t *)cb_data) == 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+lydict_init(struct ly_dict *dict)
+{
+ LY_CHECK_ARG_RET(NULL, dict, );
+
+ dict->hash_tab = lyht_new(LYDICT_MIN_SIZE, sizeof(struct ly_dict_rec), lydict_val_eq, NULL, 1);
+ LY_CHECK_ERR_RET(!dict->hash_tab, LOGINT(NULL), );
+ pthread_mutex_init(&dict->lock, NULL);
+}
+
+void
+lydict_clean(struct ly_dict *dict)
+{
+ struct ly_dict_rec *dict_rec = NULL;
+ struct ly_ht_rec *rec = NULL;
+
+ LY_CHECK_ARG_RET(NULL, dict, );
+
+ for (uint32_t i = 0; i < dict->hash_tab->size; i++) {
+ /* get ith record */
+ rec = (struct ly_ht_rec *)&dict->hash_tab->recs[i * dict->hash_tab->rec_size];
+ if (rec->hits == 1) {
+ /*
+ * this should not happen, all records inserted into
+ * dictionary are supposed to be removed using lydict_remove()
+ * before calling lydict_clean()
+ */
+ dict_rec = (struct ly_dict_rec *)rec->val;
+ LOGWRN(NULL, "String \"%s\" not freed from the dictionary, refcount %d", dict_rec->value, dict_rec->refcount);
+ /* if record wasn't removed before free string allocated for that record */
+#ifdef NDEBUG
+ free(dict_rec->value);
+#endif
+ }
+ }
+
+ /* free table and destroy mutex */
+ lyht_free(dict->hash_tab, NULL);
+ pthread_mutex_destroy(&dict->lock);
+}
+
+static ly_bool
+lydict_resize_val_eq(void *val1_p, void *val2_p, ly_bool mod, void *cb_data)
+{
+ LY_CHECK_ARG_RET(NULL, val1_p, val2_p, 0);
+
+ const char *str1 = ((struct ly_dict_rec *)val1_p)->value;
+ const char *str2 = ((struct ly_dict_rec *)val2_p)->value;
+
+ LY_CHECK_ERR_RET(!str1, LOGARG(NULL, val1_p), 0);
+ LY_CHECK_ERR_RET(!str2, LOGARG(NULL, val2_p), 0);
+
+ if (mod) {
+ /* used when inserting new values */
+ if (strcmp(str1, str2) == 0) {
+ return 1;
+ }
+ } else {
+ /* used when finding the original value again in the resized table */
+ return lydict_val_eq(val1_p, val2_p, mod, cb_data);
+ }
+
+ return 0;
+}
+
+LIBYANG_API_DEF LY_ERR
+lydict_remove(const struct ly_ctx *ctx, const char *value)
+{
+ LY_ERR ret = LY_SUCCESS;
+ size_t len;
+ uint32_t hash;
+ struct ly_dict_rec rec, *match = NULL;
+ char *val_p;
+
+ if (!ctx || !value) {
+ return LY_SUCCESS;
+ }
+
+ LOGDBG(LY_LDGDICT, "removing \"%s\"", value);
+
+ len = strlen(value);
+ hash = lyht_hash(value, len);
+
+ /* create record for lyht_find call */
+ rec.value = (char *)value;
+ rec.refcount = 0;
+
+ pthread_mutex_lock((pthread_mutex_t *)&ctx->dict.lock);
+ /* set len as data for compare callback */
+ lyht_set_cb_data(ctx->dict.hash_tab, (void *)&len);
+ /* check if value is already inserted */
+ ret = lyht_find(ctx->dict.hash_tab, &rec, hash, (void **)&match);
+
+ if (ret == LY_SUCCESS) {
+ LY_CHECK_ERR_GOTO(!match, LOGINT(ctx), finish);
+
+ /* if value is already in dictionary, decrement reference counter */
+ match->refcount--;
+ if (match->refcount == 0) {
+ /*
+ * remove record
+ * save pointer to stored string before lyht_remove to
+ * free it after it is removed from hash table
+ */
+ val_p = match->value;
+ ret = lyht_remove_with_resize_cb(ctx->dict.hash_tab, &rec, hash, lydict_resize_val_eq);
+ free(val_p);
+ LY_CHECK_ERR_GOTO(ret, LOGINT(ctx), finish);
+ }
+ } else if (ret == LY_ENOTFOUND) {
+ LOGERR(ctx, LY_ENOTFOUND, "Value \"%s\" was not found in the dictionary.", value);
+ } else {
+ LOGINT(ctx);
+ }
+
+finish:
+ pthread_mutex_unlock((pthread_mutex_t *)&ctx->dict.lock);
+ return ret;
+}
+
+LY_ERR
+dict_insert(const struct ly_ctx *ctx, char *value, size_t len, ly_bool zerocopy, const char **str_p)
+{
+ LY_ERR ret = LY_SUCCESS;
+ struct ly_dict_rec *match = NULL, rec;
+ uint32_t hash;
+
+ LOGDBG(LY_LDGDICT, "inserting \"%.*s\"", (int)len, value);
+
+ hash = lyht_hash(value, len);
+ /* set len as data for compare callback */
+ lyht_set_cb_data(ctx->dict.hash_tab, (void *)&len);
+ /* create record for lyht_insert */
+ rec.value = value;
+ rec.refcount = 1;
+
+ ret = lyht_insert_with_resize_cb(ctx->dict.hash_tab, (void *)&rec, hash, lydict_resize_val_eq, (void **)&match);
+ if (ret == LY_EEXIST) {
+ match->refcount++;
+ if (zerocopy) {
+ free(value);
+ }
+ ret = LY_SUCCESS;
+ } else if (ret == LY_SUCCESS) {
+ if (!zerocopy) {
+ /*
+ * allocate string for new record
+ * record is already inserted in hash table
+ */
+ match->value = malloc(sizeof *match->value * (len + 1));
+ LY_CHECK_ERR_RET(!match->value, LOGMEM(ctx), LY_EMEM);
+ if (len) {
+ memcpy(match->value, value, len);
+ }
+ match->value[len] = '\0';
+ }
+ } else {
+ /* lyht_insert returned error */
+ if (zerocopy) {
+ free(value);
+ }
+ return ret;
+ }
+
+ if (str_p) {
+ *str_p = match->value;
+ }
+
+ return ret;
+}
+
+LIBYANG_API_DEF LY_ERR
+lydict_insert(const struct ly_ctx *ctx, const char *value, size_t len, const char **str_p)
+{
+ LY_ERR result;
+
+ LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL);
+
+ if (!value) {
+ *str_p = NULL;
+ return LY_SUCCESS;
+ }
+
+ if (!len) {
+ len = strlen(value);
+ }
+
+ pthread_mutex_lock((pthread_mutex_t *)&ctx->dict.lock);
+ result = dict_insert(ctx, (char *)value, len, 0, str_p);
+ pthread_mutex_unlock((pthread_mutex_t *)&ctx->dict.lock);
+
+ return result;
+}
+
+LIBYANG_API_DEF LY_ERR
+lydict_insert_zc(const struct ly_ctx *ctx, char *value, const char **str_p)
+{
+ LY_ERR result;
+
+ LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL);
+
+ if (!value) {
+ *str_p = NULL;
+ return LY_SUCCESS;
+ }
+
+ pthread_mutex_lock((pthread_mutex_t *)&ctx->dict.lock);
+ result = dict_insert(ctx, value, strlen(value), 1, str_p);
+ pthread_mutex_unlock((pthread_mutex_t *)&ctx->dict.lock);
+
+ return result;
+}
diff --git a/src/hash_table.c b/src/hash_table.c
index 90915f0..0523d8e 100644
--- a/src/hash_table.c
+++ b/src/hash_table.c
@@ -1,9 +1,10 @@
/**
* @file hash_table.c
* @author Radek Krejci <rkrejci@cesnet.cz>
- * @brief libyang dictionary for storing strings and generic hash table
+ * @author Michal Vasko <mvasko@cesnet.cz>
+ * @brief libyang generic hash table implementation
*
- * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
+ * Copyright (c) 2015 - 2023 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
@@ -25,80 +26,8 @@
#include "dict.h"
#include "log.h"
-#define LYDICT_MIN_SIZE 1024
-
-/**
- * @brief Comparison callback for dictionary's hash table
- *
- * Implementation of ::lyht_value_equal_cb.
- */
-static ly_bool
-lydict_val_eq(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *cb_data)
-{
- LY_CHECK_ARG_RET(NULL, val1_p, val2_p, cb_data, 0);
-
- const char *str1 = ((struct ly_dict_rec *)val1_p)->value;
- const char *str2 = ((struct ly_dict_rec *)val2_p)->value;
-
- LY_CHECK_ERR_RET(!str1, LOGARG(NULL, val1_p), 0);
- LY_CHECK_ERR_RET(!str2, LOGARG(NULL, val2_p), 0);
-
- if (strncmp(str1, str2, *(size_t *)cb_data) == 0) {
- return 1;
- }
-
- return 0;
-}
-
-void
-lydict_init(struct ly_dict *dict)
-{
- LY_CHECK_ARG_RET(NULL, dict, );
-
- dict->hash_tab = lyht_new(LYDICT_MIN_SIZE, sizeof(struct ly_dict_rec), lydict_val_eq, NULL, 1);
- LY_CHECK_ERR_RET(!dict->hash_tab, LOGINT(NULL), );
- pthread_mutex_init(&dict->lock, NULL);
-}
-
-void
-lydict_clean(struct ly_dict *dict)
-{
- struct ly_dict_rec *dict_rec = NULL;
- struct ly_ht_rec *rec = NULL;
-
- LY_CHECK_ARG_RET(NULL, dict, );
-
- for (uint32_t i = 0; i < dict->hash_tab->size; i++) {
- /* get ith record */
- rec = (struct ly_ht_rec *)&dict->hash_tab->recs[i * dict->hash_tab->rec_size];
- if (rec->hits == 1) {
- /*
- * this should not happen, all records inserted into
- * dictionary are supposed to be removed using lydict_remove()
- * before calling lydict_clean()
- */
- dict_rec = (struct ly_dict_rec *)rec->val;
- LOGWRN(NULL, "String \"%s\" not freed from the dictionary, refcount %d", dict_rec->value, dict_rec->refcount);
- /* if record wasn't removed before free string allocated for that record */
-#ifdef NDEBUG
- free(dict_rec->value);
-#endif
- }
- }
-
- /* free table and destroy mutex */
- lyht_free(dict->hash_tab, NULL);
- pthread_mutex_destroy(&dict->lock);
-}
-
-/*
- * Usage:
- * - init hash to 0
- * - repeatedly call dict_hash_multi(), provide hash from the last call
- * - call dict_hash_multi() with key_part = NULL to finish the hash
- */
-uint32_t
-dict_hash_multi(uint32_t hash, const char *key_part, size_t len)
+LIBYANG_API_DEF uint32_t
+lyht_hash_multi(uint32_t hash, const char *key_part, size_t len)
{
uint32_t i;
@@ -117,191 +46,13 @@
return hash;
}
-/*
- * Bob Jenkin's one-at-a-time hash
- * http://www.burtleburtle.net/bob/hash/doobs.html
- *
- * Spooky hash is faster, but it works only for little endian architectures.
- */
-uint32_t
-dict_hash(const char *key, size_t len)
+LIBYANG_API_DEF uint32_t
+lyht_hash(const char *key, size_t len)
{
uint32_t hash;
- hash = dict_hash_multi(0, key, len);
- return dict_hash_multi(hash, NULL, len);
-}
-
-static ly_bool
-lydict_resize_val_eq(void *val1_p, void *val2_p, ly_bool mod, void *cb_data)
-{
- LY_CHECK_ARG_RET(NULL, val1_p, val2_p, 0);
-
- const char *str1 = ((struct ly_dict_rec *)val1_p)->value;
- const char *str2 = ((struct ly_dict_rec *)val2_p)->value;
-
- LY_CHECK_ERR_RET(!str1, LOGARG(NULL, val1_p), 0);
- LY_CHECK_ERR_RET(!str2, LOGARG(NULL, val2_p), 0);
-
- if (mod) {
- /* used when inserting new values */
- if (strcmp(str1, str2) == 0) {
- return 1;
- }
- } else {
- /* used when finding the original value again in the resized table */
- return lydict_val_eq(val1_p, val2_p, mod, cb_data);
- }
-
- return 0;
-}
-
-LIBYANG_API_DEF LY_ERR
-lydict_remove(const struct ly_ctx *ctx, const char *value)
-{
- LY_ERR ret = LY_SUCCESS;
- size_t len;
- uint32_t hash;
- struct ly_dict_rec rec, *match = NULL;
- char *val_p;
-
- if (!ctx || !value) {
- return LY_SUCCESS;
- }
-
- LOGDBG(LY_LDGDICT, "removing \"%s\"", value);
-
- len = strlen(value);
- hash = dict_hash(value, len);
-
- /* create record for lyht_find call */
- rec.value = (char *)value;
- rec.refcount = 0;
-
- pthread_mutex_lock((pthread_mutex_t *)&ctx->dict.lock);
- /* set len as data for compare callback */
- lyht_set_cb_data(ctx->dict.hash_tab, (void *)&len);
- /* check if value is already inserted */
- ret = lyht_find(ctx->dict.hash_tab, &rec, hash, (void **)&match);
-
- if (ret == LY_SUCCESS) {
- LY_CHECK_ERR_GOTO(!match, LOGINT(ctx), finish);
-
- /* if value is already in dictionary, decrement reference counter */
- match->refcount--;
- if (match->refcount == 0) {
- /*
- * remove record
- * save pointer to stored string before lyht_remove to
- * free it after it is removed from hash table
- */
- val_p = match->value;
- ret = lyht_remove_with_resize_cb(ctx->dict.hash_tab, &rec, hash, lydict_resize_val_eq);
- free(val_p);
- LY_CHECK_ERR_GOTO(ret, LOGINT(ctx), finish);
- }
- } else if (ret == LY_ENOTFOUND) {
- LOGERR(ctx, LY_ENOTFOUND, "Value \"%s\" was not found in the dictionary.", value);
- } else {
- LOGINT(ctx);
- }
-
-finish:
- pthread_mutex_unlock((pthread_mutex_t *)&ctx->dict.lock);
- return ret;
-}
-
-LY_ERR
-dict_insert(const struct ly_ctx *ctx, char *value, size_t len, ly_bool zerocopy, const char **str_p)
-{
- LY_ERR ret = LY_SUCCESS;
- struct ly_dict_rec *match = NULL, rec;
- uint32_t hash;
-
- LOGDBG(LY_LDGDICT, "inserting \"%.*s\"", (int)len, value);
-
- hash = dict_hash(value, len);
- /* set len as data for compare callback */
- lyht_set_cb_data(ctx->dict.hash_tab, (void *)&len);
- /* create record for lyht_insert */
- rec.value = value;
- rec.refcount = 1;
-
- ret = lyht_insert_with_resize_cb(ctx->dict.hash_tab, (void *)&rec, hash, lydict_resize_val_eq, (void **)&match);
- if (ret == LY_EEXIST) {
- match->refcount++;
- if (zerocopy) {
- free(value);
- }
- ret = LY_SUCCESS;
- } else if (ret == LY_SUCCESS) {
- if (!zerocopy) {
- /*
- * allocate string for new record
- * record is already inserted in hash table
- */
- match->value = malloc(sizeof *match->value * (len + 1));
- LY_CHECK_ERR_RET(!match->value, LOGMEM(ctx), LY_EMEM);
- if (len) {
- memcpy(match->value, value, len);
- }
- match->value[len] = '\0';
- }
- } else {
- /* lyht_insert returned error */
- if (zerocopy) {
- free(value);
- }
- return ret;
- }
-
- if (str_p) {
- *str_p = match->value;
- }
-
- return ret;
-}
-
-LIBYANG_API_DEF LY_ERR
-lydict_insert(const struct ly_ctx *ctx, const char *value, size_t len, const char **str_p)
-{
- LY_ERR result;
-
- LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL);
-
- if (!value) {
- *str_p = NULL;
- return LY_SUCCESS;
- }
-
- if (!len) {
- len = strlen(value);
- }
-
- pthread_mutex_lock((pthread_mutex_t *)&ctx->dict.lock);
- result = dict_insert(ctx, (char *)value, len, 0, str_p);
- pthread_mutex_unlock((pthread_mutex_t *)&ctx->dict.lock);
-
- return result;
-}
-
-LIBYANG_API_DEF LY_ERR
-lydict_insert_zc(const struct ly_ctx *ctx, char *value, const char **str_p)
-{
- LY_ERR result;
-
- LY_CHECK_ARG_RET(ctx, ctx, str_p, LY_EINVAL);
-
- if (!value) {
- *str_p = NULL;
- return LY_SUCCESS;
- }
-
- pthread_mutex_lock((pthread_mutex_t *)&ctx->dict.lock);
- result = dict_insert(ctx, value, strlen(value), 1, str_p);
- pthread_mutex_unlock((pthread_mutex_t *)&ctx->dict.lock);
-
- return result;
+ hash = lyht_hash_multi(0, key, len);
+ return lyht_hash_multi(hash, NULL, len);
}
struct ly_ht_rec *
@@ -310,7 +61,7 @@
return (struct ly_ht_rec *)&recs[idx * rec_size];
}
-struct ly_ht *
+LIBYANG_API_DEF struct ly_ht *
lyht_new(uint32_t size, uint16_t val_size, lyht_value_equal_cb val_equal, void *cb_data, uint16_t resize)
{
struct ly_ht *ht;
@@ -342,7 +93,7 @@
return ht;
}
-lyht_value_equal_cb
+LIBYANG_API_DEF lyht_value_equal_cb
lyht_set_cb(struct ly_ht *ht, lyht_value_equal_cb new_val_equal)
{
lyht_value_equal_cb prev;
@@ -352,7 +103,7 @@
return prev;
}
-void *
+LIBYANG_API_DEF void *
lyht_set_cb_data(struct ly_ht *ht, void *new_cb_data)
{
void *prev;
@@ -362,7 +113,7 @@
return prev;
}
-struct ly_ht *
+LIBYANG_API_DEF struct ly_ht *
lyht_dup(const struct ly_ht *orig)
{
struct ly_ht *ht;
@@ -380,7 +131,7 @@
return ht;
}
-void
+LIBYANG_API_DEF void
lyht_free(struct ly_ht *ht, void (*val_free)(void *val_p))
{
struct ly_ht_rec *rec;
@@ -621,7 +372,7 @@
return LY_ENOTFOUND;
}
-LY_ERR
+LIBYANG_API_DEF LY_ERR
lyht_find(struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p)
{
struct ly_ht_rec *rec;
@@ -634,7 +385,7 @@
return rec ? LY_SUCCESS : LY_ENOTFOUND;
}
-LY_ERR
+LIBYANG_API_DEF LY_ERR
lyht_find_next_with_collision_cb(struct ly_ht *ht, void *val_p, uint32_t hash,
lyht_value_equal_cb collision_val_equal, void **match_p)
{
@@ -680,13 +431,13 @@
return LY_ENOTFOUND;
}
-LY_ERR
+LIBYANG_API_DEF LY_ERR
lyht_find_next(struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p)
{
return lyht_find_next_with_collision_cb(ht, val_p, hash, NULL, match_p);
}
-LY_ERR
+LIBYANG_API_DEF LY_ERR
lyht_insert_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash, lyht_value_equal_cb resize_val_equal,
void **match_p)
{
@@ -773,13 +524,13 @@
return ret;
}
-LY_ERR
+LIBYANG_API_DEF LY_ERR
lyht_insert(struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p)
{
return lyht_insert_with_resize_cb(ht, val_p, hash, NULL, match_p);
}
-LY_ERR
+LIBYANG_API_DEF LY_ERR
lyht_remove_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash, lyht_value_equal_cb resize_val_equal)
{
struct ly_ht_rec *rec, *crec;
@@ -862,13 +613,13 @@
return ret;
}
-LY_ERR
+LIBYANG_API_DEF LY_ERR
lyht_remove(struct ly_ht *ht, void *val_p, uint32_t hash)
{
return lyht_remove_with_resize_cb(ht, val_p, hash, NULL);
}
-uint32_t
+LIBYANG_API_DEF uint32_t
lyht_get_fixed_size(uint32_t item_count)
{
uint32_t i, size = 0;
diff --git a/src/hash_table.h b/src/hash_table.h
index 170f5b9..c45a6da 100644
--- a/src/hash_table.h
+++ b/src/hash_table.h
@@ -4,7 +4,7 @@
* @author Michal Vasko <mvasko@cesnet.cz>
* @brief libyang hash table
*
- * Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
+ * Copyright (c) 2015 - 2023 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
@@ -20,6 +20,10 @@
#include <stddef.h>
#include <stdint.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "compat.h"
#include "log.h"
@@ -28,15 +32,29 @@
*
* Usage:
* - init hash to 0
- * - repeatedly call ::dict_hash_multi(), provide hash from the last call
- * - call ::dict_hash_multi() with key_part = NULL to finish the hash
+ * - repeatedly call ::lyht_hash_multi(), provide hash from the last call
+ * - call ::lyht_hash_multi() with key_part = NULL to finish the hash
+ *
+ * @param[in] hash Previous hash.
+ * @param[in] key_part Next key to hash,
+ * @param[in] len Length of @p key_part.
+ * @return Hash with the next key.
*/
-uint32_t dict_hash_multi(uint32_t hash, const char *key_part, size_t len);
+LIBYANG_API_DECL uint32_t lyht_hash_multi(uint32_t hash, const char *key_part, size_t len);
/**
* @brief Compute hash from a string.
+ *
+ * Bob Jenkin's one-at-a-time hash
+ * http://www.burtleburtle.net/bob/hash/doobs.html
+ *
+ * Spooky hash is faster, but it works only for little endian architectures.
+ *
+ * @param[in] key Key to hash.
+ * @param[in] len Length of @p key.
+ * @return Hash of the key.
*/
-uint32_t dict_hash(const char *key, size_t len);
+LIBYANG_API_DECL uint32_t lyht_hash(const char *key, size_t len);
/**
* @brief Callback for checking hash table values equivalence.
@@ -49,82 +67,6 @@
*/
typedef ly_bool (*lyht_value_equal_cb)(void *val1_p, void *val2_p, ly_bool mod, void *cb_data);
-/** reference value for 100% */
-#define LYHT_HUNDRED_PERCENTAGE 100
-
-/** when the table is at least this much percent full, it is enlarged (double the size) */
-#define LYHT_ENLARGE_PERCENTAGE 75
-
-/** only once the table is this much percent full, enable shrinking */
-#define LYHT_FIRST_SHRINK_PERCENTAGE 50
-
-/** when the table is less than this much percent full, it is shrunk (half the size) */
-#define LYHT_SHRINK_PERCENTAGE 25
-
-/** when the table has less than this much percent empty records, it is rehashed to get rid of all the invalid records */
-#define LYHT_REHASH_PERCENTAGE 2
-
-/** never shrink beyond this size */
-#define LYHT_MIN_SIZE 8
-
-/**
- * @brief Generic hash table record.
- */
-struct ly_ht_rec {
- uint32_t hash; /* hash of the value */
- int32_t hits; /* collision/overflow value count - 1 (a filled entry has 1 hit,
- * special value -1 means a deleted record) */
- unsigned char val[1]; /* arbitrary-size value */
-} _PACKED;
-
-/**
- * @brief (Very) generic hash table.
- *
- * Hash table with open addressing collision resolution and
- * linear probing of interval 1 (next free record is used).
- * Removal is lazy (removed records are only marked), but
- * if possible, they are fully emptied.
- */
-struct ly_ht {
- uint32_t used; /* number of values stored in the hash table (filled records) */
- uint32_t size; /* always holds 2^x == size (is power of 2), actually number of records allocated */
- uint32_t invalid; /* number of invalid records (deleted) */
- lyht_value_equal_cb val_equal; /* callback for testing value equivalence */
- void *cb_data; /* user data callback arbitrary value */
- uint16_t resize; /* 0 - resizing is disabled, *
- * 1 - enlarging is enabled, *
- * 2 - both shrinking and enlarging is enabled */
- uint16_t rec_size; /* real size (in bytes) of one record for accessing recs array */
- unsigned char *recs; /* pointer to the hash table itself (array of struct ht_rec) */
-};
-
-struct ly_dict_rec {
- char *value;
- uint32_t refcount;
-};
-
-/**
- * dictionary to store repeating strings
- */
-struct ly_dict {
- struct ly_ht *hash_tab;
- pthread_mutex_t lock;
-};
-
-/**
- * @brief Initiate content (non-zero values) of the dictionary
- *
- * @param[in] dict Dictionary table to initiate
- */
-void lydict_init(struct ly_dict *dict);
-
-/**
- * @brief Cleanup the dictionary content
- *
- * @param[in] dict Dictionary table to cleanup
- */
-void lydict_clean(struct ly_dict *dict);
-
/**
* @brief Create new hash table.
*
@@ -135,7 +77,8 @@
* @param[in] resize Whether to resize the table on too few/too many records taken.
* @return Empty hash table, NULL on error.
*/
-struct ly_ht *lyht_new(uint32_t size, uint16_t val_size, lyht_value_equal_cb val_equal, void *cb_data, uint16_t resize);
+LIBYANG_API_DECL struct ly_ht *lyht_new(uint32_t size, uint16_t val_size, lyht_value_equal_cb val_equal, void *cb_data,
+ uint16_t resize);
/**
* @brief Set hash table value equal callback.
@@ -144,7 +87,7 @@
* @param[in] new_val_equal New callback for checking value equivalence.
* @return Previous callback for checking value equivalence.
*/
-lyht_value_equal_cb lyht_set_cb(struct ly_ht *ht, lyht_value_equal_cb new_val_equal);
+LIBYANG_API_DECL lyht_value_equal_cb lyht_set_cb(struct ly_ht *ht, lyht_value_equal_cb new_val_equal);
/**
* @brief Set hash table value equal callback user data.
@@ -153,7 +96,7 @@
* @param[in] new_cb_data New data for values callback.
* @return Previous data for values callback.
*/
-void *lyht_set_cb_data(struct ly_ht *ht, void *new_cb_data);
+LIBYANG_API_DECL void *lyht_set_cb_data(struct ly_ht *ht, void *new_cb_data);
/**
* @brief Make a duplicate of an existing hash table.
@@ -161,7 +104,7 @@
* @param[in] orig Original hash table to duplicate.
* @return Duplicated hash table @p orig, NULL on error.
*/
-struct ly_ht *lyht_dup(const struct ly_ht *orig);
+LIBYANG_API_DECL struct ly_ht *lyht_dup(const struct ly_ht *orig);
/**
* @brief Free a hash table.
@@ -169,7 +112,7 @@
* @param[in] ht Hash table to be freed.
* @param[in] val_free Optional callback for freeing all the stored values, @p val_p is a pointer to a stored value.
*/
-void lyht_free(struct ly_ht *ht, void (*val_free)(void *val_p));
+LIBYANG_API_DECL void lyht_free(struct ly_ht *ht, void (*val_free)(void *val_p));
/**
* @brief Find a value in a hash table.
@@ -181,7 +124,7 @@
* @return LY_SUCCESS if value was found,
* @return LY_ENOTFOUND if not found.
*/
-LY_ERR lyht_find(struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p);
+LIBYANG_API_DECL LY_ERR lyht_find(struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p);
/**
* @brief Find another equal value in the hash table.
@@ -193,7 +136,7 @@
* @return LY_SUCCESS if value was found,
* @return LY_ENOTFOUND if not found.
*/
-LY_ERR lyht_find_next(struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p);
+LIBYANG_API_DECL LY_ERR lyht_find_next(struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p);
/**
* @brief Find another equal value in the hash table. Same functionality as ::lyht_find_next()
@@ -207,7 +150,7 @@
* @return LY_SUCCESS if value was found,
* @return LY_ENOTFOUND if not found.
*/
-LY_ERR lyht_find_next_with_collision_cb(struct ly_ht *ht, void *val_p, uint32_t hash,
+LIBYANG_API_DECL LY_ERR lyht_find_next_with_collision_cb(struct ly_ht *ht, void *val_p, uint32_t hash,
lyht_value_equal_cb collision_val_equal, void **match_p);
/**
@@ -222,7 +165,7 @@
* @return LY_EEXIST in case the value is already present.
* @return LY_EMEM in case of memory allocation failure.
*/
-LY_ERR lyht_insert(struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p);
+LIBYANG_API_DECL LY_ERR lyht_insert(struct ly_ht *ht, void *val_p, uint32_t hash, void **match_p);
/**
* @brief Insert a value into hash table. Same functionality as ::lyht_insert()
@@ -239,8 +182,8 @@
* @return LY_EEXIST in case the value is already present.
* @return LY_EMEM in case of memory allocation failure.
*/
-LY_ERR lyht_insert_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash, lyht_value_equal_cb resize_val_equal,
- void **match_p);
+LIBYANG_API_DECL LY_ERR lyht_insert_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash,
+ lyht_value_equal_cb resize_val_equal, void **match_p);
/**
* @brief Remove a value from a hash table.
@@ -252,7 +195,7 @@
* @return LY_SUCCESS on success,
* @return LY_ENOTFOUND if value was not found.
*/
-LY_ERR lyht_remove(struct ly_ht *ht, void *val_p, uint32_t hash);
+LIBYANG_API_DECL LY_ERR lyht_remove(struct ly_ht *ht, void *val_p, uint32_t hash);
/**
* @brief Remove a value from a hash table. Same functionality as ::lyht_remove()
@@ -267,7 +210,8 @@
* @return LY_SUCCESS on success,
* @return LY_ENOTFOUND if value was not found.
*/
-LY_ERR lyht_remove_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash, lyht_value_equal_cb resize_val_equal);
+LIBYANG_API_DECL LY_ERR lyht_remove_with_resize_cb(struct ly_ht *ht, void *val_p, uint32_t hash,
+ lyht_value_equal_cb resize_val_equal);
/**
* @brief Get suitable size of a hash table for a fixed number of items.
@@ -275,6 +219,10 @@
* @param[in] item_count Number of stored items.
* @return Hash table size.
*/
-uint32_t lyht_get_fixed_size(uint32_t item_count);
+LIBYANG_API_DECL uint32_t lyht_get_fixed_size(uint32_t item_count);
+
+#ifdef __cplusplus
+}
+#endif
#endif /* LY_HASH_TABLE_H_ */
diff --git a/src/hash_table_internal.h b/src/hash_table_internal.h
new file mode 100644
index 0000000..eaadbc7
--- /dev/null
+++ b/src/hash_table_internal.h
@@ -0,0 +1,105 @@
+/**
+ * @file hash_table_internal.h
+ * @author Radek Krejci <rkrejci@cesnet.cz>
+ * @author Michal Vasko <mvasko@cesnet.cz>
+ * @brief libyang hash table internal header
+ *
+ * Copyright (c) 2015 - 2023 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ */
+
+#ifndef LY_HASH_TABLE_INTERNAL_H_
+#define LY_HASH_TABLE_INTERNAL_H_
+
+#include <pthread.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "compat.h"
+#include "hash_table.h"
+
+/** reference value for 100% */
+#define LYHT_HUNDRED_PERCENTAGE 100
+
+/** when the table is at least this much percent full, it is enlarged (double the size) */
+#define LYHT_ENLARGE_PERCENTAGE 75
+
+/** only once the table is this much percent full, enable shrinking */
+#define LYHT_FIRST_SHRINK_PERCENTAGE 50
+
+/** when the table is less than this much percent full, it is shrunk (half the size) */
+#define LYHT_SHRINK_PERCENTAGE 25
+
+/** when the table has less than this much percent empty records, it is rehashed to get rid of all the invalid records */
+#define LYHT_REHASH_PERCENTAGE 2
+
+/** never shrink beyond this size */
+#define LYHT_MIN_SIZE 8
+
+/**
+ * @brief Generic hash table record.
+ */
+struct ly_ht_rec {
+ uint32_t hash; /* hash of the value */
+ int32_t hits; /* collision/overflow value count - 1 (a filled entry has 1 hit,
+ * special value -1 means a deleted record) */
+ unsigned char val[1]; /* arbitrary-size value */
+} _PACKED;
+
+/**
+ * @brief (Very) generic hash table.
+ *
+ * Hash table with open addressing collision resolution and
+ * linear probing of interval 1 (next free record is used).
+ * Removal is lazy (removed records are only marked), but
+ * if possible, they are fully emptied.
+ */
+struct ly_ht {
+ uint32_t used; /* number of values stored in the hash table (filled records) */
+ uint32_t size; /* always holds 2^x == size (is power of 2), actually number of records allocated */
+ uint32_t invalid; /* number of invalid records (deleted) */
+ lyht_value_equal_cb val_equal; /* callback for testing value equivalence */
+ void *cb_data; /* user data callback arbitrary value */
+ uint16_t resize; /* 0 - resizing is disabled, *
+ * 1 - enlarging is enabled, *
+ * 2 - both shrinking and enlarging is enabled */
+ uint16_t rec_size; /* real size (in bytes) of one record for accessing recs array */
+ unsigned char *recs; /* pointer to the hash table itself (array of struct ht_rec) */
+};
+
+/**
+ * @brief Dictionary hash table record.
+ */
+struct ly_dict_rec {
+ char *value; /**< stored string */
+ uint32_t refcount; /**< reference count of the string */
+};
+
+/**
+ * @brief Dictionary for storing repeated strings.
+ */
+struct ly_dict {
+ struct ly_ht *hash_tab;
+ pthread_mutex_t lock;
+};
+
+/**
+ * @brief Initiate content (non-zero values) of the dictionary
+ *
+ * @param[in] dict Dictionary table to initiate
+ */
+void lydict_init(struct ly_dict *dict);
+
+/**
+ * @brief Cleanup the dictionary content
+ *
+ * @param[in] dict Dictionary table to cleanup
+ */
+void lydict_clean(struct ly_dict *dict);
+
+#endif /* LY_HASH_TABLE_INTERNAL_H_ */
diff --git a/src/libyang.h b/src/libyang.h
index 2bfc6be..f992a78 100644
--- a/src/libyang.h
+++ b/src/libyang.h
@@ -39,6 +39,7 @@
/*
* The following headers are supposed to be included explicitly:
+ * - hash_table.h
* - metadata.h
* - plugins_types.h
* - plugins_exts.h
diff --git a/src/log.c b/src/log.c
index 3c02351..1a75dec 100644
--- a/src/log.c
+++ b/src/log.c
@@ -188,7 +188,7 @@
rec.tid = pthread_self();
/* get the pointer to the matching record */
- if (lyht_find(ctx->err_ht, &rec, dict_hash((void *)&rec.tid, sizeof rec.tid), (void **)&match)) {
+ if (lyht_find(ctx->err_ht, &rec, lyht_hash((void *)&rec.tid, sizeof rec.tid), (void **)&match)) {
return NULL;
}
@@ -215,7 +215,7 @@
/* LOCK */
pthread_mutex_lock((pthread_mutex_t *)&ctx->lyb_hash_lock);
- r = lyht_insert(ctx->err_ht, &new, dict_hash((void *)&new.tid, sizeof new.tid), (void **)&rec);
+ r = lyht_insert(ctx->err_ht, &new, lyht_hash((void *)&new.tid, sizeof new.tid), (void **)&rec);
/* UNLOCK */
pthread_mutex_unlock((pthread_mutex_t *)&ctx->lyb_hash_lock);
diff --git a/src/lyb.c b/src/lyb.c
index 87806c8..59d379c 100644
--- a/src/lyb.c
+++ b/src/lyb.c
@@ -39,8 +39,8 @@
LYB_HASH hash;
/* generate full hash */
- full_hash = dict_hash_multi(0, mod->name, strlen(mod->name));
- full_hash = dict_hash_multi(full_hash, node->name, strlen(node->name));
+ full_hash = lyht_hash_multi(0, mod->name, strlen(mod->name));
+ full_hash = lyht_hash_multi(full_hash, node->name, strlen(node->name));
if (collision_id) {
size_t ext_len;
@@ -51,9 +51,9 @@
/* use one more byte from the module name than before */
ext_len = collision_id;
}
- full_hash = dict_hash_multi(full_hash, mod->name, ext_len);
+ full_hash = lyht_hash_multi(full_hash, mod->name, ext_len);
}
- full_hash = dict_hash_multi(full_hash, NULL, 0);
+ full_hash = lyht_hash_multi(full_hash, NULL, 0);
/* use the shortened hash */
hash = full_hash & (LYB_HASH_MASK >> collision_id);
diff --git a/src/tree_data_common.c b/src/tree_data_common.c
index 4f1255e..316fad4 100644
--- a/src/tree_data_common.c
+++ b/src/tree_data_common.c
@@ -1158,9 +1158,9 @@
parent = siblings->parent;
if (parent && parent->schema && parent->children_ht) {
/* calculate our hash */
- hash = dict_hash_multi(0, schema->module->name, strlen(schema->module->name));
- hash = dict_hash_multi(hash, schema->name, strlen(schema->name));
- hash = dict_hash_multi(hash, NULL, 0);
+ hash = lyht_hash_multi(0, schema->module->name, strlen(schema->module->name));
+ hash = lyht_hash_multi(hash, schema->name, strlen(schema->name));
+ hash = lyht_hash_multi(hash, NULL, 0);
/* use special hash table function */
ht_cb = lyht_set_cb(parent->children_ht, lyd_hash_table_schema_val_equal);
diff --git a/src/tree_data_hash.c b/src/tree_data_hash.c
index 79e0031..c8ea2f2 100644
--- a/src/tree_data_hash.c
+++ b/src/tree_data_hash.c
@@ -39,15 +39,15 @@
}
/* hash always starts with the module and schema name */
- node->hash = dict_hash_multi(0, node->schema->module->name, strlen(node->schema->module->name));
- node->hash = dict_hash_multi(node->hash, node->schema->name, strlen(node->schema->name));
+ node->hash = lyht_hash_multi(0, node->schema->module->name, strlen(node->schema->module->name));
+ node->hash = lyht_hash_multi(node->hash, node->schema->name, strlen(node->schema->name));
if (node->schema->nodetype == LYS_LIST) {
if (node->schema->flags & LYS_KEYLESS) {
/* key-less list simply calls hash function again with empty key,
* just so that it differs from the first-instance hash
*/
- node->hash = dict_hash_multi(node->hash, NULL, 0);
+ node->hash = lyht_hash_multi(node->hash, NULL, 0);
} else {
struct lyd_node_inner *list = (struct lyd_node_inner *)node;
@@ -56,7 +56,7 @@
struct lyd_node_term *key = (struct lyd_node_term *)iter;
hash_key = key->value.realtype->plugin->print(NULL, &key->value, LY_VALUE_LYB, NULL, &dyn, &key_len);
- node->hash = dict_hash_multi(node->hash, hash_key, key_len);
+ node->hash = lyht_hash_multi(node->hash, hash_key, key_len);
if (dyn) {
free((void *)hash_key);
}
@@ -67,14 +67,14 @@
struct lyd_node_term *llist = (struct lyd_node_term *)node;
hash_key = llist->value.realtype->plugin->print(NULL, &llist->value, LY_VALUE_LYB, NULL, &dyn, &key_len);
- node->hash = dict_hash_multi(node->hash, hash_key, key_len);
+ node->hash = lyht_hash_multi(node->hash, hash_key, key_len);
if (dyn) {
free((void *)hash_key);
}
}
/* finish the hash */
- node->hash = dict_hash_multi(node->hash, NULL, 0);
+ node->hash = lyht_hash_multi(node->hash, NULL, 0);
return LY_SUCCESS;
}
@@ -136,9 +136,9 @@
if ((node->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) &&
(!node->prev->next || (node->prev->schema != node->schema))) {
/* get the simple hash */
- hash = dict_hash_multi(0, node->schema->module->name, strlen(node->schema->module->name));
- hash = dict_hash_multi(hash, node->schema->name, strlen(node->schema->name));
- hash = dict_hash_multi(hash, NULL, 0);
+ hash = lyht_hash_multi(0, node->schema->module->name, strlen(node->schema->module->name));
+ hash = lyht_hash_multi(hash, node->schema->name, strlen(node->schema->name));
+ hash = lyht_hash_multi(hash, NULL, 0);
/* remove any previous stored instance, only if we did not start with an empty HT */
if (!empty_ht && node->next && (node->next->schema == node->schema)) {
@@ -216,9 +216,9 @@
/* first instance of the (leaf-)list, needs to be removed from HT */
if ((node->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) && (!node->prev->next || (node->prev->schema != node->schema))) {
/* get the simple hash */
- hash = dict_hash_multi(0, node->schema->module->name, strlen(node->schema->module->name));
- hash = dict_hash_multi(hash, node->schema->name, strlen(node->schema->name));
- hash = dict_hash_multi(hash, NULL, 0);
+ hash = lyht_hash_multi(0, node->schema->module->name, strlen(node->schema->module->name));
+ hash = lyht_hash_multi(hash, node->schema->name, strlen(node->schema->name));
+ hash = lyht_hash_multi(hash, NULL, 0);
/* remove the instance */
if (lyht_remove(node->parent->children_ht, &node, hash)) {
diff --git a/src/tree_schema_common.c b/src/tree_schema_common.c
index 42032a7..5580809 100644
--- a/src/tree_schema_common.c
+++ b/src/tree_schema_common.c
@@ -361,7 +361,7 @@
LY_ERR ret;
uint32_t hash;
- hash = dict_hash(name, strlen(name));
+ hash = lyht_hash(name, strlen(name));
ret = lyht_insert(ht, &name, hash, NULL);
if (ret == LY_EEXIST) {
if (err_detail) {
@@ -433,7 +433,7 @@
/* check collision with the top-level typedefs */
if (node) {
- hash = dict_hash(name, name_len);
+ hash = lyht_hash(name, name_len);
if (!lyht_find(tpdfs_global, &name, hash, NULL)) {
LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG,
"Duplicate identifier \"%s\" of typedef statement - scoped type collide with a top-level type.", name);
@@ -566,7 +566,7 @@
/* check collision with the top-level groupings */
if (node) {
- hash = dict_hash(name, name_len);
+ hash = lyht_hash(name, name_len);
if (!lyht_find(grps_global, &name, hash, NULL)) {
LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG,
"Duplicate identifier \"%s\" of grouping statement - scoped grouping collide with a top-level grouping.", name);
diff --git a/src/validation.c b/src/validation.c
index 89ba74a..73ae19c 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -1307,7 +1307,7 @@
/* get hash key */
hash_key = val->realtype->plugin->print(NULL, val, LY_VALUE_LYB, NULL, &dyn, &key_len);
- hash = dict_hash_multi(hash, hash_key, key_len);
+ hash = lyht_hash_multi(hash, hash_key, key_len);
if (dyn) {
free((void *)hash_key);
}
@@ -1318,7 +1318,7 @@
}
/* finish the hash value */
- hash = dict_hash_multi(hash, NULL, 0);
+ hash = lyht_hash_multi(hash, NULL, 0);
/* insert into the hashtable */
ret = lyht_insert(uniqtables[u], &set->objs[i], hash, NULL);
diff --git a/src/xpath.c b/src/xpath.c
index 44ae922..b3e4c70 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -695,9 +695,9 @@
hnode.node = set->val.nodes[i].node;
hnode.type = set->val.nodes[i].type;
- hash = dict_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
- hash = dict_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
- hash = dict_hash_multi(hash, NULL, 0);
+ hash = lyht_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
+ hash = lyht_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
+ hash = lyht_hash_multi(hash, NULL, 0);
r = lyht_insert(set->ht, &hnode, hash, NULL);
assert(!r);
@@ -715,9 +715,9 @@
hnode.node = node;
hnode.type = type;
- hash = dict_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
- hash = dict_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
- hash = dict_hash_multi(hash, NULL, 0);
+ hash = lyht_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
+ hash = lyht_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
+ hash = lyht_hash_multi(hash, NULL, 0);
r = lyht_insert(set->ht, &hnode, hash, NULL);
assert(!r);
@@ -743,9 +743,9 @@
hnode.node = node;
hnode.type = type;
- hash = dict_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
- hash = dict_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
- hash = dict_hash_multi(hash, NULL, 0);
+ hash = lyht_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
+ hash = lyht_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
+ hash = lyht_hash_multi(hash, NULL, 0);
r = lyht_remove(set->ht, &hnode, hash);
assert(!r);
@@ -776,9 +776,9 @@
hnode.node = node;
hnode.type = type;
- hash = dict_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
- hash = dict_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
- hash = dict_hash_multi(hash, NULL, 0);
+ hash = lyht_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
+ hash = lyht_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
+ hash = lyht_hash_multi(hash, NULL, 0);
if (!lyht_find(set->ht, &hnode, hash, (void **)&match_p)) {
if ((skip_idx > -1) && (set->val.nodes[skip_idx].node == match_p->node) && (set->val.nodes[skip_idx].type == match_p->type)) {
@@ -1789,9 +1789,9 @@
hnode.node = set->val.nodes[i].node;
hnode.type = set->val.nodes[i].type;
- hash = dict_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
- hash = dict_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
- hash = dict_hash_multi(hash, NULL, 0);
+ hash = lyht_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
+ hash = lyht_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
+ hash = lyht_hash_multi(hash, NULL, 0);
assert(!lyht_find(set->ht, &hnode, hash, NULL));
}