Coverage Report

Created: 2025-08-28 06:29

/src/libyang/src/tree_data_helpers.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * @file tree_data_helpers.c
3
 * @author Radek Krejci <rkrejci@cesnet.cz>
4
 * @brief Parsing and validation helper functions for data trees
5
 *
6
 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
7
 *
8
 * This source code is licensed under BSD 3-Clause License (the "License").
9
 * You may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     https://opensource.org/licenses/BSD-3-Clause
13
 */
14
#define _POSIX_C_SOURCE 200809L /* strdup, strndup */
15
16
#include <assert.h>
17
#include <stdint.h>
18
#include <stdlib.h>
19
#include <string.h>
20
21
#include "common.h"
22
#include "compat.h"
23
#include "context.h"
24
#include "dict.h"
25
#include "hash_table.h"
26
#include "log.h"
27
#include "lyb.h"
28
#include "parser_data.h"
29
#include "printer_data.h"
30
#include "set.h"
31
#include "tree.h"
32
#include "tree_data.h"
33
#include "tree_data_internal.h"
34
#include "tree_edit.h"
35
#include "tree_schema.h"
36
#include "tree_schema_internal.h"
37
#include "validation.h"
38
#include "xml.h"
39
40
struct lyd_node *
41
lys_getnext_data(const struct lyd_node *last, const struct lyd_node *sibling, const struct lysc_node **slast,
42
        const struct lysc_node *parent, const struct lysc_module *module)
43
0
{
44
0
    const struct lysc_node *siter = NULL;
45
0
    struct lyd_node *match = NULL;
46
47
0
    assert(parent || module);
48
0
    assert(!last || (slast && *slast));
49
50
0
    if (slast) {
51
0
        siter = *slast;
52
0
    }
53
54
0
    if (last && last->next && (last->next->schema == siter)) {
55
        /* return next data instance */
56
0
        return last->next;
57
0
    }
58
59
    /* find next schema node data instance */
60
0
    while ((siter = lys_getnext(siter, parent, module, 0))) {
61
0
        if (!lyd_find_sibling_val(sibling, siter, NULL, 0, &match)) {
62
0
            break;
63
0
        }
64
0
    }
65
66
0
    if (slast) {
67
0
        *slast = siter;
68
0
    }
69
0
    return match;
70
0
}
71
72
struct lyd_node **
73
lyd_node_child_p(struct lyd_node *node)
74
0
{
75
0
    assert(node);
76
77
0
    if (!node->schema) {
78
0
        return &((struct lyd_node_opaq *)node)->child;
79
0
    } else {
80
0
        switch (node->schema->nodetype) {
81
0
        case LYS_CONTAINER:
82
0
        case LYS_LIST:
83
0
        case LYS_RPC:
84
0
        case LYS_ACTION:
85
0
        case LYS_NOTIF:
86
0
            return &((struct lyd_node_inner *)node)->child;
87
0
        default:
88
0
            return NULL;
89
0
        }
90
0
    }
91
0
}
92
93
API struct lyd_node *
94
lyd_child_no_keys(const struct lyd_node *node)
95
0
{
96
0
    struct lyd_node **children;
97
98
0
    if (!node) {
99
0
        return NULL;
100
0
    }
101
102
0
    if (!node->schema) {
103
        /* opaq node */
104
0
        return ((struct lyd_node_opaq *)node)->child;
105
0
    }
106
107
0
    children = lyd_node_child_p((struct lyd_node *)node);
108
0
    if (children) {
109
0
        struct lyd_node *child = *children;
110
0
        while (child && child->schema && (child->schema->flags & LYS_KEY)) {
111
0
            child = child->next;
112
0
        }
113
0
        return child;
114
0
    } else {
115
0
        return NULL;
116
0
    }
117
0
}
118
119
API const struct lys_module *
120
lyd_owner_module(const struct lyd_node *node)
121
0
{
122
0
    const struct lysc_node *schema;
123
0
    const struct lyd_node_opaq *opaq;
124
125
0
    if (!node) {
126
0
        return NULL;
127
0
    }
128
129
0
    if (!node->schema) {
130
0
        opaq = (struct lyd_node_opaq *)node;
131
0
        switch (opaq->format) {
132
0
        case LY_VALUE_XML:
133
0
            return ly_ctx_get_module_implemented_ns(LYD_CTX(node), opaq->name.module_ns);
134
0
        case LY_VALUE_JSON:
135
0
            return ly_ctx_get_module_implemented(LYD_CTX(node), opaq->name.module_name);
136
0
        default:
137
0
            return NULL;
138
0
        }
139
0
    }
140
141
0
    for (schema = node->schema; schema->parent; schema = schema->parent) {}
142
0
    return schema->module;
143
0
}
144
145
const struct lys_module *
146
lyd_mod_next_module(struct lyd_node *tree, const struct lys_module *module, const struct ly_ctx *ctx, uint32_t *i,
147
        struct lyd_node **first)
148
0
{
149
0
    struct lyd_node *iter;
150
0
    const struct lys_module *mod;
151
152
    /* get the next module */
153
0
    if (module) {
154
0
        if (*i) {
155
0
            mod = NULL;
156
0
        } else {
157
0
            mod = module;
158
0
            ++(*i);
159
0
        }
160
0
    } else {
161
0
        do {
162
0
            mod = ly_ctx_get_module_iter(ctx, i);
163
0
        } while (mod && !mod->implemented);
164
0
    }
165
166
    /* find its data */
167
0
    *first = NULL;
168
0
    if (mod) {
169
0
        LY_LIST_FOR(tree, iter) {
170
0
            if (lyd_owner_module(iter) == mod) {
171
0
                *first = iter;
172
0
                break;
173
0
            }
174
0
        }
175
0
    }
176
177
0
    return mod;
178
0
}
179
180
const struct lys_module *
181
lyd_data_next_module(struct lyd_node **next, struct lyd_node **first)
182
0
{
183
0
    const struct lys_module *mod;
184
185
0
    if (!*next) {
186
        /* all data traversed */
187
0
        *first = NULL;
188
0
        return NULL;
189
0
    }
190
191
0
    *first = *next;
192
193
    /* prepare next */
194
0
    mod = lyd_owner_module(*next);
195
0
    LY_LIST_FOR(*next, *next) {
196
0
        if (lyd_owner_module(*next) != mod) {
197
0
            break;
198
0
        }
199
0
    }
200
201
0
    return mod;
202
0
}
203
204
LY_ERR
205
lyd_parse_check_keys(struct lyd_node *node)
206
0
{
207
0
    const struct lysc_node *skey = NULL;
208
0
    const struct lyd_node *key;
209
210
0
    assert(node->schema->nodetype == LYS_LIST);
211
212
0
    key = lyd_child(node);
213
0
    while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
214
0
        if (!key || (key->schema != skey)) {
215
0
            LOGVAL(LYD_CTX(node), LY_VCODE_NOKEY, skey->name);
216
0
            return LY_EVALID;
217
0
        }
218
219
0
        key = key->next;
220
0
    }
221
222
0
    return LY_SUCCESS;
223
0
}
224
225
void
226
lyd_parse_set_data_flags(struct lyd_node *node, struct ly_set *when_check, struct ly_set *exts_check, struct lyd_meta **meta,
227
        uint32_t options)
228
0
{
229
0
    struct lyd_meta *meta2, *prev_meta = NULL;
230
231
0
    if (lysc_has_when(node->schema)) {
232
0
        if (!(options & LYD_PARSE_ONLY)) {
233
            /* remember we need to evaluate this node's when */
234
0
            LY_CHECK_RET(ly_set_add(when_check, node, 1, NULL), );
235
0
        }
236
0
    }
237
0
    LY_CHECK_RET(lysc_node_ext_tovalidate(exts_check, node), );
238
239
0
    LY_LIST_FOR(*meta, meta2) {
240
0
        if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults") &&
241
0
                meta2->value.boolean) {
242
            /* node is default according to the metadata */
243
0
            node->flags |= LYD_DEFAULT;
244
245
            /* delete the metadata */
246
0
            if (prev_meta) {
247
0
                prev_meta->next = meta2->next;
248
0
            } else {
249
0
                *meta = (*meta)->next;
250
0
            }
251
0
            lyd_free_meta_single(meta2);
252
0
            break;
253
0
        }
254
255
0
        prev_meta = meta2;
256
0
    }
257
0
}
258
259
API const char *
260
lyd_value_get_canonical(const struct ly_ctx *ctx, const struct lyd_value *value)
261
0
{
262
0
    LY_CHECK_ARG_RET(ctx, ctx, value, NULL);
263
264
0
    return value->_canonical ? value->_canonical :
265
0
           (const char *)value->realtype->plugin->print(ctx, value, LY_VALUE_CANON, NULL, NULL, NULL);
266
0
}
267
268
API LY_ERR
269
lyd_any_value_str(const struct lyd_node *any, char **value_str)
270
0
{
271
0
    const struct lyd_node_any *a;
272
0
    struct lyd_node *tree = NULL;
273
0
    const char *str = NULL;
274
0
    ly_bool dynamic = 0;
275
0
    LY_ERR ret = LY_SUCCESS;
276
277
0
    LY_CHECK_ARG_RET(NULL, any, value_str, LY_EINVAL);
278
0
    LY_CHECK_ARG_RET(NULL, any->schema, any->schema->nodetype & LYS_ANYDATA, LY_EINVAL);
279
280
0
    a = (struct lyd_node_any *)any;
281
0
    *value_str = NULL;
282
283
0
    if (!a->value.str) {
284
        /* there is no value in the union */
285
0
        return LY_SUCCESS;
286
0
    }
287
288
0
    switch (a->value_type) {
289
0
    case LYD_ANYDATA_LYB:
290
        /* parse into a data tree */
291
0
        ret = lyd_parse_data_mem(LYD_CTX(any), a->value.mem, LYD_LYB, LYD_PARSE_ONLY, 0, &tree);
292
0
        LY_CHECK_GOTO(ret, cleanup);
293
0
        dynamic = 1;
294
0
        break;
295
0
    case LYD_ANYDATA_DATATREE:
296
0
        tree = a->value.tree;
297
0
        break;
298
0
    case LYD_ANYDATA_STRING:
299
0
    case LYD_ANYDATA_XML:
300
0
    case LYD_ANYDATA_JSON:
301
        /* simply use the string */
302
0
        str = a->value.str;
303
0
        break;
304
0
    }
305
306
0
    if (tree) {
307
        /* print into a string */
308
0
        ret = lyd_print_mem(value_str, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS);
309
0
        LY_CHECK_GOTO(ret, cleanup);
310
0
    } else {
311
0
        assert(str);
312
0
        *value_str = strdup(str);
313
0
        LY_CHECK_ERR_GOTO(!*value_str, LOGMEM(LYD_CTX(any)), cleanup);
314
0
    }
315
316
    /* success */
317
318
0
cleanup:
319
0
    if (dynamic) {
320
0
        lyd_free_all(tree);
321
0
    }
322
0
    return ret;
323
0
}
324
325
API LY_ERR
326
lyd_any_copy_value(struct lyd_node *trg, const union lyd_any_value *value, LYD_ANYDATA_VALUETYPE value_type)
327
0
{
328
0
    struct lyd_node_any *t;
329
330
0
    LY_CHECK_ARG_RET(NULL, trg, LY_EINVAL);
331
0
    LY_CHECK_ARG_RET(NULL, trg->schema, trg->schema->nodetype & LYS_ANYDATA, LY_EINVAL);
332
333
0
    t = (struct lyd_node_any *)trg;
334
335
    /* free trg */
336
0
    switch (t->value_type) {
337
0
    case LYD_ANYDATA_DATATREE:
338
0
        lyd_free_all(t->value.tree);
339
0
        break;
340
0
    case LYD_ANYDATA_STRING:
341
0
    case LYD_ANYDATA_XML:
342
0
    case LYD_ANYDATA_JSON:
343
0
        lydict_remove(LYD_CTX(trg), t->value.str);
344
0
        break;
345
0
    case LYD_ANYDATA_LYB:
346
0
        free(t->value.mem);
347
0
        break;
348
0
    }
349
0
    t->value.str = NULL;
350
351
0
    if (!value) {
352
        /* only free value in this case */
353
0
        return LY_SUCCESS;
354
0
    }
355
356
    /* copy src */
357
0
    t->value_type = value_type;
358
0
    switch (value_type) {
359
0
    case LYD_ANYDATA_DATATREE:
360
0
        if (value->tree) {
361
0
            LY_CHECK_RET(lyd_dup_siblings(value->tree, NULL, LYD_DUP_RECURSIVE, &t->value.tree));
362
0
        }
363
0
        break;
364
0
    case LYD_ANYDATA_STRING:
365
0
    case LYD_ANYDATA_XML:
366
0
    case LYD_ANYDATA_JSON:
367
0
        if (value->str) {
368
0
            LY_CHECK_RET(lydict_insert(LYD_CTX(trg), value->str, 0, &t->value.str));
369
0
        }
370
0
        break;
371
0
    case LYD_ANYDATA_LYB:
372
0
        if (value->mem) {
373
0
            int len = lyd_lyb_data_length(value->mem);
374
0
            LY_CHECK_RET(len == -1, LY_EINVAL);
375
0
            t->value.mem = malloc(len);
376
0
            LY_CHECK_ERR_RET(!t->value.mem, LOGMEM(LYD_CTX(trg)), LY_EMEM);
377
0
            memcpy(t->value.mem, value->mem, len);
378
0
        }
379
0
        break;
380
0
    }
381
382
0
    return LY_SUCCESS;
383
0
}
384
385
void
386
lyd_del_move_root(struct lyd_node **root, const struct lyd_node *to_del, const struct lys_module *mod)
387
0
{
388
0
    if (*root && (lyd_owner_module(*root) != mod)) {
389
        /* there are no data of mod so this is simply the first top-level sibling */
390
0
        mod = NULL;
391
0
    }
392
393
0
    if ((*root != to_del) || (*root)->parent) {
394
0
        return;
395
0
    }
396
397
0
    *root = (*root)->next;
398
0
    if (mod && *root && (lyd_owner_module(to_del) != lyd_owner_module(*root))) {
399
        /* there are no more nodes from mod */
400
0
        *root = lyd_first_sibling(*root);
401
0
    }
402
0
}
403
404
void
405
ly_free_prefix_data(LY_VALUE_FORMAT format, void *prefix_data)
406
0
{
407
0
    struct ly_set *ns_list;
408
0
    struct lysc_prefix *prefixes;
409
0
    uint32_t i;
410
0
    LY_ARRAY_COUNT_TYPE u;
411
412
0
    if (!prefix_data) {
413
0
        return;
414
0
    }
415
416
0
    switch (format) {
417
0
    case LY_VALUE_XML:
418
0
        ns_list = prefix_data;
419
0
        for (i = 0; i < ns_list->count; ++i) {
420
0
            free(((struct lyxml_ns *)ns_list->objs[i])->prefix);
421
0
            free(((struct lyxml_ns *)ns_list->objs[i])->uri);
422
0
        }
423
0
        ly_set_free(ns_list, free);
424
0
        break;
425
0
    case LY_VALUE_SCHEMA_RESOLVED:
426
0
        prefixes = prefix_data;
427
0
        LY_ARRAY_FOR(prefixes, u) {
428
0
            free(prefixes[u].prefix);
429
0
        }
430
0
        LY_ARRAY_FREE(prefixes);
431
0
        break;
432
0
    case LY_VALUE_CANON:
433
0
    case LY_VALUE_SCHEMA:
434
0
    case LY_VALUE_JSON:
435
0
    case LY_VALUE_LYB:
436
0
        break;
437
0
    }
438
0
}
439
440
LY_ERR
441
ly_dup_prefix_data(const struct ly_ctx *ctx, LY_VALUE_FORMAT format, const void *prefix_data,
442
        void **prefix_data_p)
443
0
{
444
0
    LY_ERR ret = LY_SUCCESS;
445
0
    struct lyxml_ns *ns;
446
0
    struct lysc_prefix *prefixes = NULL, *orig_pref;
447
0
    struct ly_set *ns_list, *orig_ns;
448
0
    uint32_t i;
449
0
    LY_ARRAY_COUNT_TYPE u;
450
451
0
    assert(!*prefix_data_p);
452
453
0
    switch (format) {
454
0
    case LY_VALUE_SCHEMA:
455
0
        *prefix_data_p = (void *)prefix_data;
456
0
        break;
457
0
    case LY_VALUE_SCHEMA_RESOLVED:
458
        /* copy all the value prefixes */
459
0
        orig_pref = (struct lysc_prefix *)prefix_data;
460
0
        LY_ARRAY_CREATE_GOTO(ctx, prefixes, LY_ARRAY_COUNT(orig_pref), ret, cleanup);
461
0
        *prefix_data_p = prefixes;
462
463
0
        LY_ARRAY_FOR(orig_pref, u) {
464
0
            if (orig_pref[u].prefix) {
465
0
                prefixes[u].prefix = strdup(orig_pref[u].prefix);
466
0
                LY_CHECK_ERR_GOTO(!prefixes[u].prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
467
0
            }
468
0
            prefixes[u].mod = orig_pref[u].mod;
469
0
            LY_ARRAY_INCREMENT(prefixes);
470
0
        }
471
0
        break;
472
0
    case LY_VALUE_XML:
473
        /* copy all the namespaces */
474
0
        LY_CHECK_GOTO(ret = ly_set_new(&ns_list), cleanup);
475
0
        *prefix_data_p = ns_list;
476
477
0
        orig_ns = (struct ly_set *)prefix_data;
478
0
        for (i = 0; i < orig_ns->count; ++i) {
479
0
            ns = calloc(1, sizeof *ns);
480
0
            LY_CHECK_ERR_GOTO(!ns, LOGMEM(ctx); ret = LY_EMEM, cleanup);
481
0
            LY_CHECK_GOTO(ret = ly_set_add(ns_list, ns, 1, NULL), cleanup);
482
483
0
            if (((struct lyxml_ns *)orig_ns->objs[i])->prefix) {
484
0
                ns->prefix = strdup(((struct lyxml_ns *)orig_ns->objs[i])->prefix);
485
0
                LY_CHECK_ERR_GOTO(!ns->prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
486
0
            }
487
0
            ns->uri = strdup(((struct lyxml_ns *)orig_ns->objs[i])->uri);
488
0
            LY_CHECK_ERR_GOTO(!ns->uri, LOGMEM(ctx); ret = LY_EMEM, cleanup);
489
0
        }
490
0
        break;
491
0
    case LY_VALUE_CANON:
492
0
    case LY_VALUE_JSON:
493
0
    case LY_VALUE_LYB:
494
0
        assert(!prefix_data);
495
0
        *prefix_data_p = NULL;
496
0
        break;
497
0
    }
498
499
0
cleanup:
500
0
    if (ret) {
501
0
        ly_free_prefix_data(format, *prefix_data_p);
502
0
        *prefix_data_p = NULL;
503
0
    }
504
0
    return ret;
505
0
}
506
507
LY_ERR
508
ly_store_prefix_data(const struct ly_ctx *ctx, const void *value, size_t value_len, LY_VALUE_FORMAT format,
509
        const void *prefix_data, LY_VALUE_FORMAT *format_p, void **prefix_data_p)
510
0
{
511
0
    LY_ERR ret = LY_SUCCESS;
512
0
    const struct lys_module *mod;
513
0
    const struct lyxml_ns *ns;
514
0
    struct lyxml_ns *new_ns;
515
0
    struct ly_set *ns_list;
516
0
    struct lysc_prefix *prefixes = NULL, *val_pref;
517
0
    const char *value_iter, *value_next, *value_end;
518
0
    uint32_t substr_len;
519
0
    ly_bool is_prefix;
520
521
0
    switch (format) {
522
0
    case LY_VALUE_SCHEMA:
523
        /* copy all referenced modules as prefix - module pairs */
524
0
        if (!*prefix_data_p) {
525
            /* new prefix data */
526
0
            LY_ARRAY_CREATE_GOTO(ctx, prefixes, 0, ret, cleanup);
527
0
            *format_p = LY_VALUE_SCHEMA_RESOLVED;
528
0
            *prefix_data_p = prefixes;
529
0
        } else {
530
            /* reuse prefix data */
531
0
            assert(*format_p == LY_VALUE_SCHEMA_RESOLVED);
532
0
            prefixes = *prefix_data_p;
533
0
        }
534
535
        /* add all used prefixes */
536
0
        value_end = value + value_len;
537
0
        for (value_iter = value; value_iter; value_iter = value_next) {
538
0
            LY_CHECK_GOTO(ret = ly_value_prefix_next(value_iter, value_end, &substr_len, &is_prefix, &value_next), cleanup);
539
0
            if (is_prefix) {
540
                /* we have a possible prefix. Do we already have the prefix? */
541
0
                mod = ly_resolve_prefix(ctx, value_iter, substr_len, *format_p, *prefix_data_p);
542
0
                if (!mod) {
543
0
                    mod = ly_resolve_prefix(ctx, value_iter, substr_len, format, prefix_data);
544
0
                    if (mod) {
545
0
                        assert(*format_p == LY_VALUE_SCHEMA_RESOLVED);
546
                        /* store a new prefix - module pair */
547
0
                        LY_ARRAY_NEW_GOTO(ctx, prefixes, val_pref, ret, cleanup);
548
0
                        *prefix_data_p = prefixes;
549
550
0
                        val_pref->prefix = strndup(value_iter, substr_len);
551
0
                        LY_CHECK_ERR_GOTO(!val_pref->prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
552
0
                        val_pref->mod = mod;
553
0
                    } /* else it is not even defined */
554
0
                } /* else the prefix is already present */
555
0
            }
556
0
        }
557
0
        break;
558
0
    case LY_VALUE_XML:
559
        /* copy all referenced namespaces as prefix - namespace pairs */
560
0
        if (!*prefix_data_p) {
561
            /* new prefix data */
562
0
            LY_CHECK_GOTO(ret = ly_set_new(&ns_list), cleanup);
563
0
            *format_p = LY_VALUE_XML;
564
0
            *prefix_data_p = ns_list;
565
0
        } else {
566
            /* reuse prefix data */
567
0
            assert(*format_p == LY_VALUE_XML);
568
0
            ns_list = *prefix_data_p;
569
0
        }
570
571
        /* add all used prefixes */
572
0
        value_end = value + value_len;
573
0
        for (value_iter = value; value_iter; value_iter = value_next) {
574
0
            LY_CHECK_GOTO(ret = ly_value_prefix_next(value_iter, value_end, &substr_len, &is_prefix, &value_next), cleanup);
575
0
            if (is_prefix) {
576
                /* we have a possible prefix. Do we already have the prefix? */
577
0
                ns = lyxml_ns_get(ns_list, value_iter, substr_len);
578
0
                if (!ns) {
579
0
                    ns = lyxml_ns_get(prefix_data, value_iter, substr_len);
580
0
                    if (ns) {
581
                        /* store a new prefix - namespace pair */
582
0
                        new_ns = calloc(1, sizeof *new_ns);
583
0
                        LY_CHECK_ERR_GOTO(!new_ns, LOGMEM(ctx); ret = LY_EMEM, cleanup);
584
0
                        LY_CHECK_GOTO(ret = ly_set_add(ns_list, new_ns, 1, NULL), cleanup);
585
586
0
                        new_ns->prefix = strndup(value_iter, substr_len);
587
0
                        LY_CHECK_ERR_GOTO(!new_ns->prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
588
0
                        new_ns->uri = strdup(ns->uri);
589
0
                        LY_CHECK_ERR_GOTO(!new_ns->uri, LOGMEM(ctx); ret = LY_EMEM, cleanup);
590
0
                    } /* else it is not even defined */
591
0
                } /* else the prefix is already present */
592
0
            }
593
0
        }
594
0
        break;
595
0
    case LY_VALUE_CANON:
596
0
    case LY_VALUE_SCHEMA_RESOLVED:
597
0
    case LY_VALUE_JSON:
598
0
    case LY_VALUE_LYB:
599
0
        if (!*prefix_data_p) {
600
            /* new prefix data - simply copy all the prefix data */
601
0
            *format_p = format;
602
0
            LY_CHECK_GOTO(ret = ly_dup_prefix_data(ctx, format, prefix_data, prefix_data_p), cleanup);
603
0
        } /* else reuse prefix data - the prefix data are always the same, nothing to do */
604
0
        break;
605
0
    }
606
607
0
cleanup:
608
0
    if (ret) {
609
0
        ly_free_prefix_data(*format_p, *prefix_data_p);
610
0
        *prefix_data_p = NULL;
611
0
    }
612
0
    return ret;
613
0
}
614
615
const char *
616
ly_format2str(LY_VALUE_FORMAT format)
617
0
{
618
0
    switch (format) {
619
0
    case LY_VALUE_CANON:
620
0
        return "canonical";
621
0
    case LY_VALUE_SCHEMA:
622
0
        return "schema imports";
623
0
    case LY_VALUE_SCHEMA_RESOLVED:
624
0
        return "schema stored mapping";
625
0
    case LY_VALUE_XML:
626
0
        return "XML prefixes";
627
0
    case LY_VALUE_JSON:
628
0
        return "JSON module names";
629
0
    case LY_VALUE_LYB:
630
0
        return "LYB prefixes";
631
0
    default:
632
0
        break;
633
0
    }
634
635
0
    return NULL;
636
0
}