validation NEW default values creation
Also a lot of other refactoring and
improvements. No tests yet.
diff --git a/src/validation.c b/src/validation.c
index e2deb7a..a32a11e 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -160,27 +160,55 @@
return ly_ctx_get_module_iter(ctx, i);
}
+static int
+lyd_val_has_choice_data(const struct lysc_node *snode, struct lyd_node *sibling)
+{
+ const struct lysc_node *iter = NULL;
+
+ assert(snode->nodetype == LYS_CHOICE);
+
+ while ((iter = lys_getnext(iter, snode, NULL, 0))) {
+ switch (iter->nodetype) {
+ case LYS_CONTAINER:
+ case LYS_ANYXML:
+ case LYS_ANYDATA:
+ case LYS_LEAF:
+ if (!lyd_find_sibling_val(sibling, iter, NULL, 0, NULL)) {
+ /* one case child data instance found */
+ return 1;
+ }
+ break;
+ case LYS_LIST:
+ case LYS_LEAFLIST:
+ if (!lyd_find_sibling_next2(sibling, iter, NULL, 0, NULL)) {
+ /* one case child data instance found */
+ return 1;
+ }
+ break;
+ default:
+ assert(0);
+ LOGINT(snode->module->ctx);
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
static LY_ERR
lyd_validate_mandatory(const struct lysc_node *snode, struct lyd_node *sibling)
{
- struct lyd_node *node;
- int is_choice = 0;
-
if (snode->nodetype == LYS_CHOICE) {
- is_choice = 1;
- }
+ /* some data of a choice case exist */
+ if (lyd_val_has_choice_data(snode, sibling)) {
+ return LY_SUCCESS;
+ }
+ } else {
+ assert(snode->nodetype & (LYS_LEAF | LYS_CONTAINER | LYD_NODE_ANY));
- LY_LIST_FOR(sibling, node) {
- if (is_choice) {
- if (node->schema->parent && (node->schema->parent->nodetype & LYS_CASE) && (node->schema->parent->parent == snode)) {
- /* case data instance found */
- return LY_SUCCESS;
- }
- } else {
- if (node->schema == snode) {
- /* data instance found */
- return LY_SUCCESS;
- }
+ if (!lyd_find_sibling_val(sibling, snode, NULL, 0, NULL)) {
+ /* data instance found */
+ return LY_SUCCESS;
}
}
@@ -195,13 +223,29 @@
uint32_t count = 0;
struct lyd_node *iter;
+ assert(min || max);
+
LY_LIST_FOR(sibling, iter) {
if (iter->schema == snode) {
++count;
+
+ if (min && (count == min)) {
+ /* satisfied */
+ min = 0;
+ if (!max) {
+ /* nothing more to check */
+ break;
+ }
+ }
+ if (max && (count > max)) {
+ /* not satisifed */
+ break;
+ }
}
}
- if (min && (count < min)) {
+ if (min) {
+ assert(count < min);
LOGVAL(snode->module->ctx, LY_VLOG_LYSC, snode, LY_VCODE_NOMIN, snode->name);
return LY_EVALID;
} else if (max && (count > max)) {
@@ -215,16 +259,32 @@
static struct lyd_node *
lyd_val_uniq_find_leaf(const struct lysc_node_leaf *uniq_leaf, struct lyd_node *list)
{
- struct ly_set *set;
- struct lyd_node *node = NULL;
+ struct lyd_node *node;
+ const struct lysc_node *iter;
+ size_t depth = 0, i;
- set = lyd_find_instance(lyd_node_children(list), (struct lysc_node *)uniq_leaf);
- if (set && set->count) {
- /* we were looking for a leaf */
- assert(set->count == 1);
- node = set->objs[0];
+ /* get leaf depth */
+ for (iter = (struct lysc_node *)uniq_leaf; iter && (iter != list->schema); iter = iter->parent) {
+ if (!(iter->nodetype & (LYS_CHOICE | LYS_CASE))) {
+ ++depth;
+ }
}
- ly_set_free(set, NULL);
+
+ node = list;
+ while (node && depth) {
+ /* find schema node with this depth */
+ for (i = depth - 1, iter = (struct lysc_node *)uniq_leaf; i; iter = iter->parent) {
+ if (!(iter->nodetype & (LYS_CHOICE | LYS_CASE))) {
+ --i;
+ }
+ }
+
+ /* find iter instance in children */
+ assert(iter->nodetype & (LYS_CONTAINER | LYS_LEAF));
+ lyd_find_sibling_val(lyd_node_children(node), iter, NULL, 0, &node);
+ --depth;
+ }
+
return node;
}
@@ -346,8 +406,13 @@
assert(uniques);
/* get all list instances */
- set = lyd_find_instance(sibling, snode);
- LY_CHECK_RET(!set, LY_EINT);
+ set = ly_set_new();
+ LY_CHECK_ERR_RET(!set, LOGMEM(ctx), LY_EMEM);
+ LY_LIST_FOR(sibling, diter) {
+ if (diter->schema == snode) {
+ ly_set_add(set, diter, LY_SET_OPT_USEASLIST);
+ }
+ }
if (set->count == 2) {
/* simple comparison */
@@ -493,8 +558,8 @@
/* validate all restrictions of nodes themselves */
LY_LIST_FOR(sibling, node) {
+ /* TODO node instance duplicities */
/* TODO node's must */
- /* TODO node instance duplicites */
/* TODO node status */
/* TODO node's if-features */
/* TODO node list keys */
@@ -505,6 +570,9 @@
LY_CHECK_RET(lyd_validate_siblings_schema_r(sibling, sparent, mod, options));
LY_LIST_FOR(sibling, node) {
+ /* this sibling is valid */
+ node->flags &= ~LYD_NEW;
+
/* validate all children recursively */
LY_CHECK_RET(lyd_validate_siblings_r((struct lyd_node *)lyd_node_children(node), node->schema, mod, options));
}
@@ -514,19 +582,19 @@
LY_ERR
lyd_validate_data(const struct lyd_node **trees, const struct lys_module **modules, int mod_count, struct ly_ctx *ctx,
- int options)
+ int val_opts)
{
uint32_t i = 0, j;
const struct lys_module *mod;
struct lyd_node *tree;
- if (options & LYD_OPT_VAL_DATA_ONLY) {
+ if (val_opts & LYD_VALOPT_DATA_ONLY) {
if (trees) {
for (j = 0; j < LY_ARRAY_SIZE(trees); ++j) {
tree = (struct lyd_node *)trees[j];
/* validate all top-level nodes and then inner nodes recursively */
- LY_CHECK_RET(lyd_validate_siblings_r(tree, NULL, tree->schema->module->compiled, options));
+ LY_CHECK_RET(lyd_validate_siblings_r(tree, NULL, tree->schema->module->compiled, val_opts));
}
}
} else {
@@ -547,7 +615,112 @@
}
/* validate all top-level nodes and then inner nodes recursively */
- LY_CHECK_RET(lyd_validate_siblings_r(tree, NULL, mod->compiled, options));
+ LY_CHECK_RET(lyd_validate_siblings_r(tree, NULL, mod->compiled, val_opts));
+ }
+ }
+
+ return LY_SUCCESS;
+}
+
+LY_ERR
+lyd_validate_defaults_r(struct lyd_node_inner *parent, struct lyd_node **first, const struct lysc_node *schema,
+ const struct lysc_module *mod, struct ly_set *node_types, struct ly_set *node_when)
+{
+ const struct lysc_node *iter = NULL;
+ struct lyd_node *node;
+ struct lyd_value **dflts;
+ size_t i;
+
+ assert(first && (schema || mod) && node_types && node_when);
+
+ while ((iter = lys_getnext(iter, schema, mod, LYS_GETNEXT_WITHCHOICE))) {
+ switch (iter->nodetype) {
+ case LYS_CHOICE:
+ if (((struct lysc_node_choice *)iter)->dflt && !lyd_val_has_choice_data(iter, *first)) {
+ /* create default case data */
+ LY_CHECK_RET(lyd_validate_defaults_r(parent, first, (struct lysc_node *)((struct lysc_node_choice *)iter)->dflt,
+ NULL, node_types, node_when));
+ }
+ break;
+ case LYS_CONTAINER:
+ if (!(iter->flags & LYS_PRESENCE) && lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
+ /* create default NP container (default flag automatically set) */
+ LY_CHECK_RET(lyd_create_inner(iter, &node));
+ lyd_insert_node((struct lyd_node *)parent, first, node);
+
+ if (iter->when) {
+ /* remember to resolve when */
+ ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
+ }
+ }
+ break;
+ case LYS_LEAF:
+ if (((struct lysc_node_leaf *)iter)->dflt && lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
+ /* create default leaf */
+ LY_CHECK_RET(lyd_create_term2(iter, ((struct lysc_node_leaf *)iter)->dflt, &node));
+ node->flags |= LYD_DEFAULT;
+ lyd_insert_node((struct lyd_node *)parent, first, node);
+
+ if (iter->when) {
+ /* remember to resolve when */
+ ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
+ }
+ }
+ break;
+ case LYS_LEAFLIST:
+ if (((struct lysc_node_leaflist *)iter)->dflts && lyd_find_sibling_next2(*first, iter, NULL, 0, NULL)) {
+ /* create all default leaf-lists */
+ dflts = ((struct lysc_node_leaflist *)iter)->dflts;
+ LY_ARRAY_FOR(dflts, i) {
+ LY_CHECK_RET(lyd_create_term2(iter, dflts[i], &node));
+ node->flags |= LYD_DEFAULT;
+ lyd_insert_node((struct lyd_node *)parent, first, node);
+
+ if (iter->when) {
+ /* remember to resolve when */
+ ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
+ }
+ }
+ }
+ break;
+ default:
+ /* without defaults */
+ break;
+ }
+ }
+
+ return LY_SUCCESS;
+}
+
+LY_ERR
+lyd_validate_defaults_top(struct lyd_node **first, const struct lys_module **modules, int mod_count, struct ly_ctx *ctx,
+ struct ly_set *node_types, struct ly_set *node_when, int val_opts)
+{
+ uint32_t i = 0;
+ const struct lys_module *mod;
+ struct lyd_node *sibling;
+
+ assert(node_types && node_when);
+
+ if (val_opts & LYD_VALOPT_DATA_ONLY) {
+ mod = NULL;
+ LY_LIST_FOR(*first, sibling) {
+ if (lyd_top_node_module(sibling) != mod) {
+ /* remember this module */
+ mod = lyd_top_node_module(sibling);
+
+ /* add all top-level defaults for this module */
+ LY_CHECK_RET(lyd_validate_defaults_r(NULL, first, NULL, mod->compiled, node_types, node_when));
+ }
+ }
+ } else {
+ while ((mod = lyd_val_next_module(modules, mod_count, ctx, &i))) {
+ if (!mod->implemented) {
+ continue;
+ }
+
+ /* add all top-level defaults for this module */
+ LY_CHECK_RET(lyd_validate_defaults_r(NULL, first, NULL, mod->compiled, node_types, node_when));
}
}