Coverage Report

Created: 2023-11-19 07:06

/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 "common.h"
30
#include "compat.h"
31
#include "context.h"
32
#include "dict.h"
33
#include "diff.h"
34
#include "hash_table.h"
35
#include "in.h"
36
#include "in_internal.h"
37
#include "log.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_edit.h"
49
#include "tree_schema.h"
50
#include "tree_schema_internal.h"
51
#include "validation.h"
52
#include "xml.h"
53
#include "xpath.h"
54
55
static LY_ERR lyd_compare_siblings_(const struct lyd_node *node1, const struct lyd_node *node2, uint32_t options,
56
        ly_bool parental_schemas_checked);
57
58
static LYD_FORMAT
59
lyd_parse_get_format(const struct ly_in *in, LYD_FORMAT format)
60
7.27k
{
61
7.27k
    if (!format && (in->type == LY_IN_FILEPATH)) {
62
        /* unknown format - try to detect it from filename's suffix */
63
0
        const char *path = in->method.fpath.filepath;
64
0
        size_t len = strlen(path);
65
66
        /* ignore trailing whitespaces */
67
0
        for ( ; len > 0 && isspace(path[len - 1]); len--) {}
68
69
0
        if ((len >= LY_XML_SUFFIX_LEN + 1) &&
70
0
                !strncmp(&path[len - LY_XML_SUFFIX_LEN], LY_XML_SUFFIX, LY_XML_SUFFIX_LEN)) {
71
0
            format = LYD_XML;
72
0
        } else if ((len >= LY_JSON_SUFFIX_LEN + 1) &&
73
0
                !strncmp(&path[len - LY_JSON_SUFFIX_LEN], LY_JSON_SUFFIX, LY_JSON_SUFFIX_LEN)) {
74
0
            format = LYD_JSON;
75
0
        } else if ((len >= LY_LYB_SUFFIX_LEN + 1) &&
76
0
                !strncmp(&path[len - LY_LYB_SUFFIX_LEN], LY_LYB_SUFFIX, LY_LYB_SUFFIX_LEN)) {
77
0
            format = LYD_LYB;
78
0
        } /* else still unknown */
79
0
    }
80
81
7.27k
    return format;
82
7.27k
}
83
84
/**
85
 * @brief Parse YANG data into a data tree.
86
 *
87
 * @param[in] ctx libyang context.
88
 * @param[in] ext Optional extenion instance to parse data following the schema tree specified in the extension instance
89
 * @param[in] parent Parent to connect the parsed nodes to, if any.
90
 * @param[in,out] first_p Pointer to the first top-level parsed node, used only if @p parent is NULL.
91
 * @param[in] in Input handle to read the input from.
92
 * @param[in] format Expected format of the data in @p in.
93
 * @param[in] parse_opts Options for parser.
94
 * @param[in] val_opts Options for validation.
95
 * @param[out] op Optional pointer to the parsed operation, if any.
96
 * @return LY_ERR value.
97
 */
98
static LY_ERR
99
lyd_parse(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent, struct lyd_node **first_p,
100
        struct ly_in *in, LYD_FORMAT format, uint32_t parse_opts, uint32_t val_opts, struct lyd_node **op)
101
7.27k
{
102
7.27k
    LY_ERR r = LY_SUCCESS, rc = LY_SUCCESS;
103
7.27k
    struct lyd_ctx *lydctx = NULL;
104
7.27k
    struct ly_set parsed = {0};
105
7.27k
    uint32_t i, int_opts = 0;
106
7.27k
    ly_bool subtree_sibling = 0;
107
108
7.27k
    assert(ctx && (parent || first_p));
109
110
0
    format = lyd_parse_get_format(in, format);
111
7.27k
    if (first_p) {
112
7.27k
        *first_p = NULL;
113
7.27k
    }
114
115
    /* remember input position */
116
7.27k
    in->func_start = in->current;
117
118
    /* set internal options */
119
7.27k
    if (!(parse_opts & LYD_PARSE_SUBTREE)) {
120
7.27k
        int_opts = LYD_INTOPT_WITH_SIBLINGS;
121
7.27k
    }
122
123
    /* parse the data */
124
7.27k
    switch (format) {
125
7.21k
    case LYD_XML:
126
7.21k
        r = lyd_parse_xml(ctx, ext, parent, first_p, in, parse_opts, val_opts, int_opts, &parsed,
127
7.21k
                &subtree_sibling, &lydctx);
128
7.21k
        break;
129
55
    case LYD_JSON:
130
55
        r = lyd_parse_json(ctx, ext, parent, first_p, in, parse_opts, val_opts, int_opts, &parsed,
131
55
                &subtree_sibling, &lydctx);
132
55
        break;
133
0
    case LYD_LYB:
134
0
        r = lyd_parse_lyb(ctx, ext, parent, first_p, in, parse_opts, val_opts, int_opts, &parsed,
135
0
                &subtree_sibling, &lydctx);
136
0
        break;
137
0
    case LYD_UNKNOWN:
138
0
        LOGARG(ctx, format);
139
0
        r = LY_EINVAL;
140
0
        break;
141
7.27k
    }
142
7.27k
    if (r) {
143
6.92k
        rc = r;
144
6.92k
        if ((r != LY_EVALID) || !lydctx || !(lydctx->val_opts & LYD_VALIDATE_MULTI_ERROR) ||
145
6.92k
                (ly_vecode(ctx) == LYVE_SYNTAX)) {
146
6.92k
            goto cleanup;
147
6.92k
        }
148
6.92k
    }
149
150
350
    if (parent && parsed.count) {
151
        /* use the first parsed node */
152
0
        first_p = &parsed.dnodes[0];
153
0
    }
154
155
350
    if (!(parse_opts & LYD_PARSE_ONLY)) {
156
        /* validate data */
157
350
        r = lyd_validate(first_p, NULL, ctx, val_opts, 0, &lydctx->node_when, &lydctx->node_types, &lydctx->meta_types,
158
350
                &lydctx->ext_node, &lydctx->ext_val, NULL);
159
350
        LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
160
129
    }
161
162
    /* set the operation node */
163
129
    if (op) {
164
0
        *op = lydctx->op_node;
165
0
    }
166
167
7.27k
cleanup:
168
7.27k
    if (lydctx) {
169
350
        lydctx->free(lydctx);
170
350
    }
171
7.27k
    if (rc) {
172
7.14k
        if (parent) {
173
            /* free all the parsed subtrees */
174
0
            for (i = 0; i < parsed.count; ++i) {
175
0
                lyd_free_tree(parsed.dnodes[i]);
176
0
            }
177
7.14k
        } else {
178
            /* free everything */
179
7.14k
            lyd_free_all(*first_p);
180
7.14k
            *first_p = NULL;
181
7.14k
        }
182
7.14k
    } else if (subtree_sibling) {
183
0
        rc = LY_ENOT;
184
0
    }
185
7.27k
    ly_set_erase(&parsed, NULL);
186
7.27k
    return rc;
187
129
}
188
189
LIBYANG_API_DEF LY_ERR
190
lyd_parse_ext_data(const struct lysc_ext_instance *ext, struct lyd_node *parent, struct ly_in *in, LYD_FORMAT format,
191
        uint32_t parse_options, uint32_t validate_options, struct lyd_node **tree)
192
0
{
193
0
    const struct ly_ctx *ctx = ext ? ext->module->ctx : NULL;
194
195
0
    LY_CHECK_ARG_RET(ctx, ext, in, parent || tree, LY_EINVAL);
196
0
    LY_CHECK_ARG_RET(ctx, !(parse_options & ~LYD_PARSE_OPTS_MASK), LY_EINVAL);
197
0
    LY_CHECK_ARG_RET(ctx, !(validate_options & ~LYD_VALIDATE_OPTS_MASK), LY_EINVAL);
198
199
0
    return lyd_parse(ctx, ext, parent, tree, in, format, parse_options, validate_options, NULL);
200
0
}
201
202
LIBYANG_API_DEF LY_ERR
203
lyd_parse_data(const struct ly_ctx *ctx, struct lyd_node *parent, struct ly_in *in, LYD_FORMAT format,
204
        uint32_t parse_options, uint32_t validate_options, struct lyd_node **tree)
205
7.27k
{
206
14.5k
    LY_CHECK_ARG_RET(ctx, ctx, in, parent || tree, LY_EINVAL);
207
7.27k
    LY_CHECK_ARG_RET(ctx, !(parse_options & ~LYD_PARSE_OPTS_MASK), LY_EINVAL);
208
7.27k
    LY_CHECK_ARG_RET(ctx, !(validate_options & ~LYD_VALIDATE_OPTS_MASK), LY_EINVAL);
209
210
7.27k
    return lyd_parse(ctx, NULL, parent, tree, in, format, parse_options, validate_options, NULL);
211
7.27k
}
212
213
LIBYANG_API_DEF LY_ERR
214
lyd_parse_data_mem(const struct ly_ctx *ctx, const char *data, LYD_FORMAT format, uint32_t parse_options,
215
        uint32_t validate_options, struct lyd_node **tree)
216
7.27k
{
217
7.27k
    LY_ERR ret;
218
7.27k
    struct ly_in *in;
219
220
7.27k
    LY_CHECK_RET(ly_in_new_memory(data, &in));
221
7.27k
    ret = lyd_parse_data(ctx, NULL, in, format, parse_options, validate_options, tree);
222
223
7.27k
    ly_in_free(in, 0);
224
7.27k
    return ret;
225
7.27k
}
226
227
LIBYANG_API_DEF LY_ERR
228
lyd_parse_data_fd(const struct ly_ctx *ctx, int fd, LYD_FORMAT format, uint32_t parse_options, uint32_t validate_options,
229
        struct lyd_node **tree)
230
0
{
231
0
    LY_ERR ret;
232
0
    struct ly_in *in;
233
234
0
    LY_CHECK_RET(ly_in_new_fd(fd, &in));
235
0
    ret = lyd_parse_data(ctx, NULL, in, format, parse_options, validate_options, tree);
236
237
0
    ly_in_free(in, 0);
238
0
    return ret;
239
0
}
240
241
LIBYANG_API_DEF LY_ERR
242
lyd_parse_data_path(const struct ly_ctx *ctx, const char *path, LYD_FORMAT format, uint32_t parse_options,
243
        uint32_t validate_options, struct lyd_node **tree)
244
0
{
245
0
    LY_ERR ret;
246
0
    struct ly_in *in;
247
248
0
    LY_CHECK_RET(ly_in_new_filepath(path, 0, &in));
249
0
    ret = lyd_parse_data(ctx, NULL, in, format, parse_options, validate_options, tree);
250
251
0
    ly_in_free(in, 0);
252
0
    return ret;
253
0
}
254
255
/**
256
 * @brief Parse YANG data into an operation data tree, in case the extension instance is specified, keep the searching
257
 * for schema nodes locked inside the extension instance.
258
 *
259
 * At least one of @p parent, @p tree, or @p op must always be set.
260
 *
261
 * Specific @p data_type values have different parameter meaning as mentioned for ::lyd_parse_op().
262
 *
263
 * @param[in] ctx libyang context.
264
 * @param[in] ext Extension instance providing the specific schema tree to match with the data being parsed.
265
 * @param[in] parent Optional parent to connect the parsed nodes to.
266
 * @param[in] in Input handle to read the input from.
267
 * @param[in] format Expected format of the data in @p in.
268
 * @param[in] data_type Expected operation to parse (@ref datatype).
269
 * @param[out] tree Optional full parsed data tree. If @p parent is set, set to NULL.
270
 * @param[out] op Optional parsed operation node.
271
 * @return LY_ERR value.
272
 * @return LY_ENOT if @p data_type is a NETCONF message and the root XML element is not the expected one.
273
 */
274
static LY_ERR
275
lyd_parse_op_(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
276
        struct ly_in *in, LYD_FORMAT format, enum lyd_type data_type, struct lyd_node **tree, struct lyd_node **op)
277
0
{
278
0
    LY_ERR rc = LY_SUCCESS;
279
0
    struct lyd_ctx *lydctx = NULL;
280
0
    struct ly_set parsed = {0};
281
0
    struct lyd_node *first = NULL, *envp = NULL;
282
0
    uint32_t i, parse_opts, val_opts, int_opts = 0;
283
0
    ly_bool proto_msg = 0;
284
285
0
    if (!ctx) {
286
0
        ctx = LYD_CTX(parent);
287
0
    }
288
0
    if (tree) {
289
0
        *tree = NULL;
290
0
    }
291
0
    if (op) {
292
0
        *op = NULL;
293
0
    }
294
295
0
    format = lyd_parse_get_format(in, format);
296
297
    /* remember input position */
298
0
    in->func_start = in->current;
299
300
    /* set parse and validation opts */
301
0
    parse_opts = LYD_PARSE_ONLY | LYD_PARSE_STRICT;
302
0
    val_opts = 0;
303
304
0
    switch (data_type) {
305
0
    case LYD_TYPE_RPC_NETCONF:
306
0
    case LYD_TYPE_NOTIF_NETCONF:
307
0
        LY_CHECK_ARG_RET(ctx, format == LYD_XML, !parent, tree, op, LY_EINVAL);
308
0
        proto_msg = 1;
309
0
        break;
310
0
    case LYD_TYPE_REPLY_NETCONF:
311
0
        LY_CHECK_ARG_RET(ctx, format == LYD_XML, parent, parent->schema, parent->schema->nodetype & (LYS_RPC | LYS_ACTION),
312
0
                tree, !op, LY_EINVAL);
313
0
        proto_msg = 1;
314
0
        break;
315
0
    case LYD_TYPE_RPC_RESTCONF:
316
0
    case LYD_TYPE_REPLY_RESTCONF:
317
0
        LY_CHECK_ARG_RET(ctx, parent, parent->schema, parent->schema->nodetype & (LYS_RPC | LYS_ACTION), tree, !op, LY_EINVAL);
318
0
        proto_msg = 1;
319
0
        break;
320
0
    case LYD_TYPE_NOTIF_RESTCONF:
321
0
        LY_CHECK_ARG_RET(ctx, format == LYD_JSON, !parent, tree, op, LY_EINVAL);
322
0
        proto_msg = 1;
323
0
        break;
324
325
    /* set internal opts */
326
0
    case LYD_TYPE_RPC_YANG:
327
0
        int_opts = LYD_INTOPT_RPC | LYD_INTOPT_ACTION | (parent ? LYD_INTOPT_WITH_SIBLINGS : LYD_INTOPT_NO_SIBLINGS);
328
0
        break;
329
0
    case LYD_TYPE_NOTIF_YANG:
330
0
        int_opts = LYD_INTOPT_NOTIF | (parent ? LYD_INTOPT_WITH_SIBLINGS : LYD_INTOPT_NO_SIBLINGS);
331
0
        break;
332
0
    case LYD_TYPE_REPLY_YANG:
333
0
        int_opts = LYD_INTOPT_REPLY | (parent ? LYD_INTOPT_WITH_SIBLINGS : LYD_INTOPT_NO_SIBLINGS);
334
0
        break;
335
0
    case LYD_TYPE_DATA_YANG:
336
0
        LOGINT(ctx);
337
0
        rc = LY_EINT;
338
0
        goto cleanup;
339
0
    }
340
341
    /* parse a full protocol message */
342
0
    if (proto_msg) {
343
0
        if (format == LYD_XML) {
344
            /* parse the NETCONF (or RESTCONF XML) message */
345
0
            rc = lyd_parse_xml_netconf(ctx, ext, parent, &first, in, parse_opts, val_opts, data_type, &envp, &parsed, &lydctx);
346
0
        } else {
347
            /* parse the RESTCONF message */
348
0
            rc = lyd_parse_json_restconf(ctx, ext, parent, &first, in, parse_opts, val_opts, data_type, &envp, &parsed, &lydctx);
349
0
        }
350
0
        if (rc) {
351
0
            if (envp) {
352
                /* special situation when the envelopes were parsed successfully */
353
0
                *tree = envp;
354
0
            }
355
0
            goto cleanup;
356
0
        }
357
358
        /* set out params correctly */
359
0
        if (envp) {
360
            /* special out param meaning */
361
0
            *tree = envp;
362
0
        } else {
363
0
            *tree = parent ? NULL : first;
364
0
        }
365
0
        if (op) {
366
0
            *op = lydctx->op_node;
367
0
        }
368
0
        goto cleanup;
369
0
    }
370
371
    /* parse the data */
372
0
    switch (format) {
373
0
    case LYD_XML:
374
0
        rc = lyd_parse_xml(ctx, ext, parent, &first, in, parse_opts, val_opts, int_opts, &parsed, NULL, &lydctx);
375
0
        break;
376
0
    case LYD_JSON:
377
0
        rc = lyd_parse_json(ctx, ext, parent, &first, in, parse_opts, val_opts, int_opts, &parsed, NULL, &lydctx);
378
0
        break;
379
0
    case LYD_LYB:
380
0
        rc = lyd_parse_lyb(ctx, ext, parent, &first, in, parse_opts, val_opts, int_opts, &parsed, NULL, &lydctx);
381
0
        break;
382
0
    case LYD_UNKNOWN:
383
0
        LOGARG(ctx, format);
384
0
        rc = LY_EINVAL;
385
0
        break;
386
0
    }
387
0
    LY_CHECK_GOTO(rc, cleanup);
388
389
    /* set out params correctly */
390
0
    if (tree) {
391
0
        *tree = parent ? NULL : first;
392
0
    }
393
0
    if (op) {
394
0
        *op = lydctx->op_node;
395
0
    }
396
397
0
cleanup:
398
0
    if (lydctx) {
399
0
        lydctx->free(lydctx);
400
0
    }
401
0
    if (rc) {
402
        /* free all the parsed nodes */
403
0
        if (parsed.count) {
404
0
            i = parsed.count;
405
0
            do {
406
0
                --i;
407
0
                lyd_free_tree(parsed.dnodes[i]);
408
0
            } while (i);
409
0
        }
410
0
        if (tree && !envp) {
411
0
            *tree = NULL;
412
0
        }
413
0
        if (op) {
414
0
            *op = NULL;
415
0
        }
416
0
    }
417
0
    ly_set_erase(&parsed, NULL);
418
0
    return rc;
419
0
}
420
421
LIBYANG_API_DEF LY_ERR
422
lyd_parse_op(const struct ly_ctx *ctx, struct lyd_node *parent, struct ly_in *in, LYD_FORMAT format,
423
        enum lyd_type data_type, struct lyd_node **tree, struct lyd_node **op)
424
0
{
425
0
    LY_CHECK_ARG_RET(ctx, ctx || parent, in, data_type, parent || tree || op, LY_EINVAL);
426
427
0
    return lyd_parse_op_(ctx, NULL, parent, in, format, data_type, tree, op);
428
0
}
429
430
LIBYANG_API_DEF LY_ERR
431
lyd_parse_ext_op(const struct lysc_ext_instance *ext, struct lyd_node *parent, struct ly_in *in, LYD_FORMAT format,
432
        enum lyd_type data_type, struct lyd_node **tree, struct lyd_node **op)
433
0
{
434
0
    const struct ly_ctx *ctx = ext ? ext->module->ctx : NULL;
435
436
0
    LY_CHECK_ARG_RET(ctx, ext, in, data_type, parent || tree || op, LY_EINVAL);
437
438
0
    return lyd_parse_op_(ctx, ext, parent, in, format, data_type, tree, op);
439
0
}
440
441
struct lyd_node *
442
lyd_insert_get_next_anchor(const struct lyd_node *first_sibling, const struct lyd_node *new_node)
443
404k
{
444
404k
    const struct lysc_node *schema, *sparent;
445
404k
    struct lyd_node *match = NULL;
446
404k
    ly_bool found;
447
404k
    uint32_t getnext_opts;
448
449
404k
    assert(new_node);
450
451
404k
    if (!first_sibling || !new_node->schema || (LYD_CTX(first_sibling) != LYD_CTX(new_node))) {
452
        /* insert at the end, no next anchor */
453
11.8k
        return NULL;
454
11.8k
    }
455
456
392k
    getnext_opts = 0;
457
392k
    if (new_node->schema->flags & LYS_IS_OUTPUT) {
458
0
        getnext_opts = LYS_GETNEXT_OUTPUT;
459
0
    }
460
461
392k
    if (first_sibling->parent && first_sibling->parent->schema && first_sibling->parent->children_ht) {
462
        /* find the anchor using hashes */
463
338k
        sparent = first_sibling->parent->schema;
464
338k
        schema = lys_getnext(new_node->schema, sparent, NULL, getnext_opts);
465
651k
        while (schema) {
466
            /* keep trying to find the first existing instance of the closest following schema sibling,
467
             * otherwise return NULL - inserting at the end */
468
444k
            if (!lyd_find_sibling_schema(first_sibling, schema, &match)) {
469
130k
                break;
470
130k
            }
471
472
313k
            schema = lys_getnext(schema, sparent, NULL, getnext_opts);
473
313k
        }
474
338k
    } else {
475
        /* find the anchor without hashes */
476
54.1k
        match = (struct lyd_node *)first_sibling;
477
54.1k
        sparent = lysc_data_parent(new_node->schema);
478
54.1k
        if (!sparent) {
479
            /* we are in top-level, skip all the data from preceding modules */
480
19.5k
            LY_LIST_FOR(match, match) {
481
19.5k
                if (!match->schema || (strcmp(lyd_owner_module(match)->name, lyd_owner_module(new_node)->name) >= 0)) {
482
19.5k
                    break;
483
19.5k
                }
484
19.5k
            }
485
19.5k
        }
486
487
        /* get the first schema sibling */
488
54.1k
        schema = lys_getnext(NULL, sparent, new_node->schema->module->compiled, getnext_opts);
489
54.1k
        if (!schema) {
490
            /* must be a top-level extension instance data, no anchor */
491
0
            return NULL;
492
0
        }
493
494
54.1k
        found = 0;
495
12.6M
        LY_LIST_FOR(match, match) {
496
12.6M
            if (!match->schema || (lyd_owner_module(match) != lyd_owner_module(new_node))) {
497
                /* we have found an opaque node, which must be at the end, so use it OR
498
                 * modules do not match, so we must have traversed all the data from new_node module (if any),
499
                 * we have found the first node of the next module, that is what we want */
500
0
                break;
501
0
            }
502
503
            /* skip schema nodes until we find the instantiated one */
504
12.8M
            while (!found) {
505
326k
                if (new_node->schema == schema) {
506
                    /* we have found the schema of the new node, continue search to find the first
507
                     * data node with a different schema (after our schema) */
508
52.9k
                    found = 1;
509
52.9k
                    break;
510
52.9k
                }
511
273k
                if (match->schema == schema) {
512
                    /* current node (match) is a data node still before the new node, continue search in data */
513
37.8k
                    break;
514
37.8k
                }
515
516
235k
                schema = lys_getnext(schema, sparent, new_node->schema->module->compiled, getnext_opts);
517
235k
                if (!schema) {
518
                    /* must be a top-level extension instance data, no anchor */
519
0
                    return NULL;
520
0
                }
521
235k
            }
522
523
12.6M
            if (found && (match->schema != new_node->schema)) {
524
                /* find the next node after we have found our node schema data instance */
525
22.0k
                break;
526
22.0k
            }
527
12.6M
        }
528
54.1k
    }
529
530
392k
    return match;
531
392k
}
532
533
void
534
lyd_insert_after_node(struct lyd_node *sibling, struct lyd_node *node)
535
175k
{
536
175k
    struct lyd_node_inner *par;
537
538
175k
    assert(!node->next && (node->prev == node));
539
540
0
    node->next = sibling->next;
541
175k
    node->prev = sibling;
542
175k
    sibling->next = node;
543
175k
    if (node->next) {
544
        /* sibling had a succeeding node */
545
0
        node->next->prev = node;
546
175k
    } else {
547
        /* sibling was last, find first sibling and change its prev */
548
175k
        if (sibling->parent) {
549
157k
            sibling = sibling->parent->child;
550
157k
        } else {
551
12.4M
            for ( ; sibling->prev->next != node; sibling = sibling->prev) {}
552
17.9k
        }
553
175k
        sibling->prev = node;
554
175k
    }
555
175k
    node->parent = sibling->parent;
556
557
332k
    for (par = node->parent; par; par = par->parent) {
558
157k
        if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
559
            /* remove default flags from NP containers */
560
0
            par->flags &= ~LYD_DEFAULT;
561
0
        }
562
157k
    }
563
175k
}
564
565
void
566
lyd_insert_before_node(struct lyd_node *sibling, struct lyd_node *node)
567
80.1k
{
568
80.1k
    struct lyd_node_inner *par;
569
570
80.1k
    assert(!node->next && (node->prev == node));
571
572
0
    node->next = sibling;
573
    /* covers situation of sibling being first */
574
80.1k
    node->prev = sibling->prev;
575
80.1k
    sibling->prev = node;
576
80.1k
    if (node->prev->next) {
577
        /* sibling had a preceding node */
578
65.2k
        node->prev->next = node;
579
65.2k
    } else if (sibling->parent) {
580
        /* sibling was first and we must also change parent child pointer */
581
14.5k
        sibling->parent->child = node;
582
14.5k
    }
583
80.1k
    node->parent = sibling->parent;
584
585
158k
    for (par = node->parent; par; par = par->parent) {
586
78.5k
        if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
587
            /* remove default flags from NP containers */
588
0
            par->flags &= ~LYD_DEFAULT;
589
0
        }
590
78.5k
    }
591
80.1k
}
592
593
/**
594
 * @brief Insert node as the first and only child of a parent.
595
 *
596
 * Handles inserting into NP containers and key-less lists.
597
 *
598
 * @param[in] parent Parent to insert into.
599
 * @param[in] node Node to insert.
600
 */
601
static void
602
lyd_insert_only_child(struct lyd_node *parent, struct lyd_node *node)
603
9.72k
{
604
9.72k
    struct lyd_node_inner *par;
605
606
9.72k
    assert(parent && !lyd_child(parent) && !node->next && (node->prev == node));
607
0
    assert(!parent->schema || (parent->schema->nodetype & LYD_NODE_INNER));
608
609
0
    par = (struct lyd_node_inner *)parent;
610
611
9.72k
    par->child = node;
612
9.72k
    node->parent = par;
613
614
19.4k
    for ( ; par; par = par->parent) {
615
9.72k
        if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
616
            /* remove default flags from NP containers */
617
18
            par->flags &= ~LYD_DEFAULT;
618
18
        }
619
9.72k
    }
620
9.72k
}
621
622
/**
623
 * @brief Learn whether a list instance has all the keys.
624
 *
625
 * @param[in] list List instance to check.
626
 * @return non-zero if all the keys were found,
627
 * @return 0 otherwise.
628
 */
629
static int
630
lyd_insert_has_keys(const struct lyd_node *list)
631
138k
{
632
138k
    const struct lyd_node *key;
633
138k
    const struct lysc_node *skey = NULL;
634
635
138k
    assert(list->schema->nodetype == LYS_LIST);
636
0
    key = lyd_child(list);
637
277k
    while ((skey = lys_getnext(skey, list->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
638
172k
        if (!key || (key->schema != skey)) {
639
            /* key missing */
640
32.7k
            return 0;
641
32.7k
        }
642
643
139k
        key = key->next;
644
139k
    }
645
646
    /* all keys found */
647
105k
    return 1;
648
138k
}
649
650
void
651
lyd_insert_node(struct lyd_node *parent, struct lyd_node **first_sibling_p, struct lyd_node *node, ly_bool last)
652
265k
{
653
265k
    struct lyd_node *anchor, *first_sibling;
654
655
    /* inserting list without its keys is not supported */
656
265k
    assert((parent || first_sibling_p) && node && (node->hash || !node->schema));
657
0
    assert(!parent || !parent->schema ||
658
265k
            (parent->schema->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_ACTION | LYS_NOTIF)));
659
660
265k
    if (!parent && first_sibling_p && (*first_sibling_p) && (*first_sibling_p)->parent) {
661
0
        parent = lyd_parent(*first_sibling_p);
662
0
    }
663
664
    /* get first sibling */
665
265k
    first_sibling = parent ? lyd_child(parent) : *first_sibling_p;
666
667
265k
    if (last || (first_sibling && (first_sibling->flags & LYD_EXT))) {
668
        /* no next anchor */
669
0
        anchor = NULL;
670
265k
    } else {
671
        /* find the anchor, our next node, so we can insert before it */
672
265k
        anchor = lyd_insert_get_next_anchor(first_sibling, node);
673
674
        /* cannot insert data node after opaque nodes */
675
265k
        if (node->schema && first_sibling && !first_sibling->prev->schema) {
676
0
            anchor = first_sibling->prev;
677
0
            while ((anchor != first_sibling) && !anchor->prev->schema) {
678
0
                anchor = anchor->prev;
679
0
            }
680
0
        }
681
265k
    }
682
683
265k
    if (anchor) {
684
        /* insert before the anchor */
685
80.1k
        lyd_insert_before_node(anchor, node);
686
80.1k
        if (!parent && (*first_sibling_p == anchor)) {
687
            /* move first sibling */
688
378
            *first_sibling_p = node;
689
378
        }
690
185k
    } else if (first_sibling) {
691
        /* insert as the last node */
692
175k
        lyd_insert_after_node(first_sibling->prev, node);
693
175k
    } else if (parent) {
694
        /* insert as the only child */
695
9.72k
        lyd_insert_only_child(parent, node);
696
9.72k
    } else {
697
        /* insert as the only sibling */
698
540
        *first_sibling_p = node;
699
540
    }
700
701
    /* insert into parent HT */
702
265k
    lyd_insert_hash(node);
703
704
    /* finish hashes for our parent, if needed and possible */
705
265k
    if (node->schema && (node->schema->flags & LYS_KEY) && parent && parent->schema && lyd_insert_has_keys(parent)) {
706
105k
        lyd_hash(parent);
707
708
        /* now we can insert even the list into its parent HT */
709
105k
        lyd_insert_hash(parent);
710
105k
    }
711
265k
}
712
713
/**
714
 * @brief Check schema place of a node to be inserted.
715
 *
716
 * @param[in] parent Schema node of the parent data node.
717
 * @param[in] sibling Schema node of a sibling data node.
718
 * @param[in] schema Schema node if the data node to be inserted.
719
 * @return LY_SUCCESS on success.
720
 * @return LY_EINVAL if the place is invalid.
721
 */
722
static LY_ERR
723
lyd_insert_check_schema(const struct lysc_node *parent, const struct lysc_node *sibling, const struct lysc_node *schema)
724
0
{
725
0
    const struct lysc_node *par2;
726
727
0
    assert(!parent || !(parent->nodetype & (LYS_CASE | LYS_CHOICE)));
728
0
    assert(!sibling || !(sibling->nodetype & (LYS_CASE | LYS_CHOICE)));
729
0
    assert(!schema || !(schema->nodetype & (LYS_CASE | LYS_CHOICE)));
730
731
0
    if (!schema || (!parent && !sibling)) {
732
        /* opaque nodes can be inserted wherever */
733
0
        return LY_SUCCESS;
734
0
    }
735
736
0
    if (!parent) {
737
0
        parent = lysc_data_parent(sibling);
738
0
    }
739
740
    /* find schema parent */
741
0
    par2 = lysc_data_parent(schema);
742
743
0
    if (parent) {
744
        /* inner node */
745
0
        if (par2 != parent) {
746
0
            LOGERR(schema->module->ctx, LY_EINVAL, "Cannot insert, parent of \"%s\" is not \"%s\".", schema->name,
747
0
                    parent->name);
748
0
            return LY_EINVAL;
749
0
        }
750
0
    } else {
751
        /* top-level node */
752
0
        if (par2) {
753
0
            LOGERR(schema->module->ctx, LY_EINVAL, "Cannot insert, node \"%s\" is not top-level.", schema->name);
754
0
            return LY_EINVAL;
755
0
        }
756
0
    }
757
758
0
    return LY_SUCCESS;
759
0
}
760
761
LIBYANG_API_DEF LY_ERR
762
lyd_insert_child(struct lyd_node *parent, struct lyd_node *node)
763
0
{
764
0
    struct lyd_node *iter;
765
766
0
    LY_CHECK_ARG_RET(NULL, parent, node, !parent->schema || (parent->schema->nodetype & LYD_NODE_INNER), LY_EINVAL);
767
0
    LY_CHECK_CTX_EQUAL_RET(LYD_CTX(parent), LYD_CTX(node), LY_EINVAL);
768
769
0
    LY_CHECK_RET(lyd_insert_check_schema(parent->schema, NULL, node->schema));
770
771
0
    if (node->schema && (node->schema->flags & LYS_KEY)) {
772
0
        LOGERR(LYD_CTX(parent), LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
773
0
        return LY_EINVAL;
774
0
    }
775
776
0
    if (node->parent || node->prev->next) {
777
0
        lyd_unlink_tree(node);
778
0
    }
779
780
0
    while (node) {
781
0
        iter = node->next;
782
0
        lyd_unlink_tree(node);
783
0
        lyd_insert_node(parent, NULL, node, 0);
784
0
        node = iter;
785
0
    }
786
0
    return LY_SUCCESS;
787
0
}
788
789
LIBYANG_API_DEF LY_ERR
790
lyplg_ext_insert(struct lyd_node *parent, struct lyd_node *first)
791
0
{
792
0
    struct lyd_node *iter;
793
794
0
    LY_CHECK_ARG_RET(NULL, parent, first, !first->parent, !first->prev->next,
795
0
            !parent->schema || (parent->schema->nodetype & LYD_NODE_INNER), LY_EINVAL);
796
797
0
    if (first->schema && (first->schema->flags & LYS_KEY)) {
798
0
        LOGERR(LYD_CTX(parent), LY_EINVAL, "Cannot insert key \"%s\".", first->schema->name);
799
0
        return LY_EINVAL;
800
0
    }
801
802
0
    while (first) {
803
0
        iter = first->next;
804
0
        lyd_unlink_tree(first);
805
0
        lyd_insert_node(parent, NULL, first, 1);
806
0
        first = iter;
807
0
    }
808
0
    return LY_SUCCESS;
809
0
}
810
811
LIBYANG_API_DEF LY_ERR
812
lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, struct lyd_node **first)
813
0
{
814
0
    struct lyd_node *iter;
815
816
0
    LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
817
818
0
    if (sibling) {
819
0
        LY_CHECK_RET(lyd_insert_check_schema(NULL, sibling->schema, node->schema));
820
0
    }
821
822
0
    if (sibling == node) {
823
        /* we need to keep the connection to siblings so we can insert into them */
824
0
        sibling = sibling->prev;
825
0
    }
826
827
0
    if (node->parent || node->prev->next) {
828
0
        lyd_unlink_tree(node);
829
0
    }
830
831
0
    while (node) {
832
0
        if (lysc_is_key(node->schema)) {
833
0
            LOGERR(LYD_CTX(node), LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
834
0
            return LY_EINVAL;
835
0
        }
836
837
0
        iter = node->next;
838
0
        lyd_unlink_tree(node);
839
0
        lyd_insert_node(NULL, &sibling, node, 0);
840
0
        node = iter;
841
0
    }
842
843
0
    if (first) {
844
        /* find the first sibling */
845
0
        *first = sibling;
846
0
        while ((*first)->prev->next) {
847
0
            *first = (*first)->prev;
848
0
        }
849
0
    }
850
851
0
    return LY_SUCCESS;
852
0
}
853
854
LIBYANG_API_DEF LY_ERR
855
lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
856
0
{
857
0
    LY_CHECK_ARG_RET(NULL, sibling, node, sibling != node, LY_EINVAL);
858
0
    LY_CHECK_CTX_EQUAL_RET(LYD_CTX(sibling), LYD_CTX(node), LY_EINVAL);
859
860
0
    LY_CHECK_RET(lyd_insert_check_schema(NULL, sibling->schema, node->schema));
861
862
0
    if (node->schema && (!(node->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(node->schema->flags & LYS_ORDBY_USER))) {
863
0
        LOGERR(LYD_CTX(sibling), LY_EINVAL, "Can be used only for user-ordered nodes.");
864
0
        return LY_EINVAL;
865
0
    }
866
0
    if (node->schema && sibling->schema && (node->schema != sibling->schema)) {
867
0
        LOGERR(LYD_CTX(sibling), LY_EINVAL, "Cannot insert before a different schema node instance.");
868
0
        return LY_EINVAL;
869
0
    }
870
871
0
    lyd_unlink_tree(node);
872
0
    lyd_insert_before_node(sibling, node);
873
0
    lyd_insert_hash(node);
874
875
0
    return LY_SUCCESS;
876
0
}
877
878
LIBYANG_API_DEF LY_ERR
879
lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
880
0
{
881
0
    LY_CHECK_ARG_RET(NULL, sibling, node, sibling != node, LY_EINVAL);
882
0
    LY_CHECK_CTX_EQUAL_RET(LYD_CTX(sibling), LYD_CTX(node), LY_EINVAL);
883
884
0
    LY_CHECK_RET(lyd_insert_check_schema(NULL, sibling->schema, node->schema));
885
886
0
    if (node->schema && (!(node->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(node->schema->flags & LYS_ORDBY_USER))) {
887
0
        LOGERR(LYD_CTX(sibling), LY_EINVAL, "Can be used only for user-ordered nodes.");
888
0
        return LY_EINVAL;
889
0
    }
890
0
    if (node->schema && sibling->schema && (node->schema != sibling->schema)) {
891
0
        LOGERR(LYD_CTX(sibling), LY_EINVAL, "Cannot insert after a different schema node instance.");
892
0
        return LY_EINVAL;
893
0
    }
894
895
0
    lyd_unlink_tree(node);
896
0
    lyd_insert_after_node(sibling, node);
897
0
    lyd_insert_hash(node);
898
899
0
    return LY_SUCCESS;
900
0
}
901
902
LIBYANG_API_DEF void
903
lyd_unlink_siblings(struct lyd_node *node)
904
0
{
905
0
    struct lyd_node *next, *elem, *first = NULL;
906
907
0
    LY_LIST_FOR_SAFE(node, next, elem) {
908
0
        lyd_unlink_tree(elem);
909
0
        lyd_insert_node(NULL, &first, elem, 1);
910
0
    }
911
0
}
912
913
LIBYANG_API_DEF void
914
lyd_unlink_tree(struct lyd_node *node)
915
2.90k
{
916
2.90k
    struct lyd_node *iter;
917
918
2.90k
    if (!node) {
919
0
        return;
920
0
    }
921
922
    /* update hashes while still linked into the tree */
923
2.90k
    lyd_unlink_hash(node);
924
925
    /* unlink from siblings */
926
2.90k
    if (node->prev->next) {
927
0
        node->prev->next = node->next;
928
0
    }
929
2.90k
    if (node->next) {
930
0
        node->next->prev = node->prev;
931
2.90k
    } else {
932
        /* unlinking the last node */
933
2.90k
        if (node->parent) {
934
0
            iter = node->parent->child;
935
2.90k
        } else {
936
2.90k
            iter = node->prev;
937
2.90k
            while (iter->prev != node) {
938
0
                iter = iter->prev;
939
0
            }
940
2.90k
        }
941
        /* update the "last" pointer from the first node */
942
2.90k
        iter->prev = node->prev;
943
2.90k
    }
944
945
    /* unlink from parent */
946
2.90k
    if (node->parent) {
947
0
        if (node->parent->child == node) {
948
            /* the node is the first child */
949
0
            node->parent->child = node->next;
950
0
        }
951
952
        /* check for NP container whether its last non-default node is not being unlinked */
953
0
        lyd_cont_set_dflt(lyd_parent(node));
954
955
0
        node->parent = NULL;
956
0
    }
957
958
2.90k
    node->next = NULL;
959
2.90k
    node->prev = node;
960
2.90k
}
961
962
void
963
lyd_insert_meta(struct lyd_node *parent, struct lyd_meta *meta, ly_bool clear_dflt)
964
260k
{
965
260k
    struct lyd_meta *last, *iter;
966
967
260k
    assert(parent);
968
969
260k
    if (!meta) {
970
260k
        return;
971
260k
    }
972
973
0
    for (iter = meta; iter; iter = iter->next) {
974
0
        iter->parent = parent;
975
0
    }
976
977
    /* insert as the last attribute */
978
0
    if (parent->meta) {
979
0
        for (last = parent->meta; last->next; last = last->next) {}
980
0
        last->next = meta;
981
0
    } else {
982
0
        parent->meta = meta;
983
0
    }
984
985
    /* remove default flags from NP containers */
986
0
    while (clear_dflt && parent && (parent->schema->nodetype == LYS_CONTAINER) && (parent->flags & LYD_DEFAULT)) {
987
0
        parent->flags &= ~LYD_DEFAULT;
988
0
        parent = lyd_parent(parent);
989
0
    }
990
0
}
991
992
LY_ERR
993
lyd_create_meta(struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod, const char *name,
994
        size_t name_len, const char *value, size_t value_len, ly_bool is_utf8, ly_bool *dynamic, LY_VALUE_FORMAT format,
995
        void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node, ly_bool clear_dflt, ly_bool *incomplete)
996
12
{
997
12
    LY_ERR ret = LY_SUCCESS;
998
12
    struct lysc_ext_instance *ant = NULL;
999
12
    const struct lysc_type *ant_type;
1000
12
    struct lyd_meta *mt, *last;
1001
12
    LY_ARRAY_COUNT_TYPE u;
1002
1003
12
    assert((parent || meta) && mod);
1004
1005
12
    LY_ARRAY_FOR(mod->compiled->exts, u) {
1006
0
        if (!strncmp(mod->compiled->exts[u].def->plugin->id, "ly2 metadata", 12) &&
1007
0
                !ly_strncmp(mod->compiled->exts[u].argument, name, name_len)) {
1008
            /* we have the annotation definition */
1009
0
            ant = &mod->compiled->exts[u];
1010
0
            break;
1011
0
        }
1012
0
    }
1013
12
    if (!ant) {
1014
        /* attribute is not defined as a metadata annotation (RFC 7952) */
1015
12
        LOGVAL(mod->ctx, LYVE_REFERENCE, "Annotation definition for attribute \"%s:%.*s\" not found.",
1016
12
                mod->name, (int)name_len, name);
1017
12
        ret = LY_EINVAL;
1018
12
        goto cleanup;
1019
12
    }
1020
1021
0
    mt = calloc(1, sizeof *mt);
1022
0
    LY_CHECK_ERR_GOTO(!mt, LOGMEM(mod->ctx); ret = LY_EMEM, cleanup);
1023
0
    mt->parent = parent;
1024
0
    mt->annotation = ant;
1025
0
    lyplg_ext_get_storage(ant, LY_STMT_TYPE, sizeof ant_type, (const void **)&ant_type);
1026
0
    ret = lyd_value_store(mod->ctx, &mt->value, ant_type, value, value_len, is_utf8, dynamic, format, prefix_data, hints,
1027
0
            ctx_node, incomplete);
1028
0
    LY_CHECK_ERR_GOTO(ret, free(mt), cleanup);
1029
0
    ret = lydict_insert(mod->ctx, name, name_len, &mt->name);
1030
0
    LY_CHECK_ERR_GOTO(ret, free(mt), cleanup);
1031
1032
    /* insert as the last attribute */
1033
0
    if (parent) {
1034
0
        lyd_insert_meta(parent, mt, clear_dflt);
1035
0
    } else if (*meta) {
1036
0
        for (last = *meta; last->next; last = last->next) {}
1037
0
        last->next = mt;
1038
0
    }
1039
1040
0
    if (meta) {
1041
0
        *meta = mt;
1042
0
    }
1043
1044
12
cleanup:
1045
12
    return ret;
1046
0
}
1047
1048
void
1049
lyd_insert_attr(struct lyd_node *parent, struct lyd_attr *attr)
1050
3
{
1051
3
    struct lyd_attr *last, *iter;
1052
3
    struct lyd_node_opaq *opaq;
1053
1054
3
    assert(parent && !parent->schema);
1055
1056
3
    if (!attr) {
1057
0
        return;
1058
0
    }
1059
1060
3
    opaq = (struct lyd_node_opaq *)parent;
1061
6
    for (iter = attr; iter; iter = iter->next) {
1062
3
        iter->parent = opaq;
1063
3
    }
1064
1065
    /* insert as the last attribute */
1066
3
    if (opaq->attr) {
1067
3
        for (last = opaq->attr; last->next; last = last->next) {}
1068
2
        last->next = attr;
1069
2
    } else {
1070
1
        opaq->attr = attr;
1071
1
    }
1072
3
}
1073
1074
LY_ERR
1075
lyd_create_attr(struct lyd_node *parent, struct lyd_attr **attr, const struct ly_ctx *ctx, const char *name, size_t name_len,
1076
        const char *prefix, size_t prefix_len, const char *module_key, size_t module_key_len, const char *value,
1077
        size_t value_len, ly_bool *dynamic, LY_VALUE_FORMAT format, void *val_prefix_data, uint32_t hints)
1078
3
{
1079
3
    LY_ERR ret = LY_SUCCESS;
1080
3
    struct lyd_attr *at, *last;
1081
1082
3
    assert(ctx && (parent || attr) && (!parent || !parent->schema));
1083
0
    assert(name && name_len && format);
1084
1085
3
    if (!value_len && (!dynamic || !*dynamic)) {
1086
0
        value = "";
1087
0
    }
1088
1089
3
    at = calloc(1, sizeof *at);
1090
3
    LY_CHECK_ERR_RET(!at, LOGMEM(ctx); ly_free_prefix_data(format, val_prefix_data), LY_EMEM);
1091
1092
3
    LY_CHECK_GOTO(ret = lydict_insert(ctx, name, name_len, &at->name.name), finish);
1093
3
    if (prefix_len) {
1094
3
        LY_CHECK_GOTO(ret = lydict_insert(ctx, prefix, prefix_len, &at->name.prefix), finish);
1095
3
    }
1096
3
    if (module_key_len) {
1097
3
        LY_CHECK_GOTO(ret = lydict_insert(ctx, module_key, module_key_len, &at->name.module_ns), finish);
1098
3
    }
1099
1100
3
    if (dynamic && *dynamic) {
1101
1
        ret = lydict_insert_zc(ctx, (char *)value, &at->value);
1102
1
        LY_CHECK_GOTO(ret, finish);
1103
1
        *dynamic = 0;
1104
2
    } else {
1105
2
        LY_CHECK_GOTO(ret = lydict_insert(ctx, value, value_len, &at->value), finish);
1106
2
    }
1107
3
    at->format = format;
1108
3
    at->val_prefix_data = val_prefix_data;
1109
3
    at->hints = hints;
1110
1111
    /* insert as the last attribute */
1112
3
    if (parent) {
1113
3
        lyd_insert_attr(parent, at);
1114
3
    } else if (*attr) {
1115
0
        for (last = *attr; last->next; last = last->next) {}
1116
0
        last->next = at;
1117
0
    }
1118
1119
3
finish:
1120
3
    if (ret) {
1121
0
        lyd_free_attr_single(ctx, at);
1122
3
    } else if (attr) {
1123
0
        *attr = at;
1124
0
    }
1125
3
    return LY_SUCCESS;
1126
3
}
1127
1128
LIBYANG_API_DEF const struct lyd_node_term *
1129
lyd_target(const struct ly_path *path, const struct lyd_node *tree)
1130
0
{
1131
0
    struct lyd_node *target = NULL;
1132
1133
0
    lyd_find_target(path, tree, &target);
1134
1135
0
    return (struct lyd_node_term *)target;
1136
0
}
1137
1138
/**
1139
 * @brief Check the equality of the two schemas from different contexts.
1140
 *
1141
 * @param schema1 of first node.
1142
 * @param schema2 of second node.
1143
 * @return 1 if the schemas are equal otherwise 0.
1144
 */
1145
static ly_bool
1146
lyd_compare_schema_equal(const struct lysc_node *schema1, const struct lysc_node *schema2)
1147
0
{
1148
0
    if (!schema1 && !schema2) {
1149
0
        return 1;
1150
0
    } else if (!schema1 || !schema2) {
1151
0
        return 0;
1152
0
    }
1153
1154
0
    assert(schema1->module->ctx != schema2->module->ctx);
1155
1156
0
    if (schema1->nodetype != schema2->nodetype) {
1157
0
        return 0;
1158
0
    }
1159
1160
0
    if (strcmp(schema1->name, schema2->name)) {
1161
0
        return 0;
1162
0
    }
1163
1164
0
    if (strcmp(schema1->module->name, schema2->module->name)) {
1165
0
        return 0;
1166
0
    }
1167
1168
0
    return 1;
1169
0
}
1170
1171
/**
1172
 * @brief Check the equality of the schemas for all parent nodes.
1173
 *
1174
 * Both nodes must be from different contexts.
1175
 *
1176
 * @param node1 Data of first node.
1177
 * @param node2 Data of second node.
1178
 * @return 1 if the all related parental schemas are equal otherwise 0.
1179
 */
1180
static ly_bool
1181
lyd_compare_schema_parents_equal(const struct lyd_node *node1, const struct lyd_node *node2)
1182
0
{
1183
0
    const struct lysc_node *parent1, *parent2;
1184
1185
0
    assert(node1 && node2);
1186
1187
0
    for (parent1 = node1->schema->parent, parent2 = node2->schema->parent;
1188
0
            parent1 && parent2;
1189
0
            parent1 = parent1->parent, parent2 = parent2->parent) {
1190
0
        if (!lyd_compare_schema_equal(parent1, parent2)) {
1191
0
            return 0;
1192
0
        }
1193
0
    }
1194
1195
0
    if (parent1 || parent2) {
1196
0
        return 0;
1197
0
    }
1198
1199
0
    return 1;
1200
0
}
1201
1202
/**
1203
 * @brief Compare 2 nodes values including opaque node values.
1204
 *
1205
 * @param[in] node1 First node to compare.
1206
 * @param[in] node2 Second node to compare.
1207
 * @return LY_SUCCESS if equal.
1208
 * @return LY_ENOT if not equal.
1209
 * @return LY_ERR on error.
1210
 */
1211
static LY_ERR
1212
lyd_compare_single_value(const struct lyd_node *node1, const struct lyd_node *node2)
1213
23.5k
{
1214
23.5k
    const struct lyd_node_opaq *opaq1 = NULL, *opaq2 = NULL;
1215
23.5k
    const char *val1, *val2, *col;
1216
23.5k
    const struct lys_module *mod;
1217
23.5k
    char *val_dyn = NULL;
1218
23.5k
    LY_ERR rc = LY_SUCCESS;
1219
1220
23.5k
    if (!node1->schema) {
1221
0
        opaq1 = (struct lyd_node_opaq *)node1;
1222
0
    }
1223
23.5k
    if (!node2->schema) {
1224
0
        opaq2 = (struct lyd_node_opaq *)node2;
1225
0
    }
1226
1227
23.5k
    if (opaq1 && opaq2 && (opaq1->format == LY_VALUE_XML) && (opaq2->format == LY_VALUE_XML)) {
1228
        /* opaque XML and opaque XML node */
1229
0
        if (lyxml_value_compare(LYD_CTX(node1), opaq1->value, opaq1->val_prefix_data, LYD_CTX(node2), opaq2->value,
1230
0
                opaq2->val_prefix_data)) {
1231
0
            return LY_ENOT;
1232
0
        }
1233
0
        return LY_SUCCESS;
1234
0
    }
1235
1236
    /* get their values */
1237
23.5k
    if (opaq1 && ((opaq1->format == LY_VALUE_XML) || (opaq1->format == LY_VALUE_STR_NS)) && (col = strchr(opaq1->value, ':'))) {
1238
        /* XML value with a prefix, try to transform it into a JSON (canonical) value */
1239
0
        mod = ly_resolve_prefix(LYD_CTX(node1), opaq1->value, col - opaq1->value, opaq1->format, opaq1->val_prefix_data);
1240
0
        if (!mod) {
1241
            /* unable to compare */
1242
0
            return LY_ENOT;
1243
0
        }
1244
1245
0
        if (asprintf(&val_dyn, "%s%s", mod->name, col) == -1) {
1246
0
            LOGMEM(LYD_CTX(node1));
1247
0
            return LY_EMEM;
1248
0
        }
1249
0
        val1 = val_dyn;
1250
23.5k
    } else {
1251
23.5k
        val1 = lyd_get_value(node1);
1252
23.5k
    }
1253
23.5k
    if (opaq2 && ((opaq2->format == LY_VALUE_XML) || (opaq2->format == LY_VALUE_STR_NS)) && (col = strchr(opaq2->value, ':'))) {
1254
0
        mod = ly_resolve_prefix(LYD_CTX(node2), opaq2->value, col - opaq2->value, opaq2->format, opaq2->val_prefix_data);
1255
0
        if (!mod) {
1256
0
            return LY_ENOT;
1257
0
        }
1258
1259
0
        assert(!val_dyn);
1260
0
        if (asprintf(&val_dyn, "%s%s", mod->name, col) == -1) {
1261
0
            LOGMEM(LYD_CTX(node2));
1262
0
            return LY_EMEM;
1263
0
        }
1264
0
        val2 = val_dyn;
1265
23.5k
    } else {
1266
23.5k
        val2 = lyd_get_value(node2);
1267
23.5k
    }
1268
1269
    /* compare values */
1270
23.5k
    if (strcmp(val1, val2)) {
1271
0
        rc = LY_ENOT;
1272
0
    }
1273
1274
23.5k
    free(val_dyn);
1275
23.5k
    return rc;
1276
23.5k
}
1277
1278
/**
1279
 * @brief Compare 2 data nodes if they are equivalent regarding the schema tree.
1280
 *
1281
 * Works correctly even if @p node1 and @p node2 have different contexts.
1282
 *
1283
 * @param[in] node1 The first node to compare.
1284
 * @param[in] node2 The second node to compare.
1285
 * @param[in] options Various @ref datacompareoptions.
1286
 * @param[in] parental_schemas_checked Flag set if parent schemas were checked for match.
1287
 * @return LY_SUCCESS if the nodes are equivalent.
1288
 * @return LY_ENOT if the nodes are not equivalent.
1289
 */
1290
static LY_ERR
1291
lyd_compare_single_schema(const struct lyd_node *node1, const struct lyd_node *node2, uint32_t options,
1292
        ly_bool parental_schemas_checked)
1293
27.1k
{
1294
27.1k
    if (LYD_CTX(node1) == LYD_CTX(node2)) {
1295
        /* same contexts */
1296
27.1k
        if (options & LYD_COMPARE_OPAQ) {
1297
0
            if (lyd_node_schema(node1) != lyd_node_schema(node2)) {
1298
0
                return LY_ENOT;
1299
0
            }
1300
27.1k
        } else {
1301
27.1k
            if (node1->schema != node2->schema) {
1302
1.64k
                return LY_ENOT;
1303
1.64k
            }
1304
27.1k
        }
1305
27.1k
    } else {
1306
        /* different contexts */
1307
0
        if (!lyd_compare_schema_equal(node1->schema, node2->schema)) {
1308
0
            return LY_ENOT;
1309
0
        }
1310
0
        if (!parental_schemas_checked) {
1311
0
            if (!lyd_compare_schema_parents_equal(node1, node2)) {
1312
0
                return LY_ENOT;
1313
0
            }
1314
0
            parental_schemas_checked = 1;
1315
0
        }
1316
0
    }
1317
1318
25.5k
    return LY_SUCCESS;
1319
27.1k
}
1320
1321
/**
1322
 * @brief Compare 2 data nodes if they are equivalent regarding the data they contain.
1323
 *
1324
 * Works correctly even if @p node1 and @p node2 have different contexts.
1325
 *
1326
 * @param[in] node1 The first node to compare.
1327
 * @param[in] node2 The second node to compare.
1328
 * @param[in] options Various @ref datacompareoptions.
1329
 * @return LY_SUCCESS if the nodes are equivalent.
1330
 * @return LY_ENOT if the nodes are not equivalent.
1331
 */
1332
static LY_ERR
1333
lyd_compare_single_data(const struct lyd_node *node1, const struct lyd_node *node2, uint32_t options)
1334
25.5k
{
1335
25.5k
    const struct lyd_node *iter1, *iter2;
1336
25.5k
    struct lyd_node_any *any1, *any2;
1337
25.5k
    int len1, len2;
1338
25.5k
    LY_ERR r;
1339
1340
25.5k
    if (!(options & LYD_COMPARE_OPAQ) && (node1->hash != node2->hash)) {
1341
1.74k
        return LY_ENOT;
1342
1.74k
    }
1343
    /* equal hashes do not mean equal nodes, they can be just in collision so the nodes must be checked explicitly */
1344
1345
23.7k
    if (!node1->schema || !node2->schema) {
1346
0
        if (!(options & LYD_COMPARE_OPAQ) && ((node1->schema && !node2->schema) || (!node1->schema && node2->schema))) {
1347
0
            return LY_ENOT;
1348
0
        }
1349
0
        if ((!node1->schema && !node2->schema) || (node1->schema && (node1->schema->nodetype & LYD_NODE_TERM)) ||
1350
0
                (node2->schema && (node2->schema->nodetype & LYD_NODE_TERM))) {
1351
            /* compare values only if there are any to compare */
1352
0
            if ((r = lyd_compare_single_value(node1, node2))) {
1353
0
                return r;
1354
0
            }
1355
0
        }
1356
1357
0
        if (options & LYD_COMPARE_FULL_RECURSION) {
1358
0
            return lyd_compare_siblings_(lyd_child(node1), lyd_child(node2), options, 1);
1359
0
        }
1360
0
        return LY_SUCCESS;
1361
23.7k
    } else {
1362
23.7k
        switch (node1->schema->nodetype) {
1363
153
        case LYS_LEAF:
1364
23.5k
        case LYS_LEAFLIST:
1365
23.5k
            if (options & LYD_COMPARE_DEFAULTS) {
1366
0
                if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
1367
0
                    return LY_ENOT;
1368
0
                }
1369
0
            }
1370
23.5k
            if ((r = lyd_compare_single_value(node1, node2))) {
1371
0
                return r;
1372
0
            }
1373
1374
23.5k
            return LY_SUCCESS;
1375
35
        case LYS_CONTAINER:
1376
35
        case LYS_RPC:
1377
35
        case LYS_ACTION:
1378
35
        case LYS_NOTIF:
1379
            /* implicit container is always equal to a container with non-default descendants */
1380
35
            if (options & LYD_COMPARE_FULL_RECURSION) {
1381
0
                return lyd_compare_siblings_(lyd_child(node1), lyd_child(node2), options, 1);
1382
0
            }
1383
35
            return LY_SUCCESS;
1384
152
        case LYS_LIST:
1385
152
            iter1 = lyd_child(node1);
1386
152
            iter2 = lyd_child(node2);
1387
1388
152
            if (options & LYD_COMPARE_FULL_RECURSION) {
1389
0
                return lyd_compare_siblings_(iter1, iter2, options, 1);
1390
152
            } else if (node1->schema->flags & LYS_KEYLESS) {
1391
                /* always equal */
1392
0
                return LY_SUCCESS;
1393
0
            }
1394
1395
            /* lists with keys, their equivalence is based on their keys */
1396
152
            for (const struct lysc_node *key = lysc_node_child(node1->schema);
1397
305
                    key && (key->flags & LYS_KEY);
1398
153
                    key = key->next) {
1399
153
                if (!iter1 || !iter2) {
1400
0
                    return (iter1 == iter2) ? LY_SUCCESS : LY_ENOT;
1401
0
                }
1402
153
                r = lyd_compare_single_schema(iter1, iter2, options, 1);
1403
153
                LY_CHECK_RET(r);
1404
153
                r = lyd_compare_single_data(iter1, iter2, options);
1405
153
                LY_CHECK_RET(r);
1406
1407
153
                iter1 = iter1->next;
1408
153
                iter2 = iter2->next;
1409
153
            }
1410
1411
152
            return LY_SUCCESS;
1412
0
        case LYS_ANYXML:
1413
0
        case LYS_ANYDATA:
1414
0
            any1 = (struct lyd_node_any *)node1;
1415
0
            any2 = (struct lyd_node_any *)node2;
1416
1417
0
            if (any1->value_type != any2->value_type) {
1418
0
                return LY_ENOT;
1419
0
            }
1420
0
            switch (any1->value_type) {
1421
0
            case LYD_ANYDATA_DATATREE:
1422
0
                return lyd_compare_siblings_(any1->value.tree, any2->value.tree, options, 1);
1423
0
            case LYD_ANYDATA_STRING:
1424
0
            case LYD_ANYDATA_XML:
1425
0
            case LYD_ANYDATA_JSON:
1426
0
                if ((!any1->value.str && any2->value.str) || (any1->value.str && !any2->value.str)) {
1427
0
                    return LY_ENOT;
1428
0
                } else if (!any1->value.str && !any2->value.str) {
1429
0
                    return LY_SUCCESS;
1430
0
                }
1431
0
                len1 = strlen(any1->value.str);
1432
0
                len2 = strlen(any2->value.str);
1433
0
                if ((len1 != len2) || strcmp(any1->value.str, any2->value.str)) {
1434
0
                    return LY_ENOT;
1435
0
                }
1436
0
                return LY_SUCCESS;
1437
0
            case LYD_ANYDATA_LYB:
1438
0
                len1 = lyd_lyb_data_length(any1->value.mem);
1439
0
                len2 = lyd_lyb_data_length(any2->value.mem);
1440
0
                if ((len1 == -1) || (len2 == -1) || (len1 != len2) || memcmp(any1->value.mem, any2->value.mem, len1)) {
1441
0
                    return LY_ENOT;
1442
0
                }
1443
0
                return LY_SUCCESS;
1444
0
            }
1445
23.7k
        }
1446
23.7k
    }
1447
1448
0
    LOGINT(LYD_CTX(node1));
1449
0
    return LY_EINT;
1450
23.7k
}
1451
1452
/**
1453
 * @brief Compare all siblings at a node level.
1454
 *
1455
 * @param[in] node1 First sibling list.
1456
 * @param[in] node2 Second sibling list.
1457
 * @param[in] options Various @ref datacompareoptions.
1458
 * @param[in] parental_schemas_checked Flag set if parent schemas were checked for match.
1459
 * @return LY_SUCCESS if equal.
1460
 * @return LY_ENOT if not equal.
1461
 * @return LY_ERR on error.
1462
 */
1463
static LY_ERR
1464
lyd_compare_siblings_(const struct lyd_node *node1, const struct lyd_node *node2, uint32_t options,
1465
        ly_bool parental_schemas_checked)
1466
0
{
1467
0
    LY_ERR r;
1468
0
    const struct lyd_node *iter2;
1469
1470
0
    while (node1 && node2) {
1471
        /* schema match */
1472
0
        r = lyd_compare_single_schema(node1, node2, options, parental_schemas_checked);
1473
0
        LY_CHECK_RET(r);
1474
1475
0
        if (node1->schema && (((node1->schema->nodetype == LYS_LIST) && !(node1->schema->flags & LYS_KEYLESS)) ||
1476
0
                ((node1->schema->nodetype == LYS_LEAFLIST) && (node1->schema->flags & LYS_CONFIG_W))) &&
1477
0
                (node1->schema->flags & LYS_ORDBY_SYSTEM)) {
1478
            /* find a matching instance in case they are ordered differently */
1479
0
            r = lyd_find_sibling_first(node2, node1, (struct lyd_node **)&iter2);
1480
0
            if (r == LY_ENOTFOUND) {
1481
                /* no matching instance, data not equal */
1482
0
                r = LY_ENOT;
1483
0
            }
1484
0
            LY_CHECK_RET(r);
1485
0
        } else {
1486
            /* compare with the current node */
1487
0
            iter2 = node2;
1488
0
        }
1489
1490
        /* data match */
1491
0
        r = lyd_compare_single_data(node1, iter2, options | LYD_COMPARE_FULL_RECURSION);
1492
0
        LY_CHECK_RET(r);
1493
1494
0
        node1 = node1->next;
1495
0
        node2 = node2->next;
1496
0
    }
1497
1498
0
    return (node1 || node2) ? LY_ENOT : LY_SUCCESS;
1499
0
}
1500
1501
LIBYANG_API_DEF LY_ERR
1502
lyd_compare_single(const struct lyd_node *node1, const struct lyd_node *node2, uint32_t options)
1503
27.0k
{
1504
27.0k
    LY_ERR r;
1505
1506
27.0k
    if (!node1 || !node2) {
1507
0
        return (node1 == node2) ? LY_SUCCESS : LY_ENOT;
1508
0
    }
1509
1510
    /* schema match */
1511
27.0k
    if ((r = lyd_compare_single_schema(node1, node2, options, 0))) {
1512
1.64k
        return r;
1513
1.64k
    }
1514
1515
    /* data match */
1516
25.3k
    return lyd_compare_single_data(node1, node2, options);
1517
27.0k
}
1518
1519
LIBYANG_API_DEF LY_ERR
1520
lyd_compare_siblings(const struct lyd_node *node1, const struct lyd_node *node2, uint32_t options)
1521
0
{
1522
0
    return lyd_compare_siblings_(node1, node2, options, 0);
1523
0
}
1524
1525
LIBYANG_API_DEF LY_ERR
1526
lyd_compare_meta(const struct lyd_meta *meta1, const struct lyd_meta *meta2)
1527
0
{
1528
0
    if (!meta1 || !meta2) {
1529
0
        if (meta1 == meta2) {
1530
0
            return LY_SUCCESS;
1531
0
        } else {
1532
0
            return LY_ENOT;
1533
0
        }
1534
0
    }
1535
1536
0
    if ((meta1->annotation->module->ctx != meta2->annotation->module->ctx) || (meta1->annotation != meta2->annotation)) {
1537
0
        return LY_ENOT;
1538
0
    }
1539
1540
0
    return meta1->value.realtype->plugin->compare(&meta1->value, &meta2->value);
1541
0
}
1542
1543
/**
1544
 * @brief Create a copy of the attribute.
1545
 *
1546
 * @param[in] attr Attribute to copy.
1547
 * @param[in] node Opaque where to append the new attribute.
1548
 * @param[out] dup Optional created attribute copy.
1549
 * @return LY_ERR value.
1550
 */
1551
static LY_ERR
1552
lyd_dup_attr_single(const struct lyd_attr *attr, struct lyd_node *node, struct lyd_attr **dup)
1553
0
{
1554
0
    LY_ERR ret = LY_SUCCESS;
1555
0
    struct lyd_attr *a, *last;
1556
0
    struct lyd_node_opaq *opaq = (struct lyd_node_opaq *)node;
1557
1558
0
    LY_CHECK_ARG_RET(NULL, attr, node, !node->schema, LY_EINVAL);
1559
1560
    /* create a copy */
1561
0
    a = calloc(1, sizeof *attr);
1562
0
    LY_CHECK_ERR_RET(!a, LOGMEM(LYD_CTX(node)), LY_EMEM);
1563
1564
0
    LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), attr->name.name, 0, &a->name.name), finish);
1565
0
    LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), attr->name.prefix, 0, &a->name.prefix), finish);
1566
0
    LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), attr->name.module_ns, 0, &a->name.module_ns), finish);
1567
0
    LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), attr->value, 0, &a->value), finish);
1568
0
    a->hints = attr->hints;
1569
0
    a->format = attr->format;
1570
0
    if (attr->val_prefix_data) {
1571
0
        ret = ly_dup_prefix_data(LYD_CTX(node), attr->format, attr->val_prefix_data, &a->val_prefix_data);
1572
0
        LY_CHECK_GOTO(ret, finish);
1573
0
    }
1574
1575
    /* insert as the last attribute */
1576
0
    a->parent = opaq;
1577
0
    if (opaq->attr) {
1578
0
        for (last = opaq->attr; last->next; last = last->next) {}
1579
0
        last->next = a;
1580
0
    } else {
1581
0
        opaq->attr = a;
1582
0
    }
1583
1584
0
finish:
1585
0
    if (ret) {
1586
0
        lyd_free_attr_single(LYD_CTX(node), a);
1587
0
    } else if (dup) {
1588
0
        *dup = a;
1589
0
    }
1590
0
    return LY_SUCCESS;
1591
0
}
1592
1593
/**
1594
 * @brief Find @p schema equivalent in @p trg_ctx.
1595
 *
1596
 * @param[in] schema Schema node to find.
1597
 * @param[in] trg_ctx Target context to search in.
1598
 * @param[in] parent Data parent of @p schema, if any.
1599
 * @param[in] log Whether to log directly.
1600
 * @param[out] trg_schema Found schema from @p trg_ctx to use.
1601
 * @return LY_RRR value.
1602
 */
1603
static LY_ERR
1604
lyd_find_schema_ctx(const struct lysc_node *schema, const struct ly_ctx *trg_ctx, const struct lyd_node *parent,
1605
        ly_bool log, const struct lysc_node **trg_schema)
1606
0
{
1607
0
    const struct lysc_node *src_parent = NULL, *trg_parent = NULL, *sp, *tp;
1608
0
    const struct lys_module *trg_mod = NULL;
1609
0
    char *path;
1610
1611
0
    if (!schema) {
1612
        /* opaque node */
1613
0
        *trg_schema = NULL;
1614
0
        return LY_SUCCESS;
1615
0
    }
1616
1617
0
    if (lysc_data_parent(schema) && parent && parent->schema) {
1618
        /* start from schema parent */
1619
0
        trg_parent = parent->schema;
1620
0
        src_parent = lysc_data_parent(schema);
1621
0
    }
1622
1623
0
    do {
1624
        /* find the next parent */
1625
0
        sp = schema;
1626
0
        while (lysc_data_parent(sp) != src_parent) {
1627
0
            sp = lysc_data_parent(sp);
1628
0
        }
1629
0
        src_parent = sp;
1630
1631
0
        if (!src_parent->parent) {
1632
            /* find the module first */
1633
0
            trg_mod = ly_ctx_get_module_implemented(trg_ctx, src_parent->module->name);
1634
0
            if (!trg_mod) {
1635
0
                if (log) {
1636
0
                    LOGERR(trg_ctx, LY_ENOTFOUND, "Module \"%s\" not present/implemented in the target context.",
1637
0
                            src_parent->module->name);
1638
0
                }
1639
0
                return LY_ENOTFOUND;
1640
0
            }
1641
0
        }
1642
1643
        /* find the next parent */
1644
0
        assert(trg_parent || trg_mod);
1645
0
        tp = NULL;
1646
0
        while ((tp = lys_getnext(tp, trg_parent, trg_mod ? trg_mod->compiled : NULL, 0))) {
1647
0
            if (!strcmp(tp->name, src_parent->name) && !strcmp(tp->module->name, src_parent->module->name)) {
1648
0
                break;
1649
0
            }
1650
0
        }
1651
0
        if (!tp) {
1652
            /* schema node not found */
1653
0
            if (log) {
1654
0
                path = lysc_path(src_parent, LYSC_PATH_LOG, NULL, 0);
1655
0
                LOGERR(trg_ctx, LY_ENOTFOUND, "Schema node \"%s\" not found in the target context.", path);
1656
0
                free(path);
1657
0
            }
1658
0
            return LY_ENOTFOUND;
1659
0
        }
1660
1661
0
        trg_parent = tp;
1662
0
    } while (schema != src_parent);
1663
1664
    /* success */
1665
0
    *trg_schema = trg_parent;
1666
0
    return LY_SUCCESS;
1667
0
}
1668
1669
/**
1670
 * @brief Duplicate a single node and connect it into @p parent (if present) or last of @p first siblings.
1671
 *
1672
 * Ignores ::LYD_DUP_WITH_PARENTS and ::LYD_DUP_WITH_SIBLINGS which are supposed to be handled by lyd_dup().
1673
 *
1674
 * @param[in] node Node to duplicate.
1675
 * @param[in] trg_ctx Target context for duplicated nodes.
1676
 * @param[in] parent Parent to insert into, NULL for top-level sibling.
1677
 * @param[in] insert_last Whether the duplicated node can be inserted as the last child of @p parent. Set for
1678
 * recursive duplication as an optimization.
1679
 * @param[in,out] first First sibling, NULL if no top-level sibling exist yet. Can be also NULL if @p parent is set.
1680
 * @param[in] options Bitmask of options flags, see @ref dupoptions.
1681
 * @param[out] dup_p Pointer where the created duplicated node is placed (besides connecting it to @p parent / @p first).
1682
 * @return LY_ERR value.
1683
 */
1684
static LY_ERR
1685
lyd_dup_r(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_node *parent, ly_bool insert_last,
1686
        struct lyd_node **first, uint32_t options, struct lyd_node **dup_p)
1687
0
{
1688
0
    LY_ERR ret;
1689
0
    struct lyd_node *dup = NULL;
1690
0
    struct lyd_meta *meta;
1691
0
    struct lyd_attr *attr;
1692
0
    struct lyd_node_any *any;
1693
0
    const struct lysc_type *type;
1694
0
    const char *val_can;
1695
1696
0
    LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
1697
1698
0
    if (node->flags & LYD_EXT) {
1699
0
        if (options & LYD_DUP_NO_EXT) {
1700
            /* no not duplicate this subtree */
1701
0
            return LY_SUCCESS;
1702
0
        }
1703
1704
        /* we need to use the same context */
1705
0
        trg_ctx = LYD_CTX(node);
1706
0
    }
1707
1708
0
    if (!node->schema) {
1709
0
        dup = calloc(1, sizeof(struct lyd_node_opaq));
1710
0
        ((struct lyd_node_opaq *)dup)->ctx = trg_ctx;
1711
0
    } else {
1712
0
        switch (node->schema->nodetype) {
1713
0
        case LYS_RPC:
1714
0
        case LYS_ACTION:
1715
0
        case LYS_NOTIF:
1716
0
        case LYS_CONTAINER:
1717
0
        case LYS_LIST:
1718
0
            dup = calloc(1, sizeof(struct lyd_node_inner));
1719
0
            break;
1720
0
        case LYS_LEAF:
1721
0
        case LYS_LEAFLIST:
1722
0
            dup = calloc(1, sizeof(struct lyd_node_term));
1723
0
            break;
1724
0
        case LYS_ANYDATA:
1725
0
        case LYS_ANYXML:
1726
0
            dup = calloc(1, sizeof(struct lyd_node_any));
1727
0
            break;
1728
0
        default:
1729
0
            LOGINT(trg_ctx);
1730
0
            ret = LY_EINT;
1731
0
            goto error;
1732
0
        }
1733
0
    }
1734
0
    LY_CHECK_ERR_GOTO(!dup, LOGMEM(trg_ctx); ret = LY_EMEM, error);
1735
1736
0
    if (options & LYD_DUP_WITH_FLAGS) {
1737
0
        dup->flags = node->flags;
1738
0
    } else {
1739
0
        dup->flags = (node->flags & (LYD_DEFAULT | LYD_EXT)) | LYD_NEW;
1740
0
    }
1741
0
    if (options & LYD_DUP_WITH_PRIV) {
1742
0
        dup->priv = node->priv;
1743
0
    }
1744
0
    if (trg_ctx == LYD_CTX(node)) {
1745
0
        dup->schema = node->schema;
1746
0
    } else {
1747
0
        ret = lyd_find_schema_ctx(node->schema, trg_ctx, parent, 1, &dup->schema);
1748
0
        if (ret) {
1749
            /* has no schema but is not an opaque node */
1750
0
            free(dup);
1751
0
            dup = NULL;
1752
0
            goto error;
1753
0
        }
1754
0
    }
1755
0
    dup->prev = dup;
1756
1757
    /* duplicate metadata/attributes */
1758
0
    if (!(options & LYD_DUP_NO_META)) {
1759
0
        if (!node->schema) {
1760
0
            LY_LIST_FOR(((struct lyd_node_opaq *)node)->attr, attr) {
1761
0
                LY_CHECK_GOTO(ret = lyd_dup_attr_single(attr, dup, NULL), error);
1762
0
            }
1763
0
        } else {
1764
0
            LY_LIST_FOR(node->meta, meta) {
1765
0
                LY_CHECK_GOTO(ret = lyd_dup_meta_single(meta, dup, NULL), error);
1766
0
            }
1767
0
        }
1768
0
    }
1769
1770
    /* nodetype-specific work */
1771
0
    if (!dup->schema) {
1772
0
        struct lyd_node_opaq *opaq = (struct lyd_node_opaq *)dup;
1773
0
        struct lyd_node_opaq *orig = (struct lyd_node_opaq *)node;
1774
0
        struct lyd_node *child;
1775
1776
0
        if (options & LYD_DUP_RECURSIVE) {
1777
            /* duplicate all the children */
1778
0
            LY_LIST_FOR(orig->child, child) {
1779
0
                LY_CHECK_GOTO(ret = lyd_dup_r(child, trg_ctx, dup, 1, NULL, options, NULL), error);
1780
0
            }
1781
0
        }
1782
0
        LY_CHECK_GOTO(ret = lydict_insert(trg_ctx, orig->name.name, 0, &opaq->name.name), error);
1783
0
        LY_CHECK_GOTO(ret = lydict_insert(trg_ctx, orig->name.prefix, 0, &opaq->name.prefix), error);
1784
0
        LY_CHECK_GOTO(ret = lydict_insert(trg_ctx, orig->name.module_ns, 0, &opaq->name.module_ns), error);
1785
0
        LY_CHECK_GOTO(ret = lydict_insert(trg_ctx, orig->value, 0, &opaq->value), error);
1786
0
        opaq->hints = orig->hints;
1787
0
        opaq->format = orig->format;
1788
0
        if (orig->val_prefix_data) {
1789
0
            ret = ly_dup_prefix_data(trg_ctx, opaq->format, orig->val_prefix_data, &opaq->val_prefix_data);
1790
0
            LY_CHECK_GOTO(ret, error);
1791
0
        }
1792
0
    } else if (dup->schema->nodetype & LYD_NODE_TERM) {
1793
0
        struct lyd_node_term *term = (struct lyd_node_term *)dup;
1794
0
        struct lyd_node_term *orig = (struct lyd_node_term *)node;
1795
1796
0
        term->hash = orig->hash;
1797
0
        if (trg_ctx == LYD_CTX(node)) {
1798
0
            ret = orig->value.realtype->plugin->duplicate(trg_ctx, &orig->value, &term->value);
1799
0
            LY_CHECK_ERR_GOTO(ret, LOGERR(trg_ctx, ret, "Value duplication failed."), error);
1800
0
        } else {
1801
            /* store canonical value in the target context */
1802
0
            val_can = lyd_get_value(node);
1803
0
            type = ((struct lysc_node_leaf *)term->schema)->type;
1804
0
            ret = lyd_value_store(trg_ctx, &term->value, type, val_can, strlen(val_can), 1, NULL, LY_VALUE_CANON, NULL,
1805
0
                    LYD_HINT_DATA, term->schema, NULL);
1806
0
            LY_CHECK_GOTO(ret, error);
1807
0
        }
1808
0
    } else if (dup->schema->nodetype & LYD_NODE_INNER) {
1809
0
        struct lyd_node_inner *orig = (struct lyd_node_inner *)node;
1810
0
        struct lyd_node *child;
1811
1812
0
        if (options & LYD_DUP_RECURSIVE) {
1813
            /* duplicate all the children */
1814
0
            LY_LIST_FOR(orig->child, child) {
1815
0
                LY_CHECK_GOTO(ret = lyd_dup_r(child, trg_ctx, dup, 1, NULL, options, NULL), error);
1816
0
            }
1817
0
        } else if ((dup->schema->nodetype == LYS_LIST) && !(dup->schema->flags & LYS_KEYLESS)) {
1818
            /* always duplicate keys of a list */
1819
0
            for (child = orig->child; child && lysc_is_key(child->schema); child = child->next) {
1820
0
                LY_CHECK_GOTO(ret = lyd_dup_r(child, trg_ctx, dup, 1, NULL, options, NULL), error);
1821
0
            }
1822
0
        }
1823
0
        lyd_hash(dup);
1824
0
    } else if (dup->schema->nodetype & LYD_NODE_ANY) {
1825
0
        dup->hash = node->hash;
1826
0
        any = (struct lyd_node_any *)node;
1827
0
        LY_CHECK_GOTO(ret = lyd_any_copy_value(dup, &any->value, any->value_type), error);
1828
0
    }
1829
1830
    /* insert */
1831
0
    lyd_insert_node(parent, first, dup, insert_last);
1832
1833
0
    if (dup_p) {
1834
0
        *dup_p = dup;
1835
0
    }
1836
0
    return LY_SUCCESS;
1837
1838
0
error:
1839
0
    lyd_free_tree(dup);
1840
0
    return ret;
1841
0
}
1842
1843
/**
1844
 * @brief Get a parent node to connect duplicated subtree to.
1845
 *
1846
 * @param[in] node Node (subtree) to duplicate.
1847
 * @param[in] trg_ctx Target context for duplicated nodes.
1848
 * @param[in] parent Initial parent to connect to.
1849
 * @param[in] options Bitmask of options flags, see @ref dupoptions.
1850
 * @param[out] dup_parent First duplicated parent node, if any.
1851
 * @param[out] local_parent Correct parent to directly connect duplicated @p node to.
1852
 * @return LY_ERR value.
1853
 */
1854
static LY_ERR
1855
lyd_dup_get_local_parent(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_node *parent,
1856
        uint32_t options, struct lyd_node **dup_parent, struct lyd_node **local_parent)
1857
0
{
1858
0
    const struct lyd_node *orig_parent;
1859
0
    struct lyd_node *iter = NULL;
1860
0
    ly_bool repeat = 1, ext_parent = 0;
1861
1862
0
    *dup_parent = NULL;
1863
0
    *local_parent = NULL;
1864
1865
0
    if (node->flags & LYD_EXT) {
1866
0
        ext_parent = 1;
1867
0
    }
1868
0
    for (orig_parent = lyd_parent(node); repeat && orig_parent; orig_parent = lyd_parent(orig_parent)) {
1869
0
        if (ext_parent) {
1870
            /* use the standard context */
1871
0
            trg_ctx = LYD_CTX(orig_parent);
1872
0
        }
1873
0
        if (parent && (LYD_CTX(parent) == LYD_CTX(orig_parent)) && (parent->schema == orig_parent->schema)) {
1874
            /* stop creating parents, connect what we have into the provided parent */
1875
0
            iter = parent;
1876
0
            repeat = 0;
1877
0
        } else if (parent && (LYD_CTX(parent) != LYD_CTX(orig_parent)) &&
1878
0
                lyd_compare_schema_equal(parent->schema, orig_parent->schema) &&
1879
0
                lyd_compare_schema_parents_equal(parent, orig_parent)) {
1880
0
            iter = parent;
1881
0
            repeat = 0;
1882
0
        } else {
1883
0
            iter = NULL;
1884
0
            LY_CHECK_RET(lyd_dup_r(orig_parent, trg_ctx, NULL, 0, &iter, options, &iter));
1885
1886
            /* insert into the previous duplicated parent */
1887
0
            if (*dup_parent) {
1888
0
                lyd_insert_node(iter, NULL, *dup_parent, 0);
1889
0
            }
1890
1891
            /* update the last duplicated parent */
1892
0
            *dup_parent = iter;
1893
0
        }
1894
1895
        /* set the first parent */
1896
0
        if (!*local_parent) {
1897
0
            *local_parent = iter;
1898
0
        }
1899
1900
0
        if (orig_parent->flags & LYD_EXT) {
1901
0
            ext_parent = 1;
1902
0
        }
1903
0
    }
1904
1905
0
    if (repeat && parent) {
1906
        /* given parent and created parents chain actually do not interconnect */
1907
0
        LOGERR(trg_ctx, LY_EINVAL, "None of the duplicated node \"%s\" schema parents match the provided parent \"%s\".",
1908
0
                LYD_NAME(node), LYD_NAME(parent));
1909
0
        return LY_EINVAL;
1910
0
    }
1911
1912
0
    if (*dup_parent && parent) {
1913
        /* last insert into a prevously-existing parent */
1914
0
        lyd_insert_node(parent, NULL, *dup_parent, 0);
1915
0
    }
1916
0
    return LY_SUCCESS;
1917
0
}
1918
1919
static LY_ERR
1920
lyd_dup(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_node *parent, uint32_t options,
1921
        ly_bool nosiblings, struct lyd_node **dup)
1922
0
{
1923
0
    LY_ERR rc;
1924
0
    const struct lyd_node *orig;          /* original node to be duplicated */
1925
0
    struct lyd_node *first = NULL;        /* the first duplicated node, this is returned */
1926
0
    struct lyd_node *top = NULL;          /* the most higher created node */
1927
0
    struct lyd_node *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
1928
1929
0
    assert(node && trg_ctx);
1930
1931
0
    if (options & LYD_DUP_WITH_PARENTS) {
1932
0
        LY_CHECK_GOTO(rc = lyd_dup_get_local_parent(node, trg_ctx, parent, options & (LYD_DUP_WITH_FLAGS | LYD_DUP_NO_META),
1933
0
                &top, &local_parent), error);
1934
0
    } else {
1935
0
        local_parent = parent;
1936
0
    }
1937
1938
0
    LY_LIST_FOR(node, orig) {
1939
0
        if (lysc_is_key(orig->schema)) {
1940
0
            if (local_parent) {
1941
                /* the key must already exist in the parent */
1942
0
                rc = lyd_find_sibling_schema(lyd_child(local_parent), orig->schema, first ? NULL : &first);
1943
0
                LY_CHECK_ERR_GOTO(rc, LOGINT(trg_ctx), error);
1944
0
            } else {
1945
0
                assert(!(options & LYD_DUP_WITH_PARENTS));
1946
                /* duplicating a single key, okay, I suppose... */
1947
0
                rc = lyd_dup_r(orig, trg_ctx, NULL, 0, &first, options, first ? NULL : &first);
1948
0
                LY_CHECK_GOTO(rc, error);
1949
0
            }
1950
0
        } else {
1951
            /* if there is no local parent, it will be inserted into first */
1952
0
            rc = lyd_dup_r(orig, trg_ctx, local_parent, 0, &first, options, first ? NULL : &first);
1953
0
            LY_CHECK_GOTO(rc, error);
1954
0
        }
1955
0
        if (nosiblings) {
1956
0
            break;
1957
0
        }
1958
0
    }
1959
1960
0
    if (dup) {
1961
0
        *dup = first;
1962
0
    }
1963
0
    return LY_SUCCESS;
1964
1965
0
error:
1966
0
    if (top) {
1967
0
        lyd_free_tree(top);
1968
0
    } else {
1969
0
        lyd_free_siblings(first);
1970
0
    }
1971
0
    return rc;
1972
0
}
1973
1974
/**
1975
 * @brief Check the context of node and parent when duplicating nodes.
1976
 *
1977
 * @param[in] node Node to duplicate.
1978
 * @param[in] parent Parent of the duplicated node(s).
1979
 * @return LY_ERR value.
1980
 */
1981
static LY_ERR
1982
lyd_dup_ctx_check(const struct lyd_node *node, const struct lyd_node_inner *parent)
1983
0
{
1984
0
    const struct lyd_node *iter;
1985
1986
0
    if (!node || !parent) {
1987
0
        return LY_SUCCESS;
1988
0
    }
1989
1990
0
    if ((LYD_CTX(node) != LYD_CTX(parent))) {
1991
        /* try to find top-level ext data parent */
1992
0
        for (iter = node; iter && !(iter->flags & LYD_EXT); iter = lyd_parent(iter)) {}
1993
1994
0
        if (!iter || !lyd_parent(iter) || (LYD_CTX(lyd_parent(iter)) != LYD_CTX(parent))) {
1995
0
            LOGERR(LYD_CTX(node), LY_EINVAL, "Different contexts used in node duplication.");
1996
0
            return LY_EINVAL;
1997
0
        }
1998
0
    }
1999
2000
0
    return LY_SUCCESS;
2001
0
}
2002
2003
LIBYANG_API_DEF LY_ERR
2004
lyd_dup_single(const struct lyd_node *node, struct lyd_node_inner *parent, uint32_t options, struct lyd_node **dup)
2005
0
{
2006
0
    LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
2007
0
    LY_CHECK_RET(lyd_dup_ctx_check(node, parent));
2008
2009
0
    return lyd_dup(node, LYD_CTX(node), (struct lyd_node *)parent, options, 1, dup);
2010
0
}
2011
2012
LIBYANG_API_DEF LY_ERR
2013
lyd_dup_single_to_ctx(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_node_inner *parent,
2014
        uint32_t options, struct lyd_node **dup)
2015
0
{
2016
0
    LY_CHECK_ARG_RET(trg_ctx, node, trg_ctx, LY_EINVAL);
2017
2018
0
    return lyd_dup(node, trg_ctx, (struct lyd_node *)parent, options, 1, dup);
2019
0
}
2020
2021
LIBYANG_API_DEF LY_ERR
2022
lyd_dup_siblings(const struct lyd_node *node, struct lyd_node_inner *parent, uint32_t options, struct lyd_node **dup)
2023
0
{
2024
0
    LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
2025
0
    LY_CHECK_RET(lyd_dup_ctx_check(node, parent));
2026
2027
0
    return lyd_dup(node, LYD_CTX(node), (struct lyd_node *)parent, options, 0, dup);
2028
0
}
2029
2030
LIBYANG_API_DEF LY_ERR
2031
lyd_dup_siblings_to_ctx(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_node_inner *parent,
2032
        uint32_t options, struct lyd_node **dup)
2033
0
{
2034
0
    LY_CHECK_ARG_RET(trg_ctx, node, trg_ctx, LY_EINVAL);
2035
2036
0
    return lyd_dup(node, trg_ctx, (struct lyd_node *)parent, options, 0, dup);
2037
0
}
2038
2039
LIBYANG_API_DEF LY_ERR
2040
lyd_dup_meta_single(const struct lyd_meta *meta, struct lyd_node *node, struct lyd_meta **dup)
2041
0
{
2042
0
    LY_ERR ret = LY_SUCCESS;
2043
0
    const struct ly_ctx *ctx;
2044
0
    struct lyd_meta *mt, *last;
2045
2046
0
    LY_CHECK_ARG_RET(NULL, meta, node, LY_EINVAL);
2047
2048
    /* log to node context but value must always use the annotation context */
2049
0
    ctx = meta->annotation->module->ctx;
2050
2051
    /* create a copy */
2052
0
    mt = calloc(1, sizeof *mt);
2053
0
    LY_CHECK_ERR_RET(!mt, LOGMEM(LYD_CTX(node)), LY_EMEM);
2054
0
    mt->annotation = meta->annotation;
2055
0
    ret = meta->value.realtype->plugin->duplicate(ctx, &meta->value, &mt->value);
2056
0
    LY_CHECK_ERR_GOTO(ret, LOGERR(LYD_CTX(node), LY_EINT, "Value duplication failed."), finish);
2057
0
    LY_CHECK_GOTO(ret = lydict_insert(ctx, meta->name, 0, &mt->name), finish);
2058
2059
    /* insert as the last attribute */
2060
0
    mt->parent = node;
2061
0
    if (node->meta) {
2062
0
        for (last = node->meta; last->next; last = last->next) {}
2063
0
        last->next = mt;
2064
0
    } else {
2065
0
        node->meta = mt;
2066
0
    }
2067
2068
0
finish:
2069
0
    if (ret) {
2070
0
        lyd_free_meta_single(mt);
2071
0
    } else if (dup) {
2072
0
        *dup = mt;
2073
0
    }
2074
0
    return LY_SUCCESS;
2075
0
}
2076
2077
/**
2078
 * @brief Merge a source sibling into target siblings.
2079
 *
2080
 * @param[in,out] first_trg First target sibling, is updated if top-level.
2081
 * @param[in] parent_trg Target parent.
2082
 * @param[in,out] sibling_src Source sibling to merge, set to NULL if spent.
2083
 * @param[in] merge_cb Optional merge callback.
2084
 * @param[in] cb_data Arbitrary callback data.
2085
 * @param[in] options Merge options.
2086
 * @param[in,out] dup_inst Duplicate instance cache for all @p first_trg siblings.
2087
 * @return LY_ERR value.
2088
 */
2089
static LY_ERR
2090
lyd_merge_sibling_r(struct lyd_node **first_trg, struct lyd_node *parent_trg, const struct lyd_node **sibling_src_p,
2091
        lyd_merge_cb merge_cb, void *cb_data, uint16_t options, struct ly_ht **dup_inst)
2092
0
{
2093
0
    const struct lyd_node *child_src, *tmp, *sibling_src;
2094
0
    struct lyd_node *match_trg, *dup_src, *elem;
2095
0
    struct lyd_node_opaq *opaq_trg, *opaq_src;
2096
0
    struct lysc_type *type;
2097
0
    struct ly_ht *child_dup_inst = NULL;
2098
0
    LY_ERR ret;
2099
0
    ly_bool first_inst = 0;
2100
2101
0
    sibling_src = *sibling_src_p;
2102
0
    if (!sibling_src->schema) {
2103
        /* try to find the same opaque node */
2104
0
        lyd_find_sibling_opaq_next(*first_trg, LYD_NAME(sibling_src), &match_trg);
2105
0
    } else if (sibling_src->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
2106
        /* try to find the exact instance */
2107
0
        lyd_find_sibling_first(*first_trg, sibling_src, &match_trg);
2108
0
    } else {
2109
        /* try to simply find the node, there cannot be more instances */
2110
0
        lyd_find_sibling_val(*first_trg, sibling_src->schema, NULL, 0, &match_trg);
2111
0
    }
2112
2113
0
    if (match_trg) {
2114
        /* update match as needed */
2115
0
        LY_CHECK_RET(lyd_dup_inst_next(&match_trg, *first_trg, dup_inst));
2116
0
    } else {
2117
        /* first instance of this node */
2118
0
        first_inst = 1;
2119
0
    }
2120
2121
0
    if (match_trg) {
2122
        /* call callback */
2123
0
        if (merge_cb) {
2124
0
            LY_CHECK_RET(merge_cb(match_trg, sibling_src, cb_data));
2125
0
        }
2126
2127
        /* node found, make sure even value matches for all node types */
2128
0
        if (!match_trg->schema) {
2129
0
            if (lyd_compare_single(sibling_src, match_trg, 0)) {
2130
                /* update value */
2131
0
                opaq_trg = (struct lyd_node_opaq *)match_trg;
2132
0
                opaq_src = (struct lyd_node_opaq *)sibling_src;
2133
2134
0
                lydict_remove(LYD_CTX(opaq_trg), opaq_trg->value);
2135
0
                lydict_insert(LYD_CTX(opaq_trg), opaq_src->value, 0, &opaq_trg->value);
2136
0
                opaq_trg->hints = opaq_src->hints;
2137
2138
0
                ly_free_prefix_data(opaq_trg->format, opaq_trg->val_prefix_data);
2139
0
                opaq_trg->format = opaq_src->format;
2140
0
                ly_dup_prefix_data(LYD_CTX(opaq_trg), opaq_src->format, opaq_src->val_prefix_data,
2141
0
                        &opaq_trg->val_prefix_data);
2142
0
            }
2143
0
        } else if ((match_trg->schema->nodetype == LYS_LEAF) &&
2144
0
                lyd_compare_single(sibling_src, match_trg, LYD_COMPARE_DEFAULTS)) {
2145
            /* since they are different, they cannot both be default */
2146
0
            assert(!(sibling_src->flags & LYD_DEFAULT) || !(match_trg->flags & LYD_DEFAULT));
2147
2148
            /* update value (or only LYD_DEFAULT flag) only if flag set or the source node is not default */
2149
0
            if ((options & LYD_MERGE_DEFAULTS) || !(sibling_src->flags & LYD_DEFAULT)) {
2150
0
                type = ((struct lysc_node_leaf *)match_trg->schema)->type;
2151
0
                type->plugin->free(LYD_CTX(match_trg), &((struct lyd_node_term *)match_trg)->value);
2152
0
                LY_CHECK_RET(type->plugin->duplicate(LYD_CTX(match_trg), &((struct lyd_node_term *)sibling_src)->value,
2153
0
                        &((struct lyd_node_term *)match_trg)->value));
2154
2155
                /* copy flags and add LYD_NEW */
2156
0
                match_trg->flags = sibling_src->flags | ((options & LYD_MERGE_WITH_FLAGS) ? 0 : LYD_NEW);
2157
0
            }
2158
0
        } else if ((match_trg->schema->nodetype & LYS_ANYDATA) && lyd_compare_single(sibling_src, match_trg, 0)) {
2159
            /* update value */
2160
0
            LY_CHECK_RET(lyd_any_copy_value(match_trg, &((struct lyd_node_any *)sibling_src)->value,
2161
0
                    ((struct lyd_node_any *)sibling_src)->value_type));
2162
2163
            /* copy flags and add LYD_NEW */
2164
0
            match_trg->flags = sibling_src->flags | ((options & LYD_MERGE_WITH_FLAGS) ? 0 : LYD_NEW);
2165
0
        }
2166
2167
        /* check descendants, recursively */
2168
0
        ret = LY_SUCCESS;
2169
0
        LY_LIST_FOR_SAFE(lyd_child_no_keys(sibling_src), tmp, child_src) {
2170
0
            ret = lyd_merge_sibling_r(lyd_node_child_p(match_trg), match_trg, &child_src, merge_cb, cb_data, options,
2171
0
                    &child_dup_inst);
2172
0
            if (ret) {
2173
0
                break;
2174
0
            }
2175
0
        }
2176
0
        lyd_dup_inst_free(child_dup_inst);
2177
0
        LY_CHECK_RET(ret);
2178
0
    } else {
2179
        /* node not found, merge it */
2180
0
        if (options & LYD_MERGE_DESTRUCT) {
2181
0
            dup_src = (struct lyd_node *)sibling_src;
2182
0
            lyd_unlink_tree(dup_src);
2183
            /* spend it */
2184
0
            *sibling_src_p = NULL;
2185
0
        } else {
2186
0
            LY_CHECK_RET(lyd_dup_single(sibling_src, NULL, LYD_DUP_RECURSIVE | LYD_DUP_WITH_FLAGS, &dup_src));
2187
0
        }
2188
2189
0
        if (!(options & LYD_MERGE_WITH_FLAGS)) {
2190
            /* set LYD_NEW for all the new nodes, required for validation */
2191
0
            LYD_TREE_DFS_BEGIN(dup_src, elem) {
2192
0
                elem->flags |= LYD_NEW;
2193
0
                LYD_TREE_DFS_END(dup_src, elem);
2194
0
            }
2195
0
        }
2196
2197
        /* insert */
2198
0
        lyd_insert_node(parent_trg, first_trg, dup_src, 0);
2199
2200
0
        if (first_inst) {
2201
            /* remember not to find this instance next time */
2202
0
            LY_CHECK_RET(lyd_dup_inst_next(&dup_src, *first_trg, dup_inst));
2203
0
        }
2204
2205
        /* call callback, no source node */
2206
0
        if (merge_cb) {
2207
0
            LY_CHECK_RET(merge_cb(dup_src, NULL, cb_data));
2208
0
        }
2209
0
    }
2210
2211
0
    return LY_SUCCESS;
2212
0
}
2213
2214
static LY_ERR
2215
lyd_merge(struct lyd_node **target, const struct lyd_node *source, const struct lys_module *mod,
2216
        lyd_merge_cb merge_cb, void *cb_data, uint16_t options, ly_bool nosiblings)
2217
0
{
2218
0
    const struct lyd_node *sibling_src, *tmp;
2219
0
    struct ly_ht *dup_inst = NULL;
2220
0
    ly_bool first;
2221
0
    LY_ERR ret = LY_SUCCESS;
2222
2223
0
    LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
2224
0
    LY_CHECK_CTX_EQUAL_RET(*target ? LYD_CTX(*target) : NULL, source ? LYD_CTX(source) : NULL, mod ? mod->ctx : NULL,
2225
0
            LY_EINVAL);
2226
2227
0
    if (!source) {
2228
        /* nothing to merge */
2229
0
        return LY_SUCCESS;
2230
0
    }
2231
2232
0
    if ((*target && lysc_data_parent((*target)->schema)) || lysc_data_parent(source->schema)) {
2233
0
        LOGERR(LYD_CTX(source), LY_EINVAL, "Invalid arguments - can merge only 2 top-level subtrees (%s()).", __func__);
2234
0
        return LY_EINVAL;
2235
0
    }
2236
2237
0
    LY_LIST_FOR_SAFE(source, tmp, sibling_src) {
2238
0
        if (mod && (lyd_owner_module(sibling_src) != mod)) {
2239
            /* skip data nodes from different modules */
2240
0
            continue;
2241
0
        }
2242
2243
0
        first = (sibling_src == source) ? 1 : 0;
2244
0
        ret = lyd_merge_sibling_r(target, NULL, &sibling_src, merge_cb, cb_data, options, &dup_inst);
2245
0
        if (ret) {
2246
0
            break;
2247
0
        }
2248
0
        if (first && !sibling_src) {
2249
            /* source was spent (unlinked), move to the next node */
2250
0
            source = tmp;
2251
0
        }
2252
2253
0
        if (nosiblings) {
2254
0
            break;
2255
0
        }
2256
0
    }
2257
2258
0
    if (options & LYD_MERGE_DESTRUCT) {
2259
        /* free any leftover source data that were not merged */
2260
0
        lyd_free_siblings((struct lyd_node *)source);
2261
0
    }
2262
2263
0
    lyd_dup_inst_free(dup_inst);
2264
0
    return ret;
2265
0
}
2266
2267
LIBYANG_API_DEF LY_ERR
2268
lyd_merge_tree(struct lyd_node **target, const struct lyd_node *source, uint16_t options)
2269
0
{
2270
0
    return lyd_merge(target, source, NULL, NULL, NULL, options, 1);
2271
0
}
2272
2273
LIBYANG_API_DEF LY_ERR
2274
lyd_merge_siblings(struct lyd_node **target, const struct lyd_node *source, uint16_t options)
2275
0
{
2276
0
    return lyd_merge(target, source, NULL, NULL, NULL, options, 0);
2277
0
}
2278
2279
LIBYANG_API_DEF LY_ERR
2280
lyd_merge_module(struct lyd_node **target, const struct lyd_node *source, const struct lys_module *mod,
2281
        lyd_merge_cb merge_cb, void *cb_data, uint16_t options)
2282
0
{
2283
0
    return lyd_merge(target, source, mod, merge_cb, cb_data, options, 0);
2284
0
}
2285
2286
static LY_ERR
2287
lyd_path_str_enlarge(char **buffer, size_t *buflen, size_t reqlen, ly_bool is_static)
2288
131k
{
2289
    /* ending \0 */
2290
131k
    ++reqlen;
2291
2292
131k
    if (reqlen > *buflen) {
2293
131k
        if (is_static) {
2294
0
            return LY_EINCOMPLETE;
2295
0
        }
2296
2297
131k
        *buffer = ly_realloc(*buffer, reqlen * sizeof **buffer);
2298
131k
        if (!*buffer) {
2299
0
            return LY_EMEM;
2300
0
        }
2301
2302
131k
        *buflen = reqlen;
2303
131k
    }
2304
2305
131k
    return LY_SUCCESS;
2306
131k
}
2307
2308
LY_ERR
2309
lyd_path_list_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, ly_bool is_static)
2310
753
{
2311
753
    const struct lyd_node *key;
2312
753
    size_t len;
2313
753
    const char *val;
2314
753
    char quot;
2315
2316
129k
    for (key = lyd_child(node); key && key->schema && (key->schema->flags & LYS_KEY); key = key->next) {
2317
128k
        val = lyd_get_value(key);
2318
128k
        len = 1 + strlen(key->schema->name) + 2 + strlen(val) + 2;
2319
128k
        LY_CHECK_RET(lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static));
2320
2321
128k
        quot = '\'';
2322
128k
        if (strchr(val, '\'')) {
2323
16.1k
            quot = '"';
2324
16.1k
        }
2325
128k
        *bufused += sprintf(*buffer + *bufused, "[%s=%c%s%c]", key->schema->name, quot, val, quot);
2326
128k
    }
2327
2328
753
    return LY_SUCCESS;
2329
753
}
2330
2331
/**
2332
 * @brief Append leaf-list value predicate to path.
2333
 *
2334
 * @param[in] node Node to print.
2335
 * @param[in,out] buffer Buffer to print to.
2336
 * @param[in,out] buflen Current buffer length.
2337
 * @param[in,out] bufused Current number of characters used in @p buffer.
2338
 * @param[in] is_static Whether buffer is static or can be reallocated.
2339
 * @return LY_ERR
2340
 */
2341
static LY_ERR
2342
lyd_path_leaflist_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, ly_bool is_static)
2343
102
{
2344
102
    size_t len;
2345
102
    const char *val;
2346
102
    char quot;
2347
2348
102
    val = lyd_get_value(node);
2349
102
    len = 4 + strlen(val) + 2; /* "[.='" + val + "']" */
2350
102
    LY_CHECK_RET(lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static));
2351
2352
102
    quot = '\'';
2353
102
    if (strchr(val, '\'')) {
2354
32
        quot = '"';
2355
32
    }
2356
102
    *bufused += sprintf(*buffer + *bufused, "[.=%c%s%c]", quot, val, quot);
2357
2358
102
    return LY_SUCCESS;
2359
102
}
2360
2361
/**
2362
 * @brief Append node position (relative to its other instances) predicate to path.
2363
 *
2364
 * @param[in] node Node to print.
2365
 * @param[in,out] buffer Buffer to print to.
2366
 * @param[in,out] buflen Current buffer length.
2367
 * @param[in,out] bufused Current number of characters used in @p buffer.
2368
 * @param[in] is_static Whether buffer is static or can be reallocated.
2369
 * @return LY_ERR
2370
 */
2371
static LY_ERR
2372
lyd_path_position_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, ly_bool is_static)
2373
0
{
2374
0
    size_t len;
2375
0
    uint32_t pos;
2376
0
    char *val = NULL;
2377
0
    LY_ERR rc;
2378
2379
0
    pos = lyd_list_pos(node);
2380
0
    if (asprintf(&val, "%" PRIu32, pos) == -1) {
2381
0
        return LY_EMEM;
2382
0
    }
2383
2384
0
    len = 1 + strlen(val) + 1;
2385
0
    rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2386
0
    if (rc != LY_SUCCESS) {
2387
0
        goto cleanup;
2388
0
    }
2389
2390
0
    *bufused += sprintf(*buffer + *bufused, "[%s]", val);
2391
2392
0
cleanup:
2393
0
    free(val);
2394
0
    return rc;
2395
0
}
2396
2397
LIBYANG_API_DEF char *
2398
lyd_path(const struct lyd_node *node, LYD_PATH_TYPE pathtype, char *buffer, size_t buflen)
2399
2.38k
{
2400
2.38k
    ly_bool is_static = 0;
2401
2.38k
    uint32_t i, depth;
2402
2.38k
    size_t bufused = 0, len;
2403
2.38k
    const struct lyd_node *iter, *parent;
2404
2.38k
    const struct lys_module *mod, *prev_mod;
2405
2.38k
    LY_ERR rc = LY_SUCCESS;
2406
2407
2.38k
    LY_CHECK_ARG_RET(NULL, node, NULL);
2408
2.38k
    if (buffer) {
2409
0
        LY_CHECK_ARG_RET(LYD_CTX(node), buflen > 1, NULL);
2410
0
        is_static = 1;
2411
2.38k
    } else {
2412
2.38k
        buflen = 0;
2413
2.38k
    }
2414
2415
2.38k
    switch (pathtype) {
2416
2.38k
    case LYD_PATH_STD:
2417
2.38k
    case LYD_PATH_STD_NO_LAST_PRED:
2418
2.38k
        depth = 1;
2419
2.45k
        for (iter = node; iter->parent; iter = lyd_parent(iter)) {
2420
73
            ++depth;
2421
73
        }
2422
2423
2.38k
        goto iter_print;
2424
2.45k
        while (depth) {
2425
            /* find the right node */
2426
73
            for (iter = node, i = 1; i < depth; iter = lyd_parent(iter), ++i) {}
2427
2.45k
iter_print:
2428
            /* get the module */
2429
2.45k
            mod = lyd_node_module(iter);
2430
2.45k
            parent = lyd_parent(iter);
2431
2.45k
            prev_mod = lyd_node_module(parent);
2432
2.45k
            if (prev_mod == mod) {
2433
92
                mod = NULL;
2434
92
            }
2435
2436
            /* realloc string */
2437
2.45k
            len = 1 + (mod ? strlen(mod->name) + 1 : 0) + (iter->schema ? strlen(iter->schema->name) :
2438
2.45k
                    strlen(((struct lyd_node_opaq *)iter)->name.name));
2439
2.45k
            rc = lyd_path_str_enlarge(&buffer, &buflen, bufused + len, is_static);
2440
2.45k
            if (rc != LY_SUCCESS) {
2441
0
                break;
2442
0
            }
2443
2444
            /* print next node */
2445
2.45k
            bufused += sprintf(buffer + bufused, "/%s%s%s", mod ? mod->name : "", mod ? ":" : "", LYD_NAME(iter));
2446
2447
            /* do not always print the last (first) predicate */
2448
2.45k
            if (iter->schema && ((depth > 1) || (pathtype == LYD_PATH_STD))) {
2449
2.41k
                switch (iter->schema->nodetype) {
2450
487
                case LYS_LIST:
2451
487
                    if (iter->schema->flags & LYS_KEYLESS) {
2452
                        /* print its position */
2453
0
                        rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2454
487
                    } else {
2455
                        /* print all list keys in predicates */
2456
487
                        rc = lyd_path_list_predicate(iter, &buffer, &buflen, &bufused, is_static);
2457
487
                    }
2458
487
                    break;
2459
48
                case LYS_LEAFLIST:
2460
48
                    if (iter->schema->flags & LYS_CONFIG_W) {
2461
                        /* print leaf-list value */
2462
48
                        rc = lyd_path_leaflist_predicate(iter, &buffer, &buflen, &bufused, is_static);
2463
48
                    } else {
2464
                        /* print its position */
2465
0
                        rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2466
0
                    }
2467
48
                    break;
2468
1.88k
                default:
2469
                    /* nothing to print more */
2470
1.88k
                    break;
2471
2.41k
                }
2472
2.41k
            }
2473
2.45k
            if (rc != LY_SUCCESS) {
2474
0
                break;
2475
0
            }
2476
2477
2.45k
            --depth;
2478
2.45k
        }
2479
2.38k
        break;
2480
2.38k
    }
2481
2482
2.38k
    return buffer;
2483
2.38k
}
2484
2485
char *
2486
lyd_path_set(const struct ly_set *dnodes, LYD_PATH_TYPE pathtype)
2487
271
{
2488
271
    uint32_t depth;
2489
271
    size_t bufused = 0, buflen = 0, len;
2490
271
    char *buffer = NULL;
2491
271
    const struct lyd_node *iter, *parent;
2492
271
    const struct lys_module *mod, *prev_mod;
2493
271
    LY_ERR rc = LY_SUCCESS;
2494
2495
271
    switch (pathtype) {
2496
271
    case LYD_PATH_STD:
2497
271
    case LYD_PATH_STD_NO_LAST_PRED:
2498
813
        for (depth = 1; depth <= dnodes->count; ++depth) {
2499
            /* current node */
2500
542
            iter = dnodes->dnodes[depth - 1];
2501
542
            mod = lyd_node_module(iter);
2502
2503
            /* parent */
2504
542
            parent = (depth > 1) ? dnodes->dnodes[depth - 2] : NULL;
2505
542
            assert(!parent || !iter->schema || !parent->schema || (parent->schema->nodetype & LYD_NODE_ANY) ||
2506
542
                    (lysc_data_parent(iter->schema) == parent->schema) ||
2507
542
                    (!lysc_data_parent(iter->schema) && (LYD_CTX(iter) != LYD_CTX(parent))) ||
2508
542
                    (parent->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)));
2509
2510
            /* get module to print, if any */
2511
0
            prev_mod = lyd_node_module(parent);
2512
542
            if (prev_mod == mod) {
2513
271
                mod = NULL;
2514
271
            }
2515
2516
            /* realloc string */
2517
542
            len = 1 + (mod ? strlen(mod->name) + 1 : 0) + (iter->schema ? strlen(iter->schema->name) :
2518
542
                    strlen(((struct lyd_node_opaq *)iter)->name.name));
2519
542
            if ((rc = lyd_path_str_enlarge(&buffer, &buflen, bufused + len, 0))) {
2520
0
                break;
2521
0
            }
2522
2523
            /* print next node */
2524
542
            bufused += sprintf(buffer + bufused, "/%s%s%s", mod ? mod->name : "", mod ? ":" : "", LYD_NAME(iter));
2525
2526
            /* do not always print the last (first) predicate */
2527
542
            if (iter->schema && ((depth > 1) || (pathtype == LYD_PATH_STD))) {
2528
542
                switch (iter->schema->nodetype) {
2529
266
                case LYS_LIST:
2530
266
                    if (iter->schema->flags & LYS_KEYLESS) {
2531
                        /* print its position */
2532
0
                        rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, 0);
2533
266
                    } else {
2534
                        /* print all list keys in predicates */
2535
266
                        rc = lyd_path_list_predicate(iter, &buffer, &buflen, &bufused, 0);
2536
266
                    }
2537
266
                    break;
2538
54
                case LYS_LEAFLIST:
2539
54
                    if (iter->schema->flags & LYS_CONFIG_W) {
2540
                        /* print leaf-list value */
2541
54
                        rc = lyd_path_leaflist_predicate(iter, &buffer, &buflen, &bufused, 0);
2542
54
                    } else {
2543
                        /* print its position */
2544
0
                        rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, 0);
2545
0
                    }
2546
54
                    break;
2547
222
                default:
2548
                    /* nothing to print more */
2549
222
                    break;
2550
542
                }
2551
542
            }
2552
542
            if (rc) {
2553
0
                break;
2554
0
            }
2555
542
        }
2556
271
        break;
2557
271
    }
2558
2559
271
    return buffer;
2560
271
}
2561
2562
LIBYANG_API_DEF struct lyd_meta *
2563
lyd_find_meta(const struct lyd_meta *first, const struct lys_module *module, const char *name)
2564
0
{
2565
0
    struct lyd_meta *ret = NULL;
2566
0
    const struct ly_ctx *ctx;
2567
0
    const char *prefix, *tmp;
2568
0
    char *str;
2569
0
    size_t pref_len, name_len;
2570
2571
0
    LY_CHECK_ARG_RET(NULL, module || strchr(name, ':'), name, NULL);
2572
0
    LY_CHECK_CTX_EQUAL_RET(first ? first->annotation->module->ctx : NULL, module ? module->ctx : NULL, NULL);
2573
2574
0
    if (!first) {
2575
0
        return NULL;
2576
0
    }
2577
2578
0
    ctx = first->annotation->module->ctx;
2579
2580
    /* parse the name */
2581
0
    tmp = name;
2582
0
    if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
2583
0
        LOGERR(ctx, LY_EINVAL, "Metadata name \"%s\" is not valid.", name);
2584
0
        return NULL;
2585
0
    }
2586
2587
    /* find the module */
2588
0
    if (prefix) {
2589
0
        str = strndup(prefix, pref_len);
2590
0
        module = ly_ctx_get_module_latest(ctx, str);
2591
0
        free(str);
2592
0
        LY_CHECK_ERR_RET(!module, LOGERR(ctx, LY_EINVAL, "Module \"%.*s\" not found.", (int)pref_len, prefix), NULL);
2593
0
    }
2594
2595
    /* find the metadata */
2596
0
    LY_LIST_FOR(first, first) {
2597
0
        if ((first->annotation->module == module) && !strcmp(first->name, name)) {
2598
0
            ret = (struct lyd_meta *)first;
2599
0
            break;
2600
0
        }
2601
0
    }
2602
2603
0
    return ret;
2604
0
}
2605
2606
LIBYANG_API_DEF LY_ERR
2607
lyd_find_sibling_first(const struct lyd_node *siblings, const struct lyd_node *target, struct lyd_node **match)
2608
37.2k
{
2609
37.2k
    struct lyd_node **match_p, *iter, *dup = NULL;
2610
37.2k
    struct lyd_node_inner *parent;
2611
37.2k
    ly_bool found;
2612
2613
37.2k
    LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
2614
37.2k
    if (!siblings) {
2615
        /* no data */
2616
0
        if (match) {
2617
0
            *match = NULL;
2618
0
        }
2619
0
        return LY_ENOTFOUND;
2620
0
    }
2621
2622
37.2k
    if (LYD_CTX(siblings) != LYD_CTX(target)) {
2623
        /* create a duplicate in this context */
2624
0
        LY_CHECK_RET(lyd_dup_single_to_ctx(target, LYD_CTX(siblings), NULL, 0, &dup));
2625
0
        target = dup;
2626
0
    }
2627
2628
37.2k
    if ((siblings->schema && target->schema && (lysc_data_parent(siblings->schema) != lysc_data_parent(target->schema)))) {
2629
        /* schema mismatch */
2630
0
        lyd_free_tree(dup);
2631
0
        if (match) {
2632
0
            *match = NULL;
2633
0
        }
2634
0
        return LY_ENOTFOUND;
2635
0
    }
2636
2637
    /* get first sibling */
2638
37.2k
    siblings = lyd_first_sibling(siblings);
2639
2640
37.2k
    parent = siblings->parent;
2641
37.2k
    if (target->schema && parent && parent->schema && parent->children_ht) {
2642
37.1k
        assert(target->hash);
2643
2644
37.1k
        if (lysc_is_dup_inst_list(target->schema)) {
2645
            /* we must search the instances from beginning to find the first matching one */
2646
0
            found = 0;
2647
0
            LYD_LIST_FOR_INST(siblings, target->schema, iter) {
2648
0
                if (!lyd_compare_single(target, iter, LYD_COMPARE_FULL_RECURSION)) {
2649
0
                    found = 1;
2650
0
                    break;
2651
0
                }
2652
0
            }
2653
0
            if (found) {
2654
0
                siblings = iter;
2655
0
            } else {
2656
0
                siblings = NULL;
2657
0
            }
2658
37.1k
        } else {
2659
            /* find by hash */
2660
37.1k
            if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
2661
37.1k
                siblings = *match_p;
2662
37.1k
            } else {
2663
                /* not found */
2664
0
                siblings = NULL;
2665
0
            }
2666
37.1k
        }
2667
37.1k
    } else {
2668
        /* no children hash table or cannot be used */
2669
343
        for ( ; siblings; siblings = siblings->next) {
2670
332
            if (lysc_is_dup_inst_list(target->schema)) {
2671
0
                if (!lyd_compare_single(siblings, target, LYD_COMPARE_FULL_RECURSION)) {
2672
0
                    break;
2673
0
                }
2674
332
            } else {
2675
332
                if (!lyd_compare_single(siblings, target, 0)) {
2676
112
                    break;
2677
112
                }
2678
332
            }
2679
332
        }
2680
123
    }
2681
2682
0
    lyd_free_tree(dup);
2683
37.2k
    if (!siblings) {
2684
11
        if (match) {
2685
11
            *match = NULL;
2686
11
        }
2687
11
        return LY_ENOTFOUND;
2688
11
    }
2689
2690
37.2k
    if (match) {
2691
37.2k
        *match = (struct lyd_node *)siblings;
2692
37.2k
    }
2693
37.2k
    return LY_SUCCESS;
2694
37.2k
}
2695
2696
LIBYANG_API_DEF LY_ERR
2697
lyd_find_sibling_val(const struct lyd_node *siblings, const struct lysc_node *schema, const char *key_or_value,
2698
        size_t val_len, struct lyd_node **match)
2699
1.11k
{
2700
1.11k
    LY_ERR rc;
2701
1.11k
    struct lyd_node *target = NULL;
2702
1.11k
    const struct lyd_node *parent;
2703
2704
1.11k
    LY_CHECK_ARG_RET(NULL, schema, !(schema->nodetype & (LYS_CHOICE | LYS_CASE)), LY_EINVAL);
2705
1.11k
    if (!siblings) {
2706
        /* no data */
2707
156
        if (match) {
2708
156
            *match = NULL;
2709
156
        }
2710
156
        return LY_ENOTFOUND;
2711
156
    }
2712
2713
957
    if ((LYD_CTX(siblings) != schema->module->ctx)) {
2714
        /* parent of ext nodes is useless */
2715
0
        parent = (siblings->flags & LYD_EXT) ? NULL : lyd_parent(siblings);
2716
0
        if (lyd_find_schema_ctx(schema, LYD_CTX(siblings), parent, 0, &schema)) {
2717
            /* no schema node in siblings so certainly no data node either */
2718
0
            if (match) {
2719
0
                *match = NULL;
2720
0
            }
2721
0
            return LY_ENOTFOUND;
2722
0
        }
2723
0
    }
2724
2725
957
    if (siblings->schema && (lysc_data_parent(siblings->schema) != lysc_data_parent(schema))) {
2726
        /* schema mismatch */
2727
0
        if (match) {
2728
0
            *match = NULL;
2729
0
        }
2730
0
        return LY_ENOTFOUND;
2731
0
    }
2732
2733
957
    if (key_or_value && !val_len) {
2734
0
        val_len = strlen(key_or_value);
2735
0
    }
2736
2737
957
    if ((schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) && key_or_value) {
2738
        /* create a data node and find the instance */
2739
0
        if (schema->nodetype == LYS_LEAFLIST) {
2740
            /* target used attributes: schema, hash, value */
2741
0
            rc = lyd_create_term(schema, key_or_value, val_len, 0, NULL, LY_VALUE_JSON, NULL, LYD_HINT_DATA, NULL, &target);
2742
0
            LY_CHECK_RET(rc);
2743
0
        } else {
2744
            /* target used attributes: schema, hash, child (all keys) */
2745
0
            LY_CHECK_RET(lyd_create_list2(schema, key_or_value, val_len, &target));
2746
0
        }
2747
2748
        /* find it */
2749
0
        rc = lyd_find_sibling_first(siblings, target, match);
2750
957
    } else {
2751
        /* find the first schema node instance */
2752
957
        rc = lyd_find_sibling_schema(siblings, schema, match);
2753
957
    }
2754
2755
957
    lyd_free_tree(target);
2756
957
    return rc;
2757
957
}
2758
2759
LIBYANG_API_DEF LY_ERR
2760
lyd_find_sibling_dup_inst_set(const struct lyd_node *siblings, const struct lyd_node *target, struct ly_set **set)
2761
0
{
2762
0
    struct lyd_node **match_p, *first, *iter;
2763
0
    struct lyd_node_inner *parent;
2764
0
    uint32_t comp_opts;
2765
2766
0
    LY_CHECK_ARG_RET(NULL, target, set, LY_EINVAL);
2767
0
    LY_CHECK_CTX_EQUAL_RET(siblings ? LYD_CTX(siblings) : NULL, LYD_CTX(target), LY_EINVAL);
2768
2769
0
    LY_CHECK_RET(ly_set_new(set));
2770
2771
0
    if (!siblings || (siblings->schema && (lysc_data_parent(siblings->schema) != lysc_data_parent(target->schema)))) {
2772
        /* no data or schema mismatch */
2773
0
        return LY_ENOTFOUND;
2774
0
    }
2775
2776
    /* set options */
2777
0
    comp_opts = (lysc_is_dup_inst_list(target->schema) ? LYD_COMPARE_FULL_RECURSION : 0);
2778
2779
    /* get first sibling */
2780
0
    siblings = lyd_first_sibling(siblings);
2781
2782
0
    parent = siblings->parent;
2783
0
    if (parent && parent->schema && parent->children_ht) {
2784
0
        assert(target->hash);
2785
2786
        /* find the first instance */
2787
0
        lyd_find_sibling_first(siblings, target, &first);
2788
0
        if (first) {
2789
            /* add it so that it is the first in the set */
2790
0
            if (ly_set_add(*set, first, 1, NULL)) {
2791
0
                goto error;
2792
0
            }
2793
2794
            /* find by hash */
2795
0
            if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
2796
0
                iter = *match_p;
2797
0
            } else {
2798
                /* not found */
2799
0
                iter = NULL;
2800
0
            }
2801
0
            while (iter) {
2802
                /* add all found nodes into the set */
2803
0
                if ((iter != first) && !lyd_compare_single(iter, target, comp_opts) && ly_set_add(*set, iter, 1, NULL)) {
2804
0
                    goto error;
2805
0
                }
2806
2807
                /* find next instance */
2808
0
                if (lyht_find_next(parent->children_ht, &iter, iter->hash, (void **)&match_p)) {
2809
0
                    iter = NULL;
2810
0
                } else {
2811
0
                    iter = *match_p;
2812
0
                }
2813
0
            }
2814
0
        }
2815
0
    } else {
2816
        /* no children hash table */
2817
0
        LY_LIST_FOR(siblings, siblings) {
2818
0
            if (!lyd_compare_single(target, siblings, comp_opts)) {
2819
0
                ly_set_add(*set, (void *)siblings, 1, NULL);
2820
0
            }
2821
0
        }
2822
0
    }
2823
2824
0
    if (!(*set)->count) {
2825
0
        return LY_ENOTFOUND;
2826
0
    }
2827
0
    return LY_SUCCESS;
2828
2829
0
error:
2830
0
    ly_set_free(*set, NULL);
2831
0
    *set = NULL;
2832
0
    return LY_EMEM;
2833
0
}
2834
2835
LIBYANG_API_DEF LY_ERR
2836
lyd_find_sibling_opaq_next(const struct lyd_node *first, const char *name, struct lyd_node **match)
2837
133
{
2838
133
    LY_CHECK_ARG_RET(NULL, name, LY_EINVAL);
2839
2840
133
    if (first && first->schema) {
2841
133
        first = first->prev;
2842
133
        if (first->schema) {
2843
            /* no opaque nodes */
2844
133
            first = NULL;
2845
133
        } else {
2846
            /* opaque nodes are at the end, find quickly the first */
2847
0
            while (!first->prev->schema) {
2848
0
                first = first->prev;
2849
0
            }
2850
0
        }
2851
133
    }
2852
2853
133
    for ( ; first; first = first->next) {
2854
0
        assert(!first->schema);
2855
0
        if (!strcmp(LYD_NAME(first), name)) {
2856
0
            break;
2857
0
        }
2858
0
    }
2859
2860
133
    if (match) {
2861
133
        *match = (struct lyd_node *)first;
2862
133
    }
2863
133
    return first ? LY_SUCCESS : LY_ENOTFOUND;
2864
133
}
2865
2866
LIBYANG_API_DEF LY_ERR
2867
lyd_find_xpath(const struct lyd_node *ctx_node, const char *xpath, struct ly_set **set)
2868
0
{
2869
0
    LY_CHECK_ARG_RET(NULL, ctx_node, xpath, set, LY_EINVAL);
2870
2871
0
    return lyd_find_xpath4(ctx_node, ctx_node, xpath, LY_VALUE_JSON, NULL, NULL, set);
2872
0
}
2873
2874
LIBYANG_API_DEF LY_ERR
2875
lyd_find_xpath2(const struct lyd_node *ctx_node, const char *xpath, const struct lyxp_var *vars, struct ly_set **set)
2876
0
{
2877
0
    LY_CHECK_ARG_RET(NULL, ctx_node, xpath, set, LY_EINVAL);
2878
2879
0
    return lyd_find_xpath4(ctx_node, ctx_node, xpath, LY_VALUE_JSON, NULL, vars, set);
2880
0
}
2881
2882
LIBYANG_API_DEF LY_ERR
2883
lyd_find_xpath3(const struct lyd_node *ctx_node, const struct lyd_node *tree, const char *xpath,
2884
        const struct lyxp_var *vars, struct ly_set **set)
2885
0
{
2886
0
    LY_CHECK_ARG_RET(NULL, tree, xpath, set, LY_EINVAL);
2887
2888
0
    return lyd_find_xpath4(ctx_node, tree, xpath, LY_VALUE_JSON, NULL, vars, set);
2889
0
}
2890
2891
LIBYANG_API_DEF LY_ERR
2892
lyd_find_xpath4(const struct lyd_node *ctx_node, const struct lyd_node *tree, const char *xpath, LY_VALUE_FORMAT format,
2893
        void *prefix_data, const struct lyxp_var *vars, struct ly_set **set)
2894
0
{
2895
0
    LY_CHECK_ARG_RET(NULL, tree, xpath, set, LY_EINVAL);
2896
2897
0
    *set = NULL;
2898
2899
0
    return lyd_eval_xpath4(ctx_node, tree, NULL, xpath, format, prefix_data, vars, NULL, set, NULL, NULL, NULL);
2900
0
}
2901
2902
LIBYANG_API_DEF LY_ERR
2903
lyd_eval_xpath(const struct lyd_node *ctx_node, const char *xpath, ly_bool *result)
2904
0
{
2905
0
    return lyd_eval_xpath3(ctx_node, NULL, xpath, LY_VALUE_JSON, NULL, NULL, result);
2906
0
}
2907
2908
LIBYANG_API_DEF LY_ERR
2909
lyd_eval_xpath2(const struct lyd_node *ctx_node, const char *xpath, const struct lyxp_var *vars, ly_bool *result)
2910
0
{
2911
0
    return lyd_eval_xpath3(ctx_node, NULL, xpath, LY_VALUE_JSON, NULL, vars, result);
2912
0
}
2913
2914
LIBYANG_API_DEF LY_ERR
2915
lyd_eval_xpath3(const struct lyd_node *ctx_node, const struct lys_module *cur_mod, const char *xpath,
2916
        LY_VALUE_FORMAT format, void *prefix_data, const struct lyxp_var *vars, ly_bool *result)
2917
0
{
2918
0
    return lyd_eval_xpath4(ctx_node, ctx_node, cur_mod, xpath, format, prefix_data, vars, NULL, NULL, NULL, NULL, result);
2919
0
}
2920
2921
LIBYANG_API_DEF LY_ERR
2922
lyd_eval_xpath4(const struct lyd_node *ctx_node, const struct lyd_node *tree, const struct lys_module *cur_mod,
2923
        const char *xpath, LY_VALUE_FORMAT format, void *prefix_data, const struct lyxp_var *vars, LY_XPATH_TYPE *ret_type,
2924
        struct ly_set **node_set, char **string, long double *number, ly_bool *boolean)
2925
0
{
2926
0
    LY_ERR ret = LY_SUCCESS;
2927
0
    struct lyxp_set xp_set = {0};
2928
0
    struct lyxp_expr *exp = NULL;
2929
0
    uint32_t i;
2930
2931
0
    LY_CHECK_ARG_RET(NULL, tree, xpath, ((ret_type && node_set && string && number && boolean) ||
2932
0
            (node_set && !string && !number && !boolean) || (!node_set && string && !number && !boolean) ||
2933
0
            (!node_set && !string && number && !boolean) || (!node_set && !string && !number && boolean)), LY_EINVAL);
2934
2935
    /* parse expression */
2936
0
    ret = lyxp_expr_parse((struct ly_ctx *)LYD_CTX(tree), xpath, 0, 1, &exp);
2937
0
    LY_CHECK_GOTO(ret, cleanup);
2938
2939
    /* evaluate expression */
2940
0
    ret = lyxp_eval(LYD_CTX(tree), exp, cur_mod, format, prefix_data, ctx_node, ctx_node, tree, vars, &xp_set,
2941
0
            LYXP_IGNORE_WHEN);
2942
0
    LY_CHECK_GOTO(ret, cleanup);
2943
2944
    /* return expected result type without or with casting */
2945
0
    if (node_set) {
2946
        /* node set */
2947
0
        if (xp_set.type == LYXP_SET_NODE_SET) {
2948
            /* transform into a set */
2949
0
            LY_CHECK_GOTO(ret = ly_set_new(node_set), cleanup);
2950
0
            (*node_set)->objs = malloc(xp_set.used * sizeof *(*node_set)->objs);
2951
0
            LY_CHECK_ERR_GOTO(!(*node_set)->objs, LOGMEM(LYD_CTX(tree)); ret = LY_EMEM, cleanup);
2952
0
            (*node_set)->size = xp_set.used;
2953
0
            for (i = 0; i < xp_set.used; ++i) {
2954
0
                if (xp_set.val.nodes[i].type == LYXP_NODE_ELEM) {
2955
0
                    ret = ly_set_add(*node_set, xp_set.val.nodes[i].node, 1, NULL);
2956
0
                    LY_CHECK_GOTO(ret, cleanup);
2957
0
                }
2958
0
            }
2959
0
            if (ret_type) {
2960
0
                *ret_type = LY_XPATH_NODE_SET;
2961
0
            }
2962
0
        } else if (!string && !number && !boolean) {
2963
0
            LOGERR(LYD_CTX(tree), LY_EINVAL, "XPath \"%s\" result is not a node set.", xpath);
2964
0
            ret = LY_EINVAL;
2965
0
            goto cleanup;
2966
0
        }
2967
0
    }
2968
2969
0
    if (string) {
2970
0
        if ((xp_set.type != LYXP_SET_STRING) && !node_set) {
2971
            /* cast into string */
2972
0
            LY_CHECK_GOTO(ret = lyxp_set_cast(&xp_set, LYXP_SET_STRING), cleanup);
2973
0
        }
2974
0
        if (xp_set.type == LYXP_SET_STRING) {
2975
            /* string */
2976
0
            *string = xp_set.val.str;
2977
0
            xp_set.val.str = NULL;
2978
0
            if (ret_type) {
2979
0
                *ret_type = LY_XPATH_STRING;
2980
0
            }
2981
0
        }
2982
0
    }
2983
2984
0
    if (number) {
2985
0
        if ((xp_set.type != LYXP_SET_NUMBER) && !node_set) {
2986
            /* cast into number */
2987
0
            LY_CHECK_GOTO(ret = lyxp_set_cast(&xp_set, LYXP_SET_NUMBER), cleanup);
2988
0
        }
2989
0
        if (xp_set.type == LYXP_SET_NUMBER) {
2990
            /* number */
2991
0
            *number = xp_set.val.num;
2992
0
            if (ret_type) {
2993
0
                *ret_type = LY_XPATH_NUMBER;
2994
0
            }
2995
0
        }
2996
0
    }
2997
2998
0
    if (boolean) {
2999
0
        if ((xp_set.type != LYXP_SET_BOOLEAN) && !node_set) {
3000
            /* cast into boolean */
3001
0
            LY_CHECK_GOTO(ret = lyxp_set_cast(&xp_set, LYXP_SET_BOOLEAN), cleanup);
3002
0
        }
3003
0
        if (xp_set.type == LYXP_SET_BOOLEAN) {
3004
            /* boolean */
3005
0
            *boolean = xp_set.val.bln;
3006
0
            if (ret_type) {
3007
0
                *ret_type = LY_XPATH_BOOLEAN;
3008
0
            }
3009
0
        }
3010
0
    }
3011
3012
0
cleanup:
3013
0
    lyxp_set_free_content(&xp_set);
3014
0
    lyxp_expr_free((struct ly_ctx *)LYD_CTX(tree), exp);
3015
0
    return ret;
3016
0
}
3017
3018
LIBYANG_API_DEF LY_ERR
3019
lyd_find_path(const struct lyd_node *ctx_node, const char *path, ly_bool output, struct lyd_node **match)
3020
0
{
3021
0
    LY_ERR ret = LY_SUCCESS;
3022
0
    struct lyxp_expr *expr = NULL;
3023
0
    struct ly_path *lypath = NULL;
3024
3025
0
    LY_CHECK_ARG_RET(NULL, ctx_node, ctx_node->schema, path, LY_EINVAL);
3026
3027
    /* parse the path */
3028
0
    ret = ly_path_parse(LYD_CTX(ctx_node), ctx_node->schema, path, strlen(path), 0, LY_PATH_BEGIN_EITHER,
3029
0
            LY_PATH_PREFIX_FIRST, LY_PATH_PRED_SIMPLE, &expr);
3030
0
    LY_CHECK_GOTO(ret, cleanup);
3031
3032
    /* compile the path */
3033
0
    ret = ly_path_compile(LYD_CTX(ctx_node), NULL, ctx_node->schema, NULL, expr,
3034
0
            output ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_SINGLE, 0, LY_VALUE_JSON, NULL, &lypath);
3035
0
    LY_CHECK_GOTO(ret, cleanup);
3036
3037
    /* evaluate the path */
3038
0
    ret = ly_path_eval_partial(lypath, ctx_node, NULL, 0, NULL, match);
3039
3040
0
cleanup:
3041
0
    lyxp_expr_free(LYD_CTX(ctx_node), expr);
3042
0
    ly_path_free(LYD_CTX(ctx_node), lypath);
3043
0
    return ret;
3044
0
}
3045
3046
LIBYANG_API_DEF LY_ERR
3047
lyd_find_target(const struct ly_path *path, const struct lyd_node *tree, struct lyd_node **match)
3048
0
{
3049
0
    LY_ERR ret;
3050
0
    struct lyd_node *m;
3051
3052
0
    LY_CHECK_ARG_RET(NULL, path, LY_EINVAL);
3053
3054
0
    ret = ly_path_eval(path, tree, NULL, &m);
3055
0
    if (ret) {
3056
0
        if (match) {
3057
0
            *match = NULL;
3058
0
        }
3059
0
        return LY_ENOTFOUND;
3060
0
    }
3061
3062
0
    if (match) {
3063
0
        *match = m;
3064
0
    }
3065
0
    return LY_SUCCESS;
3066
0
}
3067
3068
LIBYANG_API_DEF struct lyd_node *
3069
lyd_parent(const struct lyd_node *node)
3070
4.65k
{
3071
4.65k
    if (!node || !node->parent) {
3072
3.04k
        return NULL;
3073
3.04k
    }
3074
3075
1.60k
    return &node->parent->node;
3076
4.65k
}
3077
3078
LIBYANG_API_DEF struct lyd_node *
3079
lyd_child(const struct lyd_node *node)
3080
558k
{
3081
558k
    if (!node) {
3082
0
        return NULL;
3083
0
    }
3084
3085
558k
    if (!node->schema) {
3086
        /* opaq node */
3087
225
        return ((const struct lyd_node_opaq *)node)->child;
3088
225
    }
3089
3090
558k
    switch (node->schema->nodetype) {
3091
3.98k
    case LYS_CONTAINER:
3092
556k
    case LYS_LIST:
3093
556k
    case LYS_RPC:
3094
556k
    case LYS_ACTION:
3095
556k
    case LYS_NOTIF:
3096
556k
        return ((const struct lyd_node_inner *)node)->child;
3097
2.70k
    default:
3098
2.70k
        return NULL;
3099
558k
    }
3100
558k
}
3101
3102
LIBYANG_API_DEF const char *
3103
lyd_get_value(const struct lyd_node *node)
3104
177k
{
3105
177k
    if (!node) {
3106
0
        return NULL;
3107
0
    }
3108
3109
177k
    if (!node->schema) {
3110
0
        return ((const struct lyd_node_opaq *)node)->value;
3111
177k
    } else if (node->schema->nodetype & LYD_NODE_TERM) {
3112
177k
        const struct lyd_value *value = &((const struct lyd_node_term *)node)->value;
3113
3114
177k
        return value->_canonical ? value->_canonical : lyd_value_get_canonical(LYD_CTX(node), value);
3115
177k
    }
3116
3117
0
    return NULL;
3118
177k
}