tree data REFACTOR recursive default node creation

Avoid multiple schema/data tree traversals when
creating default nodes.
diff --git a/src/tree_data_internal.h b/src/tree_data_internal.h
index b3a027c..358528c 100644
--- a/src/tree_data_internal.h
+++ b/src/tree_data_internal.h
@@ -345,7 +345,25 @@
         LY_VALUE_FORMAT format, void *val_prefix_data, uint32_t hints, struct lyd_node **node);
 
 /**
- * @brief Check the existence and create any non-existing implicit siblings, recursively for the created nodes.
+ * @brief Check the existence and create any non-existing implicit children.
+ *
+ * @param[in] parent Parent of the potential default values, NULL for top-level siblings.
+ * @param[in,out] first First sibling.
+ * @param[in] sparent Schema parent of the siblings, NULL if schema of @p parent can be used.
+ * @param[in] mod Module of the default values, NULL for nested siblings.
+ * @param[in] node_when Optional set to add nodes with "when" conditions into.
+ * @param[in] node_types Optional set to add nodes with unresolved types into.
+ * @param[in] ext_node Optional set to add nodes with extension instance node callbacks into.
+ * @param[in] impl_opts Implicit options (@ref implicitoptions).
+ * @param[in,out] diff Validation diff.
+ * @return LY_ERR value.
+ */
+LY_ERR lyd_new_implicit(struct lyd_node *parent, struct lyd_node **first, const struct lysc_node *sparent,
+        const struct lys_module *mod, struct ly_set *node_when, struct ly_set *node_types, struct ly_set *ext_node,
+        uint32_t impl_opts, struct lyd_node **diff);
+
+/**
+ * @brief Check the existence and create any non-existing implicit children, recursively for containers.
  *
  * @param[in] parent Parent of the potential default values, NULL for top-level siblings.
  * @param[in,out] first First sibling.
diff --git a/src/tree_data_new.c b/src/tree_data_new.c
index 1ecc9f3..cd5d63b 100644
--- a/src/tree_data_new.c
+++ b/src/tree_data_new.c
@@ -1876,7 +1876,7 @@
 }
 
 LY_ERR
-lyd_new_implicit_r(struct lyd_node *parent, struct lyd_node **first, const struct lysc_node *sparent,
+lyd_new_implicit(struct lyd_node *parent, struct lyd_node **first, const struct lysc_node *sparent,
         const struct lys_module *mod, struct ly_set *node_when, struct ly_set *node_types, struct ly_set *ext_node,
         uint32_t impl_opts, struct lyd_node **diff)
 {
@@ -1910,12 +1910,12 @@
             node = lys_getnext_data(NULL, *first, NULL, iter, NULL);
             if (!node && ((struct lysc_node_choice *)iter)->dflt) {
                 /* create default case data */
-                LY_CHECK_RET(lyd_new_implicit_r(parent, first, &((struct lysc_node_choice *)iter)->dflt->node,
+                LY_CHECK_RET(lyd_new_implicit(parent, first, &((struct lysc_node_choice *)iter)->dflt->node,
                         NULL, node_when, node_types, ext_node, impl_opts, diff));
             } else if (node) {
                 /* create any default data in the existing case */
                 assert(node->schema->parent->nodetype == LYS_CASE);
-                LY_CHECK_RET(lyd_new_implicit_r(parent, first, node->schema->parent, NULL, node_when, node_types,
+                LY_CHECK_RET(lyd_new_implicit(parent, first, node->schema->parent, NULL, node_when, node_types,
                         ext_node, impl_opts, diff));
             }
             break;
@@ -1938,10 +1938,6 @@
                     /* add into diff */
                     LY_CHECK_RET(lyd_val_diff_add(node, LYD_DIFF_OP_CREATE, diff));
                 }
-
-                /* create any default children */
-                LY_CHECK_RET(lyd_new_implicit_r(node, lyd_node_child_p(node), NULL, NULL, node_when, node_types,
-                        ext_node, impl_opts, diff));
             }
             break;
         case LYS_LEAF:
@@ -2016,6 +2012,28 @@
     return LY_SUCCESS;
 }
 
+LY_ERR
+lyd_new_implicit_r(struct lyd_node *parent, struct lyd_node **first, const struct lysc_node *sparent,
+        const struct lys_module *mod, struct ly_set *node_when, struct ly_set *node_types, struct ly_set *ext_node,
+        uint32_t impl_opts, struct lyd_node **diff)
+{
+    struct lyd_node *child;
+
+    /* parent children */
+    LY_CHECK_RET(lyd_new_implicit(parent, first, sparent, mod, node_when, node_types, ext_node,
+            impl_opts, diff));
+
+    LY_LIST_FOR(parent ? lyd_child_no_keys(parent) : *first, child) {
+        /* recursively for all the containers */
+        if ((child->flags & LYD_DEFAULT) && (child->schema->nodetype == LYS_CONTAINER)) {
+            LY_CHECK_RET(lyd_new_implicit_r(child, lyd_node_child_p(child), NULL, mod, node_when, node_types, ext_node,
+                    impl_opts, diff));
+        }
+    }
+
+    return LY_SUCCESS;
+}
+
 LIBYANG_API_DEF LY_ERR
 lyd_new_implicit_tree(struct lyd_node *tree, uint32_t implicit_options, struct lyd_node **diff)
 {
@@ -2030,7 +2048,7 @@
 
     LYD_TREE_DFS_BEGIN(tree, node) {
         if (node->schema && (node->schema->nodetype & LYD_NODE_INNER)) {
-            LY_CHECK_GOTO(ret = lyd_new_implicit_r(node, lyd_node_child_p(node), NULL, NULL, &node_when, NULL,
+            LY_CHECK_GOTO(ret = lyd_new_implicit(node, lyd_node_child_p(node), NULL, NULL, &node_when, NULL,
                     NULL, implicit_options, diff), cleanup);
         }
 
@@ -2105,14 +2123,14 @@
     }
 
     /* add all top-level defaults for this module */
-    LY_CHECK_GOTO(ret = lyd_new_implicit_r(NULL, tree, NULL, module, &node_when, NULL, NULL, implicit_options, diff),
+    LY_CHECK_GOTO(ret = lyd_new_implicit(NULL, tree, NULL, module, &node_when, NULL, NULL, implicit_options, diff),
             cleanup);
 
     /* resolve when and remove any invalid defaults */
     LY_CHECK_GOTO(ret = lyd_validate_unres(tree, module, 0, &node_when, LYXP_IGNORE_WHEN, NULL, NULL, NULL, NULL,
             0, diff), cleanup);
 
-    /* process nested nodes */
+    /* process top-level (and nested) nodes */
     LY_LIST_FOR(*tree, root) {
         LY_CHECK_GOTO(ret = lyd_new_implicit_tree(root, implicit_options, diff ? &d : NULL), cleanup);
 
diff --git a/src/validation.c b/src/validation.c
index a950c54..4f91ab3 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -1782,7 +1782,7 @@
             if (val_opts & LYD_VALIDATE_NO_DEFAULTS) {
                 impl_opts |= LYD_IMPLICIT_NO_DEFAULTS;
             }
-            r = lyd_new_implicit_r(node, lyd_node_child_p(node), NULL, NULL, NULL, NULL, NULL, impl_opts, diff);
+            r = lyd_new_implicit(node, lyd_node_child_p(node), NULL, NULL, NULL, NULL, NULL, impl_opts, diff);
             LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
         }
 
@@ -1857,9 +1857,15 @@
         if (val_opts & LYD_VALIDATE_NO_DEFAULTS) {
             impl_opts |= LYD_IMPLICIT_NO_DEFAULTS;
         }
-        r = lyd_new_implicit_r(lyd_parent(*first2), first2, NULL, mod, validate_subtree ? NULL : node_when_p,
-                validate_subtree ? NULL : node_types_p, validate_subtree ? NULL : ext_node_p, impl_opts, diff);
-        LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
+        if (validate_subtree) {
+            r = lyd_new_implicit(lyd_parent(*first2), first2, NULL, mod, NULL, NULL, NULL, impl_opts, diff);
+            LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
+        } else {
+            /* descendants will not be validated, create them all */
+            r = lyd_new_implicit_r(lyd_parent(*first2), first2, NULL, mod, node_when_p, node_types_p, ext_node_p,
+                    impl_opts, diff);
+            LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
+        }
 
         /* our first module node pointer may no longer be the first */
         first = *first2;
@@ -2069,17 +2075,22 @@
     }
 
     if (int_opts & LYD_INTOPT_REPLY) {
-        /* add output children defaults */
-        rc = lyd_new_implicit_r(op_node, lyd_node_child_p(op_node), NULL, NULL, node_when_p, node_types_p,
-                ext_node_p, LYD_IMPLICIT_OUTPUT, diff);
-        LY_CHECK_GOTO(rc, cleanup);
-
         if (validate_subtree) {
+            /* add output children defaults */
+            rc = lyd_new_implicit(op_node, lyd_node_child_p(op_node), NULL, NULL, node_when_p, node_types_p,
+                    ext_node_p, LYD_IMPLICIT_OUTPUT, diff);
+            LY_CHECK_GOTO(rc, cleanup);
+
             /* skip validating the operation itself, go to children directly */
             LY_LIST_FOR(lyd_child(op_node), child) {
                 rc = lyd_validate_subtree(child, node_when_p, node_types_p, meta_types_p, ext_node_p, ext_val_p, 0, diff);
                 LY_CHECK_GOTO(rc, cleanup);
             }
+        } else {
+            /* add output children defaults and their descendants */
+            rc = lyd_new_implicit_r(op_node, lyd_node_child_p(op_node), NULL, NULL, node_when_p, node_types_p,
+                    ext_node_p, LYD_IMPLICIT_OUTPUT, diff);
+            LY_CHECK_GOTO(rc, cleanup);
         }
     } else {
         if (validate_subtree) {