types FEATURE add hash callback for the types plugins
Since the representation of the value can be type-specific, it make
sense to let the plugin count the hash of the value instead of always
using the canonical representation (and force the plugin to create
such a representation) instead of creating hash from its specific
(e.g. binary) representation.
diff --git a/src/plugins_types.c b/src/plugins_types.c
index 7383373..22ffa5c 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -297,6 +297,14 @@
return value->_canonical;
}
+API const void *
+lyplg_type_hash_simple(const struct lyd_value *value, ly_bool *dynamic, size_t *key_len)
+{
+ *dynamic = 0;
+ *key_len = strlen(value->_canonical);
+ return value->_canonical;
+}
+
API LY_ERR
lyplg_type_dup_simple(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
diff --git a/src/plugins_types.h b/src/plugins_types.h
index 95e089b..fc49d05 100644
--- a/src/plugins_types.h
+++ b/src/plugins_types.h
@@ -439,7 +439,21 @@
LY_VALUE_FORMAT format, void *prefix_data, ly_bool *dynamic, size_t *value_len);
/**
- * @brief Callback to duplicate data in data structure.
+ * @brief Callback for getting the value hash key. The only requirement is that for 2 equal values this key
+ * MUST be equal. If possible, for 2 non-equal values this key should not be equal.
+ *
+ * It should always be possible to return the canonical value.
+ *
+ * @param[in] value Value to get the hash key of.
+ * @param[out] dynamic Flag if the returned hash key is dynamically allocated. In such a case the caller is responsible
+ * for freeing it.
+ * @param[out] key_len Returned hash key length in bytes.
+ * @return Hash key.
+ */
+typedef const void *(*lyplg_type_hash_clb)(const struct lyd_value *value, ly_bool *dynamic, size_t *key_len);
+
+/**
+ * @brief Callback to duplicate data in the data structure.
*
* @param[in] ctx libyang context of the @p dup. Note that the context of @p original and @p dup might not be the same.
* @param[in] original Original data structure to be duplicated.
@@ -474,6 +488,7 @@
lyplg_type_validate_clb validate; /**< optional, validate the value in the type-specific way in data */
lyplg_type_compare_clb compare; /**< comparison callback to compare 2 values of the same type */
lyplg_type_print_clb print; /**< printer callback to get string representing the value */
+ lyplg_type_hash_clb hash; /**< hash callback to get the hash key of the value */
lyplg_type_dup_clb duplicate; /**< data duplication callback */
lyplg_type_free_clb free; /**< optional function to free the type-spceific way stored value */
};
@@ -515,6 +530,12 @@
void *prefix_data, ly_bool *dynamic, size_t *value_len);
/**
+ * @brief Generic simple hash callback of the canonized value.
+ * Implementation of the ::lyplg_type_hash_clb.
+ */
+const void *lyplg_type_hash_simple(const struct lyd_value *value, ly_bool *dynamic, size_t *key_len);
+
+/**
* @brief Generic simple duplication callback.
* Implementation of the ::lyplg_type_dup_clb.
*/
@@ -791,6 +812,12 @@
void *prefix_data, ly_bool *dynamic, size_t *value_len);
/**
+ * @brief Hash key callback for a leafref value.
+ * Implementation of ::lyplg_type_hash_clb.
+ */
+const void *lyplg_type_hash_leafref(const struct lyd_value *value, ly_bool *dynamic, size_t *key_len);
+
+/**
* @brief Duplication callback of the leafref values.
* Implementation of the ::lyplg_type_dup_clb.
*/
@@ -859,6 +886,12 @@
void *prefix_data, ly_bool *dynamic, size_t *value_len);
/**
+ * @brief Hash key callback for a union value.
+ * Implementation of ::lyplg_type_hash_clb.
+ */
+const void *lyplg_type_hash_union(const struct lyd_value *value, ly_bool *dynamic, size_t *key_len);
+
+/**
* @brief Duplication callback of the union values.
* Implementation of the ::lyplg_type_dup_clb.
*/
diff --git a/src/plugins_types/binary.c b/src/plugins_types/binary.c
index 16833ea..23f410b 100644
--- a/src/plugins_types/binary.c
+++ b/src/plugins_types/binary.c
@@ -144,6 +144,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple,
},
diff --git a/src/plugins_types/bits.c b/src/plugins_types/bits.c
index c59de75..a74ada4 100644
--- a/src/plugins_types/bits.c
+++ b/src/plugins_types/bits.c
@@ -240,6 +240,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_bits,
.plugin.free = lyplg_type_free_bits
},
diff --git a/src/plugins_types/boolean.c b/src/plugins_types/boolean.c
index 4a8b20c..5a681ad 100644
--- a/src/plugins_types/boolean.c
+++ b/src/plugins_types/boolean.c
@@ -89,6 +89,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
},
diff --git a/src/plugins_types/date_and_time.c b/src/plugins_types/date_and_time.c
index 31ec7c7..24b5034 100644
--- a/src/plugins_types/date_and_time.c
+++ b/src/plugins_types/date_and_time.c
@@ -268,6 +268,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
},
diff --git a/src/plugins_types/decimal64.c b/src/plugins_types/decimal64.c
index ea7d5c4..54416a5 100644
--- a/src/plugins_types/decimal64.c
+++ b/src/plugins_types/decimal64.c
@@ -116,6 +116,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
},
diff --git a/src/plugins_types/empty.c b/src/plugins_types/empty.c
index 172c3ad..7eaec74 100644
--- a/src/plugins_types/empty.c
+++ b/src/plugins_types/empty.c
@@ -94,6 +94,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_empty,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
},
diff --git a/src/plugins_types/enumeration.c b/src/plugins_types/enumeration.c
index da24316..dadf51f 100644
--- a/src/plugins_types/enumeration.c
+++ b/src/plugins_types/enumeration.c
@@ -95,6 +95,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
},
diff --git a/src/plugins_types/hex_string.c b/src/plugins_types/hex_string.c
index 1a29d3e..ab8f2fa 100644
--- a/src/plugins_types/hex_string.c
+++ b/src/plugins_types/hex_string.c
@@ -93,6 +93,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
},
@@ -106,6 +107,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
},
@@ -119,6 +121,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
},
@@ -132,6 +135,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
},
diff --git a/src/plugins_types/identityref.c b/src/plugins_types/identityref.c
index 3b40c28..092d73a 100644
--- a/src/plugins_types/identityref.c
+++ b/src/plugins_types/identityref.c
@@ -214,6 +214,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_identityref,
.plugin.print = lyplg_type_print_identityref,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
},
diff --git a/src/plugins_types/instanceid.c b/src/plugins_types/instanceid.c
index f9f4707..1fa97a4 100644
--- a/src/plugins_types/instanceid.c
+++ b/src/plugins_types/instanceid.c
@@ -324,6 +324,7 @@
.plugin.validate = lyplg_type_validate_instanceid,
.plugin.compare = lyplg_type_compare_instanceid,
.plugin.print = lyplg_type_print_instanceid,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_instanceid,
.plugin.free = lyplg_type_free_instanceid
},
diff --git a/src/plugins_types/integer.c b/src/plugins_types/integer.c
index d1a5b1f..c042e49 100644
--- a/src/plugins_types/integer.c
+++ b/src/plugins_types/integer.c
@@ -193,6 +193,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
}, {
@@ -205,6 +206,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
}, {
@@ -217,6 +219,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
}, {
@@ -229,6 +232,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
}, {
@@ -241,6 +245,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
}, {
@@ -253,6 +258,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
}, {
@@ -265,6 +271,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
}, {
@@ -277,6 +284,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
},
diff --git a/src/plugins_types/ip_prefix.c b/src/plugins_types/ip_prefix.c
index 9eef670..3dcbe50 100644
--- a/src/plugins_types/ip_prefix.c
+++ b/src/plugins_types/ip_prefix.c
@@ -280,6 +280,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
},
@@ -293,6 +294,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
},
diff --git a/src/plugins_types/leafref.c b/src/plugins_types/leafref.c
index 03190ba..99baf84 100644
--- a/src/plugins_types/leafref.c
+++ b/src/plugins_types/leafref.c
@@ -96,6 +96,12 @@
return value->realtype->plugin->print(ctx, value, format, prefix_data, dynamic, value_len);
}
+API const void *
+lyplg_type_hash_leafref(const struct lyd_value *value, ly_bool *dynamic, size_t *key_len)
+{
+ return value->realtype->plugin->hash(value, dynamic, key_len);
+}
+
API LY_ERR
lyplg_type_dup_leafref(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
@@ -129,6 +135,7 @@
.plugin.validate = lyplg_type_validate_leafref,
.plugin.compare = lyplg_type_compare_leafref,
.plugin.print = lyplg_type_print_leafref,
+ .plugin.hash = lyplg_type_hash_leafref,
.plugin.duplicate = lyplg_type_dup_leafref,
.plugin.free = lyplg_type_free_leafref
},
diff --git a/src/plugins_types/string.c b/src/plugins_types/string.c
index 1d67cfa..eb05c7d 100644
--- a/src/plugins_types/string.c
+++ b/src/plugins_types/string.c
@@ -92,6 +92,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_simple,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple
},
diff --git a/src/plugins_types/union.c b/src/plugins_types/union.c
index 9b11dd8..aa33929 100644
--- a/src/plugins_types/union.c
+++ b/src/plugins_types/union.c
@@ -206,6 +206,12 @@
return ret;
}
+API const void *
+lyplg_type_hash_union(const struct lyd_value *value, ly_bool *dynamic, size_t *key_len)
+{
+ return value->subvalue->value.realtype->plugin->hash(value, dynamic, key_len);
+}
+
API LY_ERR
lyplg_type_dup_union(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
@@ -258,6 +264,7 @@
.plugin.validate = lyplg_type_validate_union,
.plugin.compare = lyplg_type_compare_union,
.plugin.print = lyplg_type_print_union,
+ .plugin.hash = lyplg_type_hash_union,
.plugin.duplicate = lyplg_type_dup_union,
.plugin.free = lyplg_type_free_union
},
diff --git a/src/plugins_types/xpath1.0.c b/src/plugins_types/xpath1.0.c
index 3ebad18..0f6fa39 100644
--- a/src/plugins_types/xpath1.0.c
+++ b/src/plugins_types/xpath1.0.c
@@ -338,6 +338,7 @@
.plugin.validate = NULL,
.plugin.compare = lyplg_type_compare_simple,
.plugin.print = lyplg_type_print_xpath10,
+ .plugin.hash = lyplg_type_hash_simple,
.plugin.duplicate = lyplg_type_dup_xpath10,
.plugin.free = lyplg_type_free_xpath10
},
diff --git a/src/tree_data_hash.c b/src/tree_data_hash.c
index b56f5b9..1704a5b 100644
--- a/src/tree_data_hash.c
+++ b/src/tree_data_hash.c
@@ -21,6 +21,7 @@
#include "compat.h"
#include "hash_table.h"
#include "log.h"
+#include "plugins_types.h"
#include "tree.h"
#include "tree_data.h"
#include "tree_schema.h"
@@ -29,6 +30,9 @@
lyd_hash(struct lyd_node *node)
{
struct lyd_node *iter;
+ const void *hash_key;
+ ly_bool dyn;
+ size_t key_len;
if (!node->schema) {
return LY_SUCCESS;
@@ -47,14 +51,24 @@
/* list hash is made up from its keys */
for (iter = list->child; iter && (iter->schema->flags & LYS_KEY); iter = iter->next) {
- const char *value = lyd_get_value(iter);
- node->hash = dict_hash_multi(node->hash, value, strlen(value));
+ struct lyd_node_term *key = (struct lyd_node_term *)iter;
+
+ hash_key = key->value.realtype->plugin->hash(&key->value, &dyn, &key_len);
+ node->hash = dict_hash_multi(node->hash, hash_key, key_len);
+ if (dyn) {
+ free((void *)hash_key);
+ }
}
}
} else if (node->schema->nodetype == LYS_LEAFLIST) {
- /* leaf-list adds its value */
- const char *value = lyd_get_value(node);
- node->hash = dict_hash_multi(node->hash, value, strlen(value));
+ /* leaf-list adds its hash key */
+ struct lyd_node_term *llist = (struct lyd_node_term *)node;
+
+ hash_key = llist->value.realtype->plugin->hash(&llist->value, &dyn, &key_len);
+ node->hash = dict_hash_multi(node->hash, hash_key, key_len);
+ if (dyn) {
+ free((void *)hash_key);
+ }
}
/* finish the hash */
diff --git a/src/validation.c b/src/validation.c
index 1a0c396..8895531 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -1038,8 +1038,9 @@
LY_ARRAY_COUNT_TYPE u, v, x = 0;
LY_ERR ret = LY_SUCCESS;
uint32_t hash, i, size = 0;
- ly_bool dynamic;
- const char *str;
+ size_t key_len;
+ ly_bool dyn;
+ const void *hash_key;
struct hash_table **uniqtables = NULL;
struct lyd_value *val;
struct ly_ctx *ctx = snode->module->ctx;
@@ -1104,11 +1105,11 @@
break;
}
- /* get canonical string value */
- str = val->realtype->plugin->print(ctx, val, LY_VALUE_JSON, NULL, &dynamic, NULL);
- hash = dict_hash_multi(hash, str, strlen(str));
- if (dynamic) {
- free((char *)str);
+ /* get hash key */
+ hash_key = val->realtype->plugin->hash(val, &dyn, &key_len);
+ hash = dict_hash_multi(hash, hash_key, key_len);
+ if (dyn) {
+ free((void *)hash_key);
}
}
if (!val) {