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.