summaryrefslogtreecommitdiffstats
path: root/src/tree_data.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-09-17 02:59:34 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-09-17 02:59:54 +0000
commit5bc4f4fb5b383ca32b382b6c0d09602346064414 (patch)
treec741e5844c2815679107d648a15841653b9b01a5 /src/tree_data.c
parentAdding upstream version 3.1.0+dfsg. (diff)
downloadlibyang3-upstream.tar.xz
libyang3-upstream.zip
Adding upstream version 3.4.2+dfsg.upstream/3.4.2+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tree_data.c')
-rw-r--r--src/tree_data.c107
1 files changed, 39 insertions, 68 deletions
diff --git a/src/tree_data.c b/src/tree_data.c
index dede407..a8c42bf 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -1078,7 +1078,7 @@ lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, struct lyd_n
{
struct lyd_node *first_sibling;
- LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
+ LY_CHECK_ARG_RET(NULL, node, sibling != node, LY_EINVAL);
if (sibling) {
LY_CHECK_RET(lyd_insert_check_schema(NULL, sibling->schema, node->schema));
@@ -2148,6 +2148,11 @@ lyd_dup_r(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_
struct lyd_node *child;
if (options & LYD_DUP_RECURSIVE) {
+ /* create a hash table with the size of the previous hash table (duplicate) */
+ if (orig->children_ht) {
+ ((struct lyd_node_inner *)dup)->children_ht = lyht_new(orig->children_ht->size, sizeof(struct lyd_node *), lyd_hash_table_val_equal, NULL, 1);
+ }
+
/* duplicate all the children */
LY_LIST_FOR(orig->child, child) {
LY_CHECK_GOTO(ret = lyd_dup_r(child, trg_ctx, dup, LYD_INSERT_NODE_LAST, NULL, options, NULL), error);
@@ -2179,58 +2184,6 @@ error:
}
/**
- * @brief Duplicate a (leaf-)list and connect it into @p parent (if present) or last of @p first siblings.
- *
- * @param[in] orig Node to duplicate.
- * @param[in] trg_ctx Target context for duplicated nodes.
- * @param[in] parent Parent to insert into, NULL for top-level sibling.
- * @param[in,out] first First sibling, NULL if no top-level sibling exist yet. Can be also NULL if @p parent is set.
- * @param[in] options Bitmask of options flags, see @ref dupoptions.
- * @param[out] dup_p Pointer where the created duplicated node is placed (besides connecting it to @p parent / @p first).
- * @return LY_ERR value.
- */
-static LY_ERR
-lyd_dup_list(const struct lyd_node **orig, const struct ly_ctx *trg_ctx, struct lyd_node *parent,
- struct lyd_node **first, uint32_t options, struct lyd_node **dup_p)
-{
- LY_ERR rc;
- struct lyd_node *start, *leader, *dup;
- const struct lysc_node *schema;
- uint32_t insert_order;
-
- /* duplicate leader */
- start = (*orig)->next;
- schema = (*orig)->schema;
- rc = lyd_dup_r(*orig, trg_ctx, parent, LYD_INSERT_NODE_DEFAULT, first, options, &leader);
- LY_CHECK_RET(rc);
-
- if (!start || !start->schema || !LYD_NODE_IS_ALONE(leader)) {
- /* no other instances */
- if (dup_p) {
- *dup_p = leader;
- }
- return LY_SUCCESS;
- }
-
- /* duplicate the rest of the nodes in the (leaf-)list */
- insert_order = leader->next ? LYD_INSERT_NODE_LAST_BY_SCHEMA : LYD_INSERT_NODE_LAST;
- LY_LIST_FOR(start, *orig) {
- if (schema != (*orig)->schema) {
- break;
- }
- rc = lyd_dup_r(*orig, trg_ctx, parent, insert_order, first, options, &dup);
- LY_CHECK_GOTO(rc, cleanup);
- }
-
-cleanup:
- if (dup_p) {
- *dup_p = leader;
- }
-
- return rc;
-}
-
-/**
* @brief Get a parent node to connect duplicated subtree to.
*
* @param[in] node Node (subtree) to duplicate.
@@ -2311,12 +2264,14 @@ lyd_dup(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_no
ly_bool nosiblings, struct lyd_node **dup_p)
{
LY_ERR rc;
- const struct lyd_node *orig; /* original node to be duplicated */
- struct lyd_node *first_dup = NULL; /* the first duplicated node, this is returned */
- struct lyd_node *top = NULL; /* the most higher created node */
- struct lyd_node *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
- struct lyd_node *dup = NULL; /* duplicate node */
- struct lyd_node *first_sibling = NULL; /* first sibling node */
+ const struct lyd_node *orig; /* original node to be duplicated */
+ struct lyd_node *first_dup = NULL; /* the first duplicated node, this is returned */
+ struct lyd_node *top = NULL; /* the most higher created node */
+ struct lyd_node *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
+ struct lyd_node *dup = NULL; /* duplicate node */
+ struct lyd_node *first_sibling = NULL; /* first sibling node */
+ const struct lyd_node *first_llist = NULL; /* first duplicated (leaf-)list node, if any */
+ uint32_t insert_order;
assert(node && trg_ctx);
@@ -2339,19 +2294,35 @@ lyd_dup(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_no
rc = lyd_dup_r(orig, trg_ctx, NULL, LYD_INSERT_NODE_DEFAULT, &first_sibling, options, &dup);
LY_CHECK_GOTO(rc, error);
}
- } else if (!nosiblings && orig->schema && (orig->schema->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
- /* duplicate the whole (leaf-)list */
- rc = lyd_dup_list(&orig, trg_ctx, local_parent, &first_sibling, options, &dup);
- LY_CHECK_GOTO(rc, error);
} else {
- rc = lyd_dup_r(orig, trg_ctx, local_parent,
- options & LYD_DUP_NO_LYDS ? LYD_INSERT_NODE_LAST_BY_SCHEMA : LYD_INSERT_NODE_DEFAULT,
- &first_sibling, options, &dup);
+ /* decide insert order */
+ insert_order = (options & LYD_DUP_NO_LYDS) ? LYD_INSERT_NODE_LAST_BY_SCHEMA : LYD_INSERT_NODE_DEFAULT;
+ if (first_llist) {
+ if (orig->schema != first_llist->schema) {
+ /* all the (leaf-)list instances duplicated */
+ first_llist = NULL;
+ } else {
+ /* duplicating all the instances of a (leaf-)list, no need to change their order */
+ insert_order = LYD_INSERT_NODE_LAST;
+ }
+ } else if (orig->schema && (orig->schema->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
+ /* duplicating the first (leaf-)list instance, duplicate the rest more efficiently */
+ first_llist = orig;
+ }
+
+ /* duplicate the node */
+ rc = lyd_dup_r(orig, trg_ctx, local_parent, insert_order, &first_sibling, options, &dup);
LY_CHECK_GOTO(rc, error);
+
+ if (first_llist && dup->next) {
+ /* orig was not the last node (because we are inserting into a parent with some previous instances),
+ * we must check find the order */
+ first_llist = NULL;
+ }
}
first_dup = first_dup ? first_dup : dup;
- if (nosiblings || !orig) {
+ if (nosiblings) {
break;
}
}
@@ -3624,7 +3595,7 @@ lyd_find_path(const struct lyd_node *ctx_node, const char *path, ly_bool output,
cleanup:
lyxp_expr_free(LYD_CTX(ctx_node), expr);
- ly_path_free(LYD_CTX(ctx_node), lypath);
+ ly_path_free(lypath);
return ret;
}