data tree FEATURE duplicating attributes of opaque nodes
Fixes cesnet/netopeer2#944
diff --git a/src/tree_data.c b/src/tree_data.c
index 3dbbe17..5a29bb2 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -3278,6 +3278,56 @@
}
/**
+ * @brief Create a copy of the attribute.
+ *
+ * @param[in] attr Attribute to copy.
+ * @param[in] node Opaque where to append the new attribute.
+ * @param[out] dup Optional created attribute copy.
+ * @return LY_ERR value.
+ */
+static LY_ERR
+lyd_dup_attr_single(const struct lyd_attr *attr, struct lyd_node *node, struct lyd_attr **dup)
+{
+ LY_ERR ret = LY_SUCCESS;
+ struct lyd_attr *a, *last;
+ struct lyd_node_opaq *opaq = (struct lyd_node_opaq *)node;
+
+ LY_CHECK_ARG_RET(NULL, attr, node, !node->schema, LY_EINVAL);
+
+ /* create a copy */
+ a = calloc(1, sizeof *attr);
+ LY_CHECK_ERR_RET(!a, LOGMEM(LYD_CTX(node)), LY_EMEM);
+
+ LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), attr->name.name, 0, &a->name.name), finish);
+ LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), attr->name.prefix, 0, &a->name.prefix), finish);
+ LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), attr->name.module_ns, 0, &a->name.module_ns), finish);
+ LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), attr->value, 0, &a->value), finish);
+ a->hints = attr->hints;
+ a->format = attr->format;
+ if (attr->val_prefix_data) {
+ ret = ly_dup_prefix_data(LYD_CTX(node), attr->format, attr->val_prefix_data, &a->val_prefix_data);
+ LY_CHECK_GOTO(ret, finish);
+ }
+
+ /* insert as the last attribute */
+ a->parent = opaq;
+ if (opaq->attr) {
+ for (last = opaq->attr; last->next; last = last->next) {}
+ last->next = a;
+ } else {
+ opaq->attr = a;
+ }
+
+finish:
+ if (ret) {
+ lyd_free_attr_single(LYD_CTX(node), a);
+ } else if (dup) {
+ *dup = a;
+ }
+ return LY_SUCCESS;
+}
+
+/**
* @brief Duplicate a single node and connect it into @p parent (if present) or last of @p first siblings.
*
* Ignores LYD_DUP_WITH_PARENTS and LYD_DUP_WITH_SIBLINGS which are supposed to be handled by lyd_dup().
@@ -3296,12 +3346,14 @@
LY_ERR ret;
struct lyd_node *dup = NULL;
struct lyd_meta *meta;
+ struct lyd_attr *attr;
struct lyd_node_any *any;
LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
if (!node->schema) {
dup = calloc(1, sizeof(struct lyd_node_opaq));
+ ((struct lyd_node_opaq *)dup)->ctx = LYD_CTX(node);
} else {
switch (node->schema->nodetype) {
case LYS_RPC:
@@ -3335,10 +3387,16 @@
dup->schema = node->schema;
dup->prev = dup;
- /* duplicate metadata */
+ /* duplicate metadata/attributes */
if (!(options & LYD_DUP_NO_META)) {
- LY_LIST_FOR(node->meta, meta) {
- LY_CHECK_GOTO(ret = lyd_dup_meta_single(meta, dup, NULL), error);
+ if (!node->schema) {
+ LY_LIST_FOR(((struct lyd_node_opaq *)node)->attr, attr) {
+ LY_CHECK_GOTO(ret = lyd_dup_attr_single(attr, dup, NULL), error);
+ }
+ } else {
+ LY_LIST_FOR(node->meta, meta) {
+ LY_CHECK_GOTO(ret = lyd_dup_meta_single(meta, dup, NULL), error);
+ }
}
}
@@ -3355,17 +3413,15 @@
}
}
LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), orig->name.name, 0, &opaq->name.name), error);
- opaq->format = orig->format;
- if (orig->name.prefix) {
- LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), orig->name.prefix, 0, &opaq->name.prefix), error);
- }
+ LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), orig->name.prefix, 0, &opaq->name.prefix), error);
LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), orig->name.module_ns, 0, &opaq->name.module_ns), error);
+ LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), orig->value, 0, &opaq->value), error);
+ opaq->hints = orig->hints;
+ opaq->format = orig->format;
if (orig->val_prefix_data) {
ret = ly_dup_prefix_data(LYD_CTX(node), opaq->format, orig->val_prefix_data, &opaq->val_prefix_data);
LY_CHECK_GOTO(ret, error);
}
- LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), orig->value, 0, &opaq->value), error);
- opaq->ctx = orig->ctx;
} else if (dup->schema->nodetype & LYD_NODE_TERM) {
struct lyd_node_term *term = (struct lyd_node_term *)dup;
struct lyd_node_term *orig = (struct lyd_node_term *)node;
diff --git a/src/tree_data.h b/src/tree_data.h
index de4f2d0..f0d3095 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -1874,7 +1874,7 @@
#define LYD_DUP_RECURSIVE 0x01 /**< Duplicate not just the node but also all the children. Note that
list's keys are always duplicated. */
-#define LYD_DUP_NO_META 0x02 /**< Do not duplicate metadata of any node. */
+#define LYD_DUP_NO_META 0x02 /**< Do not duplicate metadata (or attributes) of any node. */
#define LYD_DUP_WITH_PARENTS 0x04 /**< If a nested node is being duplicated, duplicate also all the parents.
Keys are also duplicated for lists. Return value does not change! */
#define LYD_DUP_WITH_FLAGS 0x08 /**< Also copy any data node flags. That will cause the duplicated data to preserve