data tree FEATURE dedicated any value setting function

... which can be used for freeing the value or
copying new value.
diff --git a/src/tree_data.c b/src/tree_data.c
index f0c4e89..3d9789c 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -2051,8 +2051,9 @@
                   struct lyd_node **dup_p)
 {
     LY_ERR ret;
-    int len;
     struct lyd_node *dup = NULL;
+    struct lyd_meta *meta;
+    struct lyd_node_any *any;
     LY_ARRAY_COUNT_TYPE u;
 
     LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
@@ -2161,40 +2162,9 @@
         }
         lyd_hash(dup);
     } else if (dup->schema->nodetype & LYD_NODE_ANY) {
-        struct lyd_node_any *any = (struct lyd_node_any *)dup;
-        struct lyd_node_any *orig = (struct lyd_node_any *)node;
-
-        any->hash = orig->hash;
-        any->value_type = orig->value_type;
-        switch (any->value_type) {
-        case LYD_ANYDATA_DATATREE:
-            if (orig->value.tree) {
-                any->value.tree = lyd_dup(orig->value.tree, NULL, LYD_DUP_RECURSIVE | LYD_DUP_WITH_SIBLINGS);
-                if (!any->value.tree) {
-                    /* get the last error's error code recorded by lyd_dup */
-                    struct ly_err_item *ei = ly_err_first(LYD_NODE_CTX(node));
-                    ret = ei ? ei->prev->no : LY_EOTHER;
-                    goto error;
-                }
-                LY_CHECK_ERR_GOTO(!any->value.tree, ret = 0, error);
-            }
-            break;
-        case LYD_ANYDATA_STRING:
-        case LYD_ANYDATA_XML:
-        case LYD_ANYDATA_JSON:
-            if (orig->value.str) {
-                any->value.str = lydict_insert(LYD_NODE_CTX(node), orig->value.str, strlen(orig->value.str));
-            }
-            break;
-        case LYD_ANYDATA_LYB:
-            if (orig->value.mem) {
-                len = lyd_lyb_data_length(orig->value.mem);
-                any->value.mem = malloc(len);
-                LY_CHECK_ERR_GOTO(!any->value.mem, LOGMEM(LYD_NODE_CTX(node)); ret = LY_EMEM, error);
-                memcpy(any->value.mem, orig->value.mem, len);
-            }
-            break;
-        }
+        dup->hash = node->hash;
+        any = (struct lyd_node_any *)node;
+        LY_CHECK_GOTO(ret = lyd_any_copy_value(dup, &any->value, any->value_type), error);
     }
 
     /* insert */
diff --git a/src/tree_data_free.c b/src/tree_data_free.c
index 42db31c..9cb946e 100644
--- a/src/tree_data_free.c
+++ b/src/tree_data_free.c
@@ -168,19 +168,8 @@
             lyd_free_subtree(iter, 0);
         }
     } else if (node->schema->nodetype & LYD_NODE_ANY) {
-        switch (((struct lyd_node_any *)node)->value_type) {
-        case LYD_ANYDATA_DATATREE:
-            lyd_free_all(((struct lyd_node_any *)node)->value.tree);
-            break;
-        case LYD_ANYDATA_STRING:
-        case LYD_ANYDATA_XML:
-        case LYD_ANYDATA_JSON:
-            FREE_STRING(LYD_NODE_CTX(node), ((struct lyd_node_any *)node)->value.str);
-            break;
-        case LYD_ANYDATA_LYB:
-            free(((struct lyd_node_any *)node)->value.mem);
-            break;
-        }
+        /* only frees the value this way */
+        lyd_any_copy_value(node, NULL, 0);
     } else if (node->schema->nodetype & LYD_NODE_TERM) {
         ((struct lysc_node_leaf *)node->schema)->type->plugin->free(LYD_NODE_CTX(node), &((struct lyd_node_term *)node)->value);
     }
diff --git a/src/tree_data_helpers.c b/src/tree_data_helpers.c
index 8356961..c5f3a79 100644
--- a/src/tree_data_helpers.c
+++ b/src/tree_data_helpers.c
@@ -206,6 +206,66 @@
     }
 }
 
+LY_ERR
+lyd_any_copy_value(struct lyd_node *trg, const union lyd_any_value *value, LYD_ANYDATA_VALUETYPE value_type)
+{
+    struct lyd_node_any *t;
+    int len;
+
+    assert(trg->schema->nodetype & LYS_ANYDATA);
+
+    t = (struct lyd_node_any *)trg;
+
+    /* free trg */
+    switch (t->value_type) {
+    case LYD_ANYDATA_DATATREE:
+        lyd_free_all(t->value.tree);
+        break;
+    case LYD_ANYDATA_STRING:
+    case LYD_ANYDATA_XML:
+    case LYD_ANYDATA_JSON:
+        FREE_STRING(LYD_NODE_CTX(trg), t->value.str);
+        break;
+    case LYD_ANYDATA_LYB:
+        free(t->value.mem);
+        break;
+    }
+    t->value.str = NULL;
+
+    if (!value) {
+        /* only free value in this case */
+        return LY_SUCCESS;
+    }
+
+    /* copy src */
+    t->value_type = value_type;
+    switch (value_type) {
+    case LYD_ANYDATA_DATATREE:
+        if (value->tree) {
+            t->value.tree = lyd_dup(value->tree, NULL, LYD_DUP_RECURSIVE | LYD_DUP_WITH_SIBLINGS);
+            LY_CHECK_RET(!t->value.tree, LY_EINT);
+        }
+        break;
+    case LYD_ANYDATA_STRING:
+    case LYD_ANYDATA_XML:
+    case LYD_ANYDATA_JSON:
+        if (value->str) {
+            t->value.str = lydict_insert(LYD_NODE_CTX(trg), value->str, 0);
+        }
+        break;
+    case LYD_ANYDATA_LYB:
+        if (value->mem) {
+            len = lyd_lyb_data_length(value->mem);
+            t->value.mem = malloc(len);
+            LY_CHECK_ERR_RET(!t->value.mem, LOGMEM(LYD_NODE_CTX(trg)), LY_EMEM);
+            memcpy(t->value.mem, value->mem, len);
+        }
+        break;
+    }
+
+    return LY_SUCCESS;
+}
+
 LYB_HASH
 lyb_hash(struct lysc_node *sibling, uint8_t collision_id)
 {
diff --git a/src/tree_data_internal.h b/src/tree_data_internal.h
index 00b843b..10a0b53 100644
--- a/src/tree_data_internal.h
+++ b/src/tree_data_internal.h
@@ -500,6 +500,16 @@
 void lyd_parse_set_data_flags(struct lyd_node *node, struct ly_set *when_check, struct lyd_meta **meta, int options);
 
 /**
+ * @brief Copy anydata value from one node to another. Target value is freed first.
+ *
+ * @param[in,out] trg Target node.
+ * @param[in] value Source value, may be NULL when the target value is only freed.
+ * @param[in] value_type Source value type.
+ * @return LY_ERR value.
+ */
+LY_ERR lyd_any_copy_value(struct lyd_node *trg, const union lyd_any_value *value, LYD_ANYDATA_VALUETYPE value_type);
+
+/**
  * @brief Free value prefixes.
  *
  * @param[in] ctx libyang context.