data types CHANGE validate instance-identifier values

Quite a big patch dut to the problems with instance-identifiers:
- different format in XML and JSON
- prefixes must be resolved correctly even in predicates to be able to
compare values in predicates with other values (even another
instance-identifier, prefixed identityrefs or, in contrast, strings
where 'something:' is not a prefix).
diff --git a/src/tree_data.c b/src/tree_data.c
index eb551e2..02059b9 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -14,6 +14,7 @@
 
 #include "common.h"
 
+#include <assert.h>
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -87,6 +88,197 @@
     return NULL;
 }
 
+LY_ERR
+lyd_value_parse(struct lyd_node_term *node, const char *value, size_t value_len, int dynamic,
+                ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format, struct lyd_node **trees)
+{
+    LY_ERR ret = LY_SUCCESS, rc;
+    struct ly_err_item *err = NULL;
+    struct ly_ctx *ctx;
+    struct lysc_type *type;
+    void *priv = NULL;
+    int options = LY_TYPE_OPTS_VALIDATE | LY_TYPE_OPTS_CANONIZE | LY_TYPE_OPTS_STORE |
+            (dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (trees ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
+    assert(node);
+
+    ctx = node->schema->module->ctx;
+    type = ((struct lysc_node_leaf*)node->schema)->type;
+    if (type->plugin->validate) {
+        rc = type->plugin->validate(ctx, type, value, value_len, options, get_prefix, parser, format,
+                                    trees ? (void*)node : (void*)node->schema, trees,
+                                    &node->value.canonized, &err, &priv);
+        if (rc == LY_EINCOMPLETE) {
+            ret = rc;
+            /* continue with storing, just remember what to return if storing is ok */
+        } else if (rc) {
+            ret = rc;
+            if (err) {
+                ly_err_print(err);
+                LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
+                ly_err_free(err);
+            }
+            goto error;
+        }
+    } else if (dynamic) {
+        node->value.canonized = lydict_insert_zc(ctx, (char*)value);
+    } else {
+        node->value.canonized = lydict_insert(ctx, value, value_len);
+    }
+    node->value.plugin = type->plugin;
+
+    if (type->plugin->store) {
+        rc = type->plugin->store(ctx, type, options, &node->value, &err, &priv);
+        if (rc) {
+            ret = rc;
+            if (err) {
+                ly_err_print(err);
+                LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
+                ly_err_free(err);
+            }
+            goto error;
+        }
+    }
+
+error:
+    return ret;
+}
+
+API LY_ERR
+lys_value_validate(struct ly_ctx *ctx, const struct lysc_node *node, const char *value, size_t value_len,
+                   ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format)
+{
+    LY_ERR rc = LY_SUCCESS;
+    struct ly_err_item *err = NULL;
+    struct lysc_type *type;
+    void *priv = NULL;
+    int options = LY_TYPE_OPTS_VALIDATE | LY_TYPE_OPTS_INCOMPLETE_DATA;
+
+    LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
+
+    if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
+        LOGARG(ctx, node);
+        return LY_EINVAL;
+    }
+
+    type = ((struct lysc_node_leaf*)node)->type;
+
+    if (type->plugin->validate) {
+        rc = type->plugin->validate(ctx ? ctx : node->module->ctx, type, value, value_len, options,
+                                     get_prefix, get_prefix_data, format, node, NULL, NULL, &err, &priv);
+        if (rc == LY_EINCOMPLETE) {
+            /* actually success since we do not provide the context tree and call validation with
+             * LY_TYPE_OPTS_INCOMPLETE_DATA */
+            rc = LY_SUCCESS;
+        } else if (rc && err) {
+            if (ctx) {
+                /* log only in case the ctx was provided as input parameter */
+                ly_err_print(err);
+                LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
+            }
+            ly_err_free(err);
+        }
+    }
+
+    return rc;
+}
+
+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_ERR rc;
+    struct ly_err_item *err = NULL;
+    struct lysc_type *type;
+    void *priv = NULL;
+    int options = LY_TYPE_OPTS_VALIDATE | LY_TYPE_OPTS_STORE | (trees ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
+
+    LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
+
+    type = ((struct lysc_node_leaf*)node->schema)->type;
+
+    if (type->plugin->validate) {
+        rc = type->plugin->validate(ctx ? ctx : node->schema->module->ctx, type, value, value_len, options,
+                                     get_prefix, get_prefix_data, format, trees ? (void*)node : (void*)node->schema, trees,
+                                     NULL, &err, &priv);
+        if (rc == LY_EINCOMPLETE) {
+            return rc;
+        } else if (rc) {
+            if (err) {
+                if (ctx) {
+                    ly_err_print(err);
+                    LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
+                }
+                ly_err_free(err);
+            }
+            return rc;
+        }
+    }
+
+    return LY_SUCCESS;
+}
+
+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_ERR ret = LY_SUCCESS, rc;
+    struct ly_err_item *err = NULL;
+    struct ly_ctx *ctx;
+    struct lysc_type *type;
+    void *priv = NULL;
+    struct lyd_value data = {0};
+    int options = LY_TYPE_OPTS_VALIDATE | LY_TYPE_OPTS_CANONIZE | LY_TYPE_OPTS_STORE | (trees ? 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;
+    if (type->plugin->validate) {
+        rc = type->plugin->validate(ctx, type, value, value_len, options,
+                                     get_prefix, get_prefix_data, format, (struct lyd_node*)node, trees,
+                                     &data.canonized, &err, &priv);
+        if (rc == LY_EINCOMPLETE) {
+            ret = rc;
+            /* continue with comparing, just remember what to return if storing is ok */
+        } else if (rc) {
+            /* value to compare is invalid */
+            ret = LY_EINVAL;
+            if (err) {
+                ly_err_free(err);
+            }
+            goto cleanup;
+        }
+    } else {
+        data.canonized = lydict_insert(ctx, value, value_len);
+    }
+
+    /* store the value to compare into a dummy storage to do a comparison */
+    if (type->plugin->store) {
+        if (type->plugin->store(ctx, type, options, &data, &err, &priv)) {
+            ret = LY_EINVAL;
+            if (err) {
+                ly_err_free(err);
+            }
+            goto cleanup;
+        }
+    }
+
+    /* compare data */
+    if (type->plugin->compare) {
+        ret = type->plugin->compare(&node->value, &data);
+    } else if (data.canonized != node->value.canonized) {
+        ret = LY_EVALID;
+    }
+
+cleanup:
+    if (type->plugin->free) {
+        type->plugin->free(ctx, type, &data);
+    }
+    lydict_remove(ctx, data.canonized);
+
+    return ret;
+}
+
 static struct lyd_node *
 lyd_parse_mem_(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options, va_list ap)
 {
@@ -251,3 +443,82 @@
 
     return result;
 }
+
+API const struct lyd_node_term *
+lyd_target(struct lyd_value_path *path, struct lyd_node **trees)
+{
+    unsigned int u, v, x;
+    const struct lyd_node *node = NULL, *parent = NULL, *start_search;
+    uint64_t pos = 1;
+
+    LY_CHECK_ARG_RET(NULL, path, trees, NULL);
+
+    LY_ARRAY_FOR(path, u) {
+        if (parent) {
+            start_search = lyd_node_children(parent);
+search_inner:
+            node = lyd_search(start_search, path[u].node->module, path[u].node->name, strlen(path[u].node->name), path[u].node->nodetype, NULL, 0);
+        } else {
+            LY_ARRAY_FOR(trees, v) {
+                start_search = trees[v];
+search_toplevel:
+                /* WARNING! to use search_toplevel label correctly, variable v must be preserved and not changed! */
+                node = lyd_search(start_search, path[u].node->module, path[u].node->name, strlen(path[u].node->name), path[u].node->nodetype, NULL, 0);
+                if (node) {
+                    break;
+                }
+            }
+        }
+        if (!node) {
+            return NULL;
+        }
+
+        /* check predicate if any */
+        LY_ARRAY_FOR(path[u].predicates, x) {
+            if (path[u].predicates[x].type == 0) {
+                /* position predicate */
+                if (pos != path[u].predicates[x].position) {
+                    pos++;
+                    goto search_repeat;
+                }
+                /* done, no more predicates are allowed here */
+                break;
+            } else if (path[u].predicates[x].type == 1) {
+                /* key-predicate */
+                struct lysc_type *type = ((struct lysc_node_leaf*)path[u].predicates[x].key)->type;
+                const struct lyd_node *key = lyd_search(lyd_node_children(node), path[u].predicates[x].key->module,
+                                                        path[u].predicates[x].key->name, strlen(path[u].predicates[x].key->name),
+                                                        LYS_LEAF, NULL, 0);
+                if (!key) {
+                    /* probably error and we shouldn't be here due to previous checks when creating path */
+                    goto search_repeat;
+                }
+                if (type->plugin->compare(&((struct lyd_node_term*)key)->value, path[u].predicates[x].value)) {
+                    goto search_repeat;
+                }
+            } else if (path[u].predicates[x].type == 2) {
+                /* leaf-list-predicate */
+                struct lysc_type *type = ((struct lysc_node_leaf*)path[u].node)->type;
+                if (type->plugin->compare(&((struct lyd_node_term*)node)->value, path[u].predicates[x].value)) {
+                    goto search_repeat;
+                }
+            } else {
+                LOGINT(NULL);
+            }
+        }
+
+        parent = node;
+    }
+
+    return (const struct lyd_node_term*)node;
+
+search_repeat:
+    start_search = node->next;
+    if (parent) {
+        goto search_inner;
+    } else {
+        goto search_toplevel;
+    }
+}
+
+