data tree NEW opaque data node
Used for unknown anyxml/anydata nodes.
Some refactoring including making context
const for cases when only the dictionary
is modified or replacing unsigned int with
uint32_t.
diff --git a/src/tree_data.c b/src/tree_data.c
index 634ede6..5026d4e 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -29,6 +29,7 @@
#include "tree_data_internal.h"
#include "hash_table.h"
#include "tree_schema.h"
+#include "xml.h"
#include "plugins_exts_metadata.h"
#include "plugins_exts_internal.h"
@@ -316,7 +317,7 @@
lyd_parse_lyb(ctx, data, options, trees, &result);
break;
#endif
- case LYD_UNKNOWN:
+ case LYD_SCHEMA:
LOGINT(ctx);
break;
}
@@ -659,6 +660,43 @@
return LY_SUCCESS;
}
+LY_ERR
+lyd_create_opaq(const struct ly_ctx *ctx, const char *name, size_t name_len, const char *value, size_t value_len,
+ int *dynamic, LYD_FORMAT format, struct ly_prefix *val_prefs, const char *prefix, size_t pref_len,
+ const char *ns, struct lyd_node **node)
+{
+ struct lyd_node_opaq *opaq;
+
+ assert(ctx && name && name_len && ns);
+
+ if (!value_len) {
+ value = "";
+ }
+
+ opaq = calloc(1, sizeof *opaq);
+ LY_CHECK_ERR_RET(!opaq, LOGMEM(ctx), LY_EMEM);
+
+ opaq->prev = (struct lyd_node *)opaq;
+
+ opaq->name = lydict_insert(ctx, name, name_len);
+ opaq->format = format;
+ if (pref_len) {
+ opaq->prefix.pref = lydict_insert(ctx, prefix, pref_len);
+ }
+ opaq->prefix.ns = lydict_insert(ctx, ns, 0);
+ opaq->val_prefs = val_prefs;
+ if (dynamic && *dynamic) {
+ opaq->value = lydict_insert_zc(ctx, (char *)value);
+ *dynamic = 0;
+ } else {
+ opaq->value = lydict_insert(ctx, value, value_len);
+ }
+ opaq->ctx = ctx;
+
+ *node = (struct lyd_node *)opaq;
+ return LY_SUCCESS;
+}
+
API struct lyd_node *
lyd_new_inner(struct lyd_node *parent, const struct lys_module *module, const char *name)
{
@@ -919,7 +957,7 @@
struct lyd_node_inner *par;
assert(parent && !node->next && (node->prev == node));
- assert(parent->schema->nodetype & LYD_NODE_INNER);
+ assert(!parent->schema || (parent->schema->nodetype & LYD_NODE_INNER));
par = (struct lyd_node_inner *)parent;
@@ -937,7 +975,7 @@
/* remove default flags from NP containers */
par->flags &= ~LYD_DEFAULT;
}
- if ((par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
+ if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
/* rehash key-less list */
lyd_hash((struct lyd_node *)par);
}
@@ -954,14 +992,14 @@
const struct lysc_node *skey = NULL;
int has_keys;
- assert((parent || first_sibling) && node && node->hash);
+ assert((parent || first_sibling) && node && (node->hash || !node->schema));
if (!parent && first_sibling && (*first_sibling) && (*first_sibling)->parent) {
parent = (struct lyd_node *)(*first_sibling)->parent;
}
if (parent) {
- if (node->schema->flags & LYS_KEY) {
+ if (node->schema && (node->schema->flags & LYS_KEY)) {
/* it is key and we need to insert it at the correct place */
anchor = lyd_get_prev_key_anchor(lyd_node_children(parent), node->schema);
if (anchor) {
@@ -1275,7 +1313,7 @@
LY_ERR
lyd_create_meta(struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod, const char *name,
- size_t name_len, const char *value, size_t value_len, int *dynamic, ly_clb_resolve_prefix get_prefix,
+ size_t name_len, const char *value, size_t value_len, int *dynamic, ly_clb_resolve_prefix resolve_prefix,
void *prefix_data, LYD_FORMAT format, const struct lysc_node *ctx_snode)
{
LY_ERR ret;
@@ -1304,7 +1342,7 @@
LY_CHECK_ERR_RET(!mt, LOGMEM(mod->ctx), LY_EMEM);
mt->parent = parent;
mt->annotation = ant;
- ret = lyd_value_parse_meta(mod->ctx, mt, value, value_len, dynamic, 0, get_prefix, prefix_data, format, ctx_snode, NULL);
+ ret = lyd_value_parse_meta(mod->ctx, mt, value, value_len, dynamic, 0, resolve_prefix, prefix_data, format, ctx_snode, NULL);
if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
free(mt);
return ret;
@@ -1336,6 +1374,60 @@
return ret;
}
+LY_ERR
+ly_create_attr(struct lyd_node *parent, struct ly_attr **attr, const struct ly_ctx *ctx, const char *name,
+ size_t name_len, const char *value, size_t value_len, int *dynamic, LYD_FORMAT format,
+ struct ly_prefix *val_prefs, const char *prefix, size_t prefix_len, const char *ns)
+{
+ struct ly_attr *at, *last;
+ struct lyd_node_opaq *opaq;
+
+ assert(ctx && (parent || attr) && (!parent || !parent->schema));
+ assert(name && name_len);
+ assert((prefix_len && ns) || (!prefix_len && !ns));
+
+ if (!value_len) {
+ value = "";
+ }
+
+ at = calloc(1, sizeof *at);
+ LY_CHECK_ERR_RET(!at, LOGMEM(ctx), LY_EMEM);
+ at->parent = (struct lyd_node_opaq *)parent;
+ at->name = lydict_insert(ctx, name, name_len);
+ if (dynamic && *dynamic) {
+ at->value = lydict_insert_zc(ctx, (char *)value);
+ *dynamic = 0;
+ } else {
+ at->value = lydict_insert(ctx, value, value_len);
+ }
+
+ at->format = format;
+ at->val_prefs = val_prefs;
+ if (ns) {
+ at->prefix.pref = lydict_insert(ctx, prefix, prefix_len);
+ at->prefix.ns = lydict_insert(ctx, ns, 0);
+ }
+
+ /* insert as the last attribute */
+ if (parent) {
+ opaq = (struct lyd_node_opaq *)parent;
+ if (opaq->attr) {
+ for (last = opaq->attr; last->next; last = last->next);
+ last->next = at;
+ } else {
+ opaq->attr = at;
+ }
+ } else if (*attr) {
+ for (last = *attr; last->next; last = last->next);
+ last->next = at;
+ }
+
+ if (attr) {
+ *attr = at;
+ }
+ return LY_SUCCESS;
+}
+
API const struct lyd_node_term *
lyd_target(struct lyd_value_path *path, const struct lyd_node *tree)
{
@@ -1415,6 +1507,7 @@
const struct lyd_node *iter1, *iter2;
struct lyd_node_term *term1, *term2;
struct lyd_node_any *any1, *any2;
+ struct lyd_node_opaq *opaq1, *opaq2;
struct lysc_type *type;
size_t len1, len2;
@@ -1426,212 +1519,251 @@
}
}
- if (node1->schema->module->ctx != node2->schema->module->ctx || node1->schema != node2->schema) {
+ if ((LYD_NODE_CTX(node1) != LYD_NODE_CTX(node2)) || (node1->schema != node2->schema)) {
return LY_ENOT;
}
if (node1->hash != node2->hash) {
return LY_ENOT;
}
+ /* equal hashes do not mean equal nodes, they can be just in collision (or both be 0) so the nodes must be checked explicitly */
- /* equal hashes do not mean equal nodes, they can be just in collision so the nodes must be checked explicitly */
-
- switch (node1->schema->nodetype) {
- case LYS_LEAF:
- case LYS_LEAFLIST:
- if (options & LYD_COMPARE_DEFAULTS) {
- if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
- return LY_ENOT;
- }
- }
-
- term1 = (struct lyd_node_term*)node1;
- term2 = (struct lyd_node_term*)node2;
- type = ((struct lysc_node_leaf*)node1->schema)->type;
-
- return type->plugin->compare(&term1->value, &term2->value);
- case LYS_CONTAINER:
- if (options & LYD_COMPARE_DEFAULTS) {
- if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
- return LY_ENOT;
- }
- }
- if (options & LYD_COMPARE_FULL_RECURSION) {
- iter1 = ((struct lyd_node_inner*)node1)->child;
- iter2 = ((struct lyd_node_inner*)node2)->child;
- goto all_children_compare;
- }
- return LY_SUCCESS;
- case LYS_ACTION:
- if (options & LYD_COMPARE_FULL_RECURSION) {
- /* TODO action/RPC
- goto all_children_compare;
- */
- }
- return LY_SUCCESS;
- case LYS_NOTIF:
- if (options & LYD_COMPARE_FULL_RECURSION) {
- /* TODO Notification
- goto all_children_compare;
- */
- }
- return LY_SUCCESS;
- case LYS_LIST:
- iter1 = ((struct lyd_node_inner*)node1)->child;
- iter2 = ((struct lyd_node_inner*)node2)->child;
-
- if (!(node1->schema->flags & LYS_KEYLESS) && !(options & LYD_COMPARE_FULL_RECURSION)) {
- /* lists with keys, their equivalence is based on their keys */
- for (struct lysc_node *key = ((struct lysc_node_list*)node1->schema)->child;
- key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
- key = key->next) {
- if (lyd_compare(iter1, iter2, options)) {
- return LY_ENOT;
- }
- iter1 = iter1->next;
- iter2 = iter2->next;
- }
- } else {
- /* lists without keys, their equivalence is based on equivalence of all the children (both direct and indirect) */
-
-all_children_compare:
- if (!iter1 && !iter2) {
- /* no children, nothing to compare */
- return LY_SUCCESS;
- }
-
- for (; iter1 && iter2; iter1 = iter1->next, iter2 = iter2->next) {
- if (lyd_compare(iter1, iter2, options | LYD_COMPARE_FULL_RECURSION)) {
- return LY_ENOT;
- }
- }
- if (iter1 || iter2) {
- return LY_ENOT;
- }
- }
- return LY_SUCCESS;
- case LYS_ANYXML:
- case LYS_ANYDATA:
- any1 = (struct lyd_node_any*)node1;
- any2 = (struct lyd_node_any*)node2;
-
- if (any1->value_type != any2->value_type) {
+ if (!node1->schema) {
+ opaq1 = (struct lyd_node_opaq *)node1;
+ opaq2 = (struct lyd_node_opaq *)node2;
+ if ((opaq1->name != opaq2->name) || (opaq1->prefix.ns != opaq2->prefix.ns) || (opaq1->format != opaq2->format)) {
return LY_ENOT;
}
- switch (any1->value_type) {
- case LYD_ANYDATA_DATATREE:
- iter1 = any1->value.tree;
- iter2 = any2->value.tree;
+ switch (opaq1->format) {
+ case LYD_XML:
+ if (lyxml_value_compare(opaq1->value, opaq1->val_prefs, opaq2->value, opaq2->val_prefs)) {
+ return LY_ENOT;
+ }
+ break;
+ case LYD_SCHEMA:
+ /* not allowed */
+ LOGINT(LYD_NODE_CTX(node1));
+ return LY_EINT;
+ }
+ if (options & LYD_COMPARE_FULL_RECURSION) {
+ iter1 = opaq1->child;
+ iter2 = opaq2->child;
goto all_children_compare;
- case LYD_ANYDATA_STRING:
- case LYD_ANYDATA_XML:
- case LYD_ANYDATA_JSON:
- len1 = strlen(any1->value.str);
- len2 = strlen(any2->value.str);
- if (len1 != len2 || strcmp(any1->value.str, any2->value.str)) {
- return LY_ENOT;
+ }
+ return LY_SUCCESS;
+ } else {
+ switch (node1->schema->nodetype) {
+ case LYS_LEAF:
+ case LYS_LEAFLIST:
+ if (options & LYD_COMPARE_DEFAULTS) {
+ if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
+ return LY_ENOT;
+ }
+ }
+
+ term1 = (struct lyd_node_term*)node1;
+ term2 = (struct lyd_node_term*)node2;
+ type = ((struct lysc_node_leaf*)node1->schema)->type;
+
+ return type->plugin->compare(&term1->value, &term2->value);
+ case LYS_CONTAINER:
+ if (options & LYD_COMPARE_DEFAULTS) {
+ if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
+ return LY_ENOT;
+ }
+ }
+ if (options & LYD_COMPARE_FULL_RECURSION) {
+ iter1 = ((struct lyd_node_inner*)node1)->child;
+ iter2 = ((struct lyd_node_inner*)node2)->child;
+ goto all_children_compare;
}
return LY_SUCCESS;
-#if 0 /* TODO LYB format */
- case LYD_ANYDATA_LYB:
- int len1 = lyd_lyb_data_length(any1->value.mem);
- int len2 = lyd_lyb_data_length(any2->value.mem);
- if (len1 != len2 || memcmp(any1->value.mem, any2->value.mem, len1)) {
- return LY_ENOT;
+ case LYS_ACTION:
+ if (options & LYD_COMPARE_FULL_RECURSION) {
+ /* TODO action/RPC
+ goto all_children_compare;
+ */
}
return LY_SUCCESS;
-#endif
+ case LYS_NOTIF:
+ if (options & LYD_COMPARE_FULL_RECURSION) {
+ /* TODO Notification
+ goto all_children_compare;
+ */
+ }
+ return LY_SUCCESS;
+ case LYS_LIST:
+ iter1 = ((struct lyd_node_inner*)node1)->child;
+ iter2 = ((struct lyd_node_inner*)node2)->child;
+
+ if (!(node1->schema->flags & LYS_KEYLESS) && !(options & LYD_COMPARE_FULL_RECURSION)) {
+ /* lists with keys, their equivalence is based on their keys */
+ for (struct lysc_node *key = ((struct lysc_node_list*)node1->schema)->child;
+ key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
+ key = key->next) {
+ if (lyd_compare(iter1, iter2, options)) {
+ return LY_ENOT;
+ }
+ iter1 = iter1->next;
+ iter2 = iter2->next;
+ }
+ } else {
+ /* lists without keys, their equivalence is based on equivalence of all the children (both direct and indirect) */
+
+ all_children_compare:
+ if (!iter1 && !iter2) {
+ /* no children, nothing to compare */
+ return LY_SUCCESS;
+ }
+
+ for (; iter1 && iter2; iter1 = iter1->next, iter2 = iter2->next) {
+ if (lyd_compare(iter1, iter2, options | LYD_COMPARE_FULL_RECURSION)) {
+ return LY_ENOT;
+ }
+ }
+ if (iter1 || iter2) {
+ return LY_ENOT;
+ }
+ }
+ return LY_SUCCESS;
+ case LYS_ANYXML:
+ case LYS_ANYDATA:
+ any1 = (struct lyd_node_any*)node1;
+ any2 = (struct lyd_node_any*)node2;
+
+ if (any1->value_type != any2->value_type) {
+ return LY_ENOT;
+ }
+ switch (any1->value_type) {
+ case LYD_ANYDATA_DATATREE:
+ iter1 = any1->value.tree;
+ iter2 = any2->value.tree;
+ goto all_children_compare;
+ case LYD_ANYDATA_STRING:
+ case LYD_ANYDATA_XML:
+ case LYD_ANYDATA_JSON:
+ len1 = strlen(any1->value.str);
+ len2 = strlen(any2->value.str);
+ if (len1 != len2 || strcmp(any1->value.str, any2->value.str)) {
+ return LY_ENOT;
+ }
+ return LY_SUCCESS;
+ #if 0 /* TODO LYB format */
+ case LYD_ANYDATA_LYB:
+ int len1 = lyd_lyb_data_length(any1->value.mem);
+ int len2 = lyd_lyb_data_length(any2->value.mem);
+ if (len1 != len2 || memcmp(any1->value.mem, any2->value.mem, len1)) {
+ return LY_ENOT;
+ }
+ return LY_SUCCESS;
+ #endif
+ }
}
}
- LOGINT(node1->schema->module->ctx);
+ LOGINT(LYD_NODE_CTX(node1));
return LY_EINT;
}
/**
- * @brief Duplicates just a single node and interconnect it into a @p parent (if present) and after the @p prev
- * sibling (if present).
+ * @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().
*/
-static struct lyd_node *
-lyd_dup_recursive(const struct lyd_node *node, struct lyd_node_inner *parent, struct lyd_node *prev, int options)
+static LY_ERR
+lyd_dup_recursive(const struct lyd_node *node, struct lyd_node *parent, struct lyd_node **first, int options,
+ struct lyd_node **dup_p)
{
- struct ly_ctx *ctx;
+ LY_ERR ret;
struct lyd_node *dup = NULL;
+ uint32_t u;
- LY_CHECK_ARG_RET(NULL, node, NULL);
- ctx = node->schema->module->ctx;
+ LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
- switch (node->schema->nodetype) {
- case LYS_ACTION:
- case LYS_NOTIF:
- case LYS_CONTAINER:
- case LYS_LIST:
- dup = calloc(1, sizeof(struct lyd_node_inner));
- break;
- case LYS_LEAF:
- case LYS_LEAFLIST:
- dup = calloc(1, sizeof(struct lyd_node_term));
- break;
- case LYS_ANYDATA:
- case LYS_ANYXML:
- dup = calloc(1, sizeof(struct lyd_node_any));
- break;
- default:
- LOGINT(ctx);
- goto error;
+ if (!node->schema) {
+ dup = calloc(1, sizeof(struct lyd_node_opaq));
+ } else {
+ switch (node->schema->nodetype) {
+ case LYS_ACTION:
+ case LYS_NOTIF:
+ case LYS_CONTAINER:
+ case LYS_LIST:
+ dup = calloc(1, sizeof(struct lyd_node_inner));
+ break;
+ case LYS_LEAF:
+ case LYS_LEAFLIST:
+ dup = calloc(1, sizeof(struct lyd_node_term));
+ break;
+ case LYS_ANYDATA:
+ case LYS_ANYXML:
+ dup = calloc(1, sizeof(struct lyd_node_any));
+ break;
+ default:
+ LOGINT(LYD_NODE_CTX(node));
+ ret = LY_EINT;
+ goto error;
+ }
}
+ LY_CHECK_ERR_GOTO(!dup, LOGMEM(LYD_NODE_CTX(node)); ret = LY_EMEM, error);
/* TODO implement LYD_DUP_WITH_WHEN */
dup->flags = node->flags;
dup->schema = node->schema;
-
- /* interconnect the node at the end */
- dup->parent = parent;
- if (prev) {
- dup->prev = prev;
- prev->next = dup;
- } else {
- dup->prev = dup;
- if (parent) {
- parent->child = dup;
- }
- }
- if (parent) {
- parent->child->prev = dup;
- } else if (prev) {
- struct lyd_node *first;
- for (first = prev; first->prev != prev; first = first->prev);
- first->prev = dup;
- }
+ dup->prev = dup;
/* TODO duplicate attributes, implement LYD_DUP_NO_ATTR */
/* nodetype-specific work */
- 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;
-
- term->hash = orig->hash;
- term->value.realtype = orig->value.realtype;
- LY_CHECK_ERR_GOTO(term->value.realtype->plugin->duplicate(ctx, &orig->value, &term->value),
- LOGERR(ctx, LY_EINT, "Value duplication failed."), error);
- } else if (dup->schema->nodetype & LYD_NODE_INNER) {
- struct lyd_node_inner *inner = (struct lyd_node_inner*)dup;
- struct lyd_node_inner *orig = (struct lyd_node_inner*)node;
- struct lyd_node *child, *last = NULL;
+ if (!dup->schema) {
+ struct lyd_node_opaq *opaq = (struct lyd_node_opaq *)dup;
+ struct lyd_node_opaq *orig = (struct lyd_node_opaq *)node;
+ struct lyd_node *child;
if (options & LYD_DUP_RECURSIVE) {
/* duplicate all the children */
LY_LIST_FOR(orig->child, child) {
- last = lyd_dup_recursive(child, inner, last, options);
- LY_CHECK_GOTO(!last, error);
+ LY_CHECK_GOTO(ret = lyd_dup_recursive(child, dup, NULL, options, NULL), error);
+ }
+ }
+ opaq->name = lydict_insert(LYD_NODE_CTX(node), orig->name, 0);
+ opaq->format = orig->format;
+ if (orig->prefix.pref) {
+ opaq->prefix.pref = lydict_insert(LYD_NODE_CTX(node), orig->prefix.pref, 0);
+ }
+ if (orig->prefix.ns) {
+ opaq->prefix.ns = lydict_insert(LYD_NODE_CTX(node), orig->prefix.ns, 0);
+ }
+ if (orig->val_prefs) {
+ LY_ARRAY_CREATE_GOTO(LYD_NODE_CTX(node), opaq->val_prefs, LY_ARRAY_SIZE(orig->val_prefs), ret, error);
+ LY_ARRAY_FOR(orig->val_prefs, u) {
+ opaq->val_prefs[u].pref = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].pref, 0);
+ opaq->val_prefs[u].ns = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].ns, 0);
+ LY_ARRAY_INCREMENT(opaq->val_prefs);
+ }
+ }
+ opaq->value = lydict_insert(LYD_NODE_CTX(node), orig->value, 0);
+ 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;
+
+ term->hash = orig->hash;
+ term->value.realtype = orig->value.realtype;
+ LY_CHECK_ERR_GOTO(term->value.realtype->plugin->duplicate(LYD_NODE_CTX(node), &orig->value, &term->value),
+ LOGERR(LYD_NODE_CTX(node), LY_EINT, "Value duplication failed."); ret = LY_EINT, error);
+ } else if (dup->schema->nodetype & LYD_NODE_INNER) {
+ struct lyd_node_inner *orig = (struct lyd_node_inner *)node;
+ struct lyd_node *child;
+
+ if (options & LYD_DUP_RECURSIVE) {
+ /* duplicate all the children */
+ LY_LIST_FOR(orig->child, child) {
+ LY_CHECK_GOTO(ret = lyd_dup_recursive(child, dup, NULL, options, NULL), error);
}
} else if (dup->schema->nodetype == LYS_LIST && !(dup->schema->flags & LYS_KEYLESS)) {
/* always duplicate keys of a list */
child = orig->child;
- for (struct lysc_node *key = ((struct lysc_node_list*)dup->schema)->child;
+ for (struct lysc_node *key = ((struct lysc_node_list *)dup->schema)->child;
key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
key = key->next) {
if (!child) {
@@ -1642,14 +1774,14 @@
* but there can be also some non-key nodes */
continue;
}
- last = lyd_dup_recursive(child, inner, last, options);
+ LY_CHECK_GOTO(ret = lyd_dup_recursive(child, dup, NULL, options, NULL), error);
child = child->next;
}
}
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;
+ 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;
@@ -1664,20 +1796,24 @@
case LYD_ANYDATA_XML:
case LYD_ANYDATA_JSON:
if (orig->value.str) {
- any->value.str = lydict_insert(ctx, orig->value.str, strlen(orig->value.str));
+ any->value.str = lydict_insert(LYD_NODE_CTX(node), orig->value.str, strlen(orig->value.str));
}
break;
}
}
+ /* insert */
+ lyd_insert_node(parent, first, dup);
lyd_insert_hash(dup);
- return dup;
+
+ if (dup_p) {
+ *dup_p = dup;
+ }
+ return LY_SUCCESS;
error:
- if (!parent && !prev) {
- lyd_free_tree(dup);
- }
- return NULL;
+ lyd_free_tree(dup);
+ return ret;
}
API struct lyd_node *
@@ -1686,7 +1822,6 @@
struct ly_ctx *ctx;
const struct lyd_node *orig; /* original node to be duplicated */
struct lyd_node *first = NULL; /* the first duplicated node, this is returned */
- struct lyd_node *last = NULL; /* the last sibling of the duplicated nodes */
struct lyd_node *top = NULL; /* the most higher created node */
struct lyd_node_inner *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
int keyless_parent_list = 0;
@@ -1710,8 +1845,9 @@
}
}
} else {
- iter = (struct lyd_node_inner*)lyd_dup_recursive((struct lyd_node*)orig_parent, NULL, NULL, 0);
- LY_CHECK_GOTO(!iter, error);
+ iter = NULL;
+ LY_CHECK_GOTO(lyd_dup_recursive((struct lyd_node *)orig_parent, NULL, (struct lyd_node **)&iter, 0,
+ (struct lyd_node **)&iter), error);
}
if (!local_parent) {
local_parent = iter;
@@ -1745,17 +1881,9 @@
local_parent = parent;
}
- if (local_parent && local_parent->child) {
- last = local_parent->child->prev;
- }
-
LY_LIST_FOR(node, orig) {
- last = lyd_dup_recursive(orig, local_parent, last, options);
- LY_CHECK_GOTO(!last, error);
- if (!first) {
- first = last;
- }
-
+ /* if there is no local parent, it will be inserted into first */
+ LY_CHECK_GOTO(lyd_dup_recursive(orig, (struct lyd_node *)local_parent, &first, options, first ? NULL : &first), error);
if (!(options & LYD_DUP_WITH_SIBLINGS)) {
break;
}