validation NEW default values creation

Also a lot of other refactoring and
improvements. No tests yet.
diff --git a/src/parser_xml.c b/src/parser_xml.c
index f61d6e6..bc38598 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -17,6 +17,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <assert.h>
 
 #include "context.h"
 #include "dict.h"
@@ -206,7 +207,7 @@
  * @param[in] parent Parent node where the children are inserted. NULL in case of parsing top-level elements.
  * @param[in,out] data Pointer to the XML string representation of the YANG data to parse.
  * @param[out] node Resulting list of the parsed nodes.
- * @reutn LY_ERR value.
+ * @return LY_ERR value.
  */
 static LY_ERR
 lydxml_nodes(struct lyd_xml_ctx *ctx, struct lyd_node_inner *parent, const char **data, struct lyd_node **node)
@@ -294,10 +295,27 @@
             /* buffer spent */
             buffer = NULL;
             if (ret == LY_EINCOMPLETE) {
-                ly_set_add(&ctx->incomplete_type_validation, cur, LY_SET_OPT_USEASLIST);
+                if (!(ctx->options & LYD_OPT_PARSE_ONLY)) {
+                    ly_set_add(&ctx->incomplete_type_validation, cur, LY_SET_OPT_USEASLIST);
+                }
             } else if (ret) {
                 goto cleanup;
             }
+
+            if (parent && (cur->schema->flags & LYS_KEY)) {
+                /* check the key order, the anchor must always be the last child */
+                key_anchor = lyd_get_prev_key_anchor(parent->child, cur->schema);
+                if ((!key_anchor && parent->child) || (key_anchor && key_anchor->next)) {
+                    if (ctx->options & LYD_OPT_STRICT) {
+                        LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_DATA, "Invalid position of the key \"%s\" in a list.",
+                                cur->schema->name);
+                        ret = LY_EVALID;
+                        goto cleanup;
+                    } else {
+                        LOGWRN(ctx->ctx, "Invalid position of the key \"%s\" in a list.", cur->schema->name);
+                    }
+                }
+            }
         } else if (snode->nodetype & LYD_NODE_INNER) {
             if (ctx->status == LYXML_ELEM_CONTENT) {
                 LY_ERR r = lyxml_get_string((struct lyxml_context *)ctx, data, &buffer, &buffer_size, &value, &value_len, &dynamic);
@@ -317,6 +335,18 @@
                 ret = lydxml_nodes(ctx, (struct lyd_node_inner *)cur, data, lyd_node_children_p(cur));
                 LY_CHECK_GOTO(ret, cleanup);
             }
+
+            if (!(ctx->options & LYD_OPT_PARSE_ONLY)) {
+                /* add any missing default children */
+                ret = lyd_validate_defaults_r((struct lyd_node_inner *)cur, lyd_node_children_p(cur), cur->schema, NULL,
+                                              &ctx->incomplete_type_validation, &ctx->when_check);
+                LY_CHECK_GOTO(ret, cleanup);
+            }
+
+            /* hash now that all keys should be parsed, rehash for key-less list */
+            if (snode->nodetype == LYS_LIST) {
+                lyd_hash(cur);
+            }
         } else if (snode->nodetype & LYD_NODE_ANY) {
             unsigned int cur_element_index = ctx->elements.count;
             const char *start = *data, *stop;
@@ -369,42 +399,27 @@
         /* add attributes */
         LY_CHECK_GOTO(ret = lydxml_attributes(ctx, &attrs_data, cur), cleanup);
 
-        /* remember we need to evaluate this node's when */
+        /* correct flags */
         if (!(snode->nodetype & (LYS_ACTION | LYS_NOTIF)) && snode->when) {
-            ly_set_add(&ctx->when_check, cur, LY_SET_OPT_USEASLIST);
+            if (ctx->options & LYD_OPT_TRUSTED) {
+                /* just set it to true */
+                cur->flags |= LYD_WHEN_TRUE;
+            } else {
+                /* remember we need to evaluate this node's when */
+                ly_set_add(&ctx->when_check, cur, LY_SET_OPT_USEASLIST);
+            }
         }
-
-        /* hash */
-        lyd_hash(cur);
+        if (ctx->options & LYD_OPT_TRUSTED) {
+            /* node is valid */
+            cur->flags &= ~LYD_NEW;
+        }
 
         /* insert */
-        if (parent) {
-            if (cur->schema->flags & LYS_KEY) {
-                /* check the key order, the anchor must always be the last child */
-                key_anchor = lyd_get_prev_key_anchor(parent->child, cur->schema);
-                if ((!key_anchor && parent->child) || (key_anchor && key_anchor->next)) {
-                    if (ctx->options & LYD_OPT_STRICT) {
-                        LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_DATA, "Invalid position of the key \"%s\" in a list.",
-                               cur->schema->name);
-                        ret = LY_EVALID;
-                        goto cleanup;
-                    } else {
-                        LOGWRN(ctx->ctx, "Invalid position of the key \"%s\" in a list.", cur->schema->name);
-                    }
-                }
-            }
-            lyd_insert_node((struct lyd_node *)parent, NULL, cur);
-        } else if (*node) {
-            lyd_insert_node(NULL, *node, cur);
-        } else {
-            (*node) = cur;
-        }
+        lyd_insert_node((struct lyd_node *)parent, node, cur);
 
         cur = NULL;
     }
 
-    /* TODO add missing siblings default elements */
-
     /* success */
     ret = LY_SUCCESS;
 
@@ -428,7 +443,6 @@
 lyd_parse_xml(struct ly_ctx *ctx, const char *data, int options, struct lyd_node **result)
 {
     LY_ERR ret = LY_SUCCESS;
-    struct lyd_node_inner *parent = NULL;
     const struct lyd_node **result_trees = NULL;
     struct lyd_xml_ctx xmlctx = {0};
 
@@ -439,68 +453,38 @@
     /* init */
     *result = NULL;
 
-#if 0
-    if (options & LYD_OPT_RPCREPLY) {
-        /* prepare container for RPC reply, for which we need RPC
-         * - prepare *result as top-level node
-         * - prepare parent as the RPC/action node */
-        const struct lyd_node *action;
-        for (action = trees[0]; action && action->schema->nodetype != LYS_ACTION; action = lyd_node_children(action)) {
-            /* skip list's keys */
-            for ( ;action && action->schema->nodetype == LYS_LEAF; action = action->next);
-            if (action && action->schema->nodetype == LYS_ACTION) {
-                break;
-            }
-        }
-        if (!action) {
-            LOGERR(ctx, LY_EINVAL, "Data parser invalid argument trees - the first item in the array must be the RPC/action request when parsing %s.",
-                   lyd_parse_options_type2str(options));
-            return LY_EINVAL;
-        }
-        parent = (struct lyd_node_inner*)lyd_dup(action, NULL, LYD_DUP_WITH_PARENTS);
-        LY_CHECK_ERR_RET(!parent, LOGERR(ctx, ly_errcode(ctx), "Unable to duplicate RPC/action container for RPC/action reply."), ly_errcode(ctx));
-        for (*result = (struct lyd_node*)parent; (*result)->parent; *result = (struct lyd_node*)(*result)->parent);
-    }
-#endif
-
-    if (!data || !data[0]) {
-        /* no data - just check for missing mandatory nodes */
-        goto validation;
-    }
-
-    ret = lydxml_nodes(&xmlctx, parent, &data, *result ? &parent->child : result);
+    ret = lydxml_nodes(&xmlctx, NULL, &data, result);
     LY_CHECK_GOTO(ret, cleanup);
 
-    /* prepare sized array for validator */
-    if (*result) {
-        result_trees = lyd_trees_new(1, *result);
+    if (!(options & LYD_OPT_PARSE_ONLY)) {
+        /* add top-level default nodes */
+        ret = lyd_validate_defaults_top(result, NULL, 0, ctx, &xmlctx.incomplete_type_validation, &xmlctx.when_check, options);
+        LY_CHECK_GOTO(ret, cleanup);
+
+        /* prepare sized array for validator */
+        if (*result) {
+            result_trees = lyd_trees_new(1, *result);
+        }
+
+        /* finish incompletely validated terminal values/attributes and when conditions */
+        ret = lyd_validate_unres(&xmlctx.incomplete_type_validation, &xmlctx.incomplete_type_validation_attrs,
+                                 &xmlctx.when_check, LYD_XML, lydxml_resolve_prefix, ctx, result_trees);
+        LY_CHECK_GOTO(ret, cleanup);
+
+        /* context node and other validation tasks that depend on other data nodes */
+        ret = lyd_validate_data(result_trees, NULL, 0, ctx, options);
+        LY_CHECK_GOTO(result, cleanup);
     }
 
-    /* finish incompletely validated terminal values/attributes and when conditions */
-    ret = lyd_validate_unres(&xmlctx.incomplete_type_validation, &xmlctx.incomplete_type_validation_attrs,
-                             &xmlctx.when_check, LYD_XML, lydxml_resolve_prefix, ctx, result_trees);
-    LY_CHECK_GOTO(ret, cleanup);
-
-validation:
-#if 0
-    if ((!(*result) || (parent && !parent->child)) && (options & (LYD_OPT_RPC | LYD_OPT_NOTIF))) {
-        /* error, missing top level node identify RPC and Notification */
-        LOGERR(ctx, LY_EINVAL, "Invalid input data of data parser - expected %s which cannot be empty.",
-               lyd_parse_options_type2str(options));
-        ret = LY_EINVAL;
-        goto cleanup;
-    }
-#endif
-
-    /* context node and other validation tasks that depend on other data nodes */
-    ret = lyd_validate_data(result_trees, NULL, 0, ctx, options);
-    LY_CHECK_GOTO(result, cleanup);
-
 cleanup:
+    /* there should be no unresolved types stored */
+    assert(!(options & LYD_OPT_PARSE_ONLY) || (!xmlctx.incomplete_type_validation.count
+           && !xmlctx.incomplete_type_validation_attrs.count && !xmlctx.when_check.count));
+
     ly_set_erase(&xmlctx.incomplete_type_validation, NULL);
     ly_set_erase(&xmlctx.incomplete_type_validation_attrs, NULL);
     ly_set_erase(&xmlctx.when_check, NULL);
-    lyxml_context_clear((struct lyxml_context*)&xmlctx);
+    lyxml_context_clear((struct lyxml_context *)&xmlctx);
     lyd_trees_free(result_trees, 0);
     if (ret) {
         lyd_free_all(*result);