diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-09-17 02:59:34 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-09-17 02:59:54 +0000 |
commit | 5bc4f4fb5b383ca32b382b6c0d09602346064414 (patch) | |
tree | c741e5844c2815679107d648a15841653b9b01a5 /src/tree_data.c | |
parent | Adding upstream version 3.1.0+dfsg. (diff) | |
download | libyang3-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.c | 107 |
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; } |