validation NEW duplicate instances
Also trees structure removed, some
refactoring included.
diff --git a/src/tree_data.c b/src/tree_data.c
index 78529f5..bf3402c 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -42,89 +42,16 @@
size_t key_count;
};
-API void
-lyd_trees_free(const struct lyd_node **trees, int free_data)
-{
- if (!trees) {
- return;
- }
-
- if (free_data) {
- unsigned int u;
- LY_ARRAY_FOR(trees, u) {
- lyd_free_all((struct lyd_node *)trees[u]);
- }
- }
- LY_ARRAY_FREE(trees);
-}
-
-static const struct lyd_node *
-lyd_trees_getstart(const struct lyd_node *tree)
-{
- if (!tree) {
- return NULL;
- }
- while (tree->prev->next) {
- tree = tree->prev;
- }
- return tree;
-}
-
-API const struct lyd_node **
-lyd_trees_new(size_t count, const struct lyd_node *tree, ...)
-{
- LY_ERR ret;
- const struct lyd_node **trees = NULL;
- va_list ap;
-
- LY_CHECK_ARG_RET(NULL, tree, count > 0, NULL);
-
- va_start(ap, tree);
-
- LY_ARRAY_CREATE_GOTO(tree->schema->module->ctx, trees, count, ret, error);
- /* first, mandatory, tree to insert */
- trees[0] = lyd_trees_getstart(tree);
- LY_ARRAY_INCREMENT(trees);
-
- /* variable arguments */
- for (unsigned int u = 1; u < count; ++u) {
- trees[u] = lyd_trees_getstart(va_arg(ap, const struct lyd_node *));
- LY_ARRAY_INCREMENT(trees);
- }
-
- va_end(ap);
- return trees;
-
-error:
- (void)ret; /* unused */
- lyd_trees_free(trees, 1);
- va_end(ap);
- return NULL;
-}
-
-API const struct lyd_node **
-lyd_trees_add(const struct lyd_node **trees, const struct lyd_node *tree)
-{
- const struct lyd_node **t = NULL;
-
- LY_CHECK_ARG_RET(NULL, tree, trees, trees);
-
- LY_ARRAY_NEW_RET(tree->schema->module->ctx, trees, t, NULL);
- *t = lyd_trees_getstart(tree);
-
- return trees;
-}
-
LY_ERR
lyd_value_parse(struct lyd_node_term *node, const char *value, size_t value_len, int *dynamic, int second,
- ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format, const struct lyd_node **trees)
+ ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format, const struct lyd_node *tree)
{
LY_ERR ret = LY_SUCCESS;
struct ly_err_item *err = NULL;
struct ly_ctx *ctx;
struct lysc_type *type;
int options = LY_TYPE_OPTS_STORE | (second ? LY_TYPE_OPTS_SECOND_CALL : 0) |
- (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (trees ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
+ (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
assert(node);
ctx = node->schema->module->ctx;
@@ -134,7 +61,7 @@
node->value.realtype = type;
}
ret = type->plugin->store(ctx, type, value, value_len, options, get_prefix, parser, format,
- trees ? (void*)node : (void*)node->schema, trees,
+ tree ? (void *)node : (void *)node->schema, tree,
&node->value, NULL, &err);
if (ret && (ret != LY_EINCOMPLETE)) {
if (err) {
@@ -187,15 +114,15 @@
LY_ERR
lyd_value_parse_attr(struct ly_ctx *ctx, struct lyd_attr *attr, const char *value, size_t value_len, int *dynamic,
int second, ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format,
- const struct lysc_node *ctx_snode, const struct lyd_node **trees)
+ const struct lysc_node *ctx_snode, const struct lyd_node *tree)
{
LY_ERR ret = LY_SUCCESS;
struct ly_err_item *err = NULL;
struct lyext_metadata *ant;
int options = LY_TYPE_OPTS_STORE | (second ? LY_TYPE_OPTS_SECOND_CALL : 0) |
- (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (trees ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
+ (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
- assert(ctx && attr && ((trees && attr->parent) || ctx_snode));
+ assert(ctx && attr && ((tree && attr->parent) || ctx_snode));
ant = attr->annotation->data;
@@ -203,7 +130,7 @@
attr->value.realtype = ant->type;
}
ret = ant->type->plugin->store(ctx, ant->type, value, value_len, options, get_prefix, parser, format,
- trees ? (void *)attr->parent : (void *)ctx_snode, trees, &attr->value, NULL, &err);
+ tree ? (void *)attr->parent : (void *)ctx_snode, tree, &attr->value, NULL, &err);
if (ret && (ret != LY_EINCOMPLETE)) {
if (err) {
ly_err_print(err);
@@ -256,18 +183,18 @@
API LY_ERR
lyd_value_validate(struct ly_ctx *ctx, const struct lyd_node_term *node, const char *value, size_t value_len,
- ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format, const struct lyd_node **trees)
+ ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format, const struct lyd_node *tree)
{
LY_ERR rc;
struct ly_err_item *err = NULL;
struct lysc_type *type;
- int options = (trees ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
+ int options = (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
type = ((struct lysc_node_leaf*)node->schema)->type;
rc = type->plugin->store(ctx ? ctx : node->schema->module->ctx, type, value, value_len, options,
- get_prefix, get_prefix_data, format, trees ? (void*)node : (void*)node->schema, trees,
+ get_prefix, get_prefix_data, format, tree ? (void*)node : (void*)node->schema, tree,
NULL, NULL, &err);
if (rc == LY_EINCOMPLETE) {
return rc;
@@ -287,21 +214,21 @@
API LY_ERR
lyd_value_compare(const struct lyd_node_term *node, const char *value, size_t value_len,
- ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format, const struct lyd_node **trees)
+ ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format, const struct lyd_node *tree)
{
LY_ERR ret = LY_SUCCESS, rc;
struct ly_err_item *err = NULL;
struct ly_ctx *ctx;
struct lysc_type *type;
struct lyd_value data = {0};
- int options = LY_TYPE_OPTS_STORE | (trees ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
+ int options = LY_TYPE_OPTS_STORE | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
LY_CHECK_ARG_RET(node ? node->schema->module->ctx : NULL, node, value, LY_EINVAL);
ctx = node->schema->module->ctx;
type = ((struct lysc_node_leaf*)node->schema)->type;
rc = type->plugin->store(ctx, type, value, value_len, options, get_prefix, get_prefix_data, format, (struct lyd_node*)node,
- trees, &data, NULL, &err);
+ tree, &data, NULL, &err);
if (rc == LY_EINCOMPLETE) {
ret = rc;
/* continue with comparing, just remember what to return if storing is ok */
@@ -605,7 +532,12 @@
memset(keys, 0, sizeof *keys);
- keys->str = strndup(keys_str, keys_len ? keys_len : strlen(keys_str));
+ if (!keys_str) {
+ /* nothing to parse */
+ return LY_SUCCESS;
+ }
+
+ keys->str = strndup(keys_str, keys_len);
LY_CHECK_ERR_GOTO(!keys->str, LOGMEM(list->module->ctx); ret = LY_EMEM, cleanup);
next_key = keys->str;
@@ -686,8 +618,8 @@
/* create and insert all the keys */
for (i = 0; i < keys.key_count; ++i) {
- LY_CHECK_GOTO(ret = lyd_create_term((struct lysc_node *)keys.keys[i].schema, keys.keys[i].value, 0, 0,
- lydjson_resolve_prefix, NULL, LYD_JSON, &key), cleanup);
+ LY_CHECK_GOTO(ret = lyd_create_term((struct lysc_node *)keys.keys[i].schema, keys.keys[i].value,
+ strlen(keys.keys[i].value), NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &key), cleanup);
lyd_insert_node(list, NULL, key);
}
@@ -735,6 +667,10 @@
LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
+ if (!module) {
+ module = parent->schema->module;
+ }
+
schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_CONTAINER | LYS_NOTIF | LYS_ACTION, 0);
LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Inner node \"%s\" not found.", name), NULL);
@@ -756,6 +692,10 @@
LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
+ if (!module) {
+ module = parent->schema->module;
+ }
+
schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, 0);
LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), NULL);
@@ -768,7 +708,8 @@
for (key_s = lysc_node_children(schema, 0); key_s && (key_s->flags & LYS_KEY); key_s = key_s->next) {
key_val = va_arg(ap, const char *);
- LY_CHECK_GOTO(rc = lyd_create_term(key_s, key_val, 0, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &key), cleanup);
+ rc = lyd_create_term(key_s, key_val, key_val ? strlen(key_val) : 0, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &key);
+ LY_CHECK_GOTO(rc, cleanup);
lyd_insert_node(ret, NULL, key);
}
@@ -797,10 +738,14 @@
LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
+ if (!module) {
+ module = parent->schema->module;
+ }
+
schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, 0);
LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), NULL);
- if (!lyd_create_list(schema, keys, 0, &ret) && parent) {
+ if (!lyd_create_list(schema, keys, keys ? strlen(keys) : 0, &ret) && parent) {
lyd_insert_node(parent, NULL, ret);
}
return ret;
@@ -815,10 +760,15 @@
LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
+ if (!module) {
+ module = parent->schema->module;
+ }
+
schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_TERM, 0);
LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Term node \"%s\" not found.", name), NULL);
- if (!lyd_create_term(schema, val_str, 0, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &ret) && parent) {
+ if (!lyd_create_term(schema, val_str, val_str ? strlen(val_str) : 0, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &ret)
+ && parent) {
lyd_insert_node(parent, NULL, ret);
}
return ret;
@@ -834,6 +784,10 @@
LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
+ if (!module) {
+ module = parent->schema->module;
+ }
+
schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_ANY, 0);
LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Any node \"%s\" not found.", name), NULL);
@@ -867,7 +821,7 @@
* @param[in] node Node to insert.
*/
static void
-lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
+lyd_insert_after_node(struct lyd_node *sibling, struct lyd_node *node)
{
assert(!node->next && (node->prev == node));
@@ -896,7 +850,7 @@
* @param[in] node Node to insert.
*/
static void
-lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
+lyd_insert_before_node(struct lyd_node *sibling, struct lyd_node *node)
{
assert(!node->next && (node->prev == node));
@@ -921,7 +875,7 @@
* @param[in] node Node to insert.
*/
static void
-lyd_insert_last(struct lyd_node *parent, struct lyd_node *node)
+lyd_insert_last_node(struct lyd_node *parent, struct lyd_node *node)
{
struct lyd_node_inner *par;
@@ -956,15 +910,15 @@
/* it is key and we need to insert it at the correct place */
anchor = lyd_get_prev_key_anchor(lyd_node_children(parent), node->schema);
if (anchor) {
- lyd_insert_after(anchor, node);
+ lyd_insert_after_node(anchor, node);
} else if (lyd_node_children(parent)) {
- lyd_insert_before((struct lyd_node *)lyd_node_children(parent), node);
+ lyd_insert_before_node((struct lyd_node *)lyd_node_children(parent), node);
} else {
- lyd_insert_last(parent, node);
+ lyd_insert_last_node(parent, node);
}
} else {
/* last child */
- lyd_insert_last(parent, node);
+ lyd_insert_last_node(parent, node);
}
} else if (*first_sibling) {
/* top-level siblings, find the last one from this module, or simply the last */
@@ -974,7 +928,7 @@
}
/* insert */
- lyd_insert_after(anchor, node);
+ lyd_insert_after_node(anchor, node);
} else {
/* the only sibling */
*first_sibling = node;
@@ -992,6 +946,187 @@
lyd_insert_hash(node);
}
+static LY_ERR
+lyd_insert_check_schema(const struct lysc_node *parent, const struct lysc_node *schema)
+{
+ const struct lysc_node *par2;
+
+ assert(schema);
+
+ /* adjust parent first */
+ while (parent && (parent->nodetype & (LYS_CASE | LYS_CHOICE))) {
+ parent = parent->parent;
+ }
+
+ /* find schema parent */
+ for (par2 = schema->parent; par2 && (par2->nodetype & (LYS_CASE | LYS_CHOICE)); par2 = par2->parent);
+
+ if (parent) {
+ /* inner node */
+ if (par2 != parent) {
+ LOGERR(parent->module->ctx, LY_EINVAL, "Cannot insert, parent of \"%s\" is not \"%s\".", schema->name, parent->name);
+ return LY_EINVAL;
+ }
+ } else {
+ /* top-level node */
+ if (par2) {
+ LOGERR(parent->module->ctx, LY_EINVAL, "Cannot insert, node \"%s\" is not top-level.", schema->name);
+ return LY_EINVAL;
+ }
+ }
+
+ return LY_SUCCESS;
+}
+
+API LY_ERR
+lyd_insert(struct lyd_node *parent, struct lyd_node *node)
+{
+ struct lyd_node *iter;
+
+ LY_CHECK_ARG_RET(NULL, parent, node, !(parent->schema->nodetype & LYD_NODE_INNER), LY_EINVAL);
+
+ LY_CHECK_RET(lyd_insert_check_schema(parent->schema, node->schema));
+
+ if (node->schema->flags & LYS_KEY) {
+ LOGERR(parent->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
+ return LY_EINVAL;
+ }
+
+ if (node->parent || node->prev->next) {
+ lyd_unlink_tree(node);
+ }
+
+ while (node) {
+ iter = node->next;
+ lyd_unlink_tree(node);
+ lyd_insert_node(parent, NULL, node);
+ node = iter;
+ }
+ return LY_SUCCESS;
+}
+
+API LY_ERR
+lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
+{
+ struct lyd_node *iter;
+
+ LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
+
+ LY_CHECK_RET(lyd_insert_check_schema(sibling->schema->parent, node->schema));
+
+ if (node->schema->flags & LYS_KEY) {
+ LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
+ return LY_EINVAL;
+ } else if (sibling->schema->flags & LYS_KEY) {
+ LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert into keys.");
+ return LY_EINVAL;
+ }
+
+ if (node->parent || node->prev->next) {
+ lyd_unlink_tree(node);
+ }
+
+ /* insert in reverse order to get the original order */
+ node = node->prev;
+ while (node) {
+ iter = node->prev;
+ lyd_unlink_tree(node);
+
+ lyd_insert_before_node(sibling, node);
+ /* move the anchor accordingly */
+ sibling = node;
+
+ node = (iter == node) ? NULL : iter;
+ }
+ return LY_SUCCESS;
+}
+
+API LY_ERR
+lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
+{
+ struct lyd_node *iter;
+
+ LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
+
+ LY_CHECK_RET(lyd_insert_check_schema(sibling->schema->parent, node->schema));
+
+ if (node->schema->flags & LYS_KEY) {
+ LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
+ return LY_EINVAL;
+ } else if (sibling->next && (sibling->next->schema->flags & LYS_KEY)) {
+ LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert into keys.");
+ return LY_EINVAL;
+ }
+
+ if (node->parent || node->prev->next) {
+ lyd_unlink_tree(node);
+ }
+
+ while (node) {
+ iter = node->next;
+ lyd_unlink_tree(node);
+
+ lyd_insert_after_node(sibling, node);
+ /* move the anchor accordingly */
+ sibling = node;
+
+ node = iter;
+ }
+ return LY_SUCCESS;
+}
+
+API void
+lyd_unlink_tree(struct lyd_node *node)
+{
+ struct lyd_node *iter;
+
+ if (!node) {
+ return;
+ }
+
+ /* unlink from siblings */
+ if (node->prev->next) {
+ node->prev->next = node->next;
+ }
+ if (node->next) {
+ node->next->prev = node->prev;
+ } else {
+ /* unlinking the last node */
+ if (node->parent) {
+ iter = node->parent->child;
+ } else {
+ iter = node->prev;
+ while (iter->prev != node) {
+ iter = iter->prev;
+ }
+ }
+ /* update the "last" pointer from the first node */
+ iter->prev = node->prev;
+ }
+
+ /* unlink from parent */
+ if (node->parent) {
+ if (node->parent->child == node) {
+ /* the node is the first child */
+ node->parent->child = node->next;
+ }
+
+ lyd_unlink_hash(node);
+
+ /* check for keyless list and update its hash */
+ for (iter = (struct lyd_node *)node->parent; iter; iter = (struct lyd_node *)iter->parent) {
+ if (iter->schema->flags & LYS_KEYLESS) {
+ lyd_hash(iter);
+ }
+ }
+
+ node->parent = NULL;
+ }
+
+ node->next = NULL;
+ node->prev = node;
+}
+
LY_ERR
lyd_create_attr(struct lyd_node *parent, struct lyd_attr **attr, const struct lys_module *mod, const char *name,
size_t name_len, const char *value, size_t value_len, int *dynamic, ly_clb_resolve_prefix get_prefix,
@@ -1056,14 +1191,14 @@
}
API const struct lyd_node_term *
-lyd_target(struct lyd_value_path *path, const struct lyd_node **trees)
+lyd_target(struct lyd_value_path *path, const struct lyd_node *tree)
{
- unsigned int u, v, x;
+ unsigned int u, x;
const struct lyd_node *parent = NULL, *start_search;
struct lyd_node *node = NULL;
uint64_t pos = 1;
- LY_CHECK_ARG_RET(NULL, path, trees, NULL);
+ LY_CHECK_ARG_RET(NULL, path, tree, NULL);
LY_ARRAY_FOR(path, u) {
if (parent) {
@@ -1071,15 +1206,10 @@
search_inner:
lyd_find_sibling_next(start_search, path[u].node->module, path[u].node->name, 0, NULL, 0, &node);
} else {
- LY_ARRAY_FOR(trees, v) {
- start_search = trees[v];
+ start_search = tree;
search_toplevel:
- /* WARNING! to use search_toplevel label correctly, variable v must be preserved and not changed! */
- lyd_find_sibling_next(start_search, path[u].node->module, path[u].node->name, 0, NULL, 0, &node);
- if (node) {
- break;
- }
- }
+ /* WARNING! to use search_toplevel label correctly, variable v must be preserved and not changed! */
+ lyd_find_sibling_next(start_search, path[u].node->module, path[u].node->name, 0, NULL, 0, &node);
}
if (!node) {
return NULL;
@@ -1498,7 +1628,7 @@
if (top) {
lyd_free_tree(top);
} else {
- lyd_free_withsiblings(first);
+ lyd_free_siblings(first);
}
return NULL;
}
@@ -1864,7 +1994,7 @@
struct lyd_node **match_p;
struct lyd_node_inner *parent;
- LY_CHECK_ARG_RET(NULL, target, match, LY_EINVAL);
+ LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
if (!siblings) {
/* no data */
@@ -2101,6 +2231,10 @@
return LY_ENOTFOUND;
}
+ if (key_or_value && !val_len) {
+ val_len = strlen(key_or_value);
+ }
+
/* create data node if needed and find it */
switch (schema->nodetype) {
case LYS_CONTAINER: