tree REFACTOR basic adjustments based on new strict ordering
Redundant functions removed, it is no longer
needed to search data siblings without hashes,
ever. But a macro was added for easier iterating
over all instances of a schema node.
diff --git a/src/path.c b/src/path.c
index eb72c2f..4017be7 100644
--- a/src/path.c
+++ b/src/path.c
@@ -25,6 +25,7 @@
#include "log.h"
#include "plugins_types.h"
#include "set.h"
+#include "tree.h"
#include "tree_data_internal.h"
#include "tree_schema.h"
#include "tree_schema_internal.h"
@@ -793,8 +794,7 @@
case LY_PATH_PREDTYPE_POSITION:
/* we cannot use hashes and want an instance on a specific position */
pos = 1;
- node = (struct lyd_node *)start;
- while (!lyd_find_sibling_next2(node, path[u].node, NULL, 0, &node)) {
+ LYD_LIST_FOR_INST(start, path[u].node, node) {
if (pos == path[u].predicates[0].position) {
break;
}
diff --git a/src/tree.h b/src/tree.h
index 11df43d..0fe7264 100644
--- a/src/tree.h
+++ b/src/tree.h
@@ -134,6 +134,31 @@
(ELEM) = (NEXT))
/**
+ * @brief Macro to iterate via all schema node data instances in data siblings.
+ *
+ * @param START Pointer to the starting sibling. Even if it is not first, all the siblings are searched.
+ * @param SCHEMA Schema node of the searched instances.
+ * @param ELEM Iterator.
+ */
+#define LYD_LIST_FOR_INST(START, SCHEMA, ELEM) \
+ for (lyd_find_sibling_val(START, SCHEMA, NULL, 0, &(ELEM)); \
+ (ELEM) && ((ELEM)->schema == (SCHEMA)); \
+ (ELEM) = (ELEM)->next)
+
+/**
+ * @brief Macro to iterate via all schema node data instances in data siblings allowing to modify the list itself.
+ *
+ * @param START Pointer to the starting sibling. Even if it is not first, all the siblings are searched.
+ * @param SCHEMA Schema node of the searched instances.
+ * @param NEXT Temporary storage to allow removing of the current iterator content.
+ * @param ELEM Iterator.
+ */
+#define LYD_LIST_FOR_INST_SAFE(START, SCHEMA, NEXT, ELEM) \
+ for (lyd_find_sibling_val(START, SCHEMA, NULL, 0, &(ELEM)); \
+ (ELEM) && ((ELEM)->schema == (SCHEMA)) ? ((NEXT) = (ELEM)->next, 1) : 0; \
+ (ELEM) = (NEXT))
+
+/**
* @brief YANG built-in types
*/
typedef enum
diff --git a/src/tree_data.c b/src/tree_data.c
index 72e8c7b..8de7ba2 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -2413,8 +2413,6 @@
const struct lyd_node *child_src, *tmp, *sibling_src;
struct lyd_node *match_trg, *dup_src, *next, *elem;
struct lysc_type *type;
- LYD_ANYDATA_VALUETYPE tmp_val_type;
- union lyd_any_value tmp_val;
sibling_src = *sibling_src_p;
if (sibling_src->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
@@ -2442,27 +2440,12 @@
match_trg->flags = sibling_src->flags | LYD_NEW;
}
} else if ((match_trg->schema->nodetype & LYS_ANYDATA) && lyd_compare(sibling_src, match_trg, 0)) {
- if (options & LYD_MERGE_DESTRUCT) {
- dup_src = (struct lyd_node *)sibling_src;
- lyd_unlink_tree(dup_src);
- /* spend it */
- *sibling_src_p = NULL;
- } else {
- LY_CHECK_RET(lyd_dup_single(sibling_src, NULL, 0, &dup_src));
- }
- /* just switch values */
- tmp_val_type = ((struct lyd_node_any *)match_trg)->value_type;
- tmp_val = ((struct lyd_node_any *)match_trg)->value;
- ((struct lyd_node_any *)match_trg)->value_type = ((struct lyd_node_any *)sibling_src)->value_type;
- ((struct lyd_node_any *)match_trg)->value = ((struct lyd_node_any *)sibling_src)->value;
- ((struct lyd_node_any *)sibling_src)->value_type = tmp_val_type;
- ((struct lyd_node_any *)sibling_src)->value = tmp_val;
+ /* update value */
+ LY_CHECK_RET(lyd_any_copy_value(match_trg, &((struct lyd_node_any *)sibling_src)->value,
+ ((struct lyd_node_any *)sibling_src)->value_type));
/* copy flags and add LYD_NEW */
match_trg->flags = sibling_src->flags | LYD_NEW;
-
- /* dup_src is not needed, actually */
- lyd_free_tree(dup_src);
} else {
/* check descendants, recursively */
LY_LIST_FOR_SAFE(LYD_CHILD(sibling_src), tmp, child_src) {
@@ -2810,135 +2793,6 @@
return ret;
}
-LY_ERR
-lyd_find_sibling_next2(const struct lyd_node *first, const struct lysc_node *schema, const char *key_or_value,
- size_t val_len, struct lyd_node **match)
-{
- LY_ERR rc;
- const struct lyd_node *node = NULL;
- struct lyd_node_term *term;
- struct lyxp_expr *expr = NULL;
- uint16_t exp_idx = 0;
- struct ly_path_predicate *predicates = NULL;
- enum ly_path_pred_type pred_type = 0;
- struct lyd_value val = {0};
- LY_ARRAY_COUNT_TYPE u;
-
- LY_CHECK_ARG_RET(NULL, schema, LY_EINVAL);
-
- if (!first) {
- /* no data */
- if (match) {
- *match = NULL;
- }
- return LY_ENOTFOUND;
- }
-
- if (key_or_value && !val_len) {
- val_len = strlen(key_or_value);
- }
-
- if (key_or_value && (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
- /* store the value */
- LY_CHECK_GOTO(rc = lyd_value_store(&val, schema, key_or_value, val_len, 0, lydjson_resolve_prefix, NULL, LYD_JSON), cleanup);
- } else if (key_or_value && (schema->nodetype == LYS_LIST)) {
- /* parse keys */
- LY_CHECK_GOTO(rc = ly_path_parse_predicate(schema->module->ctx, key_or_value, val_len, LY_PATH_PREFIX_OPTIONAL,
- LY_PATH_PRED_KEYS, &expr), cleanup);
-
- /* compile them */
- LY_CHECK_GOTO(rc = ly_path_compile_predicate(schema->module->ctx, NULL, schema, expr, &exp_idx, lydjson_resolve_prefix,
- NULL, LYD_JSON, &predicates, &pred_type), cleanup);
- }
-
- /* find first matching value */
- LY_LIST_FOR(first, node) {
- if (node->schema != schema) {
- continue;
- }
-
- if ((schema->nodetype == LYS_LIST) && predicates) {
- /* compare all set keys */
- LY_ARRAY_FOR(predicates, u) {
- /* find key */
- rc = lyd_find_sibling_val(lyd_node_children(node, 0), predicates[u].key, NULL, 0, (struct lyd_node **)&term);
- if (rc == LY_ENOTFOUND) {
- /* all keys must always exist */
- LOGINT_RET(schema->module->ctx);
- }
- LY_CHECK_GOTO(rc, cleanup);
-
- /* compare values */
- if (!term->value.realtype->plugin->compare(&term->value, &predicates[u].value)) {
- break;
- }
- }
-
- if (u < LY_ARRAY_COUNT(predicates)) {
- /* not a match */
- continue;
- }
- } else if ((schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && val.realtype) {
- term = (struct lyd_node_term *)node;
-
- /* compare values */
- if (!term->value.realtype->plugin->compare(&term->value, &val)) {
- /* not a match */
- continue;
- }
- }
-
- /* all criteria passed */
- break;
- }
-
- if (!node) {
- rc = LY_ENOTFOUND;
- if (match) {
- *match = NULL;
- }
- goto cleanup;
- }
-
- /* success */
- if (match) {
- *match = (struct lyd_node *)node;
- }
- rc = LY_SUCCESS;
-
-cleanup:
- ly_path_predicates_free(schema->module->ctx, pred_type, NULL, predicates);
- lyxp_expr_free(schema->module->ctx, expr);
- if (val.realtype) {
- val.realtype->plugin->free(schema->module->ctx, &val);
- }
- return rc;
-}
-
-API LY_ERR
-lyd_find_sibling_next(const struct lyd_node *first, const struct lys_module *module, const char *name, size_t name_len,
- const char *key_or_value, size_t val_len, struct lyd_node **match)
-{
- const struct lysc_node *schema;
-
- LY_CHECK_ARG_RET(NULL, module, name, match, LY_EINVAL);
-
- if (!first) {
- /* no data */
- *match = NULL;
- return LY_ENOTFOUND;
- }
-
- /* find schema */
- schema = lys_find_child(first->parent ? first->parent->schema : NULL, module, name, name_len, 0, 0);
- if (!schema) {
- LOGERR(module->ctx, LY_EINVAL, "Schema node not found.");
- return LY_EINVAL;
- }
-
- return lyd_find_sibling_next2(first, schema, key_or_value, val_len, match);
-}
-
API LY_ERR
lyd_find_sibling_first(const struct lyd_node *siblings, const struct lyd_node *target, struct lyd_node **match)
{
@@ -3002,92 +2856,6 @@
return LY_SUCCESS;
}
-API LY_ERR
-lyd_find_sibling_set(const struct lyd_node *siblings, const struct lyd_node *target, struct ly_set **set)
-{
- struct lyd_node_inner *parent;
- struct lyd_node *match;
- struct lyd_node **match_p;
- struct ly_set *ret;
-
- LY_CHECK_ARG_RET(NULL, target, set, LY_EINVAL);
-
- if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(target->schema))) {
- /* no data or schema mismatch */
- return LY_ENOTFOUND;
- }
-
- ret = ly_set_new();
- LY_CHECK_ERR_RET(!ret, LOGMEM(target->schema->module->ctx), LY_EMEM);
-
- /* find first sibling */
- if (siblings->parent) {
- siblings = siblings->parent->child;
- } else {
- while (siblings->prev->next) {
- siblings = siblings->prev;
- }
- }
-
- parent = (struct lyd_node_inner *)siblings->parent;
- if (parent && parent->children_ht) {
- assert(target->hash);
-
- /* find by hash */
- if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
- /* check even value when needed */
- if (!(target->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !lyd_compare(target, *match_p, 0)) {
- match = *match_p;
- } else {
- match = NULL;
- }
- } else {
- /* not found */
- match = NULL;
- }
- while (match) {
- /* add all found nodes into the return set */
- if (ly_set_add(ret, match, LY_SET_OPT_USEASLIST) == -1) {
- goto error;
- }
-
- /* find next instance */
- if (lyht_find_next(parent->children_ht, &match, match->hash, (void **)&match_p)) {
- match = NULL;
- } else {
- /* check even value when needed */
- if (!(match->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !lyd_compare(match, *match_p, 0)) {
- match = *match_p;
- } else {
- match = NULL;
- }
- }
- }
- } else {
- /* no children hash table */
- for (; siblings; siblings = siblings->next) {
- if (!lyd_compare(siblings, target, 0)) {
- /* a match */
- if (ly_set_add(ret, (struct lyd_node *)siblings, LY_SET_OPT_USEASLIST) == -1) {
- goto error;
- }
- }
- }
- }
-
- if (!ret->count) {
- ly_set_free(ret, NULL);
- return LY_ENOTFOUND;
- }
-
- *set = ret;
- return LY_SUCCESS;
-
-error:
- ly_set_free(ret, NULL);
- return LY_EMEM;
-}
-
static int
lyd_hash_table_schema_val_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *UNUSED(cb_data))
{
@@ -3174,15 +2942,7 @@
LY_ERR rc;
struct lyd_node *target = NULL;
- LY_CHECK_ARG_RET(NULL, schema, LY_EINVAL);
- if ((schema->nodetype == LYS_LIST) && (schema->flags & LYS_KEYLESS)) {
- LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - key-less list (%s()).", __func__);
- return LY_EINVAL;
- } else if (schema->nodetype & (LYS_CHOICE | LYS_CASE)) {
- LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - schema type %s (%s()).",
- lys_nodetype2str(schema->nodetype), __func__);
- return LY_EINVAL;
- }
+ LY_CHECK_ARG_RET(NULL, schema, !(schema->nodetype & (LYS_CHOICE | LYS_CASE)), LY_EINVAL);
if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(schema))) {
/* no data or schema mismatch */
diff --git a/src/tree_data.h b/src/tree_data.h
index fd7d421..dd69444 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -1180,41 +1180,6 @@
struct lyd_meta *lyd_find_meta(const struct lyd_meta *first, const struct lys_module *module, const char *name);
/**
- * @brief Find the node, in the list, satisfying the given restrictions.
- * Does **not** use hashes - should not be used unless necessary for best performance.
- *
- * @param[in] first Starting sibling node for search, only succeeding ones are searched.
- * @param[in] module Module of the node to find.
- * @param[in] name Name of the node to find.
- * @param[in] name_len Optional length of @p name in case it is not 0-terminated string.
- * @param[in] key_or_value Expected value depends on the type of @p name node:
- * LYS_CONTAINER:
- * LYS_ANYXML:
- * LYS_ANYDATA:
- * LYS_NOTIF:
- * LYS_RPC:
- * LYS_ACTION:
- * NULL should be always set, will be ignored.
- * LYS_LEAF:
- * LYS_LEAFLIST:
- * Optional restriction on the specific leaf(-list) value.
- * LYS_LIST:
- * Optional keys values of the matching list instances in the form of "[key1='val1'][key2='val2']...".
- * The keys do not have to be ordered and not all keys need to be specified.
- *
- * Note that any explicit values (leaf, leaf-list or list key values) will be canonized first
- * before comparison. But values that do not have a canonical value are expected to be in the
- * JSON format!
- * @param[in] val_len Optional length of @p key_or_value in case it is not a 0-terminated string.
- * @param[out] match Found data node.
- * @return LY_SUCCESS on success, @p match set.
- * @return LY_ENOTFOUND if not found, @p match set to NULL.
- * @return LY_ERR value if another error occurred.
- */
-LY_ERR lyd_find_sibling_next(const struct lyd_node *first, const struct lys_module *module, const char *name,
- size_t name_len, const char *key_or_value, size_t val_len, struct lyd_node **match);
-
-/**
* @brief Search in the given siblings (NOT recursively) for the first target instance with the same value.
* Uses hashes - should be used whenever possible for best performance.
*
@@ -1228,20 +1193,6 @@
LY_ERR lyd_find_sibling_first(const struct lyd_node *siblings, const struct lyd_node *target, struct lyd_node **match);
/**
- * @brief Search in the given siblings for all target instances with the same value.
- * Uses hashes - should be used whenever possible for best performance.
- *
- * @param[in] siblings Siblings to search in including preceding and succeeding nodes.
- * @param[in] target Target node to find. Key-less lists are compared based on
- * all its descendants (both direct and indirect).
- * @param[out] set Found nodes in a set in case of success.
- * @return LY_SUCCESS on success.
- * @return LY_ENOTFOUND if no matching siblings found.
- * @return LY_ERR value if another error occurred.
- */
-LY_ERR lyd_find_sibling_set(const struct lyd_node *siblings, const struct lyd_node *target, struct ly_set **set);
-
-/**
* @brief Search in the given siblings for the first schema instance.
* Uses hashes - should be used whenever possible for best performance.
*
diff --git a/src/tree_data_internal.h b/src/tree_data_internal.h
index 2271c4b..980af5e 100644
--- a/src/tree_data_internal.h
+++ b/src/tree_data_internal.h
@@ -421,39 +421,6 @@
/** @} datahash */
/**
- * @brief Find the node, in the list, satisfying the given restrictions.
- * Does **not** use hashes - should not be used unless necessary for best performance.
- *
- * @param[in] first Starting sibling node for search, only succeeding ones are searched.
- * @param[in] schema Schema node of the data node to find.
- * @param[in] key_or_value Expected value depends on the type of @p schema:
- * LYS_CONTAINER:
- * LYS_ANYXML:
- * LYS_ANYDATA:
- * LYS_NOTIF:
- * LYS_RPC:
- * LYS_ACTION:
- * NULL should be always set, will be ignored.
- * LYS_LEAF:
- * LYS_LEAFLIST:
- * Optional restriction on the specific leaf(-list) value.
- * LYS_LIST:
- * Optional keys values of the matching list instances in the form of "[key1='val1'][key2='val2']...".
- * The keys do not have to be ordered and not all keys need to be specified.
- *
- * Note that any explicit values (leaf, leaf-list or list key values) will be canonized first
- * before comparison. But values that do not have a canonical value are expected to be in the
- * JSON format!
- * @param[in] val_len Optional length of the @p key_or_value argument in case it is not NULL-terminated string.
- * @param[out] match Can be NULL, otherwise the found data node.
- * @return LY_SUCCESS on success, @p match set.
- * @return LY_ENOTFOUND if not found, @p match set to NULL.
- * @return LY_ERR value if another error occurred.
- */
-LY_ERR lyd_find_sibling_next2(const struct lyd_node *first, const struct lysc_node *schema, const char *key_or_value,
- size_t val_len, struct lyd_node **match);
-
-/**
* @brief Iterate over implemented modules for functions that accept specific modules or the whole context.
*
* @param[in] tree Data tree.
diff --git a/src/validation.c b/src/validation.c
index 437ce21..1c4bc45 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -60,33 +60,14 @@
siter = *slast;
}
- if (last && last->next) {
- /* find next data instance */
- lyd_find_sibling_next2(last->next, siter, NULL, 0, &match);
- if (match) {
- return match;
- }
+ if (last && last->next && (last->next->schema == siter)) {
+ /* return next data instance */
+ return last->next;
}
/* find next schema node data instance */
while ((siter = lys_getnext(siter, parent, module, 0))) {
- switch (siter->nodetype) {
- case LYS_CONTAINER:
- case LYS_ANYXML:
- case LYS_ANYDATA:
- case LYS_LEAF:
- lyd_find_sibling_val(sibling, siter, NULL, 0, &match);
- break;
- case LYS_LIST:
- case LYS_LEAFLIST:
- lyd_find_sibling_next2(sibling, siter, NULL, 0, &match);
- break;
- default:
- assert(0);
- LOGINT(NULL);
- }
-
- if (match) {
+ if (!lyd_find_sibling_val(sibling, siter, NULL, 0, &match)) {
break;
}
}
@@ -450,14 +431,7 @@
if (lyd_val_has_default(node->schema)) {
assert(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CONTAINER));
- if (node->schema->nodetype == LYS_LEAFLIST) {
- lyd_find_sibling_next2(*first, node->schema, NULL, 0, &match);
- } else {
- lyd_find_sibling_val(*first, node->schema, NULL, 0, &match);
- }
-
- while (match) {
- next = match->next;
+ LYD_LIST_FOR_INST_SAFE(*first, node->schema, next, match) {
if ((match->flags & LYD_DEFAULT) && !(match->flags & LYD_NEW)) {
/* default instance found, remove it */
if (LYD_DEL_IS_ROOT(*first, match)) {
@@ -484,8 +458,6 @@
break;
}
}
-
- lyd_find_sibling_next2(next, node->schema, NULL, 0, &match);
}
}
}
@@ -572,27 +544,25 @@
lyd_validate_minmax(const struct lyd_node *first, const struct lysc_node *snode, uint32_t min, uint32_t max)
{
uint32_t count = 0;
- const struct lyd_node *iter;
+ struct lyd_node *iter;
assert(min || max);
- LY_LIST_FOR(first, iter) {
- if (iter->schema == snode) {
- ++count;
+ LYD_LIST_FOR_INST(first, snode, iter) {
+ ++count;
- if (min && (count == min)) {
- /* satisfied */
- min = 0;
- if (!max) {
- /* nothing more to check */
- break;
- }
- }
- if (max && (count > max)) {
- /* not satisifed */
+ if (min && (count == min)) {
+ /* satisfied */
+ min = 0;
+ if (!max) {
+ /* nothing more to check */
break;
}
}
+ if (max && (count > max)) {
+ /* not satisifed */
+ break;
+ }
}
if (min) {
@@ -1160,7 +1130,7 @@
}
break;
case LYS_LEAFLIST:
- if (((struct lysc_node_leaflist *)iter)->dflts && lyd_find_sibling_next2(*first, iter, NULL, 0, NULL)) {
+ if (((struct lysc_node_leaflist *)iter)->dflts && lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
/* create all default leaf-lists */
dflts = ((struct lysc_node_leaflist *)iter)->dflts;
LY_ARRAY_FOR(dflts, u) {