data FEATURE add helpers functions to work with data trees (sized arrays)

Adds lyd_trees_new() and lyd_trees_free() and unifies work with the data
trees in validation functions.
diff --git a/src/parser_xml.c b/src/parser_xml.c
index e94e4f5..75e3c55 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -306,18 +306,16 @@
         /* finish incompletely validated terminal values */
         for (unsigned int u = 0; u < xmlctx.incomplete_type_validation.count; u++) {
             struct lyd_node_term *node = (struct lyd_node_term*)xmlctx.incomplete_type_validation.objs[u];
-            struct lyd_node **trees = NULL;
+            const struct lyd_node **trees = NULL;
 
             /* prepare sized array for validator */
             if (*result) {
-                struct lyd_node **tree;
-                LY_ARRAY_NEW_RET(ctx, trees, tree, LY_EMEM);
-                *tree = *result;
+                trees = lyd_trees_new(1, *result);
             }
             /* validate and store the value of the node */
             ret = lyd_value_parse(node, node->value.canonized, node->value.canonized ? strlen(node->value.canonized) : 0, 0, 1,
                                   lydxml_resolve_prefix, ctx, LYD_XML, trees);
-            LY_ARRAY_FREE(trees);
+            lyd_trees_free(trees, 0);
             if (ret) {
                 lyd_free_all(*result);
                 *result = NULL;
diff --git a/src/plugins_types.c b/src/plugins_types.c
index 9658afd..736f173 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -405,7 +405,7 @@
 static LY_ERR
 ly_type_store_int(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
                   ly_clb_resolve_prefix UNUSED(get_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
-                  const void *UNUSED(context_node), struct lyd_node **UNUSED(trees),
+                  const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
                   struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
 {
     LY_ERR ret;
@@ -468,7 +468,7 @@
 static LY_ERR
 ly_type_store_uint(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
                    ly_clb_resolve_prefix UNUSED(get_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
-                   const void *UNUSED(context_node), struct lyd_node **UNUSED(trees),
+                   const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
                    struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
 {
     LY_ERR ret;
@@ -529,7 +529,7 @@
 static LY_ERR
 ly_type_store_decimal64(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
                         ly_clb_resolve_prefix UNUSED(get_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
-                        const void *UNUSED(context_node), struct lyd_node **UNUSED(trees),
+                        const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
                         struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
 {
     int64_t d;
@@ -601,7 +601,7 @@
 static LY_ERR
 ly_type_store_binary(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
                      ly_clb_resolve_prefix UNUSED(get_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
-                     const void *UNUSED(context_node), struct lyd_node **UNUSED(trees),
+                     const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
                      struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
 {
     size_t start = 0, stop = 0, count = 0, u, termination = 0;
@@ -704,7 +704,7 @@
 static LY_ERR
 ly_type_store_string(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
                      ly_clb_resolve_prefix UNUSED(get_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
-                     const void *UNUSED(context_node), struct lyd_node **UNUSED(trees),
+                     const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
                      struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
 {
     struct lysc_type_str *type_str = (struct lysc_type_str *)type;
@@ -747,7 +747,7 @@
 static LY_ERR
 ly_type_store_bits(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
                    ly_clb_resolve_prefix UNUSED(get_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
-                   const void *UNUSED(context_node), struct lyd_node **UNUSED(trees),
+                   const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
                    struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
 {
     LY_ERR ret = LY_EVALID;
@@ -915,7 +915,7 @@
 static LY_ERR
 ly_type_store_enum(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
                    ly_clb_resolve_prefix UNUSED(get_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
-                   const void *UNUSED(context_node), struct lyd_node **UNUSED(trees),
+                   const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
                    struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
 {
     unsigned int u, v;
@@ -983,7 +983,7 @@
 static LY_ERR
 ly_type_store_boolean(struct ly_ctx *ctx, struct lysc_type *UNUSED(type), const char *value, size_t value_len, int options,
                       ly_clb_resolve_prefix UNUSED(get_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
-                      const void *UNUSED(context_node), struct lyd_node **UNUSED(trees),
+                      const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
                       struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
 {
     int8_t i;
@@ -1031,7 +1031,7 @@
 static LY_ERR
 ly_type_store_empty(struct ly_ctx *ctx, struct lysc_type *UNUSED(type), const char *value, size_t value_len, int options,
                     ly_clb_resolve_prefix UNUSED(get_prefix), void *UNUSED(parser), LYD_FORMAT UNUSED(format),
-                    const void *UNUSED(context_node), struct lyd_node **UNUSED(trees),
+                    const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
                     struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
 {
     if (options & LY_TYPE_OPTS_SECOND_CALL) {
@@ -1088,7 +1088,7 @@
 static LY_ERR
 ly_type_store_identityref(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
                           ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT UNUSED(format),
-                          const void *UNUSED(context_node), struct lyd_node **UNUSED(trees),
+                          const void *UNUSED(context_node), const struct lyd_node **UNUSED(trees),
                           struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
 {
     struct lysc_type_identityref *type_ident = (struct lysc_type_identityref *)type;
@@ -1219,7 +1219,7 @@
 ly_type_store_instanceid_checknodeid(const char *orig, size_t orig_len, int options, int require_instance,
                                      const char **token, struct lyd_value_prefix *prefixes, LYD_FORMAT format,
                                      const struct lysc_node **node_s, const struct lyd_node **node_d,
-                                     struct lyd_node **trees, char **errmsg)
+                                     const struct lyd_node **trees, char **errmsg)
 {
     const char *id, *prefix;
     size_t id_len, prefix_len;
@@ -1405,7 +1405,7 @@
 static LY_ERR
 ly_type_store_instanceid(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
                          ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format,
-                         const void *context_node, struct lyd_node **trees,
+                         const void *context_node, const struct lyd_node **trees,
                          struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
 {
     LY_ERR ret = LY_EVALID;
@@ -1807,7 +1807,7 @@
 static LY_ERR
 ly_type_store_leafref(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
                       ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format,
-                      const void *context_node, struct lyd_node **trees,
+                      const void *context_node, const struct lyd_node **trees,
                       struct lyd_value *storage, const char **canonized, struct ly_err_item **err)
 {
     LY_ERR ret;
diff --git a/src/plugins_types.h b/src/plugins_types.h
index e3c2356..4b13f1f 100644
--- a/src/plugins_types.h
+++ b/src/plugins_types.h
@@ -116,7 +116,7 @@
  */
 typedef LY_ERR (*ly_type_store_clb)(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
                                     ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format,
-                                    const void *context_node, struct lyd_node **trees,
+                                    const void *context_node, const struct lyd_node **trees,
                                     struct lyd_value *storage, const char **canonized, struct ly_err_item **err);
 
 /**
diff --git a/src/tree_data.c b/src/tree_data.c
index 87c1569..c9ef10f 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -29,6 +29,66 @@
 #include "tree_data_internal.h"
 #include "tree_schema.h"
 
+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;
+}
+
 static int
 cmp_str(const char *refstr, const char *str, size_t str_len)
 {
@@ -90,7 +150,7 @@
 
 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, struct lyd_node **trees)
+                ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format, const struct lyd_node **trees)
 {
     LY_ERR ret = LY_SUCCESS, rc;
     struct ly_err_item *err = NULL;
@@ -161,7 +221,7 @@
 
 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, struct lyd_node **trees)
+                   ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format, const struct lyd_node **trees)
 {
     LY_ERR rc;
     struct ly_err_item *err = NULL;
@@ -192,7 +252,7 @@
 
 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, struct lyd_node **trees)
+                  ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format,  const struct lyd_node **trees)
 {
     LY_ERR ret = LY_SUCCESS, rc;
     struct ly_err_item *err = NULL;
@@ -397,7 +457,7 @@
 }
 
 API const struct lyd_node_term *
-lyd_target(struct lyd_value_path *path, struct lyd_node **trees)
+lyd_target(struct lyd_value_path *path, const struct lyd_node **trees)
 {
     unsigned int u, v, x;
     const struct lyd_node *node = NULL, *parent = NULL, *start_search;
diff --git a/src/tree_data.h b/src/tree_data.h
index 84021b5..060f869 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -592,6 +592,24 @@
 void lyd_free_attr(struct ly_ctx *ctx, struct lyd_attr *attr, int recursive);
 
 /**
+ * @brief Prepare ([sized array](@ref sizedarrays)) of data trees required by various (mostly validation) functions.
+ *
+ * @param[in] count Number of trees to include (including the mandatory @p tree).
+ * @param[in] tree First (and mandatory) tree to be included into the resulting ([sized array](@ref sizedarrays)).
+ * @return NULL in case of memory allocation failure or invalid argument, prepared ([sized array](@ref sizedarrays)) otherwise.
+ */
+const struct lyd_node **lyd_trees_new(size_t count, const struct lyd_node *tree, ...);
+
+/**
+ * @brief Free the trees ([sized array](@ref sizedarrays)).
+ *
+ * @param[in] trees ([Sized array](@ref sizedarrays)) of data trees.
+ * @param[in] free_data Flag to free also the particular trees in the @p trees ([sized array](@ref sizedarrays)).
+ * If set to zero, only the trees envelope is freed and data are untouched.
+ */
+void lyd_trees_free(const struct lyd_node **trees, int free_data);
+
+/**
  * @brief Check type restrictions applicable to the particular leaf/leaf-list with the given string @p value.
  *
  * The given node is not modified in any way - it is just checked if the @p value can be set to the node.
@@ -608,13 +626,13 @@
  * @param[in] format Input format of the data.
  * @param[in] trees ([Sized array](@ref sizedarrays)) of data trees (e.g. when validating RPC/Notification) where the required
  *            data instance (leafref target, instance-identifier) can be placed. NULL in case the data tree are not yet complete,
- *            then LY_EINCOMPLETE can be returned.
+ *            then LY_EINCOMPLETE can be returned. To simply prepare this structure, use lyd_trees_new().
  * @return LY_SUCCESS on success
  * @return LY_EINCOMPLETE in case the @p trees is not provided and it was needed to finish the validation (e.g. due to require-instance).
  * @return LY_ERR value if an error occurred.
  */
 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, struct lyd_node **trees);
+                          ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format, const struct lyd_node **trees);
 
 /**
  * @brief Compare the node's value with the given string value. The string value is first validated according to the node's type.
@@ -628,17 +646,25 @@
  * @param[in] format Input format of the data.
  * @param[in] trees ([Sized array](@ref sizedarrays)) of data trees (e.g. when validating RPC/Notification) where the required
  *            data instance (leafref target, instance-identifier) can be placed. NULL in case the data tree are not yet complete,
- *            then LY_EINCOMPLETE can be returned in case the validation was not completed, but values matches.
+ *            then LY_EINCOMPLETE can be returned in case the validation was not completed, but values matches. To simply prepare
+ *            this structure, use lyd_trees_new(). To simply prepare this structure, use lyd_trees_new().
  * @return LY_SUCCESS on success
  * @return LY_EINCOMPLETE in case of success when the @p trees is not provided and it was needed to finish the validation of
  * the given string @p value (e.g. due to require-instance).
  * @return LY_ERR value if an error occurred.
  */
 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, struct lyd_node **trees);
+                         ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format, const struct lyd_node **trees);
 
-
-const struct lyd_node_term *lyd_target(struct lyd_value_path *path, struct lyd_node **trees);
+/**
+ * @brief Resolve instance-identifier defined by lyd_value_path structure.
+ *
+ * @param[in] path Path structure specifying the instance-identifier target.
+ * @param[in] trees ([Sized array](@ref sizedarrays)) of data trees to be searched.
+ *            To simply prepare this structure, use lyd_trees_new().
+ * @return Target node of the instance-identifier present in the given data @p trees.
+ */
+const struct lyd_node_term *lyd_target(struct lyd_value_path *path, const struct lyd_node **trees);
 
 #ifdef __cplusplus
 }
diff --git a/src/tree_data_internal.h b/src/tree_data_internal.h
index a9ff2e6..75ef8f3 100644
--- a/src/tree_data_internal.h
+++ b/src/tree_data_internal.h
@@ -57,7 +57,7 @@
  * @return LY_ERR value if an error occurred.
  */
 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,struct lyd_node **trees);
+                       ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format, const struct lyd_node **trees);
 
 /**
  * @brief Parse XML string as YANG data tree.