Coverage Report

Created: 2024-05-20 06:25

/src/libyang/src/tree_data.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * @file tree_data.c
3
 * @author Radek Krejci <rkrejci@cesnet.cz>
4
 * @author Michal Vasko <mvasko@cesnet.cz>
5
 * @brief Data tree functions
6
 *
7
 * Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
8
 *
9
 * This source code is licensed under BSD 3-Clause License (the "License").
10
 * You may not use this file except in compliance with the License.
11
 * You may obtain a copy of the License at
12
 *
13
 *     https://opensource.org/licenses/BSD-3-Clause
14
 */
15
16
#define _GNU_SOURCE
17
18
#include "tree_data.h"
19
20
#include <assert.h>
21
#include <ctype.h>
22
#include <inttypes.h>
23
#include <stdarg.h>
24
#include <stdint.h>
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <string.h>
28
29
#include "compat.h"
30
#include "context.h"
31
#include "dict.h"
32
#include "diff.h"
33
#include "hash_table.h"
34
#include "in.h"
35
#include "in_internal.h"
36
#include "log.h"
37
#include "ly_common.h"
38
#include "parser_data.h"
39
#include "parser_internal.h"
40
#include "path.h"
41
#include "plugins.h"
42
#include "plugins_exts/metadata.h"
43
#include "plugins_internal.h"
44
#include "plugins_types.h"
45
#include "set.h"
46
#include "tree.h"
47
#include "tree_data_internal.h"
48
#include "tree_data_sorted.h"
49
#include "tree_edit.h"
50
#include "tree_schema.h"
51
#include "tree_schema_internal.h"
52
#include "validation.h"
53
#include "xml.h"
54
#include "xpath.h"
55
56
static LY_ERR lyd_compare_siblings_(const struct lyd_node *node1, const struct lyd_node *node2, uint32_t options,
57
        ly_bool parental_schemas_checked);
58
59
static LYD_FORMAT
60
lyd_parse_get_format(const struct ly_in *in, LYD_FORMAT format)
61
10.2k
{
62
10.2k
    if (!format && (in->type == LY_IN_FILEPATH)) {
63
        /* unknown format - try to detect it from filename's suffix */
64
0
        const char *path = in->method.fpath.filepath;
65
0
        size_t len = strlen(path);
66
67
        /* ignore trailing whitespaces */
68
0
        for ( ; len > 0 && isspace(path[len - 1]); len--) {}
69
70
0
        if ((len >= LY_XML_SUFFIX_LEN + 1) &&
71
0
                !strncmp(&path[len - LY_XML_SUFFIX_LEN], LY_XML_SUFFIX, LY_XML_SUFFIX_LEN)) {
72
0
            format = LYD_XML;
73
0
        } else if ((len >= LY_JSON_SUFFIX_LEN + 1) &&
74
0
                !strncmp(&path[len - LY_JSON_SUFFIX_LEN], LY_JSON_SUFFIX, LY_JSON_SUFFIX_LEN)) {
75
0
            format = LYD_JSON;
76
0
        } else if ((len >= LY_LYB_SUFFIX_LEN + 1) &&
77
0
                !strncmp(&path[len - LY_LYB_SUFFIX_LEN], LY_LYB_SUFFIX, LY_LYB_SUFFIX_LEN)) {
78
0
            format = LYD_LYB;
79
0
        } /* else still unknown */
80
0
    }
81
82
10.2k
    return format;
83
10.2k
}
84
85
/**
86
 * @brief Parse YANG data into a data tree.
87
 *
88
 * @param[in] ctx libyang context.
89
 * @param[in] ext Optional extenion instance to parse data following the schema tree specified in the extension instance
90
 * @param[in] parent Parent to connect the parsed nodes to, if any.
91
 * @param[in,out] first_p Pointer to the first parsed node.
92
 * @param[in] in Input handle to read the input from.
93
 * @param[in] format Expected format of the data in @p in.
94
 * @param[in] parse_opts Options for parser.
95
 * @param[in] val_opts Options for validation.
96
 * @param[out] op Optional pointer to the parsed operation, if any.
97
 * @return LY_ERR value.
98
 */
99
static LY_ERR
100
lyd_parse(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent, struct lyd_node **first_p,
101
        struct ly_in *in, LYD_FORMAT format, uint32_t parse_opts, uint32_t val_opts, struct lyd_node **op)
102
10.2k
{
103
10.2k
    LY_ERR r = LY_SUCCESS, rc = LY_SUCCESS;
104
10.2k
    struct lyd_ctx *lydctx = NULL;
105
10.2k
    struct ly_set parsed = {0};
106
10.2k
    uint32_t i, int_opts = 0;
107
10.2k
    const struct ly_err_item *eitem;
108
10.2k
    ly_bool subtree_sibling = 0;
109
110
10.2k
    assert(ctx && (parent || first_p));
111
112
10.2k
    format = lyd_parse_get_format(in, format);
113
10.2k
    if (first_p) {
114
10.2k
        *first_p = NULL;
115
10.2k
    }
116
117
    /* remember input position */
118
10.2k
    in->func_start = in->current;
119
120
    /* set internal options */
121
10.2k
    if (!(parse_opts & LYD_PARSE_SUBTREE)) {
122
10.2k
        int_opts = LYD_INTOPT_WITH_SIBLINGS;
123
10.2k
    }
124
125
    /* parse the data */
126
10.2k
    switch (format) {
127
10.1k
    case LYD_XML:
128
10.1k
        r = lyd_parse_xml(ctx, ext, parent, first_p, in, parse_opts, val_opts, int_opts, &parsed,
129
10.1k
                &subtree_sibling, &lydctx);
130
10.1k
        break;
131
77
    case LYD_JSON:
132
77
        r = lyd_parse_json(ctx, ext, parent, first_p, in, parse_opts, val_opts, int_opts, &parsed,
133
77
                &subtree_sibling, &lydctx);
134
77
        break;
135
0
    case LYD_LYB:
136
0
        r = lyd_parse_lyb(ctx, ext, parent, first_p, in, parse_opts, val_opts, int_opts, &parsed,
137
0
                &subtree_sibling, &lydctx);
138
0
        break;
139
0
    case LYD_UNKNOWN:
140
0
        LOGARG(ctx, format);
141
0
        r = LY_EINVAL;
142
0
        break;
143
10.2k
    }
144
10.2k
    if (r) {
145
9.68k
        rc = r;
146
9.68k
        if ((r != LY_EVALID) || !lydctx || !(lydctx->val_opts & LYD_VALIDATE_MULTI_ERROR)) {
147
9.68k
            goto cleanup;
148
9.68k
        }
149
150
0
        eitem = ly_err_last(ctx);
151
0
        assert(eitem);
152
0
        if (eitem->vecode == LYVE_SYNTAX) {
153
            /* cannot get more errors on a syntax error */
154
0
            goto cleanup;
155
0
        }
156
0
    }
157
158
533
    if (parent && parsed.count) {
159
        /* use the first parsed node */
160
0
        if (first_p) {
161
0
            *first_p = parsed.dnodes[0];
162
0
        } else {
163
0
            first_p = &parsed.dnodes[0];
164
0
        }
165
0
    }
166
167
533
    if (!(parse_opts & LYD_PARSE_ONLY)) {
168
        /* validate data */
169
533
        r = lyd_validate(first_p, NULL, ctx, val_opts, 0, &lydctx->node_when, &lydctx->node_types, &lydctx->meta_types,
170
533
                &lydctx->ext_node, &lydctx->ext_val, NULL);
171
533
        LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
172
258
    }
173
174
    /* set the operation node */
175
258
    if (op) {
176
0
        *op = lydctx->op_node;
177
0
    }
178
179
10.2k
cleanup:
180
10.2k
    if (lydctx) {
181
533
        lydctx->free(lydctx);
182
533
    }
183
10.2k
    if (rc) {
184
9.96k
        if (parent) {
185
            /* free all the parsed subtrees */
186
0
            for (i = 0; i < parsed.count; ++i) {
187
0
                lyd_free_tree(parsed.dnodes[i]);
188
0
            }
189
9.96k
        } else {
190
            /* free everything */
191
9.96k
            lyd_free_all(*first_p);
192
9.96k
            *first_p = NULL;
193
9.96k
        }
194
9.96k
    } else if (subtree_sibling) {
195
0
        rc = LY_ENOT;
196
0
    }
197
10.2k
    ly_set_erase(&parsed, NULL);
198
10.2k
    return rc;
199
258
}
200
201
LIBYANG_API_DEF LY_ERR
202
lyd_parse_ext_data(const struct lysc_ext_instance *ext, struct lyd_node *parent, struct ly_in *in, LYD_FORMAT format,
203
        uint32_t parse_options, uint32_t validate_options, struct lyd_node **tree)
204
0
{
205
0
    const struct ly_ctx *ctx = ext ? ext->module->ctx : NULL;
206
207
0
    LY_CHECK_ARG_RET(ctx, ext, in, parent || tree, LY_EINVAL);
208
0
    LY_CHECK_ARG_RET(ctx, !(parse_options & ~LYD_PARSE_OPTS_MASK), LY_EINVAL);
209
0
    LY_CHECK_ARG_RET(ctx, !(validate_options & ~LYD_VALIDATE_OPTS_MASK), LY_EINVAL);
210
211
0
    return lyd_parse(ctx, ext, parent, tree, in, format, parse_options, validate_options, NULL);
212
0
}
213
214
LIBYANG_API_DEF LY_ERR
215
lyd_parse_data(const struct ly_ctx *ctx, struct lyd_node *parent, struct ly_in *in, LYD_FORMAT format,
216
        uint32_t parse_options, uint32_t validate_options, struct lyd_node **tree)
217
10.2k
{
218
20.4k
    LY_CHECK_ARG_RET(ctx, ctx, in, parent || tree, LY_EINVAL);
219
10.2k
    LY_CHECK_ARG_RET(ctx, !(parse_options & ~LYD_PARSE_OPTS_MASK), LY_EINVAL);
220
10.2k
    LY_CHECK_ARG_RET(ctx, !(validate_options & ~LYD_VALIDATE_OPTS_MASK), LY_EINVAL);
221
222
10.2k
    return lyd_parse(ctx, NULL, parent, tree, in, format, parse_options, validate_options, NULL);
223
10.2k
}
224
225
LIBYANG_API_DEF LY_ERR
226
lyd_parse_data_mem(const struct ly_ctx *ctx, const char *data, LYD_FORMAT format, uint32_t parse_options,
227
        uint32_t validate_options, struct lyd_node **tree)
228
10.2k
{
229
10.2k
    LY_ERR ret;
230
10.2k
    struct ly_in *in;
231
232
10.2k
    LY_CHECK_RET(ly_in_new_memory(data, &in));
233
10.2k
    ret = lyd_parse_data(ctx, NULL, in, format, parse_options, validate_options, tree);
234
235
10.2k
    ly_in_free(in, 0);
236
10.2k
    return ret;
237
10.2k
}
238
239
LIBYANG_API_DEF LY_ERR
240
lyd_parse_data_fd(const struct ly_ctx *ctx, int fd, LYD_FORMAT format, uint32_t parse_options, uint32_t validate_options,
241
        struct lyd_node **tree)
242
0
{
243
0
    LY_ERR ret;
244
0
    struct ly_in *in;
245
246
0
    LY_CHECK_RET(ly_in_new_fd(fd, &in));
247
0
    ret = lyd_parse_data(ctx, NULL, in, format, parse_options, validate_options, tree);
248
249
0
    ly_in_free(in, 0);
250
0
    return ret;
251
0
}
252
253
LIBYANG_API_DEF LY_ERR
254
lyd_parse_data_path(const struct ly_ctx *ctx, const char *path, LYD_FORMAT format, uint32_t parse_options,
255
        uint32_t validate_options, struct lyd_node **tree)
256
0
{
257
0
    LY_ERR ret;
258
0
    struct ly_in *in;
259
260
0
    LY_CHECK_RET(ly_in_new_filepath(path, 0, &in));
261
0
    ret = lyd_parse_data(ctx, NULL, in, format, parse_options, validate_options, tree);
262
263
0
    ly_in_free(in, 0);
264
0
    return ret;
265
0
}
266
267
/**
268
 * @brief Parse YANG data into an operation data tree, in case the extension instance is specified, keep the searching
269
 * for schema nodes locked inside the extension instance.
270
 *
271
 * At least one of @p parent, @p tree, or @p op must always be set.
272
 *
273
 * Specific @p data_type values have different parameter meaning as mentioned for ::lyd_parse_op().
274
 *
275
 * @param[in] ctx libyang context.
276
 * @param[in] ext Extension instance providing the specific schema tree to match with the data being parsed.
277
 * @param[in] parent Optional parent to connect the parsed nodes to.
278
 * @param[in] in Input handle to read the input from.
279
 * @param[in] format Expected format of the data in @p in.
280
 * @param[in] data_type Expected operation to parse (@ref datatype).
281
 * @param[out] tree Optional full parsed data tree. If @p parent is set, set to NULL.
282
 * @param[out] op Optional parsed operation node.
283
 * @return LY_ERR value.
284
 * @return LY_ENOT if @p data_type is a NETCONF message and the root XML element is not the expected one.
285
 */
286
static LY_ERR
287
lyd_parse_op_(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
288
        struct ly_in *in, LYD_FORMAT format, enum lyd_type data_type, struct lyd_node **tree, struct lyd_node **op)
289
0
{
290
0
    LY_ERR rc = LY_SUCCESS;
291
0
    struct lyd_ctx *lydctx = NULL;
292
0
    struct ly_set parsed = {0};
293
0
    struct lyd_node *first = NULL, *envp = NULL;
294
0
    uint32_t i, parse_opts, val_opts, int_opts = 0;
295
0
    ly_bool proto_msg = 0;
296
297
0
    if (!ctx) {
298
0
        ctx = LYD_CTX(parent);
299
0
    }
300
0
    if (tree) {
301
0
        *tree = NULL;
302
0
    }
303
0
    if (op) {
304
0
        *op = NULL;
305
0
    }
306
307
0
    format = lyd_parse_get_format(in, format);
308
309
    /* remember input position */
310
0
    in->func_start = in->current;
311
312
    /* set parse and validation opts */
313
0
    parse_opts = LYD_PARSE_ONLY | LYD_PARSE_STRICT;
314
0
    val_opts = 0;
315
316
0
    switch (data_type) {
317
0
    case LYD_TYPE_RPC_NETCONF:
318
0
    case LYD_TYPE_NOTIF_NETCONF:
319
0
        LY_CHECK_ARG_RET(ctx, format == LYD_XML, !parent, tree, op, LY_EINVAL);
320
0
        proto_msg = 1;
321
0
        break;
322
0
    case LYD_TYPE_REPLY_NETCONF:
323
0
        LY_CHECK_ARG_RET(ctx, format == LYD_XML, parent, parent->schema, parent->schema->nodetype & (LYS_RPC | LYS_ACTION),
324
0
                tree, !op, LY_EINVAL);
325
0
        proto_msg = 1;
326
0
        break;
327
0
    case LYD_TYPE_RPC_RESTCONF:
328
0
    case LYD_TYPE_REPLY_RESTCONF:
329
0
        LY_CHECK_ARG_RET(ctx, parent, parent->schema, parent->schema->nodetype & (LYS_RPC | LYS_ACTION), tree, !op, LY_EINVAL);
330
0
        proto_msg = 1;
331
0
        break;
332
0
    case LYD_TYPE_NOTIF_RESTCONF:
333
0
        LY_CHECK_ARG_RET(ctx, format == LYD_JSON, !parent, tree, op, LY_EINVAL);
334
0
        proto_msg = 1;
335
0
        break;
336
337
    /* set internal opts */
338
0
    case LYD_TYPE_RPC_YANG:
339
0
        int_opts = LYD_INTOPT_RPC | LYD_INTOPT_ACTION | (parent ? LYD_INTOPT_WITH_SIBLINGS : LYD_INTOPT_NO_SIBLINGS);
340
0
        break;
341
0
    case LYD_TYPE_NOTIF_YANG:
342
0
        int_opts = LYD_INTOPT_NOTIF | (parent ? LYD_INTOPT_WITH_SIBLINGS : LYD_INTOPT_NO_SIBLINGS);
343
0
        break;
344
0
    case LYD_TYPE_REPLY_YANG:
345
0
        int_opts = LYD_INTOPT_REPLY | (parent ? LYD_INTOPT_WITH_SIBLINGS : LYD_INTOPT_NO_SIBLINGS);
346
0
        break;
347
0
    case LYD_TYPE_DATA_YANG:
348
0
        LOGINT(ctx);
349
0
        rc = LY_EINT;
350
0
        goto cleanup;
351
0
    }
352
353
    /* parse a full protocol message */
354
0
    if (proto_msg) {
355
0
        if (format == LYD_XML) {
356
            /* parse the NETCONF (or RESTCONF XML) message */
357
0
            rc = lyd_parse_xml_netconf(ctx, ext, parent, &first, in, parse_opts, val_opts, data_type, &envp, &parsed, &lydctx);
358
0
        } else {
359
            /* parse the RESTCONF message */
360
0
            rc = lyd_parse_json_restconf(ctx, ext, parent, &first, in, parse_opts, val_opts, data_type, &envp, &parsed, &lydctx);
361
0
        }
362
0
        if (rc) {
363
0
            if (envp) {
364
                /* special situation when the envelopes were parsed successfully */
365
0
                *tree = envp;
366
0
            }
367
0
            goto cleanup;
368
0
        }
369
370
        /* set out params correctly */
371
0
        if (envp) {
372
            /* special out param meaning */
373
0
            *tree = envp;
374
0
        } else {
375
0
            *tree = parent ? NULL : first;
376
0
        }
377
0
        if (op) {
378
0
            *op = lydctx->op_node;
379
0
        }
380
0
        goto cleanup;
381
0
    }
382
383
    /* parse the data */
384
0
    switch (format) {
385
0
    case LYD_XML:
386
0
        rc = lyd_parse_xml(ctx, ext, parent, &first, in, parse_opts, val_opts, int_opts, &parsed, NULL, &lydctx);
387
0
        break;
388
0
    case LYD_JSON:
389
0
        rc = lyd_parse_json(ctx, ext, parent, &first, in, parse_opts, val_opts, int_opts, &parsed, NULL, &lydctx);
390
0
        break;
391
0
    case LYD_LYB:
392
0
        rc = lyd_parse_lyb(ctx, ext, parent, &first, in, parse_opts, val_opts, int_opts, &parsed, NULL, &lydctx);
393
0
        break;
394
0
    case LYD_UNKNOWN:
395
0
        LOGARG(ctx, format);
396
0
        rc = LY_EINVAL;
397
0
        break;
398
0
    }
399
0
    LY_CHECK_GOTO(rc, cleanup);
400
401
    /* set out params correctly */
402
0
    if (tree) {
403
0
        *tree = parent ? NULL : first;
404
0
    }
405
0
    if (op) {
406
0
        *op = lydctx->op_node;
407
0
    }
408
409
0
cleanup:
410
0
    if (lydctx) {
411
0
        lydctx->free(lydctx);
412
0
    }
413
0
    if (rc) {
414
        /* free all the parsed nodes */
415
0
        if (parsed.count) {
416
0
            i = parsed.count;
417
0
            do {
418
0
                --i;
419
0
                lyd_free_tree(parsed.dnodes[i]);
420
0
            } while (i);
421
0
        }
422
0
        if (tree && !envp) {
423
0
            *tree = NULL;
424
0
        }
425
0
        if (op) {
426
0
            *op = NULL;
427
0
        }
428
0
    }
429
0
    ly_set_erase(&parsed, NULL);
430
0
    return rc;
431
0
}
432
433
LIBYANG_API_DEF LY_ERR
434
lyd_parse_op(const struct ly_ctx *ctx, struct lyd_node *parent, struct ly_in *in, LYD_FORMAT format,
435
        enum lyd_type data_type, struct lyd_node **tree, struct lyd_node **op)
436
0
{
437
0
    LY_CHECK_ARG_RET(ctx, ctx || parent, in, data_type, parent || tree || op, LY_EINVAL);
438
439
0
    return lyd_parse_op_(ctx, NULL, parent, in, format, data_type, tree, op);
440
0
}
441
442
LIBYANG_API_DEF LY_ERR
443
lyd_parse_ext_op(const struct lysc_ext_instance *ext, struct lyd_node *parent, struct ly_in *in, LYD_FORMAT format,
444
        enum lyd_type data_type, struct lyd_node **tree, struct lyd_node **op)
445
0
{
446
0
    const struct ly_ctx *ctx = ext ? ext->module->ctx : NULL;
447
448
0
    LY_CHECK_ARG_RET(ctx, ext, in, data_type, parent || tree || op, LY_EINVAL);
449
450
0
    return lyd_parse_op_(ctx, ext, parent, in, format, data_type, tree, op);
451
0
}
452
453
struct lyd_node *
454
lyd_insert_get_next_anchor(const struct lyd_node *first_sibling, const struct lyd_node *new_node)
455
505k
{
456
505k
    const struct lysc_node *schema, *sparent;
457
505k
    struct lyd_node *match = NULL;
458
505k
    ly_bool found;
459
505k
    uint32_t getnext_opts;
460
461
505k
    assert(new_node);
462
463
505k
    if (!first_sibling || !new_node->schema || (LYD_CTX(first_sibling) != LYD_CTX(new_node))) {
464
        /* insert at the end, no next anchor */
465
22.1k
        return NULL;
466
22.1k
    }
467
468
483k
    getnext_opts = 0;
469
483k
    if (new_node->schema->flags & LYS_IS_OUTPUT) {
470
0
        getnext_opts = LYS_GETNEXT_OUTPUT;
471
0
    }
472
473
483k
    if (first_sibling->parent && first_sibling->parent->schema && first_sibling->parent->children_ht) {
474
        /* find the anchor using hashes */
475
446k
        sparent = first_sibling->parent->schema;
476
446k
        schema = lys_getnext(new_node->schema, sparent, NULL, getnext_opts);
477
904k
        while (schema) {
478
            /* keep trying to find the first existing instance of the closest following schema sibling,
479
             * otherwise return NULL - inserting at the end */
480
699k
            if (!lyd_find_sibling_schema(first_sibling, schema, &match)) {
481
241k
                break;
482
241k
            }
483
484
457k
            schema = lys_getnext(schema, sparent, NULL, getnext_opts);
485
457k
        }
486
446k
    } else {
487
        /* find the anchor without hashes */
488
36.3k
        match = (struct lyd_node *)first_sibling;
489
36.3k
        sparent = lysc_data_parent(new_node->schema);
490
36.3k
        if (!sparent) {
491
            /* we are in top-level, skip all the data from preceding modules */
492
11.0k
            LY_LIST_FOR(match, match) {
493
11.0k
                if (!match->schema || (strcmp(lyd_owner_module(match)->name, lyd_owner_module(new_node)->name) >= 0)) {
494
11.0k
                    break;
495
11.0k
                }
496
11.0k
            }
497
11.0k
        }
498
499
        /* get the first schema sibling */
500
36.3k
        schema = lys_getnext(NULL, sparent, new_node->schema->module->compiled, getnext_opts);
501
36.3k
        if (!schema) {
502
            /* must be a top-level extension instance data, no anchor */
503
0
            return NULL;
504
0
        }
505
506
36.3k
        found = 0;
507
5.17M
        LY_LIST_FOR(match, match) {
508
5.17M
            if (!match->schema || (lyd_owner_module(match) != lyd_owner_module(new_node))) {
509
                /* we have found an opaque node, which must be at the end, so use it OR
510
                 * modules do not match, so we must have traversed all the data from new_node module (if any),
511
                 * we have found the first node of the next module, that is what we want */
512
1
                break;
513
1
            }
514
515
            /* skip schema nodes until we find the instantiated one */
516
5.31M
            while (!found) {
517
184k
                if (new_node->schema == schema) {
518
                    /* we have found the schema of the new node, continue search to find the first
519
                     * data node with a different schema (after our schema) */
520
31.0k
                    found = 1;
521
31.0k
                    break;
522
31.0k
                }
523
153k
                if (match->schema == schema) {
524
                    /* current node (match) is a data node still before the new node, continue search in data */
525
11.3k
                    break;
526
11.3k
                }
527
528
142k
                schema = lys_getnext(schema, sparent, new_node->schema->module->compiled, getnext_opts);
529
142k
                if (!schema) {
530
                    /* must be a top-level extension instance data, no anchor */
531
0
                    return NULL;
532
0
                }
533
142k
            }
534
535
5.17M
            if (found && (match->schema != new_node->schema)) {
536
                /* find the next node after we have found our node schema data instance */
537
17.7k
                break;
538
17.7k
            }
539
5.17M
        }
540
36.3k
    }
541
542
483k
    return match;
543
483k
}
544
545
void
546
lyd_insert_after_node(struct lyd_node **first_sibling_p, struct lyd_node *sibling, struct lyd_node *node)
547
251k
{
548
251k
    struct lyd_node_inner *par;
549
251k
    struct lyd_node *first_sibling;
550
551
251k
    assert(!node->next && (node->prev == node));
552
553
251k
    if (sibling->next) {
554
        /* sibling had a succeeding node */
555
28.7k
        sibling->next->prev = node;
556
28.7k
        node->next = sibling->next;
557
223k
    } else {
558
        /* sibling was last, find first sibling and change its prev */
559
223k
        if (first_sibling_p && *first_sibling_p) {
560
223k
            assert(!(*first_sibling_p)->prev->next);
561
223k
            (*first_sibling_p)->prev = node;
562
223k
        } else {
563
0
            first_sibling = lyd_first_sibling(sibling);
564
0
            first_sibling->prev = node;
565
0
            if (first_sibling_p) {
566
0
                *first_sibling_p = first_sibling;
567
0
            }
568
0
        }
569
223k
    }
570
251k
    node->prev = sibling;
571
251k
    sibling->next = node;
572
251k
    node->parent = sibling->parent;
573
574
465k
    for (par = node->parent; par; par = par->parent) {
575
214k
        if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
576
            /* remove default flags from NP containers */
577
0
            par->flags &= ~LYD_DEFAULT;
578
0
        }
579
214k
    }
580
251k
}
581
582
void
583
lyd_insert_before_node(struct lyd_node *sibling, struct lyd_node *node)
584
147k
{
585
147k
    struct lyd_node_inner *par;
586
587
147k
    assert(!node->next && (node->prev == node));
588
589
147k
    node->next = sibling;
590
    /* covers situation of sibling being first */
591
147k
    node->prev = sibling->prev;
592
147k
    sibling->prev = node;
593
147k
    if (node->prev->next) {
594
        /* sibling had a preceding node */
595
126k
        node->prev->next = node;
596
126k
    } else if (sibling->parent) {
597
        /* sibling was first and we must also change parent child pointer */
598
20.6k
        sibling->parent->child = node;
599
20.6k
    }
600
147k
    node->parent = sibling->parent;
601
602
294k
    for (par = node->parent; par; par = par->parent) {
603
146k
        if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
604
            /* remove default flags from NP containers */
605
0
            par->flags &= ~LYD_DEFAULT;
606
0
        }
607
146k
    }
608
147k
}
609
610
/**
611
 * @brief Insert node as the first and only child of a parent.
612
 *
613
 * Handles inserting into NP containers and key-less lists.
614
 *
615
 * @param[in] parent Parent to insert into.
616
 * @param[in] node Node to insert.
617
 */
618
static void
619
lyd_insert_only_child(struct lyd_node *parent, struct lyd_node *node)
620
14.3k
{
621
14.3k
    struct lyd_node_inner *par;
622
623
14.3k
    assert(parent && !lyd_child(parent) && !node->next && (node->prev == node));
624
14.3k
    assert(!parent->schema || (parent->schema->nodetype & LYD_NODE_INNER));
625
626
14.3k
    par = (struct lyd_node_inner *)parent;
627
628
14.3k
    par->child = node;
629
14.3k
    node->parent = par;
630
631
28.6k
    for ( ; par; par = par->parent) {
632
14.3k
        if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
633
            /* remove default flags from NP containers */
634
9
            par->flags &= ~LYD_DEFAULT;
635
9
        }
636
14.3k
    }
637
14.3k
}
638
639
/**
640
 * @brief Learn whether a list instance has all the keys.
641
 *
642
 * @param[in] list List instance to check.
643
 * @return non-zero if all the keys were found,
644
 * @return 0 otherwise.
645
 */
646
static int
647
lyd_insert_has_keys(const struct lyd_node *list)
648
238k
{
649
238k
    const struct lyd_node *key;
650
238k
    const struct lysc_node *skey = NULL;
651
652
238k
    assert(list->schema->nodetype == LYS_LIST);
653
238k
    key = lyd_child(list);
654
476k
    while ((skey = lys_getnext(skey, list->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
655
334k
        if (!key || (key->schema != skey)) {
656
            /* key missing */
657
96.1k
            return 0;
658
96.1k
        }
659
660
238k
        key = key->next;
661
238k
    }
662
663
    /* all keys found */
664
141k
    return 1;
665
238k
}
666
667
/**
668
 * @brief Get the first subsequent data node that contains a different schema definition.
669
 *
670
 * @param[in] first_sibling First sibling, NULL if no top-level sibling exist yet.
671
 * @param[in] node Node to be inserted.
672
 * @return Subsequent data node with a different schema.
673
 */
674
static struct lyd_node *
675
lyd_insert_node_find_anchor(struct lyd_node *first_sibling, struct lyd_node *node)
676
266k
{
677
266k
    struct lyd_node *anchor;
678
679
266k
    if (first_sibling && (first_sibling->flags & LYD_EXT)) {
680
0
        return NULL;
681
0
    }
682
683
    /* find the anchor, so we can insert somewhere before it */
684
266k
    anchor = lyd_insert_get_next_anchor(first_sibling, node);
685
    /* cannot insert data node after opaque nodes */
686
266k
    if (!anchor && node->schema && first_sibling && !first_sibling->prev->schema) {
687
0
        anchor = first_sibling->prev;
688
0
        while ((anchor != first_sibling) && !anchor->prev->schema) {
689
0
            anchor = anchor->prev;
690
0
        }
691
0
    }
692
693
266k
    return anchor;
694
266k
}
695
696
/**
697
 * @brief Insert @p node as the last node.
698
 *
699
 * @param[in] parent Parent to insert into, NULL for top-level sibling.
700
 * @param[in,out] first_sibling First sibling, NULL if no top-level sibling exist yet.
701
 * Can be also NULL if @p parent is set.
702
 * @param[in] node Individual node (without siblings) to insert.
703
 */
704
static void
705
lyd_insert_node_last(struct lyd_node *parent, struct lyd_node **first_sibling, struct lyd_node *node)
706
134k
{
707
134k
    assert(first_sibling && node);
708
709
134k
    if (*first_sibling) {
710
119k
        lyd_insert_after_node(first_sibling, (*first_sibling)->prev, node);
711
119k
    } else if (parent) {
712
14.3k
        lyd_insert_only_child(parent, node);
713
14.3k
        *first_sibling = node;
714
14.3k
    } else {
715
938
        *first_sibling = node;
716
938
    }
717
134k
}
718
719
void
720
lyd_insert_node_ordby_schema(struct lyd_node *parent, struct lyd_node **first_sibling, struct lyd_node *node)
721
266k
{
722
266k
    struct lyd_node *anchor;
723
724
266k
    assert(first_sibling && node);
725
726
266k
    if ((anchor = lyd_insert_node_find_anchor(*first_sibling, node))) {
727
132k
        lyd_insert_before_node(anchor, node);
728
132k
        *first_sibling = *first_sibling != anchor ? *first_sibling : node;
729
134k
    } else if (*first_sibling && node->schema && !(*first_sibling)->prev->schema) {
730
        /* cannot insert data node after opaque nodes */
731
0
        anchor = (*first_sibling)->prev;
732
0
        while ((anchor != *first_sibling) && !anchor->prev->schema) {
733
0
            anchor = anchor->prev;
734
0
        }
735
0
        lyd_insert_before_node(anchor, node);
736
0
        *first_sibling = *first_sibling != anchor ? *first_sibling : node;
737
134k
    } else {
738
134k
        lyd_insert_node_last(parent, first_sibling, node);
739
134k
    }
740
266k
}
741
742
void
743
lyd_insert_node(struct lyd_node *parent, struct lyd_node **first_sibling_p, struct lyd_node *node, uint32_t order)
744
414k
{
745
414k
    LY_ERR ret = LY_SUCCESS;
746
414k
    struct lyd_node *first_sibling, *leader;
747
748
    /* inserting list without its keys is not supported */
749
414k
    assert((parent || first_sibling_p) && node && (node->hash || !node->schema));
750
414k
    assert(!parent || !parent->schema ||
751
414k
            (parent->schema->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_ACTION | LYS_NOTIF)));
752
753
414k
    if (!parent && first_sibling_p && (*first_sibling_p)) {
754
38.6k
        parent = lyd_parent(*first_sibling_p);
755
38.6k
    }
756
414k
    first_sibling = parent ? lyd_child(parent) : *first_sibling_p;
757
758
414k
    if ((order == LYD_INSERT_NODE_LAST) || !node->schema || (first_sibling && (first_sibling->flags & LYD_EXT))) {
759
12
        lyd_insert_node_last(parent, &first_sibling, node);
760
414k
    } else if (order == LYD_INSERT_NODE_LAST_BY_SCHEMA) {
761
0
        lyd_insert_node_ordby_schema(parent, &first_sibling, node);
762
414k
    } else if (lyds_is_supported(node) &&
763
414k
            (lyd_find_sibling_schema(first_sibling, node->schema, &leader) == LY_SUCCESS)) {
764
147k
        ret = lyds_insert(&first_sibling, &leader, node);
765
147k
        if (ret) {
766
            /* The operation on the sorting tree unexpectedly failed due to some internal issue,
767
             * but insert the node anyway although the nodes will not be sorted.
768
             */
769
0
            LOGWRN(LYD_CTX(node), "Data in \"%s\" are not sorted.", node->schema->name);
770
0
            lyd_insert_node_ordby_schema(parent, &first_sibling, node);
771
0
        }
772
266k
    } else {
773
266k
        lyd_insert_node_ordby_schema(parent, &first_sibling, node);
774
266k
    }
775
776
    /* insert into parent HT */
777
414k
    lyd_insert_hash(node);
778
779
    /* finish hashes for our parent, if needed and possible */
780
414k
    if (node->schema && (node->schema->flags & LYS_KEY) && parent && parent->schema && lyd_insert_has_keys(parent)) {
781
141k
        lyd_hash(parent);
782
783
        /* now we can insert even the list into its parent HT */
784
141k
        lyd_insert_hash(parent);
785
141k
    }
786
787
414k
    if (first_sibling_p) {
788
414k
        *first_sibling_p = first_sibling;
789
414k
    }
790
791
414k
#ifndef NDEBUG
792
414k
    if ((order == LYD_INSERT_NODE_LAST) && lyds_is_supported(node) &&
793
414k
            (node->prev->schema == node->schema) && (lyds_compare_single(node->prev, node) > 0)) {
794
0
        LOGWRN(LYD_CTX(node), "Data in \"%s\" are not sorted, inserted node should not be added to the end.",
795
0
                node->schema->name);
796
0
    }
797
414k
#endif
798
414k
}
799
800
/**
801
 * @brief Check that @p node can be unlinked.
802
 *
803
 * @param[in] node Node to check
804
 * @return LY_ERR value.
805
 */
806
static LY_ERR
807
lyd_unlink_check(struct lyd_node *node)
808
0
{
809
0
    if (!node) {
810
0
        return LY_SUCCESS;
811
0
    }
812
813
0
    if (lysc_is_key(node->schema) && node->parent) {
814
0
        LOGERR(LYD_CTX(node), LY_EINVAL, "Cannot unlink a list key \"%s\", unlink the list instance instead.",
815
0
                LYD_NAME(node));
816
0
        return LY_EINVAL;
817
0
    }
818
819
0
    return LY_SUCCESS;
820
0
}
821
822
/**
823
 * @brief Move schema instances before anchor or as the last.
824
 *
825
 * The nodes will remain sorted according to the schema.
826
 *
827
 * @param[in] first_dst First sibling, destination.
828
 * @param[in] node Starting node, all following nodes with the same schema will be moved.
829
 * @param[out] next_p Next node that has a different schema or NULL.
830
 * @return LY_ERR value.
831
 */
832
static LY_ERR
833
lyd_move_nodes_ordby_schema(struct lyd_node **first_dst, struct lyd_node *node, struct lyd_node **next_p)
834
0
{
835
0
    struct lyd_node *second, *anchor, *iter, *next, *dst, *src, *first_src = NULL;
836
837
0
    assert(first_dst && *first_dst && !(*first_dst)->prev->next && node && next_p);
838
839
0
    if ((anchor = lyd_insert_node_find_anchor(*first_dst, node))) {
840
        /* move the first node to the correct place according to the schema */
841
0
        LY_CHECK_RET(lyd_unlink_check(node));
842
0
        second = node->next;
843
0
        lyd_unlink_ignore_lyds(&first_src, node);
844
0
        lyd_insert_before_node(anchor, node);
845
0
        lyd_insert_hash(node);
846
0
        *first_dst = *first_dst != anchor ? *first_dst : node;
847
0
        if (!second || (node->schema != second->schema)) {
848
            /* no more nodes to move */
849
0
            *next_p = second;
850
0
            return LY_SUCCESS;
851
0
        }
852
0
        dst = node;
853
0
        src = second;
854
0
    } else {
855
        /* just move all instances to the end */
856
0
        dst = (*first_dst)->prev;
857
0
        src = node;
858
0
    }
859
860
    /* move the rest of source instances after @p node */
861
0
    LY_LIST_FOR_SAFE(src, next, iter) {
862
0
        LY_CHECK_RET(lyd_unlink_check(iter));
863
0
        if (iter->schema != src->schema) {
864
0
            break;
865
0
        }
866
0
        lyd_unlink_ignore_lyds(&first_src, iter);
867
0
        lyd_insert_after_node(first_dst, dst, iter);
868
0
        lyd_insert_hash(iter);
869
0
        dst = iter;
870
0
    }
871
0
    *next_p = iter;
872
873
0
    return LY_SUCCESS;
874
0
}
875
876
/**
877
 * @brief Move nodes regardless of schema.
878
 *
879
 * The destination for the move is NULL, or a childless parent.
880
 *
881
 * @param[in] parent Parent to insert into, NULL for top-level sibling.
882
 * @param[in] first_src First sibling, all following nodes will be moved.
883
 * @return LY_ERR value.
884
 */
885
static LY_ERR
886
lyd_move_nodes_at_once(struct lyd_node *parent, struct lyd_node *first_src)
887
0
{
888
0
    struct lyd_node *start, *next, *iter, *first_dst;
889
890
0
    assert(!lyd_child(parent) && first_src && !first_src->prev->next && !first_src->parent);
891
892
0
    LY_CHECK_RET(lyd_unlink_check(first_src));
893
894
    /* move the first node */
895
0
    start = first_src->next;
896
0
    first_dst = first_src;
897
0
    if (parent) {
898
0
        lyd_unlink_ignore_lyds(&first_src, first_dst);
899
0
        lyd_insert_only_child(parent, first_dst);
900
0
        lyd_insert_hash(first_dst);
901
0
    } else {
902
0
        lyd_unlink_ignore_lyds(&first_src, first_dst);
903
0
    }
904
905
    /* move the rest of the nodes */
906
0
    LY_LIST_FOR_SAFE(start, next, iter) {
907
0
        LY_CHECK_RET(lyd_unlink_check(iter));
908
0
        lyd_unlink_ignore_lyds(&first_src, iter);
909
0
        lyd_insert_after_node(&first_dst, first_dst->prev, iter);
910
0
        lyd_insert_hash(iter);
911
0
    }
912
913
0
    return LY_SUCCESS;
914
0
}
915
916
/**
917
 * @brief Move the nodes in parts according to the schema.
918
 *
919
 * @param[in,out] first_dst First sibling, destination.
920
 * @param[in] first_src First sibling, all following nodes will be moved.
921
 * @return LY_ERR value.
922
 */
923
static LY_ERR
924
lyd_move_nodes_by_schema(struct lyd_node **first_dst, struct lyd_node *first_src)
925
0
{
926
0
    LY_ERR ret;
927
0
    struct lyd_node *next, *iter, *leader;
928
929
0
    assert(first_dst && *first_dst && !(*first_dst)->prev->next && first_src &&
930
0
            !first_src->prev->next && !first_src->parent);
931
932
0
    for (iter = first_src; iter; iter = next) {
933
0
        if (lyds_is_supported(iter) &&
934
0
                (lyd_find_sibling_schema(*first_dst, iter->schema, &leader) == LY_SUCCESS)) {
935
0
            ret = lyds_merge(first_dst, &leader, &first_src, iter, &next);
936
0
            if (ret) {
937
                /* The operation on the sorting tree unexpectedly failed due to some internal issue,
938
                 * but insert the node anyway although the nodes will not be sorted.
939
                 */
940
0
                LOGWRN(LYD_CTX(first_src), "Data in \"%s\" are not sorted.", leader->schema->name);
941
0
                LY_CHECK_RET(lyd_move_nodes_ordby_schema(first_dst, next, &next));
942
0
            }
943
0
        } else {
944
0
            LY_CHECK_RET(lyd_move_nodes_ordby_schema(first_dst, iter, &next));
945
0
        }
946
0
    }
947
948
0
    return LY_SUCCESS;
949
0
}
950
951
/**
952
 * @brief Move a nodes into parent/siblings.
953
 *
954
 * @param[in] parent Parent to insert into, NULL for top-level sibling.
955
 * @param[in,out] first_dst_p First sibling, NULL if no top-level sibling exist yet.
956
 * Can be also NULL if @p parent is set.
957
 * @param[in] first_src First sibling, all following nodes will be moved.
958
 * @return LY_ERR value.
959
 */
960
static LY_ERR
961
lyd_move_nodes(struct lyd_node *parent, struct lyd_node **first_dst_p, struct lyd_node *first_src)
962
0
{
963
0
    LY_ERR ret;
964
0
    struct lyd_node *first_dst;
965
966
0
    assert((parent || first_dst_p) && first_src && !first_src->prev->next);
967
968
0
    if (!first_dst_p || !*first_dst_p) {
969
0
        first_dst = lyd_child(parent);
970
0
    } else {
971
0
        first_dst = *first_dst_p;
972
0
    }
973
974
0
    if (first_dst) {
975
0
        ret = lyd_move_nodes_by_schema(&first_dst, first_src);
976
0
    } else {
977
0
        ret = lyd_move_nodes_at_once(parent, first_src);
978
0
        first_dst = first_src;
979
0
    }
980
981
0
    if (first_dst_p) {
982
0
        *first_dst_p = first_dst;
983
0
    }
984
985
0
    return ret;
986
0
}
987
988
/**
989
 * @brief Check schema place of a node to be inserted.
990
 *
991
 * @param[in] parent Schema node of the parent data node.
992
 * @param[in] sibling Schema node of a sibling data node.
993
 * @param[in] schema Schema node if the data node to be inserted.
994
 * @return LY_SUCCESS on success.
995
 * @return LY_EINVAL if the place is invalid.
996
 */
997
static LY_ERR
998
lyd_insert_check_schema(const struct lysc_node *parent, const struct lysc_node *sibling, const struct lysc_node *schema)
999
0
{
1000
0
    const struct lysc_node *par2;
1001
1002
0
    assert(!parent || !(parent->nodetype & (LYS_CASE | LYS_CHOICE)));
1003
0
    assert(!sibling || !(sibling->nodetype & (LYS_CASE | LYS_CHOICE)));
1004
0
    assert(!schema || !(schema->nodetype & (LYS_CASE | LYS_CHOICE)));
1005
1006
0
    if (!schema || (!parent && !sibling)) {
1007
        /* opaque nodes can be inserted wherever */
1008
0
        return LY_SUCCESS;
1009
0
    }
1010
1011
0
    if (!parent) {
1012
0
        parent = lysc_data_parent(sibling);
1013
0
    }
1014
1015
    /* find schema parent */
1016
0
    par2 = lysc_data_parent(schema);
1017
1018
0
    if (parent) {
1019
        /* inner node */
1020
0
        if (par2 != parent) {
1021
0
            LOGERR(schema->module->ctx, LY_EINVAL, "Cannot insert, parent of \"%s\" is not \"%s\".", schema->name,
1022
0
                    parent->name);
1023
0
            return LY_EINVAL;
1024
0
        }
1025
0
    } else {
1026
        /* top-level node */
1027
0
        if (par2) {
1028
0
            LOGERR(schema->module->ctx, LY_EINVAL, "Cannot insert, node \"%s\" is not top-level.", schema->name);
1029
0
            return LY_EINVAL;
1030
0
        }
1031
0
    }
1032
1033
0
    return LY_SUCCESS;
1034
0
}
1035
1036
LIBYANG_API_DEF LY_ERR
1037
lyd_insert_child(struct lyd_node *parent, struct lyd_node *node)
1038
0
{
1039
0
    LY_CHECK_ARG_RET(NULL, parent, node, !parent->schema || (parent->schema->nodetype & LYD_NODE_INNER), LY_EINVAL);
1040
0
    LY_CHECK_CTX_EQUAL_RET(LYD_CTX(parent), LYD_CTX(node), LY_EINVAL);
1041
1042
0
    LY_CHECK_RET(lyd_insert_check_schema(parent->schema, NULL, node->schema));
1043
1044
0
    if (node->parent || node->prev->next || !node->next) {
1045
0
        LY_CHECK_RET(lyd_unlink_tree(node));
1046
0
        lyd_insert_node(parent, NULL, node, LYD_INSERT_NODE_DEFAULT);
1047
0
    } else {
1048
0
        LY_CHECK_RET(lyd_move_nodes(parent, NULL, node));
1049
0
    }
1050
1051
0
    return LY_SUCCESS;
1052
0
}
1053
1054
LIBYANG_API_DEF LY_ERR
1055
lyplg_ext_insert(struct lyd_node *parent, struct lyd_node *first)
1056
0
{
1057
0
    struct lyd_node *iter;
1058
1059
0
    LY_CHECK_ARG_RET(NULL, parent, first, !first->parent, !first->prev->next,
1060
0
            !parent->schema || (parent->schema->nodetype & LYD_NODE_INNER), LY_EINVAL);
1061
1062
0
    if (first->schema && (first->schema->flags & LYS_KEY)) {
1063
0
        LOGERR(LYD_CTX(parent), LY_EINVAL, "Cannot insert key \"%s\".", first->schema->name);
1064
0
        return LY_EINVAL;
1065
0
    }
1066
1067
0
    while (first) {
1068
0
        iter = first->next;
1069
0
        lyd_unlink(first);
1070
0
        lyd_insert_node(parent, NULL, first, LYD_INSERT_NODE_LAST);
1071
0
        first = iter;
1072
0
    }
1073
0
    return LY_SUCCESS;
1074
0
}
1075
1076
LIBYANG_API_DEF LY_ERR
1077
lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, struct lyd_node **first)
1078
0
{
1079
0
    struct lyd_node *first_sibling;
1080
1081
0
    LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
1082
1083
0
    if (sibling) {
1084
0
        LY_CHECK_RET(lyd_insert_check_schema(NULL, sibling->schema, node->schema));
1085
0
    }
1086
1087
0
    first_sibling = lyd_first_sibling(sibling);
1088
0
    if (node->parent || node->prev->next || !node->next) {
1089
0
        LY_CHECK_RET(lyd_unlink_tree(node));
1090
0
        lyd_insert_node(NULL, &first_sibling, node, LYD_INSERT_NODE_DEFAULT);
1091
0
    } else {
1092
0
        LY_CHECK_RET(lyd_move_nodes(NULL, &first_sibling, node));
1093
0
    }
1094
1095
0
    if (first) {
1096
0
        *first = first_sibling;
1097
0
    }
1098
1099
0
    return LY_SUCCESS;
1100
0
}
1101
1102
LIBYANG_API_DEF LY_ERR
1103
lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
1104
0
{
1105
0
    LY_CHECK_ARG_RET(NULL, sibling, node, sibling != node, LY_EINVAL);
1106
0
    LY_CHECK_CTX_EQUAL_RET(LYD_CTX(sibling), LYD_CTX(node), LY_EINVAL);
1107
1108
0
    LY_CHECK_RET(lyd_insert_check_schema(NULL, sibling->schema, node->schema));
1109
1110
0
    if (node->schema && (!(node->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(node->schema->flags & LYS_ORDBY_USER))) {
1111
0
        LOGERR(LYD_CTX(sibling), LY_EINVAL, "Can be used only for user-ordered nodes.");
1112
0
        return LY_EINVAL;
1113
0
    }
1114
0
    if (node->schema && sibling->schema && (node->schema != sibling->schema)) {
1115
0
        LOGERR(LYD_CTX(sibling), LY_EINVAL, "Cannot insert before a different schema node instance.");
1116
0
        return LY_EINVAL;
1117
0
    }
1118
1119
0
    lyd_unlink(node);
1120
0
    lyd_insert_before_node(sibling, node);
1121
0
    lyd_insert_hash(node);
1122
1123
0
    return LY_SUCCESS;
1124
0
}
1125
1126
LIBYANG_API_DEF LY_ERR
1127
lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
1128
0
{
1129
0
    LY_CHECK_ARG_RET(NULL, sibling, node, sibling != node, LY_EINVAL);
1130
0
    LY_CHECK_CTX_EQUAL_RET(LYD_CTX(sibling), LYD_CTX(node), LY_EINVAL);
1131
1132
0
    LY_CHECK_RET(lyd_insert_check_schema(NULL, sibling->schema, node->schema));
1133
1134
0
    if (node->schema && (!(node->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(node->schema->flags & LYS_ORDBY_USER))) {
1135
0
        LOGERR(LYD_CTX(sibling), LY_EINVAL, "Can be used only for user-ordered nodes.");
1136
0
        return LY_EINVAL;
1137
0
    }
1138
0
    if (node->schema && sibling->schema && (node->schema != sibling->schema)) {
1139
0
        LOGERR(LYD_CTX(sibling), LY_EINVAL, "Cannot insert after a different schema node instance.");
1140
0
        return LY_EINVAL;
1141
0
    }
1142
1143
0
    lyd_unlink(node);
1144
0
    lyd_insert_after_node(NULL, sibling, node);
1145
0
    lyd_insert_hash(node);
1146
1147
0
    return LY_SUCCESS;
1148
0
}
1149
1150
void
1151
lyd_unlink_ignore_lyds(struct lyd_node **first_sibling_p, struct lyd_node *node)
1152
4.17k
{
1153
4.17k
    struct lyd_node *first_sibling;
1154
1155
    /* update hashes while still linked into the tree */
1156
4.17k
    lyd_unlink_hash(node);
1157
1158
    /* unlink leafref nodes */
1159
4.17k
    if (node->schema && (node->schema->nodetype & LYD_NODE_TERM)) {
1160
2.61k
        lyd_free_leafref_nodes((struct lyd_node_term *)node);
1161
2.61k
    }
1162
1163
    /* unlink from siblings */
1164
4.17k
    if (node->next) {
1165
0
        node->next->prev = node->prev;
1166
0
        if (node->prev->next) {
1167
0
            node->prev->next = node->next;
1168
0
        } else if (first_sibling_p) {
1169
            /* unlinking the first node */
1170
0
            *first_sibling_p = node->next;
1171
0
        }
1172
4.17k
    } else {
1173
        /* unlinking the last node */
1174
        /* update the "last" pointer from the first node */
1175
4.17k
        if (first_sibling_p && *first_sibling_p) {
1176
0
            (*first_sibling_p)->prev = node->prev;
1177
4.17k
        } else {
1178
4.17k
            first_sibling = lyd_first_sibling(node);
1179
4.17k
            first_sibling->prev = node->prev;
1180
4.17k
            if (first_sibling_p) {
1181
0
                *first_sibling_p = first_sibling;
1182
0
            }
1183
4.17k
        }
1184
4.17k
        node->prev->next = NULL;
1185
4.17k
    }
1186
1187
    /* unlink from parent */
1188
4.17k
    if (node->parent) {
1189
0
        if (node->parent->child == node) {
1190
            /* the node is the first child */
1191
0
            node->parent->child = node->next;
1192
0
        }
1193
1194
        /* check for NP container whether its last non-default node is not being unlinked */
1195
0
        lyd_cont_set_dflt(lyd_parent(node));
1196
1197
0
        node->parent = NULL;
1198
0
    }
1199
1200
4.17k
    node->next = NULL;
1201
4.17k
    node->prev = node;
1202
4.17k
}
1203
1204
void
1205
lyd_unlink(struct lyd_node *node)
1206
4.17k
{
1207
4.17k
    struct lyd_node *leader;
1208
1209
4.17k
    if (!node) {
1210
0
        return;
1211
0
    }
1212
1213
    /* unlink from the lyds tree */
1214
4.17k
    if (lyds_is_supported(node)) {
1215
1.55k
        if (!node->prev->next || (node->prev->schema != node->schema)) {
1216
1.55k
            leader = node;
1217
1.55k
        } else {
1218
0
            lyd_find_sibling_val(node, node->schema, NULL, 0, &leader);
1219
0
            assert(leader);
1220
0
        }
1221
1.55k
        lyds_unlink(&leader, node);
1222
1.55k
    }
1223
1224
    /* unlink data tree */
1225
4.17k
    lyd_unlink_ignore_lyds(NULL, node);
1226
4.17k
}
1227
1228
LIBYANG_API_DEF LY_ERR
1229
lyd_unlink_siblings(struct lyd_node *node)
1230
0
{
1231
0
    struct lyd_node *next, *iter, *leader, *start, *first_sibling = NULL;
1232
1233
0
    if (lyds_is_supported(node) && node->prev->next && (node->prev->schema == node->schema)) {
1234
        /* unlink starts at the non-first item in the (leaf-)list */
1235
0
        lyd_find_sibling_val(node, node->schema, NULL, 0, &leader);
1236
0
        lyds_split(&first_sibling, leader, node, &start);
1237
0
    } else {
1238
        /* unlink @p node */
1239
0
        LY_CHECK_RET(lyd_unlink_check(node));
1240
0
        start = node->next;
1241
0
        lyd_unlink_ignore_lyds(&first_sibling, node);
1242
0
    }
1243
1244
    /* continue unlinking the rest */
1245
0
    LY_LIST_FOR_SAFE(start, next, iter) {
1246
0
        LY_CHECK_RET(lyd_unlink_check(iter));
1247
0
        lyd_unlink_ignore_lyds(&first_sibling, iter);
1248
0
        lyd_insert_after_node(&node, node->prev, iter);
1249
0
        lyd_insert_hash(iter);
1250
0
    }
1251
1252
0
    return LY_SUCCESS;
1253
0
}
1254
1255
LIBYANG_API_DEF LY_ERR
1256
lyd_unlink_tree(struct lyd_node *node)
1257
0
{
1258
0
    LY_CHECK_RET(lyd_unlink_check(node));
1259
0
    lyd_unlink(node);
1260
1261
0
    return LY_SUCCESS;
1262
0
}
1263
1264
void
1265
lyd_insert_meta(struct lyd_node *parent, struct lyd_meta *meta, ly_bool clear_dflt)
1266
437k
{
1267
437k
    struct lyd_meta *last, *iter;
1268
1269
437k
    assert(parent);
1270
1271
437k
    if (!meta) {
1272
411k
        return;
1273
411k
    }
1274
1275
53.7k
    for (iter = meta; iter; iter = iter->next) {
1276
26.8k
        iter->parent = parent;
1277
26.8k
    }
1278
1279
    /* insert as the last attribute */
1280
26.8k
    if (parent->meta) {
1281
0
        for (last = parent->meta; last->next; last = last->next) {}
1282
0
        last->next = meta;
1283
26.8k
    } else {
1284
26.8k
        parent->meta = meta;
1285
26.8k
    }
1286
1287
    /* remove default flags from NP containers */
1288
26.8k
    while (clear_dflt && parent && (parent->schema->nodetype == LYS_CONTAINER) && (parent->flags & LYD_DEFAULT)) {
1289
0
        parent->flags &= ~LYD_DEFAULT;
1290
0
        parent = lyd_parent(parent);
1291
0
    }
1292
26.8k
}
1293
1294
void
1295
lyd_unlink_meta_single(struct lyd_meta *meta)
1296
15.2k
{
1297
15.2k
    struct lyd_meta *iter;
1298
1299
15.2k
    if (!meta) {
1300
0
        return;
1301
0
    }
1302
1303
15.2k
    if (meta->parent && (meta->parent->meta == meta)) {
1304
15.2k
        meta->parent->meta = meta->next;
1305
15.2k
    } else if (meta->parent) {
1306
0
        for (iter = meta->parent->meta; iter->next && (iter->next != meta); iter = iter->next) {}
1307
0
        if (iter->next) {
1308
0
            iter->next = meta->next;
1309
0
        }
1310
0
    }
1311
1312
15.2k
    meta->next = NULL;
1313
15.2k
    meta->parent = NULL;
1314
15.2k
}
1315
1316
/**
1317
 * @brief Get the annotation definition in the module.
1318
 *
1319
 * @param[in] mod Metadata module (with the annotation definition).
1320
 * @param[in] name Attribute name.
1321
 * @param[in] name_len Length of @p name, must be set correctly.
1322
 * @return compiled YANG extension instance on success.
1323
 */
1324
static struct lysc_ext_instance *
1325
lyd_get_meta_annotation(const struct lys_module *mod, const char *name, size_t name_len)
1326
11.6k
{
1327
11.6k
    LY_ARRAY_COUNT_TYPE u;
1328
11.6k
    struct lyplg_ext *plugin;
1329
1330
11.6k
    if (!mod) {
1331
0
        return NULL;
1332
0
    }
1333
1334
116k
    LY_ARRAY_FOR(mod->compiled->exts, u) {
1335
116k
        plugin = mod->compiled->exts[u].def->plugin;
1336
116k
        if (plugin && !strncmp(plugin->id, "ly2 metadata", 12) &&
1337
116k
                !ly_strncmp(mod->compiled->exts[u].argument, name, name_len)) {
1338
11.6k
            return &mod->compiled->exts[u];
1339
11.6k
        }
1340
116k
    }
1341
1342
15
    return NULL;
1343
11.6k
}
1344
1345
LY_ERR
1346
lyd_create_meta(struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod, const char *name,
1347
        size_t name_len, const char *value, size_t value_len, ly_bool is_utf8, ly_bool store_only, ly_bool *dynamic,
1348
        LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node, ly_bool clear_dflt,
1349
        ly_bool *incomplete)
1350
11.6k
{
1351
11.6k
    LY_ERR ret = LY_SUCCESS;
1352
11.6k
    struct lysc_ext_instance *ant = NULL;
1353
11.6k
    const struct lysc_type *ant_type;
1354
11.6k
    struct lyd_meta *mt, *last;
1355
1356
11.6k
    assert((parent || meta) && mod);
1357
1358
11.6k
    ant = lyd_get_meta_annotation(mod, name, name_len);
1359
11.6k
    if (!ant) {
1360
        /* attribute is not defined as a metadata annotation (RFC 7952) */
1361
15
        LOGVAL(mod->ctx, LYVE_REFERENCE, "Annotation definition for attribute \"%s:%.*s\" not found.",
1362
15
                mod->name, (int)name_len, name);
1363
15
        ret = LY_EINVAL;
1364
15
        goto cleanup;
1365
15
    }
1366
1367
11.6k
    mt = calloc(1, sizeof *mt);
1368
11.6k
    LY_CHECK_ERR_GOTO(!mt, LOGMEM(mod->ctx); ret = LY_EMEM, cleanup);
1369
11.6k
    mt->parent = parent;
1370
11.6k
    mt->annotation = ant;
1371
11.6k
    lyplg_ext_get_storage(ant, LY_STMT_TYPE, sizeof ant_type, (const void **)&ant_type);
1372
11.6k
    ret = lyd_value_store(mod->ctx, &mt->value, ant_type, value, value_len, is_utf8, store_only, dynamic, format, prefix_data, hints,
1373
11.6k
            ctx_node, incomplete);
1374
11.6k
    LY_CHECK_ERR_GOTO(ret, free(mt), cleanup);
1375
11.6k
    ret = lydict_insert(mod->ctx, name, name_len, &mt->name);
1376
11.6k
    LY_CHECK_ERR_GOTO(ret, free(mt), cleanup);
1377
1378
    /* insert as the last attribute */
1379
11.6k
    if (parent) {
1380
11.6k
        lyd_insert_meta(parent, mt, clear_dflt);
1381
11.6k
    } else if (*meta) {
1382
0
        for (last = *meta; last->next; last = last->next) {}
1383
0
        last->next = mt;
1384
0
    }
1385
1386
11.6k
    if (meta) {
1387
11.6k
        *meta = mt;
1388
11.6k
    }
1389
1390
11.6k
cleanup:
1391
11.6k
    return ret;
1392
11.6k
}
1393
1394
void
1395
lyd_insert_attr(struct lyd_node *parent, struct lyd_attr *attr)
1396
90
{
1397
90
    struct lyd_attr *last, *iter;
1398
90
    struct lyd_node_opaq *opaq;
1399
1400
90
    assert(parent && !parent->schema);
1401
1402
90
    if (!attr) {
1403
0
        return;
1404
0
    }
1405
1406
90
    opaq = (struct lyd_node_opaq *)parent;
1407
180
    for (iter = attr; iter; iter = iter->next) {
1408
90
        iter->parent = opaq;
1409
90
    }
1410
1411
    /* insert as the last attribute */
1412
90
    if (opaq->attr) {
1413
2.00k
        for (last = opaq->attr; last->next; last = last->next) {}
1414
88
        last->next = attr;
1415
88
    } else {
1416
2
        opaq->attr = attr;
1417
2
    }
1418
90
}
1419
1420
LY_ERR
1421
lyd_create_attr(struct lyd_node *parent, struct lyd_attr **attr, const struct ly_ctx *ctx, const char *name, size_t name_len,
1422
        const char *prefix, size_t prefix_len, const char *module_key, size_t module_key_len, const char *value,
1423
        size_t value_len, ly_bool *dynamic, LY_VALUE_FORMAT format, void *val_prefix_data, uint32_t hints)
1424
90
{
1425
90
    LY_ERR ret = LY_SUCCESS;
1426
90
    struct lyd_attr *at, *last;
1427
1428
90
    assert(ctx && (parent || attr) && (!parent || !parent->schema));
1429
90
    assert(name && name_len && format);
1430
1431
90
    if (!value_len && (!dynamic || !*dynamic)) {
1432
0
        value = "";
1433
0
    }
1434
1435
90
    at = calloc(1, sizeof *at);
1436
90
    LY_CHECK_ERR_RET(!at, LOGMEM(ctx); ly_free_prefix_data(format, val_prefix_data), LY_EMEM);
1437
1438
90
    LY_CHECK_GOTO(ret = lydict_insert(ctx, name, name_len, &at->name.name), finish);
1439
90
    if (prefix_len) {
1440
90
        LY_CHECK_GOTO(ret = lydict_insert(ctx, prefix, prefix_len, &at->name.prefix), finish);
1441
90
    }
1442
90
    if (module_key_len) {
1443
90
        LY_CHECK_GOTO(ret = lydict_insert(ctx, module_key, module_key_len, &at->name.module_ns), finish);
1444
90
    }
1445
1446
90
    if (dynamic && *dynamic) {
1447
90
        ret = lydict_insert_zc(ctx, (char *)value, &at->value);
1448
90
        LY_CHECK_GOTO(ret, finish);
1449
90
        *dynamic = 0;
1450
90
    } else {
1451
0
        LY_CHECK_GOTO(ret = lydict_insert(ctx, value, value_len, &at->value), finish);
1452
0
    }
1453
90
    at->format = format;
1454
90
    at->val_prefix_data = val_prefix_data;
1455
90
    at->hints = hints;
1456
1457
    /* insert as the last attribute */
1458
90
    if (parent) {
1459
90
        lyd_insert_attr(parent, at);
1460
90
    } else if (*attr) {
1461
0
        for (last = *attr; last->next; last = last->next) {}
1462
0
        last->next = at;
1463
0
    }
1464
1465
90
finish:
1466
90
    if (ret) {
1467
0
        lyd_free_attr_single(ctx, at);
1468
90
    } else if (attr) {
1469
0
        *attr = at;
1470
0
    }
1471
90
    return LY_SUCCESS;
1472
90
}
1473
1474
/**
1475
 * @brief Check the equality of the two schemas from different contexts.
1476
 *
1477
 * @param schema1 of first node.
1478
 * @param schema2 of second node.
1479
 * @return 1 if the schemas are equal otherwise 0.
1480
 */
1481
static ly_bool
1482
lyd_compare_schema_equal(const struct lysc_node *schema1, const struct lysc_node *schema2)
1483
0
{
1484
0
    if (!schema1 && !schema2) {
1485
0
        return 1;
1486
0
    } else if (!schema1 || !schema2) {
1487
0
        return 0;
1488
0
    }
1489
1490
0
    assert(schema1->module->ctx != schema2->module->ctx);
1491
1492
0
    if (schema1->nodetype != schema2->nodetype) {
1493
0
        return 0;
1494
0
    }
1495
1496
0
    if (strcmp(schema1->name, schema2->name)) {
1497
0
        return 0;
1498
0
    }
1499
1500
0
    if (strcmp(schema1->module->name, schema2->module->name)) {
1501
0
        return 0;
1502
0
    }
1503
1504
0
    return 1;
1505
0
}
1506
1507
/**
1508
 * @brief Check the equality of the schemas for all parent nodes.
1509
 *
1510
 * Both nodes must be from different contexts.
1511
 *
1512
 * @param node1 Data of first node.
1513
 * @param node2 Data of second node.
1514
 * @return 1 if the all related parental schemas are equal otherwise 0.
1515
 */
1516
static ly_bool
1517
lyd_compare_schema_parents_equal(const struct lyd_node *node1, const struct lyd_node *node2)
1518
0
{
1519
0
    const struct lysc_node *parent1, *parent2;
1520
1521
0
    assert(node1 && node2);
1522
1523
0
    for (parent1 = node1->schema->parent, parent2 = node2->schema->parent;
1524
0
            parent1 && parent2;
1525
0
            parent1 = parent1->parent, parent2 = parent2->parent) {
1526
0
        if (!lyd_compare_schema_equal(parent1, parent2)) {
1527
0
            return 0;
1528
0
        }
1529
0
    }
1530
1531
0
    if (parent1 || parent2) {
1532
0
        return 0;
1533
0
    }
1534
1535
0
    return 1;
1536
0
}
1537
1538
/**
1539
 * @brief Compare 2 nodes values including opaque node values.
1540
 *
1541
 * @param[in] node1 First node to compare.
1542
 * @param[in] node2 Second node to compare.
1543
 * @return LY_SUCCESS if equal.
1544
 * @return LY_ENOT if not equal.
1545
 * @return LY_ERR on error.
1546
 */
1547
static LY_ERR
1548
lyd_compare_single_value(const struct lyd_node *node1, const struct lyd_node *node2)
1549
35.9k
{
1550
35.9k
    const struct lyd_node_opaq *opaq1 = NULL, *opaq2 = NULL;
1551
35.9k
    const char *val1, *val2, *col;
1552
35.9k
    const struct lys_module *mod;
1553
35.9k
    char *val_dyn = NULL;
1554
35.9k
    LY_ERR rc = LY_SUCCESS;
1555
1556
35.9k
    if (!node1->schema) {
1557
0
        opaq1 = (struct lyd_node_opaq *)node1;
1558
0
    }
1559
35.9k
    if (!node2->schema) {
1560
0
        opaq2 = (struct lyd_node_opaq *)node2;
1561
0
    }
1562
1563
35.9k
    if (opaq1 && opaq2 && (opaq1->format == LY_VALUE_XML) && (opaq2->format == LY_VALUE_XML)) {
1564
        /* opaque XML and opaque XML node */
1565
0
        if (lyxml_value_compare(LYD_CTX(node1), opaq1->value, opaq1->val_prefix_data, LYD_CTX(node2), opaq2->value,
1566
0
                opaq2->val_prefix_data)) {
1567
0
            return LY_ENOT;
1568
0
        }
1569
0
        return LY_SUCCESS;
1570
0
    }
1571
1572
    /* get their values */
1573
35.9k
    if (opaq1 && ((opaq1->format == LY_VALUE_XML) || (opaq1->format == LY_VALUE_STR_NS)) && (col = strchr(opaq1->value, ':'))) {
1574
        /* XML value with a prefix, try to transform it into a JSON (canonical) value */
1575
0
        mod = ly_resolve_prefix(LYD_CTX(node1), opaq1->value, col - opaq1->value, opaq1->format, opaq1->val_prefix_data);
1576
0
        if (!mod) {
1577
            /* unable to compare */
1578
0
            return LY_ENOT;
1579
0
        }
1580
1581
0
        if (asprintf(&val_dyn, "%s%s", mod->name, col) == -1) {
1582
0
            LOGMEM(LYD_CTX(node1));
1583
0
            return LY_EMEM;
1584
0
        }
1585
0
        val1 = val_dyn;
1586
35.9k
    } else {
1587
35.9k
        val1 = lyd_get_value(node1);
1588
35.9k
    }
1589
35.9k
    if (opaq2 && ((opaq2->format == LY_VALUE_XML) || (opaq2->format == LY_VALUE_STR_NS)) && (col = strchr(opaq2->value, ':'))) {
1590
0
        mod = ly_resolve_prefix(LYD_CTX(node2), opaq2->value, col - opaq2->value, opaq2->format, opaq2->val_prefix_data);
1591
0
        if (!mod) {
1592
0
            return LY_ENOT;
1593
0
        }
1594
1595
0
        assert(!val_dyn);
1596
0
        if (asprintf(&val_dyn, "%s%s", mod->name, col) == -1) {
1597
0
            LOGMEM(LYD_CTX(node2));
1598
0
            return LY_EMEM;
1599
0
        }
1600
0
        val2 = val_dyn;
1601
35.9k
    } else {
1602
35.9k
        val2 = lyd_get_value(node2);
1603
35.9k
    }
1604
1605
    /* compare values */
1606
35.9k
    if (strcmp(val1, val2)) {
1607
0
        rc = LY_ENOT;
1608
0
    }
1609
1610
35.9k
    free(val_dyn);
1611
35.9k
    return rc;
1612
35.9k
}
1613
1614
/**
1615
 * @brief Compare 2 data nodes if they are equivalent regarding the schema tree.
1616
 *
1617
 * Works correctly even if @p node1 and @p node2 have different contexts.
1618
 *
1619
 * @param[in] node1 The first node to compare.
1620
 * @param[in] node2 The second node to compare.
1621
 * @param[in] options Various @ref datacompareoptions.
1622
 * @param[in] parental_schemas_checked Flag set if parent schemas were checked for match.
1623
 * @return LY_SUCCESS if the nodes are equivalent.
1624
 * @return LY_ENOT if the nodes are not equivalent.
1625
 */
1626
static LY_ERR
1627
lyd_compare_single_schema(const struct lyd_node *node1, const struct lyd_node *node2, uint32_t options,
1628
        ly_bool parental_schemas_checked)
1629
46.9k
{
1630
46.9k
    if (LYD_CTX(node1) == LYD_CTX(node2)) {
1631
        /* same contexts */
1632
46.9k
        if (options & LYD_COMPARE_OPAQ) {
1633
0
            if (lyd_node_schema(node1) != lyd_node_schema(node2)) {
1634
0
                return LY_ENOT;
1635
0
            }
1636
46.9k
        } else {
1637
46.9k
            if (node1->schema != node2->schema) {
1638
4.92k
                return LY_ENOT;
1639
4.92k
            }
1640
46.9k
        }
1641
46.9k
    } else {
1642
        /* different contexts */
1643
0
        if (!lyd_compare_schema_equal(node1->schema, node2->schema)) {
1644
0
            return LY_ENOT;
1645
0
        }
1646
0
        if (!parental_schemas_checked) {
1647
0
            if (!lyd_compare_schema_parents_equal(node1, node2)) {
1648
0
                return LY_ENOT;
1649
0
            }
1650
0
            parental_schemas_checked = 1;
1651
0
        }
1652
0
    }
1653
1654
41.9k
    return LY_SUCCESS;
1655
46.9k
}
1656
1657
/**
1658
 * @brief Compare 2 data nodes if they are equivalent regarding the data they contain.
1659
 *
1660
 * Works correctly even if @p node1 and @p node2 have different contexts.
1661
 *
1662
 * @param[in] node1 The first node to compare.
1663
 * @param[in] node2 The second node to compare.
1664
 * @param[in] options Various @ref datacompareoptions.
1665
 * @return LY_SUCCESS if the nodes are equivalent.
1666
 * @return LY_ENOT if the nodes are not equivalent.
1667
 */
1668
static LY_ERR
1669
lyd_compare_single_data(const struct lyd_node *node1, const struct lyd_node *node2, uint32_t options)
1670
41.9k
{
1671
41.9k
    const struct lyd_node *iter1, *iter2;
1672
41.9k
    struct lyd_node_any *any1, *any2;
1673
41.9k
    int len1, len2;
1674
41.9k
    LY_ERR r;
1675
1676
41.9k
    if (!(options & LYD_COMPARE_OPAQ) && (node1->hash != node2->hash)) {
1677
5.77k
        return LY_ENOT;
1678
5.77k
    }
1679
    /* equal hashes do not mean equal nodes, they can be just in collision so the nodes must be checked explicitly */
1680
1681
36.2k
    if (!node1->schema || !node2->schema) {
1682
0
        if (!(options & LYD_COMPARE_OPAQ) && ((node1->schema && !node2->schema) || (!node1->schema && node2->schema))) {
1683
0
            return LY_ENOT;
1684
0
        }
1685
0
        if ((!node1->schema && !node2->schema) || (node1->schema && (node1->schema->nodetype & LYD_NODE_TERM)) ||
1686
0
                (node2->schema && (node2->schema->nodetype & LYD_NODE_TERM))) {
1687
            /* compare values only if there are any to compare */
1688
0
            if ((r = lyd_compare_single_value(node1, node2))) {
1689
0
                return r;
1690
0
            }
1691
0
        }
1692
1693
0
        if (options & LYD_COMPARE_FULL_RECURSION) {
1694
0
            return lyd_compare_siblings_(lyd_child(node1), lyd_child(node2), options, 1);
1695
0
        }
1696
0
        return LY_SUCCESS;
1697
36.2k
    } else {
1698
36.2k
        switch (node1->schema->nodetype) {
1699
205
        case LYS_LEAF:
1700
35.9k
        case LYS_LEAFLIST:
1701
35.9k
            if (options & LYD_COMPARE_DEFAULTS) {
1702
0
                if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
1703
0
                    return LY_ENOT;
1704
0
                }
1705
0
            }
1706
35.9k
            if ((r = lyd_compare_single_value(node1, node2))) {
1707
0
                return r;
1708
0
            }
1709
1710
35.9k
            return LY_SUCCESS;
1711
32
        case LYS_CONTAINER:
1712
32
        case LYS_RPC:
1713
32
        case LYS_ACTION:
1714
32
        case LYS_NOTIF:
1715
            /* implicit container is always equal to a container with non-default descendants */
1716
32
            if (options & LYD_COMPARE_FULL_RECURSION) {
1717
0
                return lyd_compare_siblings_(lyd_child(node1), lyd_child(node2), options, 1);
1718
0
            }
1719
32
            return LY_SUCCESS;
1720
202
        case LYS_LIST:
1721
202
            iter1 = lyd_child(node1);
1722
202
            iter2 = lyd_child(node2);
1723
1724
202
            if (options & LYD_COMPARE_FULL_RECURSION) {
1725
0
                return lyd_compare_siblings_(iter1, iter2, options, 1);
1726
202
            } else if (node1->schema->flags & LYS_KEYLESS) {
1727
                /* always equal */
1728
0
                return LY_SUCCESS;
1729
0
            }
1730
1731
            /* lists with keys, their equivalence is based on their keys */
1732
202
            for (const struct lysc_node *key = lysc_node_child(node1->schema);
1733
407
                    key && (key->flags & LYS_KEY);
1734
205
                    key = key->next) {
1735
205
                if (!iter1 || !iter2) {
1736
0
                    return (iter1 == iter2) ? LY_SUCCESS : LY_ENOT;
1737
0
                }
1738
205
                r = lyd_compare_single_schema(iter1, iter2, options, 1);
1739
205
                LY_CHECK_RET(r);
1740
205
                r = lyd_compare_single_data(iter1, iter2, options);
1741
205
                LY_CHECK_RET(r);
1742
1743
205
                iter1 = iter1->next;
1744
205
                iter2 = iter2->next;
1745
205
            }
1746
1747
202
            return LY_SUCCESS;
1748
0
        case LYS_ANYXML:
1749
0
        case LYS_ANYDATA:
1750
0
            any1 = (struct lyd_node_any *)node1;
1751
0
            any2 = (struct lyd_node_any *)node2;
1752
1753
0
            if (any1->value_type != any2->value_type) {
1754
0
                return LY_ENOT;
1755
0
            }
1756
0
            switch (any1->value_type) {
1757
0
            case LYD_ANYDATA_DATATREE:
1758
0
                return lyd_compare_siblings_(any1->value.tree, any2->value.tree, options, 1);
1759
0
            case LYD_ANYDATA_STRING:
1760
0
            case LYD_ANYDATA_XML:
1761
0
            case LYD_ANYDATA_JSON:
1762
0
                if ((!any1->value.str && any2->value.str) || (any1->value.str && !any2->value.str)) {
1763
0
                    return LY_ENOT;
1764
0
                } else if (!any1->value.str && !any2->value.str) {
1765
0
                    return LY_SUCCESS;
1766
0
                }
1767
0
                len1 = strlen(any1->value.str);
1768
0
                len2 = strlen(any2->value.str);
1769
0
                if ((len1 != len2) || strcmp(any1->value.str, any2->value.str)) {
1770
0
                    return LY_ENOT;
1771
0
                }
1772
0
                return LY_SUCCESS;
1773
0
            case LYD_ANYDATA_LYB:
1774
0
                len1 = lyd_lyb_data_length(any1->value.mem);
1775
0
                len2 = lyd_lyb_data_length(any2->value.mem);
1776
0
                if ((len1 == -1) || (len2 == -1) || (len1 != len2) || memcmp(any1->value.mem, any2->value.mem, len1)) {
1777
0
                    return LY_ENOT;
1778
0
                }
1779
0
                return LY_SUCCESS;
1780
0
            }
1781
36.2k
        }
1782
36.2k
    }
1783
1784
0
    LOGINT(LYD_CTX(node1));
1785
0
    return LY_EINT;
1786
36.2k
}
1787
1788
/**
1789
 * @brief Compare all siblings at a node level.
1790
 *
1791
 * @param[in] node1 First sibling list.
1792
 * @param[in] node2 Second sibling list.
1793
 * @param[in] options Various @ref datacompareoptions.
1794
 * @param[in] parental_schemas_checked Flag set if parent schemas were checked for match.
1795
 * @return LY_SUCCESS if equal.
1796
 * @return LY_ENOT if not equal.
1797
 * @return LY_ERR on error.
1798
 */
1799
static LY_ERR
1800
lyd_compare_siblings_(const struct lyd_node *node1, const struct lyd_node *node2, uint32_t options,
1801
        ly_bool parental_schemas_checked)
1802
0
{
1803
0
    LY_ERR r;
1804
0
    const struct lyd_node *iter2;
1805
1806
0
    while (node1 && node2) {
1807
        /* schema match */
1808
0
        r = lyd_compare_single_schema(node1, node2, options, parental_schemas_checked);
1809
0
        LY_CHECK_RET(r);
1810
1811
0
        if (node1->schema && (((node1->schema->nodetype == LYS_LIST) && !(node1->schema->flags & LYS_KEYLESS)) ||
1812
0
                ((node1->schema->nodetype == LYS_LEAFLIST) && (node1->schema->flags & LYS_CONFIG_W))) &&
1813
0
                (node1->schema->flags & LYS_ORDBY_SYSTEM)) {
1814
            /* find a matching instance in case they are ordered differently */
1815
0
            r = lyd_find_sibling_first(node2, node1, (struct lyd_node **)&iter2);
1816
0
            if (r == LY_ENOTFOUND) {
1817
                /* no matching instance, data not equal */
1818
0
                r = LY_ENOT;
1819
0
            }
1820
0
            LY_CHECK_RET(r);
1821
0
        } else {
1822
            /* compare with the current node */
1823
0
            iter2 = node2;
1824
0
        }
1825
1826
        /* data match */
1827
0
        r = lyd_compare_single_data(node1, iter2, options | LYD_COMPARE_FULL_RECURSION);
1828
0
        LY_CHECK_RET(r);
1829
1830
0
        node1 = node1->next;
1831
0
        node2 = node2->next;
1832
0
    }
1833
1834
0
    return (node1 || node2) ? LY_ENOT : LY_SUCCESS;
1835
0
}
1836
1837
LIBYANG_API_DEF LY_ERR
1838
lyd_compare_single(const struct lyd_node *node1, const struct lyd_node *node2, uint32_t options)
1839
46.7k
{
1840
46.7k
    LY_ERR r;
1841
1842
46.7k
    if (!node1 || !node2) {
1843
0
        return (node1 == node2) ? LY_SUCCESS : LY_ENOT;
1844
0
    }
1845
1846
    /* schema match */
1847
46.7k
    if ((r = lyd_compare_single_schema(node1, node2, options, 0))) {
1848
4.92k
        return r;
1849
4.92k
    }
1850
1851
    /* data match */
1852
41.7k
    return lyd_compare_single_data(node1, node2, options);
1853
46.7k
}
1854
1855
LIBYANG_API_DEF LY_ERR
1856
lyd_compare_siblings(const struct lyd_node *node1, const struct lyd_node *node2, uint32_t options)
1857
0
{
1858
0
    return lyd_compare_siblings_(node1, node2, options, 0);
1859
0
}
1860
1861
LIBYANG_API_DEF LY_ERR
1862
lyd_compare_meta(const struct lyd_meta *meta1, const struct lyd_meta *meta2)
1863
0
{
1864
0
    const struct ly_ctx *ctx;
1865
1866
0
    if (!meta1 || !meta2) {
1867
0
        if (meta1 == meta2) {
1868
0
            return LY_SUCCESS;
1869
0
        } else {
1870
0
            return LY_ENOT;
1871
0
        }
1872
0
    }
1873
1874
0
    ctx = meta1->annotation->module->ctx;
1875
0
    if ((ctx != meta2->annotation->module->ctx) || (meta1->annotation != meta2->annotation)) {
1876
0
        return LY_ENOT;
1877
0
    }
1878
1879
0
    return meta1->value.realtype->plugin->compare(ctx, &meta1->value, &meta2->value);
1880
0
}
1881
1882
/**
1883
 * @brief Create a copy of the attribute.
1884
 *
1885
 * @param[in] attr Attribute to copy.
1886
 * @param[in] node Opaque where to append the new attribute.
1887
 * @param[out] dup Optional created attribute copy.
1888
 * @return LY_ERR value.
1889
 */
1890
static LY_ERR
1891
lyd_dup_attr_single(const struct lyd_attr *attr, struct lyd_node *node, struct lyd_attr **dup)
1892
0
{
1893
0
    LY_ERR ret = LY_SUCCESS;
1894
0
    struct lyd_attr *a, *last;
1895
0
    struct lyd_node_opaq *opaq = (struct lyd_node_opaq *)node;
1896
1897
0
    LY_CHECK_ARG_RET(NULL, attr, node, !node->schema, LY_EINVAL);
1898
1899
    /* create a copy */
1900
0
    a = calloc(1, sizeof *attr);
1901
0
    LY_CHECK_ERR_RET(!a, LOGMEM(LYD_CTX(node)), LY_EMEM);
1902
1903
0
    LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), attr->name.name, 0, &a->name.name), finish);
1904
0
    LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), attr->name.prefix, 0, &a->name.prefix), finish);
1905
0
    LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), attr->name.module_ns, 0, &a->name.module_ns), finish);
1906
0
    LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), attr->value, 0, &a->value), finish);
1907
0
    a->hints = attr->hints;
1908
0
    a->format = attr->format;
1909
0
    if (attr->val_prefix_data) {
1910
0
        ret = ly_dup_prefix_data(LYD_CTX(node), attr->format, attr->val_prefix_data, &a->val_prefix_data);
1911
0
        LY_CHECK_GOTO(ret, finish);
1912
0
    }
1913
1914
    /* insert as the last attribute */
1915
0
    a->parent = opaq;
1916
0
    if (opaq->attr) {
1917
0
        for (last = opaq->attr; last->next; last = last->next) {}
1918
0
        last->next = a;
1919
0
    } else {
1920
0
        opaq->attr = a;
1921
0
    }
1922
1923
0
finish:
1924
0
    if (ret) {
1925
0
        lyd_free_attr_single(LYD_CTX(node), a);
1926
0
    } else if (dup) {
1927
0
        *dup = a;
1928
0
    }
1929
0
    return LY_SUCCESS;
1930
0
}
1931
1932
/**
1933
 * @brief Find @p schema equivalent in @p trg_ctx.
1934
 *
1935
 * @param[in] schema Schema node to find.
1936
 * @param[in] trg_ctx Target context to search in.
1937
 * @param[in] parent Data parent of @p schema, if any.
1938
 * @param[in] log Whether to log directly.
1939
 * @param[out] trg_schema Found schema from @p trg_ctx to use.
1940
 * @return LY_RRR value.
1941
 */
1942
static LY_ERR
1943
lyd_find_schema_ctx(const struct lysc_node *schema, const struct ly_ctx *trg_ctx, const struct lyd_node *parent,
1944
        ly_bool log, const struct lysc_node **trg_schema)
1945
0
{
1946
0
    const struct lysc_node *src_parent = NULL, *trg_parent = NULL, *sp, *tp;
1947
0
    const struct lys_module *trg_mod = NULL;
1948
0
    char *path;
1949
1950
0
    if (!schema) {
1951
        /* opaque node */
1952
0
        *trg_schema = NULL;
1953
0
        return LY_SUCCESS;
1954
0
    }
1955
1956
0
    if (lysc_data_parent(schema) && parent && parent->schema) {
1957
        /* start from schema parent */
1958
0
        trg_parent = parent->schema;
1959
0
        src_parent = lysc_data_parent(schema);
1960
0
    }
1961
1962
0
    do {
1963
        /* find the next parent */
1964
0
        sp = schema;
1965
0
        while (lysc_data_parent(sp) != src_parent) {
1966
0
            sp = lysc_data_parent(sp);
1967
0
        }
1968
0
        src_parent = sp;
1969
1970
0
        if (!src_parent->parent) {
1971
            /* find the module first */
1972
0
            trg_mod = ly_ctx_get_module_implemented(trg_ctx, src_parent->module->name);
1973
0
            if (!trg_mod) {
1974
0
                if (log) {
1975
0
                    LOGERR(trg_ctx, LY_ENOTFOUND, "Module \"%s\" not present/implemented in the target context.",
1976
0
                            src_parent->module->name);
1977
0
                }
1978
0
                return LY_ENOTFOUND;
1979
0
            }
1980
0
        }
1981
1982
        /* find the next parent */
1983
0
        assert(trg_parent || trg_mod);
1984
0
        tp = NULL;
1985
0
        while ((tp = lys_getnext(tp, trg_parent, trg_mod ? trg_mod->compiled : NULL, 0))) {
1986
0
            if (!strcmp(tp->name, src_parent->name) && !strcmp(tp->module->name, src_parent->module->name)) {
1987
0
                break;
1988
0
            }
1989
0
        }
1990
0
        if (!tp) {
1991
            /* schema node not found */
1992
0
            if (log) {
1993
0
                path = lysc_path(src_parent, LYSC_PATH_LOG, NULL, 0);
1994
0
                LOGERR(trg_ctx, LY_ENOTFOUND, "Schema node \"%s\" not found in the target context.", path);
1995
0
                free(path);
1996
0
            }
1997
0
            return LY_ENOTFOUND;
1998
0
        }
1999
2000
0
        trg_parent = tp;
2001
0
    } while (schema != src_parent);
2002
2003
    /* success */
2004
0
    *trg_schema = trg_parent;
2005
0
    return LY_SUCCESS;
2006
0
}
2007
2008
/**
2009
 * @brief Duplicate a single node and connect it into @p parent (if present) or last of @p first siblings.
2010
 *
2011
 * Ignores ::LYD_DUP_WITH_PARENTS which is supposed to be handled by lyd_dup().
2012
 *
2013
 * @param[in] node Node to duplicate.
2014
 * @param[in] trg_ctx Target context for duplicated nodes.
2015
 * @param[in] parent Parent to insert into, NULL for top-level sibling.
2016
 * @param[in] insert_order Options for inserting (sorting) duplicated node, @ref insertorder.
2017
 * @param[in,out] first First sibling, NULL if no top-level sibling exist yet. Can be also NULL if @p parent is set.
2018
 * @param[in] options Bitmask of options flags, see @ref dupoptions.
2019
 * @param[out] dup_p Pointer where the created duplicated node is placed (besides connecting it to @p parent / @p first).
2020
 * @return LY_ERR value.
2021
 */
2022
static LY_ERR
2023
lyd_dup_r(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_node *parent, uint32_t insert_order,
2024
        struct lyd_node **first, uint32_t options, struct lyd_node **dup_p)
2025
0
{
2026
0
    LY_ERR ret;
2027
0
    struct lyd_node *dup = NULL;
2028
0
    struct lyd_meta *meta;
2029
0
    struct lyd_attr *attr;
2030
0
    struct lyd_node_any *any;
2031
0
    const struct lysc_type *type;
2032
0
    const char *val_can;
2033
2034
0
    LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
2035
2036
0
    if (node->flags & LYD_EXT) {
2037
0
        if (options & LYD_DUP_NO_EXT) {
2038
            /* no not duplicate this subtree */
2039
0
            return LY_SUCCESS;
2040
0
        }
2041
2042
        /* we need to use the same context */
2043
0
        trg_ctx = LYD_CTX(node);
2044
0
    }
2045
2046
0
    if (!node->schema) {
2047
0
        dup = calloc(1, sizeof(struct lyd_node_opaq));
2048
0
        ((struct lyd_node_opaq *)dup)->ctx = trg_ctx;
2049
0
    } else {
2050
0
        switch (node->schema->nodetype) {
2051
0
        case LYS_RPC:
2052
0
        case LYS_ACTION:
2053
0
        case LYS_NOTIF:
2054
0
        case LYS_CONTAINER:
2055
0
        case LYS_LIST:
2056
0
            dup = calloc(1, sizeof(struct lyd_node_inner));
2057
0
            break;
2058
0
        case LYS_LEAF:
2059
0
        case LYS_LEAFLIST:
2060
0
            dup = calloc(1, sizeof(struct lyd_node_term));
2061
0
            break;
2062
0
        case LYS_ANYDATA:
2063
0
        case LYS_ANYXML:
2064
0
            dup = calloc(1, sizeof(struct lyd_node_any));
2065
0
            break;
2066
0
        default:
2067
0
            LOGINT(trg_ctx);
2068
0
            ret = LY_EINT;
2069
0
            goto error;
2070
0
        }
2071
0
    }
2072
0
    LY_CHECK_ERR_GOTO(!dup, LOGMEM(trg_ctx); ret = LY_EMEM, error);
2073
2074
0
    if (options & LYD_DUP_WITH_FLAGS) {
2075
0
        dup->flags = node->flags;
2076
0
    } else {
2077
0
        dup->flags = (node->flags & (LYD_DEFAULT | LYD_EXT)) | LYD_NEW;
2078
0
    }
2079
0
    if (options & LYD_DUP_WITH_PRIV) {
2080
0
        dup->priv = node->priv;
2081
0
    }
2082
0
    if (trg_ctx == LYD_CTX(node)) {
2083
0
        dup->schema = node->schema;
2084
0
    } else {
2085
0
        ret = lyd_find_schema_ctx(node->schema, trg_ctx, parent, 1, &dup->schema);
2086
0
        if (ret) {
2087
            /* has no schema but is not an opaque node */
2088
0
            free(dup);
2089
0
            dup = NULL;
2090
0
            goto error;
2091
0
        }
2092
0
    }
2093
0
    dup->prev = dup;
2094
2095
    /* duplicate metadata/attributes */
2096
0
    if (!(options & LYD_DUP_NO_META)) {
2097
0
        if (!node->schema) {
2098
0
            LY_LIST_FOR(((struct lyd_node_opaq *)node)->attr, attr) {
2099
0
                LY_CHECK_GOTO(ret = lyd_dup_attr_single(attr, dup, NULL), error);
2100
0
            }
2101
0
        } else {
2102
0
            LY_LIST_FOR(node->meta, meta) {
2103
0
                LY_CHECK_GOTO(ret = lyd_dup_meta_single_to_ctx(trg_ctx, meta, dup, NULL), error);
2104
0
            }
2105
0
        }
2106
0
    }
2107
2108
    /* nodetype-specific work */
2109
0
    if (!dup->schema) {
2110
0
        struct lyd_node_opaq *opaq = (struct lyd_node_opaq *)dup;
2111
0
        struct lyd_node_opaq *orig = (struct lyd_node_opaq *)node;
2112
0
        struct lyd_node *child;
2113
2114
0
        if (options & LYD_DUP_RECURSIVE) {
2115
            /* duplicate all the children */
2116
0
            LY_LIST_FOR(orig->child, child) {
2117
0
                LY_CHECK_GOTO(ret = lyd_dup_r(child, trg_ctx, dup, LYD_INSERT_NODE_LAST, NULL, options, NULL), error);
2118
0
            }
2119
0
        }
2120
0
        LY_CHECK_GOTO(ret = lydict_insert(trg_ctx, orig->name.name, 0, &opaq->name.name), error);
2121
0
        LY_CHECK_GOTO(ret = lydict_insert(trg_ctx, orig->name.prefix, 0, &opaq->name.prefix), error);
2122
0
        LY_CHECK_GOTO(ret = lydict_insert(trg_ctx, orig->name.module_ns, 0, &opaq->name.module_ns), error);
2123
0
        LY_CHECK_GOTO(ret = lydict_insert(trg_ctx, orig->value, 0, &opaq->value), error);
2124
0
        opaq->hints = orig->hints;
2125
0
        opaq->format = orig->format;
2126
0
        if (orig->val_prefix_data) {
2127
0
            ret = ly_dup_prefix_data(trg_ctx, opaq->format, orig->val_prefix_data, &opaq->val_prefix_data);
2128
0
            LY_CHECK_GOTO(ret, error);
2129
0
        }
2130
0
    } else if (dup->schema->nodetype & LYD_NODE_TERM) {
2131
0
        struct lyd_node_term *term = (struct lyd_node_term *)dup;
2132
0
        struct lyd_node_term *orig = (struct lyd_node_term *)node;
2133
2134
0
        term->hash = orig->hash;
2135
0
        if (trg_ctx == LYD_CTX(node)) {
2136
0
            ret = orig->value.realtype->plugin->duplicate(trg_ctx, &orig->value, &term->value);
2137
0
            LY_CHECK_ERR_GOTO(ret, LOGERR(trg_ctx, ret, "Value duplication failed."), error);
2138
0
        } else {
2139
            /* store canonical value in the target context */
2140
0
            val_can = lyd_get_value(node);
2141
0
            type = ((struct lysc_node_leaf *)term->schema)->type;
2142
0
            ret = lyd_value_store(trg_ctx, &term->value, type, val_can, strlen(val_can), 1, 1, NULL, LY_VALUE_CANON, NULL,
2143
0
                    LYD_HINT_DATA, term->schema, NULL);
2144
0
            LY_CHECK_GOTO(ret, error);
2145
0
        }
2146
0
    } else if (dup->schema->nodetype & LYD_NODE_INNER) {
2147
0
        struct lyd_node_inner *orig = (struct lyd_node_inner *)node;
2148
0
        struct lyd_node *child;
2149
2150
0
        if (options & LYD_DUP_RECURSIVE) {
2151
            /* duplicate all the children */
2152
0
            LY_LIST_FOR(orig->child, child) {
2153
0
                LY_CHECK_GOTO(ret = lyd_dup_r(child, trg_ctx, dup, LYD_INSERT_NODE_LAST, NULL, options, NULL), error);
2154
0
            }
2155
0
        } else if ((dup->schema->nodetype == LYS_LIST) && !(dup->schema->flags & LYS_KEYLESS)) {
2156
            /* always duplicate keys of a list */
2157
0
            for (child = orig->child; child && lysc_is_key(child->schema); child = child->next) {
2158
0
                LY_CHECK_GOTO(ret = lyd_dup_r(child, trg_ctx, dup, LYD_INSERT_NODE_LAST, NULL, options, NULL), error);
2159
0
            }
2160
0
        }
2161
0
        lyd_hash(dup);
2162
0
    } else if (dup->schema->nodetype & LYD_NODE_ANY) {
2163
0
        dup->hash = node->hash;
2164
0
        any = (struct lyd_node_any *)node;
2165
0
        LY_CHECK_GOTO(ret = lyd_any_copy_value(dup, &any->value, any->value_type), error);
2166
0
    }
2167
2168
    /* insert */
2169
0
    lyd_insert_node(parent, first, dup, insert_order);
2170
2171
0
    if (dup_p) {
2172
0
        *dup_p = dup;
2173
0
    }
2174
0
    return LY_SUCCESS;
2175
2176
0
error:
2177
0
    lyd_free_tree(dup);
2178
0
    return ret;
2179
0
}
2180
2181
/**
2182
 * @brief Duplicate a (leaf-)list and connect it into @p parent (if present) or last of @p first siblings.
2183
 *
2184
 * @param[in] orig Node to duplicate.
2185
 * @param[in] trg_ctx Target context for duplicated nodes.
2186
 * @param[in] parent Parent to insert into, NULL for top-level sibling.
2187
 * @param[in,out] first First sibling, NULL if no top-level sibling exist yet. Can be also NULL if @p parent is set.
2188
 * @param[in] options Bitmask of options flags, see @ref dupoptions.
2189
 * @param[out] dup_p Pointer where the created duplicated node is placed (besides connecting it to @p parent / @p first).
2190
 * @return LY_ERR value.
2191
 */
2192
static LY_ERR
2193
lyd_dup_list(const struct lyd_node **orig, const struct ly_ctx *trg_ctx, struct lyd_node *parent,
2194
        struct lyd_node **first, uint32_t options, struct lyd_node **dup_p)
2195
0
{
2196
0
    LY_ERR rc;
2197
0
    struct lyd_node *start, *leader, *dup;
2198
0
    const struct lysc_node *schema;
2199
0
    uint32_t insert_order;
2200
2201
    /* duplicate leader */
2202
0
    start = (*orig)->next;
2203
0
    schema = (*orig)->schema;
2204
0
    rc = lyd_dup_r(*orig, trg_ctx, parent, LYD_INSERT_NODE_DEFAULT, first, options, &leader);
2205
0
    LY_CHECK_RET(rc);
2206
2207
0
    if (!start || !start->schema || !LYD_NODE_IS_ALONE(leader)) {
2208
        /* no other instances */
2209
0
        if (dup_p) {
2210
0
            *dup_p = leader;
2211
0
        }
2212
0
        return LY_SUCCESS;
2213
0
    }
2214
2215
    /* duplicate the rest of the nodes in the (leaf-)list */
2216
0
    insert_order = leader->next ? LYD_INSERT_NODE_LAST_BY_SCHEMA : LYD_INSERT_NODE_LAST;
2217
0
    LY_LIST_FOR(start, *orig) {
2218
0
        if (schema != (*orig)->schema) {
2219
0
            break;
2220
0
        }
2221
0
        rc = lyd_dup_r(*orig, trg_ctx, parent, insert_order, first, options, &dup);
2222
0
        LY_CHECK_GOTO(rc, cleanup);
2223
0
    }
2224
2225
0
cleanup:
2226
0
    if (dup_p) {
2227
0
        *dup_p = leader;
2228
0
    }
2229
2230
0
    return rc;
2231
0
}
2232
2233
/**
2234
 * @brief Get a parent node to connect duplicated subtree to.
2235
 *
2236
 * @param[in] node Node (subtree) to duplicate.
2237
 * @param[in] trg_ctx Target context for duplicated nodes.
2238
 * @param[in] parent Initial parent to connect to.
2239
 * @param[in] options Bitmask of options flags, see @ref dupoptions.
2240
 * @param[out] dup_parent First duplicated parent node, if any.
2241
 * @param[out] local_parent Correct parent to directly connect duplicated @p node to.
2242
 * @return LY_ERR value.
2243
 */
2244
static LY_ERR
2245
lyd_dup_get_local_parent(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_node *parent,
2246
        uint32_t options, struct lyd_node **dup_parent, struct lyd_node **local_parent)
2247
0
{
2248
0
    const struct lyd_node *orig_parent;
2249
0
    struct lyd_node *iter = NULL;
2250
0
    ly_bool repeat = 1, ext_parent = 0;
2251
2252
0
    *dup_parent = NULL;
2253
0
    *local_parent = NULL;
2254
2255
0
    if (node->flags & LYD_EXT) {
2256
0
        ext_parent = 1;
2257
0
    }
2258
0
    for (orig_parent = lyd_parent(node); repeat && orig_parent; orig_parent = lyd_parent(orig_parent)) {
2259
0
        if (ext_parent) {
2260
            /* use the standard context */
2261
0
            trg_ctx = LYD_CTX(orig_parent);
2262
0
        }
2263
0
        if (parent && (LYD_CTX(parent) == LYD_CTX(orig_parent)) && (parent->schema == orig_parent->schema)) {
2264
            /* stop creating parents, connect what we have into the provided parent */
2265
0
            iter = parent;
2266
0
            repeat = 0;
2267
0
        } else if (parent && (LYD_CTX(parent) != LYD_CTX(orig_parent)) &&
2268
0
                lyd_compare_schema_equal(parent->schema, orig_parent->schema) &&
2269
0
                lyd_compare_schema_parents_equal(parent, orig_parent)) {
2270
0
            iter = parent;
2271
0
            repeat = 0;
2272
0
        } else {
2273
0
            iter = NULL;
2274
0
            LY_CHECK_RET(lyd_dup_r(orig_parent, trg_ctx, NULL, LYD_INSERT_NODE_DEFAULT, &iter, options, &iter));
2275
2276
            /* insert into the previous duplicated parent */
2277
0
            if (*dup_parent) {
2278
0
                lyd_insert_node(iter, NULL, *dup_parent, LYD_INSERT_NODE_DEFAULT);
2279
0
            }
2280
2281
            /* update the last duplicated parent */
2282
0
            *dup_parent = iter;
2283
0
        }
2284
2285
        /* set the first parent */
2286
0
        if (!*local_parent) {
2287
0
            *local_parent = iter;
2288
0
        }
2289
2290
0
        if (orig_parent->flags & LYD_EXT) {
2291
0
            ext_parent = 1;
2292
0
        }
2293
0
    }
2294
2295
0
    if (repeat && parent) {
2296
        /* given parent and created parents chain actually do not interconnect */
2297
0
        LOGERR(trg_ctx, LY_EINVAL, "None of the duplicated node \"%s\" schema parents match the provided parent \"%s\".",
2298
0
                LYD_NAME(node), LYD_NAME(parent));
2299
0
        return LY_EINVAL;
2300
0
    }
2301
2302
0
    if (*dup_parent && parent) {
2303
        /* last insert into a prevously-existing parent */
2304
0
        lyd_insert_node(parent, NULL, *dup_parent, LYD_INSERT_NODE_DEFAULT);
2305
0
    }
2306
0
    return LY_SUCCESS;
2307
0
}
2308
2309
static LY_ERR
2310
lyd_dup(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_node *parent, uint32_t options,
2311
        ly_bool nosiblings, struct lyd_node **dup_p)
2312
0
{
2313
0
    LY_ERR rc;
2314
0
    const struct lyd_node *orig;          /* original node to be duplicated */
2315
0
    struct lyd_node *first_dup = NULL;    /* the first duplicated node, this is returned */
2316
0
    struct lyd_node *top = NULL;          /* the most higher created node */
2317
0
    struct lyd_node *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
2318
0
    struct lyd_node *dup = NULL;          /* duplicate node */
2319
0
    struct lyd_node *first_sibling = NULL; /* first sibling node */
2320
2321
0
    assert(node && trg_ctx);
2322
2323
0
    if (options & LYD_DUP_WITH_PARENTS) {
2324
0
        LY_CHECK_GOTO(rc = lyd_dup_get_local_parent(node, trg_ctx, parent, options & (LYD_DUP_WITH_FLAGS | LYD_DUP_NO_META),
2325
0
                &top, &local_parent), error);
2326
0
    } else {
2327
0
        local_parent = parent;
2328
0
    }
2329
2330
0
    LY_LIST_FOR(node, orig) {
2331
0
        if (lysc_is_key(orig->schema)) {
2332
0
            if (local_parent) {
2333
                /* the key must already exist in the parent */
2334
0
                rc = lyd_find_sibling_schema(lyd_child(local_parent), orig->schema, &dup);
2335
0
                LY_CHECK_ERR_GOTO(rc, LOGINT(trg_ctx), error);
2336
0
            } else {
2337
0
                assert(!(options & LYD_DUP_WITH_PARENTS));
2338
                /* duplicating a single key, okay, I suppose... */
2339
0
                rc = lyd_dup_r(orig, trg_ctx, NULL, LYD_INSERT_NODE_DEFAULT, &first_sibling, options, &dup);
2340
0
                LY_CHECK_GOTO(rc, error);
2341
0
            }
2342
0
        } else if (!nosiblings && orig->schema && (orig->schema->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
2343
            /* duplicate the whole (leaf-)list */
2344
0
            rc = lyd_dup_list(&orig, trg_ctx, local_parent, &first_sibling, options, &dup);
2345
0
            LY_CHECK_GOTO(rc, error);
2346
0
        } else {
2347
0
            rc = lyd_dup_r(orig, trg_ctx, local_parent,
2348
0
                    options & LYD_DUP_NO_LYDS ? LYD_INSERT_NODE_LAST_BY_SCHEMA : LYD_INSERT_NODE_DEFAULT,
2349
0
                    &first_sibling, options, &dup);
2350
0
            LY_CHECK_GOTO(rc, error);
2351
0
        }
2352
0
        first_dup = first_dup ? first_dup : dup;
2353
2354
0
        if (nosiblings || !orig) {
2355
0
            break;
2356
0
        }
2357
0
    }
2358
2359
0
    if (dup_p) {
2360
0
        *dup_p = first_dup;
2361
0
    }
2362
0
    return LY_SUCCESS;
2363
2364
0
error:
2365
0
    if (top) {
2366
0
        lyd_free_tree(top);
2367
0
    } else if (first_dup) {
2368
0
        lyd_free_siblings(first_dup);
2369
0
    } else {
2370
0
        lyd_free_siblings(dup);
2371
0
    }
2372
0
    return rc;
2373
0
}
2374
2375
/**
2376
 * @brief Check the context of node and parent when duplicating nodes.
2377
 *
2378
 * @param[in] node Node to duplicate.
2379
 * @param[in] parent Parent of the duplicated node(s).
2380
 * @return LY_ERR value.
2381
 */
2382
static LY_ERR
2383
lyd_dup_ctx_check(const struct lyd_node *node, const struct lyd_node_inner *parent)
2384
0
{
2385
0
    const struct lyd_node *iter;
2386
2387
0
    if (!node || !parent) {
2388
0
        return LY_SUCCESS;
2389
0
    }
2390
2391
0
    if ((LYD_CTX(node) != LYD_CTX(parent))) {
2392
        /* try to find top-level ext data parent */
2393
0
        for (iter = node; iter && !(iter->flags & LYD_EXT); iter = lyd_parent(iter)) {}
2394
2395
0
        if (!iter || !lyd_parent(iter) || (LYD_CTX(lyd_parent(iter)) != LYD_CTX(parent))) {
2396
0
            LOGERR(LYD_CTX(node), LY_EINVAL, "Different contexts used in node duplication.");
2397
0
            return LY_EINVAL;
2398
0
        }
2399
0
    }
2400
2401
0
    return LY_SUCCESS;
2402
0
}
2403
2404
LIBYANG_API_DEF LY_ERR
2405
lyd_dup_single(const struct lyd_node *node, struct lyd_node_inner *parent, uint32_t options, struct lyd_node **dup)
2406
0
{
2407
0
    LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
2408
0
    LY_CHECK_RET(lyd_dup_ctx_check(node, parent));
2409
2410
0
    return lyd_dup(node, LYD_CTX(node), (struct lyd_node *)parent, options, 1, dup);
2411
0
}
2412
2413
LIBYANG_API_DEF LY_ERR
2414
lyd_dup_single_to_ctx(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_node_inner *parent,
2415
        uint32_t options, struct lyd_node **dup)
2416
0
{
2417
0
    LY_CHECK_ARG_RET(trg_ctx, node, trg_ctx, LY_EINVAL);
2418
2419
0
    return lyd_dup(node, trg_ctx, (struct lyd_node *)parent, options, 1, dup);
2420
0
}
2421
2422
LIBYANG_API_DEF LY_ERR
2423
lyd_dup_siblings(const struct lyd_node *node, struct lyd_node_inner *parent, uint32_t options, struct lyd_node **dup)
2424
0
{
2425
0
    LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
2426
0
    LY_CHECK_RET(lyd_dup_ctx_check(node, parent));
2427
2428
0
    return lyd_dup(node, LYD_CTX(node), (struct lyd_node *)parent, options, 0, dup);
2429
0
}
2430
2431
LIBYANG_API_DEF LY_ERR
2432
lyd_dup_siblings_to_ctx(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_node_inner *parent,
2433
        uint32_t options, struct lyd_node **dup)
2434
0
{
2435
0
    LY_CHECK_ARG_RET(trg_ctx, node, trg_ctx, LY_EINVAL);
2436
2437
0
    return lyd_dup(node, trg_ctx, (struct lyd_node *)parent, options, 0, dup);
2438
0
}
2439
2440
LY_ERR
2441
lyd_dup_meta_single_to_ctx(const struct ly_ctx *parent_ctx, const struct lyd_meta *meta, struct lyd_node *parent,
2442
        struct lyd_meta **dup)
2443
0
{
2444
0
    LY_ERR ret = LY_SUCCESS;
2445
0
    struct lyd_meta *mt, *last;
2446
0
    const struct lysc_type *ant_type;
2447
0
    struct lys_module *mod;
2448
0
    const char *val_can;
2449
2450
0
    LY_CHECK_ARG_RET(NULL, meta, parent, LY_EINVAL);
2451
2452
    /* create a copy */
2453
0
    mt = calloc(1, sizeof *mt);
2454
0
    LY_CHECK_ERR_RET(!mt, LOGMEM(LYD_CTX(parent)), LY_EMEM);
2455
2456
0
    if (parent_ctx != meta->annotation->module->ctx) {
2457
        /* different contexts */
2458
0
        mod = ly_ctx_get_module(parent_ctx, meta->annotation->module->name, meta->annotation->module->revision);
2459
2460
        /* annotation */
2461
0
        mt->annotation = lyd_get_meta_annotation(mod, meta->name, strlen(meta->name));
2462
0
        lyplg_ext_get_storage(mt->annotation, LY_STMT_TYPE, sizeof ant_type, (const void **)&ant_type);
2463
0
        LY_CHECK_ERR_GOTO((ret = mt->annotation ? LY_SUCCESS : LY_EINVAL), LOGERR(parent_ctx, LY_EINVAL,
2464
0
                "Annotation for metadata %s not found, value duplication failed.", meta->name), finish);
2465
2466
        /* duplicate callback expect only the same contexts, so use the store callback */
2467
0
        val_can = lyd_value_get_canonical(meta->annotation->module->ctx, &meta->value);
2468
0
        ret = lyd_value_store(parent_ctx, &mt->value, ant_type, val_can, strlen(val_can), 1, 1, NULL,
2469
0
                LY_VALUE_CANON, NULL, LYD_HINT_DATA, parent->schema, NULL);
2470
0
    } else {
2471
        /* annotation */
2472
0
        mt->annotation = meta->annotation;
2473
        /* duplication of value */
2474
0
        ret = meta->value.realtype->plugin->duplicate(parent_ctx, &meta->value, &mt->value);
2475
0
    }
2476
0
    LY_CHECK_ERR_GOTO(ret, LOGERR(LYD_CTX(parent), LY_EINT, "Value duplication failed."), finish);
2477
0
    LY_CHECK_GOTO(ret = lydict_insert(parent_ctx, meta->name, 0, &mt->name), finish);
2478
2479
    /* insert as the last attribute */
2480
0
    mt->parent = parent;
2481
0
    if (parent->meta) {
2482
0
        for (last = parent->meta; last->next; last = last->next) {}
2483
0
        last->next = mt;
2484
0
    } else {
2485
0
        parent->meta = mt;
2486
0
    }
2487
2488
0
finish:
2489
0
    if (ret) {
2490
0
        lyd_free_meta_single(mt);
2491
0
    } else if (dup) {
2492
0
        *dup = mt;
2493
0
    }
2494
0
    return LY_SUCCESS;
2495
0
}
2496
2497
LIBYANG_API_DEF LY_ERR
2498
lyd_dup_meta_single(const struct lyd_meta *meta, struct lyd_node *node, struct lyd_meta **dup)
2499
0
{
2500
0
    LY_CHECK_ARG_RET(NULL, meta, LY_EINVAL);
2501
2502
    /* log to node context but value must always use the annotation context */
2503
0
    return lyd_dup_meta_single_to_ctx(meta->annotation->module->ctx, meta, node, dup);
2504
0
}
2505
2506
/**
2507
 * @brief Merge a source sibling into target siblings.
2508
 *
2509
 * @param[in,out] first_trg First target sibling, is updated if top-level.
2510
 * @param[in] parent_trg Target parent.
2511
 * @param[in,out] sibling_src_p Source sibling to merge, set to NULL if spent.
2512
 * @param[in] merge_cb Optional merge callback.
2513
 * @param[in] cb_data Arbitrary callback data.
2514
 * @param[in] options Merge options.
2515
 * @param[in] lyds Pool of lyds data which can be reused.
2516
 * @param[in,out] leader_p Cached first instance of target (leaf-)list.
2517
 * @param[in,out] dup_inst Duplicate instance cache for all @p first_trg siblings.
2518
 * @return LY_ERR value.
2519
 */
2520
static LY_ERR
2521
lyd_merge_sibling_r(struct lyd_node **first_trg, struct lyd_node *parent_trg,
2522
        const struct lyd_node **sibling_src_p, lyd_merge_cb merge_cb, void *cb_data, uint16_t options,
2523
        struct lyds_pool *lyds, struct lyd_node **leader_p, struct ly_ht **dup_inst)
2524
0
{
2525
0
    const struct lyd_node *child_src, *tmp, *sibling_src;
2526
0
    struct lyd_node *match_trg, *dup_src, *elem, *leader;
2527
0
    struct lyd_node_opaq *opaq_trg, *opaq_src;
2528
0
    struct lysc_type *type;
2529
0
    const struct lysc_node *schema;
2530
0
    struct ly_ht *child_dup_inst = NULL;
2531
0
    LY_ERR r;
2532
0
    ly_bool first_inst = 0;
2533
2534
0
    sibling_src = *sibling_src_p;
2535
0
    if (!sibling_src->schema) {
2536
        /* try to find the same opaque node */
2537
0
        r = lyd_find_sibling_opaq_next(*first_trg, LYD_NAME(sibling_src), &match_trg);
2538
0
    } else if (sibling_src->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
2539
        /* try to find the exact instance */
2540
0
        r = lyd_find_sibling_first(*first_trg, sibling_src, &match_trg);
2541
0
    } else {
2542
        /* try to simply find the node, there cannot be more instances */
2543
0
        r = lyd_find_sibling_val(*first_trg, sibling_src->schema, NULL, 0, &match_trg);
2544
0
    }
2545
0
    LY_CHECK_RET(r && (r != LY_ENOTFOUND), r);
2546
2547
0
    if (match_trg) {
2548
        /* update match as needed */
2549
0
        LY_CHECK_RET(lyd_dup_inst_next(&match_trg, *first_trg, dup_inst));
2550
0
    } else {
2551
        /* first instance of this node */
2552
0
        first_inst = 1;
2553
0
    }
2554
2555
0
    if (match_trg) {
2556
        /* call callback */
2557
0
        if (merge_cb) {
2558
0
            LY_CHECK_RET(merge_cb(match_trg, sibling_src, cb_data));
2559
0
        }
2560
2561
        /* node found, make sure even value matches for all node types */
2562
0
        if (!match_trg->schema) {
2563
0
            if (lyd_compare_single(sibling_src, match_trg, 0)) {
2564
                /* update value */
2565
0
                opaq_trg = (struct lyd_node_opaq *)match_trg;
2566
0
                opaq_src = (struct lyd_node_opaq *)sibling_src;
2567
2568
0
                lydict_remove(LYD_CTX(opaq_trg), opaq_trg->value);
2569
0
                lydict_insert(LYD_CTX(opaq_trg), opaq_src->value, 0, &opaq_trg->value);
2570
0
                opaq_trg->hints = opaq_src->hints;
2571
2572
0
                ly_free_prefix_data(opaq_trg->format, opaq_trg->val_prefix_data);
2573
0
                opaq_trg->format = opaq_src->format;
2574
0
                ly_dup_prefix_data(LYD_CTX(opaq_trg), opaq_src->format, opaq_src->val_prefix_data,
2575
0
                        &opaq_trg->val_prefix_data);
2576
0
            }
2577
0
        } else if ((match_trg->schema->nodetype == LYS_LEAF) &&
2578
0
                lyd_compare_single(sibling_src, match_trg, LYD_COMPARE_DEFAULTS)) {
2579
            /* since they are different, they cannot both be default */
2580
0
            assert(!(sibling_src->flags & LYD_DEFAULT) || !(match_trg->flags & LYD_DEFAULT));
2581
2582
            /* update value (or only LYD_DEFAULT flag) only if flag set or the source node is not default */
2583
0
            if ((options & LYD_MERGE_DEFAULTS) || !(sibling_src->flags & LYD_DEFAULT)) {
2584
0
                type = ((struct lysc_node_leaf *)match_trg->schema)->type;
2585
0
                type->plugin->free(LYD_CTX(match_trg), &((struct lyd_node_term *)match_trg)->value);
2586
0
                LY_CHECK_RET(type->plugin->duplicate(LYD_CTX(match_trg), &((struct lyd_node_term *)sibling_src)->value,
2587
0
                        &((struct lyd_node_term *)match_trg)->value));
2588
2589
                /* copy flags and add LYD_NEW */
2590
0
                match_trg->flags = sibling_src->flags | ((options & LYD_MERGE_WITH_FLAGS) ? 0 : LYD_NEW);
2591
0
            }
2592
0
        } else if ((match_trg->schema->nodetype & LYS_ANYDATA) && lyd_compare_single(sibling_src, match_trg, 0)) {
2593
            /* update value */
2594
0
            LY_CHECK_RET(lyd_any_copy_value(match_trg, &((struct lyd_node_any *)sibling_src)->value,
2595
0
                    ((struct lyd_node_any *)sibling_src)->value_type));
2596
2597
            /* copy flags and add LYD_NEW */
2598
0
            match_trg->flags = sibling_src->flags | ((options & LYD_MERGE_WITH_FLAGS) ? 0 : LYD_NEW);
2599
0
        }
2600
2601
        /* check descendants, recursively */
2602
0
        r = LY_SUCCESS;
2603
0
        leader = NULL;
2604
0
        schema = NULL;
2605
0
        LY_LIST_FOR_SAFE(lyd_child_no_keys(sibling_src), tmp, child_src) {
2606
0
            if ((options & LYD_MERGE_DESTRUCT) && (schema != child_src->schema) && LYDS_NODE_IS_LEADER(child_src)) {
2607
0
                schema = child_src->schema;
2608
                /* unlink lyds data and add them to the pool */
2609
0
                lyds_pool_add((struct lyd_node *)child_src, lyds);
2610
0
            }
2611
2612
0
            r = lyd_merge_sibling_r(lyd_node_child_p(match_trg), match_trg, &child_src,
2613
0
                    merge_cb, cb_data, options, lyds, &leader, &child_dup_inst);
2614
0
            if (r) {
2615
0
                break;
2616
0
            }
2617
0
        }
2618
2619
0
        lyd_dup_inst_free(child_dup_inst);
2620
0
        LY_CHECK_RET(r);
2621
0
    } else {
2622
        /* node not found, merge it */
2623
0
        if (options & LYD_MERGE_DESTRUCT) {
2624
0
            dup_src = (struct lyd_node *)sibling_src;
2625
0
            lyd_unlink_ignore_lyds(NULL, dup_src);
2626
            /* spend it */
2627
0
            *sibling_src_p = NULL;
2628
0
        } else {
2629
0
            LY_CHECK_RET(lyd_dup_single(sibling_src, NULL, LYD_DUP_RECURSIVE | LYD_DUP_WITH_FLAGS, &dup_src));
2630
0
        }
2631
2632
0
        if (!(options & LYD_MERGE_WITH_FLAGS)) {
2633
            /* set LYD_NEW for all the new nodes, required for validation */
2634
0
            LYD_TREE_DFS_BEGIN(dup_src, elem) {
2635
0
                elem->flags |= LYD_NEW;
2636
0
                LYD_TREE_DFS_END(dup_src, elem);
2637
0
            }
2638
0
        }
2639
2640
0
        if (lyds->rbn) {
2641
            /* insert node and try to reuse free lyds data */
2642
0
            lyds_insert2(parent_trg, first_trg, leader_p, dup_src, lyds);
2643
0
        } else {
2644
            /* generic insert node */
2645
0
            lyd_insert_node(parent_trg, first_trg, dup_src, LYD_INSERT_NODE_DEFAULT);
2646
0
        }
2647
2648
0
        if (first_inst) {
2649
            /* remember not to find this instance next time */
2650
0
            LY_CHECK_RET(lyd_dup_inst_next(&dup_src, *first_trg, dup_inst));
2651
0
        }
2652
2653
        /* call callback, no source node */
2654
0
        if (merge_cb) {
2655
0
            LY_CHECK_RET(merge_cb(dup_src, NULL, cb_data));
2656
0
        }
2657
0
    }
2658
2659
0
    return LY_SUCCESS;
2660
0
}
2661
2662
static LY_ERR
2663
lyd_merge(struct lyd_node **target, const struct lyd_node *source, const struct lys_module *mod,
2664
        lyd_merge_cb merge_cb, void *cb_data, uint16_t options, ly_bool nosiblings)
2665
0
{
2666
0
    const struct lyd_node *sibling_src, *tmp;
2667
0
    const struct lysc_node *schema;
2668
0
    struct lyd_node *leader;
2669
0
    struct ly_ht *dup_inst = NULL;
2670
0
    ly_bool first;
2671
0
    LY_ERR ret = LY_SUCCESS;
2672
0
    struct lyds_pool lyds = {0};
2673
2674
0
    LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
2675
0
    LY_CHECK_CTX_EQUAL_RET(*target ? LYD_CTX(*target) : NULL, source ? LYD_CTX(source) : NULL, mod ? mod->ctx : NULL,
2676
0
            LY_EINVAL);
2677
2678
0
    if (!source) {
2679
        /* nothing to merge */
2680
0
        return LY_SUCCESS;
2681
0
    }
2682
2683
0
    if ((*target && lysc_data_parent((*target)->schema)) || lysc_data_parent(source->schema)) {
2684
0
        LOGERR(LYD_CTX(source), LY_EINVAL, "Invalid arguments - can merge only 2 top-level subtrees (%s()).", __func__);
2685
0
        return LY_EINVAL;
2686
0
    }
2687
2688
0
    leader = NULL;
2689
0
    schema = NULL;
2690
0
    LY_LIST_FOR_SAFE(source, tmp, sibling_src) {
2691
0
        if (mod && (lyd_owner_module(sibling_src) != mod)) {
2692
            /* skip data nodes from different modules */
2693
0
            continue;
2694
0
        }
2695
2696
0
        if ((options & LYD_MERGE_DESTRUCT) && (schema != sibling_src->schema) && LYDS_NODE_IS_LEADER(sibling_src)) {
2697
0
            schema = sibling_src->schema;
2698
            /* unlink lyds data and add them to the pool */
2699
0
            lyds_pool_add((struct lyd_node *)sibling_src, &lyds);
2700
0
        }
2701
2702
0
        first = (sibling_src == source) ? 1 : 0;
2703
0
        ret = lyd_merge_sibling_r(target, NULL, &sibling_src, merge_cb, cb_data, options,
2704
0
                &lyds, &leader, &dup_inst);
2705
0
        if (ret) {
2706
0
            break;
2707
0
        }
2708
0
        if (first && !sibling_src) {
2709
            /* source was spent (unlinked), move to the next node */
2710
0
            source = tmp;
2711
0
        }
2712
2713
0
        if (nosiblings) {
2714
0
            break;
2715
0
        }
2716
0
    }
2717
0
    lyds_pool_clean(&lyds);
2718
2719
0
    if (options & LYD_MERGE_DESTRUCT) {
2720
        /* free any leftover source data that were not merged */
2721
0
        lyd_free_siblings((struct lyd_node *)source);
2722
0
    }
2723
2724
0
    lyd_dup_inst_free(dup_inst);
2725
0
    return ret;
2726
0
}
2727
2728
LIBYANG_API_DEF LY_ERR
2729
lyd_merge_tree(struct lyd_node **target, const struct lyd_node *source, uint16_t options)
2730
0
{
2731
0
    return lyd_merge(target, source, NULL, NULL, NULL, options, 1);
2732
0
}
2733
2734
LIBYANG_API_DEF LY_ERR
2735
lyd_merge_siblings(struct lyd_node **target, const struct lyd_node *source, uint16_t options)
2736
0
{
2737
0
    return lyd_merge(target, source, NULL, NULL, NULL, options, 0);
2738
0
}
2739
2740
LIBYANG_API_DEF LY_ERR
2741
lyd_merge_module(struct lyd_node **target, const struct lyd_node *source, const struct lys_module *mod,
2742
        lyd_merge_cb merge_cb, void *cb_data, uint16_t options)
2743
0
{
2744
0
    return lyd_merge(target, source, mod, merge_cb, cb_data, options, 0);
2745
0
}
2746
2747
static LY_ERR
2748
lyd_path_str_enlarge(char **buffer, size_t *buflen, size_t reqlen, ly_bool is_static)
2749
228k
{
2750
    /* ending \0 */
2751
228k
    ++reqlen;
2752
2753
228k
    if (reqlen > *buflen) {
2754
228k
        if (is_static) {
2755
0
            return LY_EINCOMPLETE;
2756
0
        }
2757
2758
228k
        *buffer = ly_realloc(*buffer, reqlen * sizeof **buffer);
2759
228k
        if (!*buffer) {
2760
0
            return LY_EMEM;
2761
0
        }
2762
2763
228k
        *buflen = reqlen;
2764
228k
    }
2765
2766
228k
    return LY_SUCCESS;
2767
228k
}
2768
2769
LY_ERR
2770
lyd_path_list_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, ly_bool is_static)
2771
1.28k
{
2772
1.28k
    const struct lyd_node *key;
2773
1.28k
    size_t len;
2774
1.28k
    const char *val;
2775
1.28k
    char quot;
2776
2777
225k
    for (key = lyd_child(node); key && key->schema && (key->schema->flags & LYS_KEY); key = key->next) {
2778
224k
        val = lyd_get_value(key);
2779
224k
        len = 1 + strlen(key->schema->name) + 2 + strlen(val) + 2;
2780
224k
        LY_CHECK_RET(lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static));
2781
2782
224k
        quot = '\'';
2783
224k
        if (strchr(val, '\'')) {
2784
12.7k
            quot = '"';
2785
12.7k
        }
2786
224k
        *bufused += sprintf(*buffer + *bufused, "[%s=%c%s%c]", key->schema->name, quot, val, quot);
2787
224k
    }
2788
2789
1.28k
    return LY_SUCCESS;
2790
1.28k
}
2791
2792
/**
2793
 * @brief Append leaf-list value predicate to path.
2794
 *
2795
 * @param[in] node Node to print.
2796
 * @param[in,out] buffer Buffer to print to.
2797
 * @param[in,out] buflen Current buffer length.
2798
 * @param[in,out] bufused Current number of characters used in @p buffer.
2799
 * @param[in] is_static Whether buffer is static or can be reallocated.
2800
 * @return LY_ERR
2801
 */
2802
static LY_ERR
2803
lyd_path_leaflist_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, ly_bool is_static)
2804
129
{
2805
129
    size_t len;
2806
129
    const char *val;
2807
129
    char quot;
2808
2809
129
    val = lyd_get_value(node);
2810
129
    len = 4 + strlen(val) + 2; /* "[.='" + val + "']" */
2811
129
    LY_CHECK_RET(lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static));
2812
2813
129
    quot = '\'';
2814
129
    if (strchr(val, '\'')) {
2815
24
        quot = '"';
2816
24
    }
2817
129
    *bufused += sprintf(*buffer + *bufused, "[.=%c%s%c]", quot, val, quot);
2818
2819
129
    return LY_SUCCESS;
2820
129
}
2821
2822
/**
2823
 * @brief Append node position (relative to its other instances) predicate to path.
2824
 *
2825
 * @param[in] node Node to print.
2826
 * @param[in,out] buffer Buffer to print to.
2827
 * @param[in,out] buflen Current buffer length.
2828
 * @param[in,out] bufused Current number of characters used in @p buffer.
2829
 * @param[in] is_static Whether buffer is static or can be reallocated.
2830
 * @return LY_ERR
2831
 */
2832
static LY_ERR
2833
lyd_path_position_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, ly_bool is_static)
2834
0
{
2835
0
    size_t len;
2836
0
    uint32_t pos;
2837
0
    char *val = NULL;
2838
0
    LY_ERR rc;
2839
2840
0
    pos = lyd_list_pos(node);
2841
0
    if (asprintf(&val, "%" PRIu32, pos) == -1) {
2842
0
        return LY_EMEM;
2843
0
    }
2844
2845
0
    len = 1 + strlen(val) + 1;
2846
0
    rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2847
0
    if (rc != LY_SUCCESS) {
2848
0
        goto cleanup;
2849
0
    }
2850
2851
0
    *bufused += sprintf(*buffer + *bufused, "[%s]", val);
2852
2853
0
cleanup:
2854
0
    free(val);
2855
0
    return rc;
2856
0
}
2857
2858
LIBYANG_API_DEF char *
2859
lyd_path(const struct lyd_node *node, LYD_PATH_TYPE pathtype, char *buffer, size_t buflen)
2860
3.40k
{
2861
3.40k
    ly_bool is_static = 0;
2862
3.40k
    uint32_t i, depth;
2863
3.40k
    size_t bufused = 0, len;
2864
3.40k
    const struct lyd_node *iter, *parent;
2865
3.40k
    const struct lys_module *mod, *prev_mod;
2866
3.40k
    LY_ERR rc = LY_SUCCESS;
2867
2868
3.40k
    LY_CHECK_ARG_RET(NULL, node, NULL);
2869
3.40k
    if (buffer) {
2870
0
        LY_CHECK_ARG_RET(LYD_CTX(node), buflen > 1, NULL);
2871
0
        is_static = 1;
2872
3.40k
    } else {
2873
3.40k
        buflen = 0;
2874
3.40k
    }
2875
2876
3.40k
    switch (pathtype) {
2877
3.40k
    case LYD_PATH_STD:
2878
3.40k
    case LYD_PATH_STD_NO_LAST_PRED:
2879
3.40k
        depth = 1;
2880
3.48k
        for (iter = node; iter->parent; iter = lyd_parent(iter)) {
2881
81
            ++depth;
2882
81
        }
2883
2884
3.40k
        goto iter_print;
2885
3.48k
        while (depth) {
2886
            /* find the right node */
2887
81
            for (iter = node, i = 1; i < depth; iter = lyd_parent(iter), ++i) {}
2888
3.48k
iter_print:
2889
            /* get the module */
2890
3.48k
            mod = lyd_node_module(iter);
2891
3.48k
            parent = lyd_parent(iter);
2892
3.48k
            prev_mod = lyd_node_module(parent);
2893
3.48k
            if (prev_mod == mod) {
2894
89
                mod = NULL;
2895
89
            }
2896
2897
            /* realloc string */
2898
3.48k
            len = 1 + (mod ? strlen(mod->name) + 1 : 0) + (iter->schema ? strlen(iter->schema->name) :
2899
3.48k
                    strlen(((struct lyd_node_opaq *)iter)->name.name));
2900
3.48k
            rc = lyd_path_str_enlarge(&buffer, &buflen, bufused + len, is_static);
2901
3.48k
            if (rc != LY_SUCCESS) {
2902
0
                break;
2903
0
            }
2904
2905
            /* print next node */
2906
3.48k
            bufused += sprintf(buffer + bufused, "/%s%s%s", mod ? mod->name : "", mod ? ":" : "", LYD_NAME(iter));
2907
2908
            /* do not always print the last (first) predicate */
2909
3.48k
            if (iter->schema && ((depth > 1) || (pathtype == LYD_PATH_STD))) {
2910
3.47k
                switch (iter->schema->nodetype) {
2911
894
                case LYS_LIST:
2912
894
                    if (iter->schema->flags & LYS_KEYLESS) {
2913
                        /* print its position */
2914
0
                        rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2915
894
                    } else {
2916
                        /* print all list keys in predicates */
2917
894
                        rc = lyd_path_list_predicate(iter, &buffer, &buflen, &bufused, is_static);
2918
894
                    }
2919
894
                    break;
2920
47
                case LYS_LEAFLIST:
2921
47
                    if (iter->schema->flags & LYS_CONFIG_W) {
2922
                        /* print leaf-list value */
2923
47
                        rc = lyd_path_leaflist_predicate(iter, &buffer, &buflen, &bufused, is_static);
2924
47
                    } else {
2925
                        /* print its position */
2926
0
                        rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2927
0
                    }
2928
47
                    break;
2929
2.53k
                default:
2930
                    /* nothing to print more */
2931
2.53k
                    break;
2932
3.47k
                }
2933
3.47k
            }
2934
3.48k
            if (rc != LY_SUCCESS) {
2935
0
                break;
2936
0
            }
2937
2938
3.48k
            --depth;
2939
3.48k
        }
2940
3.40k
        break;
2941
3.40k
    }
2942
2943
3.40k
    return buffer;
2944
3.40k
}
2945
2946
char *
2947
lyd_path_set(const struct ly_set *dnodes, LYD_PATH_TYPE pathtype)
2948
393
{
2949
393
    uint32_t depth;
2950
393
    size_t bufused = 0, buflen = 0, len;
2951
393
    char *buffer = NULL;
2952
393
    const struct lyd_node *iter, *parent;
2953
393
    const struct lys_module *mod, *prev_mod;
2954
393
    LY_ERR rc = LY_SUCCESS;
2955
2956
393
    switch (pathtype) {
2957
393
    case LYD_PATH_STD:
2958
393
    case LYD_PATH_STD_NO_LAST_PRED:
2959
1.18k
        for (depth = 1; depth <= dnodes->count; ++depth) {
2960
            /* current node */
2961
787
            iter = dnodes->dnodes[depth - 1];
2962
787
            mod = lyd_node_module(iter);
2963
2964
            /* parent */
2965
787
            parent = (depth > 1) ? dnodes->dnodes[depth - 2] : NULL;
2966
787
            assert(!parent || !iter->schema || !parent->schema || (parent->schema->nodetype & LYD_NODE_ANY) ||
2967
787
                    (lysc_data_parent(iter->schema) == parent->schema) ||
2968
787
                    (!lysc_data_parent(iter->schema) && (LYD_CTX(iter) != LYD_CTX(parent))) ||
2969
787
                    (parent->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)));
2970
2971
            /* get module to print, if any */
2972
787
            prev_mod = lyd_node_module(parent);
2973
787
            if (prev_mod == mod) {
2974
394
                mod = NULL;
2975
394
            }
2976
2977
            /* realloc string */
2978
787
            len = 1 + (mod ? strlen(mod->name) + 1 : 0) + (iter->schema ? strlen(iter->schema->name) :
2979
787
                    strlen(((struct lyd_node_opaq *)iter)->name.name));
2980
787
            if ((rc = lyd_path_str_enlarge(&buffer, &buflen, bufused + len, 0))) {
2981
0
                break;
2982
0
            }
2983
2984
            /* print next node */
2985
787
            bufused += sprintf(buffer + bufused, "/%s%s%s", mod ? mod->name : "", mod ? ":" : "", LYD_NAME(iter));
2986
2987
            /* do not always print the last (first) predicate */
2988
787
            if (iter->schema && ((depth > 1) || (pathtype == LYD_PATH_STD))) {
2989
787
                switch (iter->schema->nodetype) {
2990
386
                case LYS_LIST:
2991
386
                    if (iter->schema->flags & LYS_KEYLESS) {
2992
                        /* print its position */
2993
0
                        rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, 0);
2994
386
                    } else {
2995
                        /* print all list keys in predicates */
2996
386
                        rc = lyd_path_list_predicate(iter, &buffer, &buflen, &bufused, 0);
2997
386
                    }
2998
386
                    break;
2999
82
                case LYS_LEAFLIST:
3000
82
                    if (iter->schema->flags & LYS_CONFIG_W) {
3001
                        /* print leaf-list value */
3002
82
                        rc = lyd_path_leaflist_predicate(iter, &buffer, &buflen, &bufused, 0);
3003
82
                    } else {
3004
                        /* print its position */
3005
0
                        rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, 0);
3006
0
                    }
3007
82
                    break;
3008
319
                default:
3009
                    /* nothing to print more */
3010
319
                    break;
3011
787
                }
3012
787
            }
3013
787
            if (rc) {
3014
0
                break;
3015
0
            }
3016
787
        }
3017
393
        break;
3018
393
    }
3019
3020
393
    return buffer;
3021
393
}
3022
3023
LIBYANG_API_DEF struct lyd_meta *
3024
lyd_find_meta(const struct lyd_meta *first, const struct lys_module *module, const char *name)
3025
0
{
3026
0
    struct lyd_meta *ret = NULL;
3027
0
    const struct ly_ctx *ctx;
3028
0
    const char *prefix, *tmp;
3029
0
    char *str;
3030
0
    size_t pref_len, name_len;
3031
3032
0
    LY_CHECK_ARG_RET(NULL, module || strchr(name, ':'), name, NULL);
3033
0
    LY_CHECK_CTX_EQUAL_RET(first ? first->annotation->module->ctx : NULL, module ? module->ctx : NULL, NULL);
3034
3035
0
    if (!first) {
3036
0
        return NULL;
3037
0
    }
3038
3039
0
    ctx = first->annotation->module->ctx;
3040
3041
    /* parse the name */
3042
0
    tmp = name;
3043
0
    if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
3044
0
        LOGERR(ctx, LY_EINVAL, "Metadata name \"%s\" is not valid.", name);
3045
0
        return NULL;
3046
0
    }
3047
3048
    /* find the module */
3049
0
    if (prefix) {
3050
0
        str = strndup(prefix, pref_len);
3051
0
        module = ly_ctx_get_module_latest(ctx, str);
3052
0
        free(str);
3053
0
        LY_CHECK_ERR_RET(!module, LOGERR(ctx, LY_EINVAL, "Module \"%.*s\" not found.", (int)pref_len, prefix), NULL);
3054
0
    }
3055
3056
    /* find the metadata */
3057
0
    LY_LIST_FOR(first, first) {
3058
0
        if ((first->annotation->module == module) && !strcmp(first->name, name)) {
3059
0
            ret = (struct lyd_meta *)first;
3060
0
            break;
3061
0
        }
3062
0
    }
3063
3064
0
    return ret;
3065
0
}
3066
3067
LIBYANG_API_DEF LY_ERR
3068
lyd_find_sibling_first(const struct lyd_node *siblings, const struct lyd_node *target, struct lyd_node **match)
3069
49.2k
{
3070
49.2k
    struct lyd_node **match_p, *iter, *dup = NULL;
3071
49.2k
    struct lyd_node_inner *parent;
3072
49.2k
    ly_bool found;
3073
3074
49.2k
    LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
3075
49.2k
    if (!siblings) {
3076
        /* no data */
3077
0
        if (match) {
3078
0
            *match = NULL;
3079
0
        }
3080
0
        return LY_ENOTFOUND;
3081
0
    }
3082
3083
49.2k
    if (LYD_CTX(siblings) != LYD_CTX(target)) {
3084
        /* create a duplicate in this context */
3085
0
        LY_CHECK_RET(lyd_dup_single_to_ctx(target, LYD_CTX(siblings), NULL, 0, &dup));
3086
0
        target = dup;
3087
0
    }
3088
3089
49.2k
    if ((siblings->schema && target->schema && (lysc_data_parent(siblings->schema) != lysc_data_parent(target->schema)))) {
3090
        /* schema mismatch */
3091
0
        lyd_free_tree(dup);
3092
0
        if (match) {
3093
0
            *match = NULL;
3094
0
        }
3095
0
        return LY_ENOTFOUND;
3096
0
    }
3097
3098
    /* get first sibling */
3099
49.2k
    siblings = lyd_first_sibling(siblings);
3100
3101
49.2k
    parent = siblings->parent;
3102
49.2k
    if (target->schema && parent && parent->schema && parent->children_ht) {
3103
49.1k
        assert(target->hash);
3104
3105
49.1k
        if (lysc_is_dup_inst_list(target->schema)) {
3106
            /* we must search the instances from beginning to find the first matching one */
3107
0
            found = 0;
3108
0
            LYD_LIST_FOR_INST(siblings, target->schema, iter) {
3109
0
                if (!lyd_compare_single(target, iter, LYD_COMPARE_FULL_RECURSION)) {
3110
0
                    found = 1;
3111
0
                    break;
3112
0
                }
3113
0
            }
3114
0
            if (found) {
3115
0
                siblings = iter;
3116
0
            } else {
3117
0
                siblings = NULL;
3118
0
            }
3119
49.1k
        } else {
3120
            /* find by hash */
3121
49.1k
            if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
3122
49.1k
                siblings = *match_p;
3123
49.1k
            } else {
3124
                /* not found */
3125
0
                siblings = NULL;
3126
0
            }
3127
49.1k
        }
3128
49.1k
    } else {
3129
        /* no children hash table or cannot be used */
3130
343
        for ( ; siblings; siblings = siblings->next) {
3131
332
            if (lysc_is_dup_inst_list(target->schema)) {
3132
0
                if (!lyd_compare_single(siblings, target, LYD_COMPARE_FULL_RECURSION)) {
3133
0
                    break;
3134
0
                }
3135
332
            } else {
3136
332
                if (!lyd_compare_single(siblings, target, 0)) {
3137
134
                    break;
3138
134
                }
3139
332
            }
3140
332
        }
3141
145
    }
3142
3143
49.2k
    lyd_free_tree(dup);
3144
49.2k
    if (!siblings) {
3145
11
        if (match) {
3146
11
            *match = NULL;
3147
11
        }
3148
11
        return LY_ENOTFOUND;
3149
11
    }
3150
3151
49.2k
    if (match) {
3152
49.2k
        *match = (struct lyd_node *)siblings;
3153
49.2k
    }
3154
49.2k
    return LY_SUCCESS;
3155
49.2k
}
3156
3157
LIBYANG_API_DEF LY_ERR
3158
lyd_find_sibling_val(const struct lyd_node *siblings, const struct lysc_node *schema, const char *key_or_value,
3159
        size_t val_len, struct lyd_node **match)
3160
2.23k
{
3161
2.23k
    LY_ERR rc;
3162
2.23k
    struct lyd_node *target = NULL;
3163
2.23k
    const struct lyd_node *parent;
3164
3165
2.23k
    LY_CHECK_ARG_RET(NULL, schema, !(schema->nodetype & (LYS_CHOICE | LYS_CASE)), LY_EINVAL);
3166
2.23k
    if (!siblings) {
3167
        /* no data */
3168
390
        if (match) {
3169
390
            *match = NULL;
3170
390
        }
3171
390
        return LY_ENOTFOUND;
3172
390
    }
3173
3174
1.84k
    if ((LYD_CTX(siblings) != schema->module->ctx)) {
3175
        /* parent of ext nodes is useless */
3176
0
        parent = (siblings->flags & LYD_EXT) ? NULL : lyd_parent(siblings);
3177
0
        if (lyd_find_schema_ctx(schema, LYD_CTX(siblings), parent, 0, &schema)) {
3178
            /* no schema node in siblings so certainly no data node either */
3179
0
            if (match) {
3180
0
                *match = NULL;
3181
0
            }
3182
0
            return LY_ENOTFOUND;
3183
0
        }
3184
0
    }
3185
3186
1.84k
    if (siblings->schema && (lysc_data_parent(siblings->schema) != lysc_data_parent(schema))) {
3187
        /* schema mismatch */
3188
0
        if (match) {
3189
0
            *match = NULL;
3190
0
        }
3191
0
        return LY_ENOTFOUND;
3192
0
    }
3193
3194
1.84k
    if (key_or_value && !val_len) {
3195
0
        val_len = strlen(key_or_value);
3196
0
    }
3197
3198
1.84k
    if ((schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) && key_or_value) {
3199
        /* create a data node and find the instance */
3200
0
        if (schema->nodetype == LYS_LEAFLIST) {
3201
            /* target used attributes: schema, hash, value */
3202
0
            rc = lyd_create_term(schema, key_or_value, val_len, 0, 1, NULL, LY_VALUE_JSON, NULL, LYD_HINT_DATA, NULL, &target);
3203
0
            LY_CHECK_RET(rc);
3204
0
        } else {
3205
            /* target used attributes: schema, hash, child (all keys) */
3206
0
            LY_CHECK_RET(lyd_create_list2(schema, key_or_value, val_len, 1, &target));
3207
0
        }
3208
3209
        /* find it */
3210
0
        rc = lyd_find_sibling_first(siblings, target, match);
3211
1.84k
    } else {
3212
        /* find the first schema node instance */
3213
1.84k
        rc = lyd_find_sibling_schema(siblings, schema, match);
3214
1.84k
    }
3215
3216
1.84k
    lyd_free_tree(target);
3217
1.84k
    return rc;
3218
1.84k
}
3219
3220
LIBYANG_API_DEF LY_ERR
3221
lyd_find_sibling_dup_inst_set(const struct lyd_node *siblings, const struct lyd_node *target, struct ly_set **set)
3222
0
{
3223
0
    struct lyd_node **match_p, *first, *iter;
3224
0
    struct lyd_node_inner *parent;
3225
0
    uint32_t comp_opts;
3226
3227
0
    LY_CHECK_ARG_RET(NULL, target, set, LY_EINVAL);
3228
0
    LY_CHECK_CTX_EQUAL_RET(siblings ? LYD_CTX(siblings) : NULL, LYD_CTX(target), LY_EINVAL);
3229
3230
0
    LY_CHECK_RET(ly_set_new(set));
3231
3232
0
    if (!siblings || (siblings->schema && (lysc_data_parent(siblings->schema) != lysc_data_parent(target->schema)))) {
3233
        /* no data or schema mismatch */
3234
0
        return LY_ENOTFOUND;
3235
0
    }
3236
3237
    /* set options */
3238
0
    comp_opts = (lysc_is_dup_inst_list(target->schema) ? LYD_COMPARE_FULL_RECURSION : 0);
3239
3240
    /* get first sibling */
3241
0
    siblings = lyd_first_sibling(siblings);
3242
3243
0
    parent = siblings->parent;
3244
0
    if (parent && parent->schema && parent->children_ht) {
3245
0
        assert(target->hash);
3246
3247
        /* find the first instance */
3248
0
        lyd_find_sibling_first(siblings, target, &first);
3249
0
        if (first) {
3250
            /* add it so that it is the first in the set */
3251
0
            if (ly_set_add(*set, first, 1, NULL)) {
3252
0
                goto error;
3253
0
            }
3254
3255
            /* find by hash */
3256
0
            if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
3257
0
                iter = *match_p;
3258
0
            } else {
3259
                /* not found */
3260
0
                iter = NULL;
3261
0
            }
3262
0
            while (iter) {
3263
                /* add all found nodes into the set */
3264
0
                if ((iter != first) && !lyd_compare_single(iter, target, comp_opts) && ly_set_add(*set, iter, 1, NULL)) {
3265
0
                    goto error;
3266
0
                }
3267
3268
                /* find next instance */
3269
0
                if (lyht_find_next(parent->children_ht, &iter, iter->hash, (void **)&match_p)) {
3270
0
                    iter = NULL;
3271
0
                } else {
3272
0
                    iter = *match_p;
3273
0
                }
3274
0
            }
3275
0
        }
3276
0
    } else {
3277
        /* no children hash table */
3278
0
        LY_LIST_FOR(siblings, siblings) {
3279
0
            if (!lyd_compare_single(target, siblings, comp_opts)) {
3280
0
                ly_set_add(*set, (void *)siblings, 1, NULL);
3281
0
            }
3282
0
        }
3283
0
    }
3284
3285
0
    if (!(*set)->count) {
3286
0
        return LY_ENOTFOUND;
3287
0
    }
3288
0
    return LY_SUCCESS;
3289
3290
0
error:
3291
0
    ly_set_free(*set, NULL);
3292
0
    *set = NULL;
3293
0
    return LY_EMEM;
3294
0
}
3295
3296
LIBYANG_API_DEF LY_ERR
3297
lyd_find_sibling_opaq_next(const struct lyd_node *first, const char *name, struct lyd_node **match)
3298
154
{
3299
154
    LY_CHECK_ARG_RET(NULL, name, LY_EINVAL);
3300
3301
154
    if (first && first->schema) {
3302
154
        first = first->prev;
3303
154
        if (first->schema) {
3304
            /* no opaque nodes */
3305
154
            first = NULL;
3306
154
        } else {
3307
            /* opaque nodes are at the end, find quickly the first */
3308
0
            while (!first->prev->schema) {
3309
0
                first = first->prev;
3310
0
            }
3311
0
        }
3312
154
    }
3313
3314
154
    for ( ; first; first = first->next) {
3315
0
        assert(!first->schema);
3316
0
        if (!strcmp(LYD_NAME(first), name)) {
3317
0
            break;
3318
0
        }
3319
0
    }
3320
3321
154
    if (match) {
3322
154
        *match = (struct lyd_node *)first;
3323
154
    }
3324
154
    return first ? LY_SUCCESS : LY_ENOTFOUND;
3325
154
}
3326
3327
LIBYANG_API_DEF LY_ERR
3328
lyd_find_xpath(const struct lyd_node *ctx_node, const char *xpath, struct ly_set **set)
3329
0
{
3330
0
    LY_CHECK_ARG_RET(NULL, ctx_node, xpath, set, LY_EINVAL);
3331
3332
0
    return lyd_find_xpath3(ctx_node, ctx_node, xpath, LY_VALUE_JSON, NULL, NULL, set);
3333
0
}
3334
3335
LIBYANG_API_DEF LY_ERR
3336
lyd_find_xpath2(const struct lyd_node *ctx_node, const char *xpath, const struct lyxp_var *vars, struct ly_set **set)
3337
0
{
3338
0
    LY_CHECK_ARG_RET(NULL, ctx_node, xpath, set, LY_EINVAL);
3339
3340
0
    return lyd_find_xpath3(ctx_node, ctx_node, xpath, LY_VALUE_JSON, NULL, vars, set);
3341
0
}
3342
3343
LIBYANG_API_DEF LY_ERR
3344
lyd_find_xpath3(const struct lyd_node *ctx_node, const struct lyd_node *tree, const char *xpath, LY_VALUE_FORMAT format,
3345
        void *prefix_data, const struct lyxp_var *vars, struct ly_set **set)
3346
0
{
3347
0
    LY_CHECK_ARG_RET(NULL, tree, xpath, set, LY_EINVAL);
3348
3349
0
    *set = NULL;
3350
3351
0
    return lyd_eval_xpath4(ctx_node, tree, NULL, xpath, format, prefix_data, vars, NULL, set, NULL, NULL, NULL);
3352
0
}
3353
3354
LIBYANG_API_DEF LY_ERR
3355
lyd_eval_xpath(const struct lyd_node *ctx_node, const char *xpath, ly_bool *result)
3356
0
{
3357
0
    return lyd_eval_xpath3(ctx_node, NULL, xpath, LY_VALUE_JSON, NULL, NULL, result);
3358
0
}
3359
3360
LIBYANG_API_DEF LY_ERR
3361
lyd_eval_xpath2(const struct lyd_node *ctx_node, const char *xpath, const struct lyxp_var *vars, ly_bool *result)
3362
0
{
3363
0
    return lyd_eval_xpath3(ctx_node, NULL, xpath, LY_VALUE_JSON, NULL, vars, result);
3364
0
}
3365
3366
LIBYANG_API_DEF LY_ERR
3367
lyd_eval_xpath3(const struct lyd_node *ctx_node, const struct lys_module *cur_mod, const char *xpath,
3368
        LY_VALUE_FORMAT format, void *prefix_data, const struct lyxp_var *vars, ly_bool *result)
3369
0
{
3370
0
    return lyd_eval_xpath4(ctx_node, ctx_node, cur_mod, xpath, format, prefix_data, vars, NULL, NULL, NULL, NULL, result);
3371
0
}
3372
3373
LIBYANG_API_DEF LY_ERR
3374
lyd_eval_xpath4(const struct lyd_node *ctx_node, const struct lyd_node *tree, const struct lys_module *cur_mod,
3375
        const char *xpath, LY_VALUE_FORMAT format, void *prefix_data, const struct lyxp_var *vars, LY_XPATH_TYPE *ret_type,
3376
        struct ly_set **node_set, char **string, long double *number, ly_bool *boolean)
3377
0
{
3378
0
    LY_ERR ret = LY_SUCCESS;
3379
0
    struct lyxp_set xp_set = {0};
3380
0
    struct lyxp_expr *exp = NULL;
3381
0
    uint32_t i;
3382
3383
0
    LY_CHECK_ARG_RET(NULL, tree, xpath, ((ret_type && node_set && string && number && boolean) ||
3384
0
            (node_set && !string && !number && !boolean) || (!node_set && string && !number && !boolean) ||
3385
0
            (!node_set && !string && number && !boolean) || (!node_set && !string && !number && boolean)), LY_EINVAL);
3386
3387
    /* parse expression */
3388
0
    ret = lyxp_expr_parse((struct ly_ctx *)LYD_CTX(tree), xpath, 0, 1, &exp);
3389
0
    LY_CHECK_GOTO(ret, cleanup);
3390
3391
    /* evaluate expression */
3392
0
    ret = lyxp_eval(LYD_CTX(tree), exp, cur_mod, format, prefix_data, ctx_node, ctx_node, tree, vars, &xp_set,
3393
0
            LYXP_IGNORE_WHEN);
3394
0
    LY_CHECK_GOTO(ret, cleanup);
3395
3396
    /* return expected result type without or with casting */
3397
0
    if (node_set) {
3398
        /* node set */
3399
0
        if (xp_set.type == LYXP_SET_NODE_SET) {
3400
            /* transform into a set */
3401
0
            LY_CHECK_GOTO(ret = ly_set_new(node_set), cleanup);
3402
0
            (*node_set)->objs = malloc(xp_set.used * sizeof *(*node_set)->objs);
3403
0
            LY_CHECK_ERR_GOTO(!(*node_set)->objs, LOGMEM(LYD_CTX(tree)); ret = LY_EMEM, cleanup);
3404
0
            (*node_set)->size = xp_set.used;
3405
0
            for (i = 0; i < xp_set.used; ++i) {
3406
0
                if (xp_set.val.nodes[i].type == LYXP_NODE_ELEM) {
3407
0
                    ret = ly_set_add(*node_set, xp_set.val.nodes[i].node, 1, NULL);
3408
0
                    LY_CHECK_GOTO(ret, cleanup);
3409
0
                }
3410
0
            }
3411
0
            if (ret_type) {
3412
0
                *ret_type = LY_XPATH_NODE_SET;
3413
0
            }
3414
0
        } else if (!string && !number && !boolean) {
3415
0
            LOGERR(LYD_CTX(tree), LY_EINVAL, "XPath \"%s\" result is not a node set.", xpath);
3416
0
            ret = LY_EINVAL;
3417
0
            goto cleanup;
3418
0
        }
3419
0
    }
3420
3421
0
    if (string) {
3422
0
        if ((xp_set.type != LYXP_SET_STRING) && !node_set) {
3423
            /* cast into string */
3424
0
            LY_CHECK_GOTO(ret = lyxp_set_cast(&xp_set, LYXP_SET_STRING), cleanup);
3425
0
        }
3426
0
        if (xp_set.type == LYXP_SET_STRING) {
3427
            /* string */
3428
0
            *string = xp_set.val.str;
3429
0
            xp_set.val.str = NULL;
3430
0
            if (ret_type) {
3431
0
                *ret_type = LY_XPATH_STRING;
3432
0
            }
3433
0
        }
3434
0
    }
3435
3436
0
    if (number) {
3437
0
        if ((xp_set.type != LYXP_SET_NUMBER) && !node_set) {
3438
            /* cast into number */
3439
0
            LY_CHECK_GOTO(ret = lyxp_set_cast(&xp_set, LYXP_SET_NUMBER), cleanup);
3440
0
        }
3441
0
        if (xp_set.type == LYXP_SET_NUMBER) {
3442
            /* number */
3443
0
            *number = xp_set.val.num;
3444
0
            if (ret_type) {
3445
0
                *ret_type = LY_XPATH_NUMBER;
3446
0
            }
3447
0
        }
3448
0
    }
3449
3450
0
    if (boolean) {
3451
0
        if ((xp_set.type != LYXP_SET_BOOLEAN) && !node_set) {
3452
            /* cast into boolean */
3453
0
            LY_CHECK_GOTO(ret = lyxp_set_cast(&xp_set, LYXP_SET_BOOLEAN), cleanup);
3454
0
        }
3455
0
        if (xp_set.type == LYXP_SET_BOOLEAN) {
3456
            /* boolean */
3457
0
            *boolean = xp_set.val.bln;
3458
0
            if (ret_type) {
3459
0
                *ret_type = LY_XPATH_BOOLEAN;
3460
0
            }
3461
0
        }
3462
0
    }
3463
3464
0
cleanup:
3465
0
    lyxp_set_free_content(&xp_set);
3466
0
    lyxp_expr_free((struct ly_ctx *)LYD_CTX(tree), exp);
3467
0
    return ret;
3468
0
}
3469
3470
/**
3471
 * @brief Hash table node equal callback.
3472
 */
3473
static ly_bool
3474
lyd_trim_equal_cb(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *UNUSED(cb_data))
3475
0
{
3476
0
    struct lyd_node *node1, *node2;
3477
3478
0
    node1 = *(struct lyd_node **)val1_p;
3479
0
    node2 = *(struct lyd_node **)val2_p;
3480
3481
0
    return node1 == node2;
3482
0
}
3483
3484
LIBYANG_API_DEF LY_ERR
3485
lyd_trim_xpath(struct lyd_node **tree, const char *xpath, const struct lyxp_var *vars)
3486
0
{
3487
0
    LY_ERR ret = LY_SUCCESS;
3488
0
    struct ly_ctx *ctx = NULL;
3489
0
    struct lyxp_set xp_set = {0};
3490
0
    struct lyxp_expr *exp = NULL;
3491
0
    struct lyd_node *node, *parent;
3492
0
    struct lyxp_set_hash_node hnode;
3493
0
    struct ly_ht *parent_ht = NULL;
3494
0
    struct ly_set free_set = {0};
3495
0
    uint32_t i, hash;
3496
0
    ly_bool is_result;
3497
3498
0
    LY_CHECK_ARG_RET(NULL, tree, xpath, LY_EINVAL);
3499
3500
0
    if (!*tree) {
3501
        /* nothing to do */
3502
0
        goto cleanup;
3503
0
    }
3504
3505
0
    *tree = lyd_first_sibling(*tree);
3506
0
    ctx = (struct ly_ctx *)LYD_CTX(*tree);
3507
3508
    /* parse expression */
3509
0
    ret = lyxp_expr_parse(ctx, xpath, 0, 1, &exp);
3510
0
    LY_CHECK_GOTO(ret, cleanup);
3511
3512
    /* evaluate expression */
3513
0
    ret = lyxp_eval(ctx, exp, NULL, LY_VALUE_JSON, NULL, *tree, *tree, *tree, vars, &xp_set, LYXP_IGNORE_WHEN);
3514
0
    LY_CHECK_GOTO(ret, cleanup);
3515
3516
    /* create hash table for all the parents of results */
3517
0
    parent_ht = lyht_new(32, sizeof node, lyd_trim_equal_cb, NULL, 1);
3518
0
    LY_CHECK_GOTO(!parent_ht, cleanup);
3519
3520
0
    for (i = 0; i < xp_set.used; ++i) {
3521
0
        if (xp_set.val.nodes[i].type != LYXP_NODE_ELEM) {
3522
            /* ignore */
3523
0
            continue;
3524
0
        }
3525
3526
0
        for (parent = lyd_parent(xp_set.val.nodes[i].node); parent; parent = lyd_parent(parent)) {
3527
            /* add the parent into parent_ht */
3528
0
            ret = lyht_insert(parent_ht, &parent, parent->hash, NULL);
3529
0
            if (ret == LY_EEXIST) {
3530
                /* shared parent, we are done */
3531
0
                break;
3532
0
            }
3533
0
            LY_CHECK_GOTO(ret, cleanup);
3534
0
        }
3535
0
    }
3536
3537
0
    hnode.type = LYXP_NODE_ELEM;
3538
0
    LY_LIST_FOR(*tree, parent) {
3539
0
        LYD_TREE_DFS_BEGIN(parent, node) {
3540
0
            if (lysc_is_key(node->schema)) {
3541
                /* ignore */
3542
0
                goto next_iter;
3543
0
            }
3544
3545
            /* check the results */
3546
0
            is_result = 0;
3547
0
            if (xp_set.ht) {
3548
0
                hnode.node = node;
3549
0
                hash = lyht_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node);
3550
0
                hash = lyht_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type);
3551
0
                hash = lyht_hash_multi(hash, NULL, 0);
3552
3553
0
                if (!lyht_find(xp_set.ht, &hnode, hash, NULL)) {
3554
0
                    is_result = 1;
3555
0
                }
3556
0
            } else {
3557
                /* not enough elements for a hash table */
3558
0
                for (i = 0; i < xp_set.used; ++i) {
3559
0
                    if (xp_set.val.nodes[i].type != LYXP_NODE_ELEM) {
3560
                        /* ignore */
3561
0
                        continue;
3562
0
                    }
3563
3564
0
                    if (xp_set.val.nodes[i].node == node) {
3565
0
                        is_result = 1;
3566
0
                        break;
3567
0
                    }
3568
0
                }
3569
0
            }
3570
3571
0
            if (is_result) {
3572
                /* keep the whole subtree if the node is in the results */
3573
0
                LYD_TREE_DFS_continue = 1;
3574
0
            } else if (lyht_find(parent_ht, &node, node->hash, NULL)) {
3575
                /* free the whole subtree if the node is not even among the selected parents */
3576
0
                ret = ly_set_add(&free_set, node, 1, NULL);
3577
0
                LY_CHECK_GOTO(ret, cleanup);
3578
0
                LYD_TREE_DFS_continue = 1;
3579
0
            } /* else keep the parent node because a subtree is in the results */
3580
3581
0
next_iter:
3582
0
            LYD_TREE_DFS_END(parent, node);
3583
0
        }
3584
0
    }
3585
3586
    /* free */
3587
0
    for (i = 0; i < free_set.count; ++i) {
3588
0
        node = free_set.dnodes[i];
3589
0
        if (*tree == node) {
3590
0
            *tree = (*tree)->next;
3591
0
        }
3592
0
        lyd_free_tree(node);
3593
0
    }
3594
3595
0
cleanup:
3596
0
    lyxp_set_free_content(&xp_set);
3597
0
    lyxp_expr_free(ctx, exp);
3598
0
    lyht_free(parent_ht, NULL);
3599
0
    ly_set_erase(&free_set, NULL);
3600
0
    return ret;
3601
0
}
3602
3603
LIBYANG_API_DEF LY_ERR
3604
lyd_find_path(const struct lyd_node *ctx_node, const char *path, ly_bool output, struct lyd_node **match)
3605
0
{
3606
0
    LY_ERR ret = LY_SUCCESS;
3607
0
    struct lyxp_expr *expr = NULL;
3608
0
    struct ly_path *lypath = NULL;
3609
3610
0
    LY_CHECK_ARG_RET(NULL, ctx_node, ctx_node->schema, path, LY_EINVAL);
3611
3612
    /* parse the path */
3613
0
    ret = ly_path_parse(LYD_CTX(ctx_node), ctx_node->schema, path, strlen(path), 0, LY_PATH_BEGIN_EITHER,
3614
0
            LY_PATH_PREFIX_FIRST, LY_PATH_PRED_SIMPLE, &expr);
3615
0
    LY_CHECK_GOTO(ret, cleanup);
3616
3617
    /* compile the path */
3618
0
    ret = ly_path_compile(LYD_CTX(ctx_node), NULL, ctx_node->schema, NULL, expr,
3619
0
            output ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_SINGLE, 0, LY_VALUE_JSON, NULL, &lypath);
3620
0
    LY_CHECK_GOTO(ret, cleanup);
3621
3622
    /* evaluate the path */
3623
0
    ret = ly_path_eval_partial(lypath, ctx_node, NULL, 0, NULL, match);
3624
3625
0
cleanup:
3626
0
    lyxp_expr_free(LYD_CTX(ctx_node), expr);
3627
0
    ly_path_free(LYD_CTX(ctx_node), lypath);
3628
0
    return ret;
3629
0
}
3630
3631
LIBYANG_API_DEF LY_ERR
3632
lyd_find_target(const struct ly_path *path, const struct lyd_node *tree, struct lyd_node **match)
3633
0
{
3634
0
    LY_ERR ret;
3635
0
    struct lyd_node *m;
3636
3637
0
    LY_CHECK_ARG_RET(NULL, path, LY_EINVAL);
3638
3639
0
    ret = ly_path_eval(path, tree, NULL, &m);
3640
0
    if (ret) {
3641
0
        if (match) {
3642
0
            *match = NULL;
3643
0
        }
3644
0
        return LY_ENOTFOUND;
3645
0
    }
3646
3647
0
    if (match) {
3648
0
        *match = m;
3649
0
    }
3650
0
    return LY_SUCCESS;
3651
0
}
3652
3653
LY_ERR
3654
lyd_get_or_create_leafref_links_record(const struct lyd_node_term *node, struct lyd_leafref_links_rec **record, ly_bool create)
3655
401k
{
3656
401k
    struct ly_ht *ht;
3657
401k
    uint32_t hash;
3658
401k
    struct lyd_leafref_links_rec rec = {0};
3659
3660
401k
    assert(node);
3661
401k
    assert(record);
3662
3663
401k
    *record = NULL;
3664
3665
401k
    if (!(ly_ctx_get_options(LYD_CTX(node)) & LY_CTX_LEAFREF_LINKING)) {
3666
401k
        return LY_EDENIED;
3667
401k
    }
3668
3669
0
    rec.node = node;
3670
0
    ht = LYD_CTX(node)->leafref_links_ht;
3671
0
    hash = lyht_hash((const char *)&node, sizeof node);
3672
3673
0
    if (lyht_find(ht, &rec, hash, (void **)record) == LY_ENOTFOUND) {
3674
0
        if (create) {
3675
0
            LY_CHECK_RET(lyht_insert_no_check(ht, &rec, hash, (void **)record));
3676
0
        } else {
3677
0
            return LY_ENOTFOUND;
3678
0
        }
3679
0
    }
3680
3681
0
    return LY_SUCCESS;
3682
0
}
3683
3684
LIBYANG_API_DEF LY_ERR
3685
lyd_leafref_get_links(const struct lyd_node_term *node, const struct lyd_leafref_links_rec **record)
3686
0
{
3687
0
    LY_CHECK_ARG_RET(NULL, node, record, LY_EINVAL);
3688
3689
0
    return lyd_get_or_create_leafref_links_record(node, (struct lyd_leafref_links_rec **)record, 0);
3690
0
}
3691
3692
LY_ERR
3693
lyd_link_leafref_node(const struct lyd_node_term *node, const struct lyd_node_term *leafref_node)
3694
0
{
3695
0
    const struct lyd_node_term **item = NULL;
3696
0
    struct lyd_leafref_links_rec *rec;
3697
0
    LY_ARRAY_COUNT_TYPE u;
3698
3699
0
    assert(node);
3700
0
    assert(leafref_node);
3701
3702
0
    if (!(ly_ctx_get_options(LYD_CTX(node)) & LY_CTX_LEAFREF_LINKING)) {
3703
0
        return LY_EDENIED;
3704
0
    }
3705
3706
    /* add leafref node into the list of target node */
3707
0
    LY_CHECK_RET(lyd_get_or_create_leafref_links_record(node, &rec, 1));
3708
0
    LY_ARRAY_FOR(rec->leafref_nodes, u) {
3709
0
        if (rec->leafref_nodes[u] == leafref_node) {
3710
0
            return LY_SUCCESS;
3711
0
        }
3712
0
    }
3713
3714
0
    LY_ARRAY_NEW_RET(LYD_CTX(node), rec->leafref_nodes, item, LY_EMEM);
3715
0
    *item = leafref_node;
3716
3717
    /* add target node into the list of leafref node*/
3718
0
    LY_CHECK_RET(lyd_get_or_create_leafref_links_record(leafref_node, &rec, 1));
3719
0
    LY_ARRAY_FOR(rec->target_nodes, u) {
3720
0
        if (rec->target_nodes[u] == node) {
3721
0
            return LY_SUCCESS;
3722
0
        }
3723
0
    }
3724
3725
0
    LY_ARRAY_NEW_RET(LYD_CTX(node), rec->target_nodes, item, LY_EMEM);
3726
0
    *item = node;
3727
3728
0
    return LY_SUCCESS;
3729
0
}
3730
3731
LIBYANG_API_DEF LY_ERR
3732
lyd_leafref_link_node_tree(const struct lyd_node *tree)
3733
0
{
3734
0
    const struct lyd_node *sibling, *elem;
3735
0
    struct ly_set *targets = NULL;
3736
0
    char *errmsg;
3737
0
    struct lyd_node_term *leafref_node;
3738
0
    struct lysc_node_leaf *leaf_schema;
3739
0
    struct lysc_type_leafref *lref;
3740
0
    LY_ERR ret = LY_SUCCESS;
3741
0
    uint32_t i;
3742
3743
0
    LY_CHECK_ARG_RET(NULL, tree, LY_EINVAL);
3744
3745
0
    if (!(ly_ctx_get_options(LYD_CTX(tree)) & LY_CTX_LEAFREF_LINKING)) {
3746
0
        return LY_EDENIED;
3747
0
    }
3748
3749
0
    LY_LIST_FOR(tree, sibling) {
3750
0
        LYD_TREE_DFS_BEGIN(sibling, elem) {
3751
0
            if (elem->schema && (elem->schema->nodetype & LYD_NODE_TERM)) {
3752
0
                leafref_node = (struct lyd_node_term *)elem;
3753
0
                leaf_schema = (struct lysc_node_leaf *)elem->schema;
3754
3755
0
                if (leaf_schema->type->basetype == LY_TYPE_LEAFREF) {
3756
0
                    lref = (struct lysc_type_leafref *)leaf_schema->type;
3757
0
                    ly_set_free(targets, NULL);
3758
0
                    if (lyplg_type_resolve_leafref(lref, elem, &leafref_node->value, tree, &targets, &errmsg)) {
3759
                        /* leafref target not found */
3760
0
                        free(errmsg);
3761
0
                    } else {
3762
                        /* leafref target found, link it */
3763
0
                        for (i = 0; i < targets->count; ++i) {
3764
0
                            if (targets->dnodes[i]->schema->nodetype & LYD_NODE_TERM) {
3765
0
                                ret = lyd_link_leafref_node((struct lyd_node_term *)targets->dnodes[i], leafref_node);
3766
0
                                LY_CHECK_GOTO(ret, cleanup);
3767
0
                            }
3768
0
                        }
3769
0
                    }
3770
0
                }
3771
0
            }
3772
0
            LYD_TREE_DFS_END(sibling, elem);
3773
0
        }
3774
0
    }
3775
3776
0
cleanup:
3777
0
    ly_set_free(targets, NULL);
3778
0
    return ret;
3779
0
}
3780
3781
LY_ERR
3782
lyd_unlink_leafref_node(const struct lyd_node_term *node, const struct lyd_node_term *leafref_node)
3783
0
{
3784
0
    LY_ERR ret;
3785
0
    struct lyd_leafref_links_rec *rec;
3786
3787
0
    assert(node);
3788
0
    assert(leafref_node);
3789
3790
0
    if (!(ly_ctx_get_options(LYD_CTX(node)) & LY_CTX_LEAFREF_LINKING)) {
3791
0
        return LY_EDENIED;
3792
0
    }
3793
3794
    /* remove link from target node to leafref node */
3795
0
    ret = lyd_get_or_create_leafref_links_record(node, &rec, 0);
3796
0
    if (ret == LY_SUCCESS) {
3797
0
        LY_ARRAY_REMOVE_VALUE(rec->leafref_nodes, leafref_node);
3798
0
        if ((LY_ARRAY_COUNT(rec->leafref_nodes) == 0) && (LY_ARRAY_COUNT(rec->target_nodes) == 0)) {
3799
0
            lyd_free_leafref_nodes(node);
3800
0
        }
3801
0
    } else if (ret != LY_ENOTFOUND) {
3802
0
        return ret;
3803
0
    }
3804
3805
    /* remove link from leafref node to target node */
3806
0
    ret = lyd_get_or_create_leafref_links_record(leafref_node, &rec, 0);
3807
0
    if (ret == LY_SUCCESS) {
3808
0
        LY_ARRAY_REMOVE_VALUE(rec->target_nodes, node);
3809
0
        if ((LY_ARRAY_COUNT(rec->leafref_nodes) == 0) && (LY_ARRAY_COUNT(rec->target_nodes) == 0)) {
3810
0
            lyd_free_leafref_nodes(leafref_node);
3811
0
        }
3812
0
    } else if (ret != LY_ENOTFOUND) {
3813
0
        return ret;
3814
0
    }
3815
3816
0
    return LY_SUCCESS;
3817
0
}