blob: bb4b734c7541946d020ca5239f13b00954ca24ff [file] [log] [blame]
Radek Krejcie7b95092019-05-15 11:03:07 +02001/**
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 */
Radek Krejcif8dc59a2020-11-25 13:47:44 +010014#define _POSIX_C_SOURCE 200809L /* strdup, strndup */
Radek Krejcie7b95092019-05-15 11:03:07 +020015
16#include <assert.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020017#include <stdint.h>
Radek Krejcie7b95092019-05-15 11:03:07 +020018#include <stdlib.h>
Radek Krejciad97c5f2020-06-30 09:19:28 +020019#include <string.h>
Radek Krejcie7b95092019-05-15 11:03:07 +020020
Radek Krejci535ea9f2020-05-29 16:01:05 +020021#include "common.h"
Michal Vasko6b5cb2a2020-11-11 19:11:21 +010022#include "compat.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020023#include "context.h"
Radek Krejci47fab892020-11-05 17:02:41 +010024#include "dict.h"
Radek Krejciad97c5f2020-06-30 09:19:28 +020025#include "hash_table.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020026#include "log.h"
Radek Krejciad97c5f2020-06-30 09:19:28 +020027#include "lyb.h"
Radek Krejci7931b192020-06-25 17:05:03 +020028#include "parser_data.h"
Michal Vaskoa820c312021-02-05 16:33:00 +010029#include "printer_data.h"
Radek Krejciad97c5f2020-06-30 09:19:28 +020030#include "set.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020031#include "tree.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020032#include "tree_data.h"
Michal Vasko60ea6352020-06-29 13:39:39 +020033#include "tree_data_internal.h"
Radek Krejci859a15a2021-03-05 20:56:59 +010034#include "tree_edit.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020035#include "tree_schema.h"
Radek Krejci0aa1f702021-04-01 16:16:19 +020036#include "tree_schema_internal.h"
Radek Krejci4f2e3e52021-03-30 14:20:28 +020037#include "validation.h"
Radek Krejci77114102021-03-10 15:21:57 +010038#include "xml.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020039
Michal Vaskod7c048c2021-05-18 16:12:55 +020040/**
41 * @brief Find an entry in duplicate instance cache for an instance. Create it if it does not exist.
42 *
43 * @param[in] first_inst Instance of the cache entry.
44 * @param[in,out] dup_inst_cache Duplicate instance cache.
45 * @return Instance cache entry.
46 */
47static struct lyd_dup_inst *
48lyd_dup_inst_get(const struct lyd_node *first_inst, struct lyd_dup_inst **dup_inst_cache)
49{
50 struct lyd_dup_inst *item;
51 LY_ARRAY_COUNT_TYPE u;
52
53 LY_ARRAY_FOR(*dup_inst_cache, u) {
54 if ((*dup_inst_cache)[u].inst_set->dnodes[0] == first_inst) {
55 return &(*dup_inst_cache)[u];
56 }
57 }
58
59 /* it was not added yet, add it now */
60 LY_ARRAY_NEW_RET(LYD_CTX(first_inst), *dup_inst_cache, item, NULL);
61
62 return item;
63}
64
65LY_ERR
66lyd_dup_inst_next(struct lyd_node **inst, const struct lyd_node *siblings, struct lyd_dup_inst **dup_inst_cache)
67{
68 struct lyd_dup_inst *dup_inst;
69
70 if (!*inst || !lysc_is_dup_inst_list((*inst)->schema)) {
71 /* no match or not dup-inst list, inst is unchanged */
72 return LY_SUCCESS;
73 }
74
75 /* there can be more exact same instances and we must make sure we do not match a single node more times */
76 dup_inst = lyd_dup_inst_get(*inst, dup_inst_cache);
77 LY_CHECK_ERR_RET(!dup_inst, LOGMEM(LYD_CTX(siblings)), LY_EMEM);
78
79 if (!dup_inst->used) {
80 /* we did not cache these instances yet, do so */
81 lyd_find_sibling_dup_inst_set(siblings, *inst, &dup_inst->inst_set);
82 assert(dup_inst->inst_set->count && (dup_inst->inst_set->dnodes[0] == *inst));
83 }
84
85 if (dup_inst->used == dup_inst->inst_set->count) {
86 /* we have used all the instances */
87 *inst = NULL;
88 } else {
89 assert(dup_inst->used < dup_inst->inst_set->count);
90
91 /* use another instance */
92 *inst = dup_inst->inst_set->dnodes[dup_inst->used];
93 ++dup_inst->used;
94 }
95
96 return LY_SUCCESS;
97}
98
99void
100lyd_dup_inst_free(struct lyd_dup_inst *dup_inst)
101{
102 LY_ARRAY_COUNT_TYPE u;
103
104 LY_ARRAY_FOR(dup_inst, u) {
105 ly_set_free(dup_inst[u].inst_set, NULL);
106 }
107 LY_ARRAY_FREE(dup_inst);
108}
109
Michal Vaskoa6669ba2020-08-06 16:14:26 +0200110struct lyd_node *
111lys_getnext_data(const struct lyd_node *last, const struct lyd_node *sibling, const struct lysc_node **slast,
Radek Krejci0f969882020-08-21 16:56:47 +0200112 const struct lysc_node *parent, const struct lysc_module *module)
Michal Vaskoa6669ba2020-08-06 16:14:26 +0200113{
114 const struct lysc_node *siter = NULL;
115 struct lyd_node *match = NULL;
116
117 assert(parent || module);
118 assert(!last || (slast && *slast));
119
120 if (slast) {
121 siter = *slast;
122 }
123
124 if (last && last->next && (last->next->schema == siter)) {
125 /* return next data instance */
126 return last->next;
127 }
128
129 /* find next schema node data instance */
130 while ((siter = lys_getnext(siter, parent, module, 0))) {
131 if (!lyd_find_sibling_val(sibling, siter, NULL, 0, &match)) {
132 break;
133 }
134 }
135
136 if (slast) {
137 *slast = siter;
138 }
139 return match;
140}
141
Radek Krejcie7b95092019-05-15 11:03:07 +0200142struct lyd_node **
Michal Vaskoe0665742021-02-11 11:08:44 +0100143lyd_node_child_p(struct lyd_node *node)
Radek Krejcie7b95092019-05-15 11:03:07 +0200144{
145 assert(node);
Michal Vasko52927e22020-03-16 17:26:14 +0100146
147 if (!node->schema) {
148 return &((struct lyd_node_opaq *)node)->child;
149 } else {
150 switch (node->schema->nodetype) {
151 case LYS_CONTAINER:
152 case LYS_LIST:
Michal Vasko1bf09392020-03-27 12:38:10 +0100153 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +0100154 case LYS_ACTION:
155 case LYS_NOTIF:
156 return &((struct lyd_node_inner *)node)->child;
157 default:
158 return NULL;
159 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200160 }
161}
162
Radek Krejcidae0ee82020-05-06 16:53:24 +0200163API struct lyd_node *
Radek Krejcia1c1e542020-09-29 16:06:52 +0200164lyd_child_no_keys(const struct lyd_node *node)
165{
166 struct lyd_node **children;
167
168 if (!node) {
169 return NULL;
170 }
171
172 if (!node->schema) {
173 /* opaq node */
Michal Vasko9e685082021-01-29 14:49:09 +0100174 return ((struct lyd_node_opaq *)node)->child;
Radek Krejcia1c1e542020-09-29 16:06:52 +0200175 }
176
Michal Vaskoe0665742021-02-11 11:08:44 +0100177 children = lyd_node_child_p((struct lyd_node *)node);
Radek Krejcia1c1e542020-09-29 16:06:52 +0200178 if (children) {
179 struct lyd_node *child = *children;
180 while (child && child->schema && (child->schema->flags & LYS_KEY)) {
181 child = child->next;
Michal Vasko5bfd4be2020-06-23 13:26:19 +0200182 }
183 return child;
Radek Krejcie7b95092019-05-15 11:03:07 +0200184 } else {
185 return NULL;
186 }
187}
Michal Vasko9b368d32020-02-14 13:53:31 +0100188
Michal Vaskoc193ce92020-03-06 11:04:48 +0100189API const struct lys_module *
190lyd_owner_module(const struct lyd_node *node)
Michal Vasko9b368d32020-02-14 13:53:31 +0100191{
192 const struct lysc_node *schema;
Michal Vaskod5cfa6e2020-11-23 16:56:08 +0100193 const struct lyd_node_opaq *opaq;
Michal Vasko9b368d32020-02-14 13:53:31 +0100194
Michal Vaskod5cfa6e2020-11-23 16:56:08 +0100195 if (!node) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100196 return NULL;
197 }
Michal Vasko9b368d32020-02-14 13:53:31 +0100198
Michal Vaskod5cfa6e2020-11-23 16:56:08 +0100199 if (!node->schema) {
200 opaq = (struct lyd_node_opaq *)node;
201 switch (opaq->format) {
Radek Krejci8df109d2021-04-23 12:19:08 +0200202 case LY_VALUE_XML:
Michal Vaskod5cfa6e2020-11-23 16:56:08 +0100203 return ly_ctx_get_module_implemented_ns(LYD_CTX(node), opaq->name.module_ns);
Radek Krejci8df109d2021-04-23 12:19:08 +0200204 case LY_VALUE_JSON:
Michal Vaskod5cfa6e2020-11-23 16:56:08 +0100205 return ly_ctx_get_module_implemented(LYD_CTX(node), opaq->name.module_name);
206 default:
207 return NULL;
208 }
209 }
210
Radek Krejci1e008d22020-08-17 11:37:37 +0200211 for (schema = node->schema; schema->parent; schema = schema->parent) {}
Michal Vasko9b368d32020-02-14 13:53:31 +0100212 return schema->module;
213}
Michal Vaskob1b5c262020-03-05 14:29:47 +0100214
215const struct lys_module *
Michal Vasko26e80012020-07-08 10:55:46 +0200216lyd_mod_next_module(struct lyd_node *tree, const struct lys_module *module, const struct ly_ctx *ctx, uint32_t *i,
Radek Krejci0f969882020-08-21 16:56:47 +0200217 struct lyd_node **first)
Michal Vaskob1b5c262020-03-05 14:29:47 +0100218{
219 struct lyd_node *iter;
220 const struct lys_module *mod;
221
222 /* get the next module */
Michal Vasko26e80012020-07-08 10:55:46 +0200223 if (module) {
224 if (*i) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100225 mod = NULL;
Michal Vasko26e80012020-07-08 10:55:46 +0200226 } else {
227 mod = module;
228 ++(*i);
Michal Vaskob1b5c262020-03-05 14:29:47 +0100229 }
230 } else {
231 do {
232 mod = ly_ctx_get_module_iter(ctx, i);
233 } while (mod && !mod->implemented);
234 }
235
236 /* find its data */
237 *first = NULL;
238 if (mod) {
239 LY_LIST_FOR(tree, iter) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100240 if (lyd_owner_module(iter) == mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100241 *first = iter;
242 break;
243 }
244 }
245 }
246
247 return mod;
248}
249
250const struct lys_module *
251lyd_data_next_module(struct lyd_node **next, struct lyd_node **first)
252{
253 const struct lys_module *mod;
254
255 if (!*next) {
256 /* all data traversed */
257 *first = NULL;
258 return NULL;
259 }
260
261 *first = *next;
262
263 /* prepare next */
Michal Vaskoc193ce92020-03-06 11:04:48 +0100264 mod = lyd_owner_module(*next);
Michal Vaskob1b5c262020-03-05 14:29:47 +0100265 LY_LIST_FOR(*next, *next) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100266 if (lyd_owner_module(*next) != mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100267 break;
268 }
269 }
270
271 return mod;
272}
Michal Vasko9f96a052020-03-10 09:41:45 +0100273
274LY_ERR
275lyd_parse_check_keys(struct lyd_node *node)
276{
277 const struct lysc_node *skey = NULL;
278 const struct lyd_node *key;
279
280 assert(node->schema->nodetype == LYS_LIST);
281
Radek Krejcia1c1e542020-09-29 16:06:52 +0200282 key = lyd_child(node);
Michal Vasko9f96a052020-03-10 09:41:45 +0100283 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
284 if (!key || (key->schema != skey)) {
Radek Krejci2efc45b2020-12-22 16:25:44 +0100285 LOGVAL(LYD_CTX(node), LY_VCODE_NOKEY, skey->name);
Michal Vasko9f96a052020-03-10 09:41:45 +0100286 return LY_EVALID;
287 }
288
289 key = key->next;
290 }
291
292 return LY_SUCCESS;
293}
Michal Vasko60ea6352020-06-29 13:39:39 +0200294
295void
Radek Krejci4f2e3e52021-03-30 14:20:28 +0200296lyd_parse_set_data_flags(struct lyd_node *node, struct ly_set *when_check, struct ly_set *exts_check, struct lyd_meta **meta,
297 uint32_t options)
Michal Vasko60ea6352020-06-29 13:39:39 +0200298{
299 struct lyd_meta *meta2, *prev_meta = NULL;
300
Michal Vaskoa5705e52020-12-09 18:15:14 +0100301 if (lysc_has_when(node->schema)) {
Michal Vasko0f3377d2020-11-09 20:56:11 +0100302 if (!(options & LYD_PARSE_ONLY)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200303 /* remember we need to evaluate this node's when */
Radek Krejci3d92e442020-10-12 12:48:13 +0200304 LY_CHECK_RET(ly_set_add(when_check, node, 1, NULL), );
Michal Vasko60ea6352020-06-29 13:39:39 +0200305 }
306 }
Radek Krejci4f2e3e52021-03-30 14:20:28 +0200307 LY_CHECK_RET(lysc_node_ext_tovalidate(exts_check, node), );
Michal Vasko60ea6352020-06-29 13:39:39 +0200308
Michal Vasko60ea6352020-06-29 13:39:39 +0200309 LY_LIST_FOR(*meta, meta2) {
Michal Vasko69730152020-10-09 16:30:07 +0200310 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults") &&
311 meta2->value.boolean) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200312 /* node is default according to the metadata */
313 node->flags |= LYD_DEFAULT;
314
315 /* delete the metadata */
316 if (prev_meta) {
317 prev_meta->next = meta2->next;
318 } else {
319 *meta = (*meta)->next;
320 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200321 lyd_free_meta_single(meta2);
Michal Vasko60ea6352020-06-29 13:39:39 +0200322 break;
323 }
324
325 prev_meta = meta2;
326 }
327}
328
Radek Krejci6d5ba0c2021-04-26 07:49:59 +0200329API const char *
Christian Hopps46bd21b2021-04-27 09:43:58 -0400330lyd_value_get_canonical(const struct ly_ctx *ctx, const struct lyd_value *value)
Radek Krejci6d5ba0c2021-04-26 07:49:59 +0200331{
Michal Vaskoab40e7e2021-04-28 17:04:24 +0200332 LY_CHECK_ARG_RET(ctx, ctx, value, NULL);
333
Michal Vasko33876022021-04-27 16:42:24 +0200334 return value->_canonical ? value->_canonical :
335 (const char *)value->realtype->plugin->print(ctx, value, LY_VALUE_CANON, NULL, NULL, NULL);
Radek Krejci6d5ba0c2021-04-26 07:49:59 +0200336}
337
Michal Vaskoc0004272020-08-06 08:32:34 +0200338API LY_ERR
Michal Vaskoa820c312021-02-05 16:33:00 +0100339lyd_any_value_str(const struct lyd_node *any, char **value_str)
340{
341 const struct lyd_node_any *a;
342 struct lyd_node *tree = NULL;
343 const char *str = NULL;
344 ly_bool dynamic = 0;
345 LY_ERR ret = LY_SUCCESS;
346
347 LY_CHECK_ARG_RET(NULL, any, value_str, LY_EINVAL);
Radek Krejci71877df2021-04-06 17:24:06 +0200348 LY_CHECK_ARG_RET(NULL, any->schema, any->schema->nodetype & LYS_ANYDATA, LY_EINVAL);
Michal Vaskoa820c312021-02-05 16:33:00 +0100349
350 a = (struct lyd_node_any *)any;
351 *value_str = NULL;
352
353 if (!a->value.str) {
354 /* there is no value in the union */
355 return LY_SUCCESS;
356 }
357
358 switch (a->value_type) {
359 case LYD_ANYDATA_LYB:
360 /* parse into a data tree */
361 ret = lyd_parse_data_mem(LYD_CTX(any), a->value.mem, LYD_LYB, LYD_PARSE_ONLY, 0, &tree);
362 LY_CHECK_GOTO(ret, cleanup);
363 dynamic = 1;
364 break;
365 case LYD_ANYDATA_DATATREE:
366 tree = a->value.tree;
367 break;
368 case LYD_ANYDATA_STRING:
369 case LYD_ANYDATA_XML:
370 case LYD_ANYDATA_JSON:
371 /* simply use the string */
372 str = a->value.str;
373 break;
374 }
375
376 if (tree) {
377 /* print into a string */
378 ret = lyd_print_mem(value_str, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS);
379 LY_CHECK_GOTO(ret, cleanup);
380 } else {
381 assert(str);
382 *value_str = strdup(str);
383 LY_CHECK_ERR_GOTO(!*value_str, LOGMEM(LYD_CTX(any)), cleanup);
384 }
385
386 /* success */
387
388cleanup:
389 if (dynamic) {
390 lyd_free_all(tree);
391 }
392 return ret;
393}
394
395API LY_ERR
Michal Vasko61551fa2020-07-09 15:45:45 +0200396lyd_any_copy_value(struct lyd_node *trg, const union lyd_any_value *value, LYD_ANYDATA_VALUETYPE value_type)
397{
398 struct lyd_node_any *t;
Michal Vasko61551fa2020-07-09 15:45:45 +0200399
Michal Vaskoa820c312021-02-05 16:33:00 +0100400 LY_CHECK_ARG_RET(NULL, trg, LY_EINVAL);
Radek Krejci71877df2021-04-06 17:24:06 +0200401 LY_CHECK_ARG_RET(NULL, trg->schema, trg->schema->nodetype & LYS_ANYDATA, LY_EINVAL);
Michal Vasko61551fa2020-07-09 15:45:45 +0200402
403 t = (struct lyd_node_any *)trg;
404
405 /* free trg */
406 switch (t->value_type) {
407 case LYD_ANYDATA_DATATREE:
408 lyd_free_all(t->value.tree);
409 break;
410 case LYD_ANYDATA_STRING:
411 case LYD_ANYDATA_XML:
412 case LYD_ANYDATA_JSON:
Michal Vaskoe180ed02021-02-05 16:31:20 +0100413 lydict_remove(LYD_CTX(trg), t->value.str);
Michal Vasko61551fa2020-07-09 15:45:45 +0200414 break;
415 case LYD_ANYDATA_LYB:
416 free(t->value.mem);
417 break;
418 }
419 t->value.str = NULL;
420
421 if (!value) {
422 /* only free value in this case */
423 return LY_SUCCESS;
424 }
425
426 /* copy src */
427 t->value_type = value_type;
428 switch (value_type) {
429 case LYD_ANYDATA_DATATREE:
430 if (value->tree) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200431 LY_CHECK_RET(lyd_dup_siblings(value->tree, NULL, LYD_DUP_RECURSIVE, &t->value.tree));
Michal Vasko61551fa2020-07-09 15:45:45 +0200432 }
433 break;
434 case LYD_ANYDATA_STRING:
435 case LYD_ANYDATA_XML:
436 case LYD_ANYDATA_JSON:
437 if (value->str) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200438 LY_CHECK_RET(lydict_insert(LYD_CTX(trg), value->str, 0, &t->value.str));
Michal Vasko61551fa2020-07-09 15:45:45 +0200439 }
440 break;
441 case LYD_ANYDATA_LYB:
442 if (value->mem) {
Radek Krejci1deb5be2020-08-26 16:43:36 +0200443 int len = lyd_lyb_data_length(value->mem);
Radek Krejci82fa8d42020-07-11 22:00:59 +0200444 LY_CHECK_RET(len == -1, LY_EINVAL);
Michal Vasko61551fa2020-07-09 15:45:45 +0200445 t->value.mem = malloc(len);
Michal Vaskob7be7a82020-08-20 09:09:04 +0200446 LY_CHECK_ERR_RET(!t->value.mem, LOGMEM(LYD_CTX(trg)), LY_EMEM);
Michal Vasko61551fa2020-07-09 15:45:45 +0200447 memcpy(t->value.mem, value->mem, len);
448 }
449 break;
450 }
451
452 return LY_SUCCESS;
453}
454
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100455void
Michal Vaskod3bb12f2020-12-04 14:33:09 +0100456lyd_del_move_root(struct lyd_node **root, const struct lyd_node *to_del, const struct lys_module *mod)
457{
458 if (*root && (lyd_owner_module(*root) != mod)) {
459 /* there are no data of mod so this is simply the first top-level sibling */
460 mod = NULL;
461 }
462
463 if ((*root != to_del) || (*root)->parent) {
464 return;
465 }
466
467 *root = (*root)->next;
468 if (mod && *root && (lyd_owner_module(to_del) != lyd_owner_module(*root))) {
469 /* there are no more nodes from mod */
470 *root = lyd_first_sibling(*root);
471 }
472}
473
474void
Radek Krejci8df109d2021-04-23 12:19:08 +0200475ly_free_prefix_data(LY_VALUE_FORMAT format, void *prefix_data)
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100476{
477 struct ly_set *ns_list;
478 struct lysc_prefix *prefixes;
479 uint32_t i;
480 LY_ARRAY_COUNT_TYPE u;
481
482 if (!prefix_data) {
483 return;
484 }
485
486 switch (format) {
Radek Krejci8df109d2021-04-23 12:19:08 +0200487 case LY_VALUE_XML:
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100488 ns_list = prefix_data;
489 for (i = 0; i < ns_list->count; ++i) {
490 free(((struct lyxml_ns *)ns_list->objs[i])->prefix);
491 free(((struct lyxml_ns *)ns_list->objs[i])->uri);
492 }
493 ly_set_free(ns_list, free);
494 break;
Radek Krejci8df109d2021-04-23 12:19:08 +0200495 case LY_VALUE_SCHEMA_RESOLVED:
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100496 prefixes = prefix_data;
497 LY_ARRAY_FOR(prefixes, u) {
498 free(prefixes[u].prefix);
499 }
500 LY_ARRAY_FREE(prefixes);
501 break;
Radek Krejci224d4b42021-04-23 13:54:59 +0200502 case LY_VALUE_CANON:
Radek Krejci8df109d2021-04-23 12:19:08 +0200503 case LY_VALUE_SCHEMA:
504 case LY_VALUE_JSON:
Radek Krejcif9943642021-04-26 10:18:21 +0200505 case LY_VALUE_LYB:
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100506 break;
507 }
508}
509
510LY_ERR
Radek Krejci8df109d2021-04-23 12:19:08 +0200511ly_dup_prefix_data(const struct ly_ctx *ctx, LY_VALUE_FORMAT format, const void *prefix_data,
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100512 void **prefix_data_p)
513{
514 LY_ERR ret = LY_SUCCESS;
515 struct lyxml_ns *ns;
516 struct lysc_prefix *prefixes = NULL, *orig_pref;
517 struct ly_set *ns_list, *orig_ns;
518 uint32_t i;
519 LY_ARRAY_COUNT_TYPE u;
520
521 assert(!*prefix_data_p);
522
523 switch (format) {
Radek Krejci8df109d2021-04-23 12:19:08 +0200524 case LY_VALUE_SCHEMA:
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100525 *prefix_data_p = (void *)prefix_data;
526 break;
Radek Krejci8df109d2021-04-23 12:19:08 +0200527 case LY_VALUE_SCHEMA_RESOLVED:
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100528 /* copy all the value prefixes */
529 orig_pref = (struct lysc_prefix *)prefix_data;
530 LY_ARRAY_CREATE_GOTO(ctx, prefixes, LY_ARRAY_COUNT(orig_pref), ret, cleanup);
531 *prefix_data_p = prefixes;
532
533 LY_ARRAY_FOR(orig_pref, u) {
534 if (orig_pref[u].prefix) {
535 prefixes[u].prefix = strdup(orig_pref[u].prefix);
536 LY_CHECK_ERR_GOTO(!prefixes[u].prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
537 }
538 prefixes[u].mod = orig_pref[u].mod;
539 LY_ARRAY_INCREMENT(prefixes);
540 }
541 break;
Radek Krejci8df109d2021-04-23 12:19:08 +0200542 case LY_VALUE_XML:
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100543 /* copy all the namespaces */
544 LY_CHECK_GOTO(ret = ly_set_new(&ns_list), cleanup);
545 *prefix_data_p = ns_list;
546
547 orig_ns = (struct ly_set *)prefix_data;
548 for (i = 0; i < orig_ns->count; ++i) {
549 ns = calloc(1, sizeof *ns);
550 LY_CHECK_ERR_GOTO(!ns, LOGMEM(ctx); ret = LY_EMEM, cleanup);
551 LY_CHECK_GOTO(ret = ly_set_add(ns_list, ns, 1, NULL), cleanup);
552
553 if (((struct lyxml_ns *)orig_ns->objs[i])->prefix) {
554 ns->prefix = strdup(((struct lyxml_ns *)orig_ns->objs[i])->prefix);
555 LY_CHECK_ERR_GOTO(!ns->prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
556 }
557 ns->uri = strdup(((struct lyxml_ns *)orig_ns->objs[i])->uri);
558 LY_CHECK_ERR_GOTO(!ns->uri, LOGMEM(ctx); ret = LY_EMEM, cleanup);
559 }
560 break;
Radek Krejci224d4b42021-04-23 13:54:59 +0200561 case LY_VALUE_CANON:
Radek Krejci8df109d2021-04-23 12:19:08 +0200562 case LY_VALUE_JSON:
Radek Krejcif9943642021-04-26 10:18:21 +0200563 case LY_VALUE_LYB:
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100564 assert(!prefix_data);
565 *prefix_data_p = NULL;
566 break;
567 }
568
569cleanup:
570 if (ret) {
571 ly_free_prefix_data(format, *prefix_data_p);
572 *prefix_data_p = NULL;
573 }
574 return ret;
575}
576
577LY_ERR
Radek Krejcif9943642021-04-26 10:18:21 +0200578ly_store_prefix_data(const struct ly_ctx *ctx, const void *value, size_t value_len, LY_VALUE_FORMAT format,
Radek Krejci8df109d2021-04-23 12:19:08 +0200579 const void *prefix_data, LY_VALUE_FORMAT *format_p, void **prefix_data_p)
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100580{
581 LY_ERR ret = LY_SUCCESS;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100582 const struct lys_module *mod;
Michal Vaskofc2cd072021-02-24 13:17:17 +0100583 const struct lyxml_ns *ns;
584 struct lyxml_ns *new_ns;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100585 struct ly_set *ns_list;
586 struct lysc_prefix *prefixes = NULL, *val_pref;
aPiecek83436bc2021-03-30 12:20:45 +0200587 const char *value_iter, *value_next, *value_end;
588 uint32_t substr_len;
589 ly_bool is_prefix;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100590
591 switch (format) {
Radek Krejci8df109d2021-04-23 12:19:08 +0200592 case LY_VALUE_SCHEMA:
Michal Vaskofc2cd072021-02-24 13:17:17 +0100593 /* copy all referenced modules as prefix - module pairs */
594 if (!*prefix_data_p) {
595 /* new prefix data */
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100596 LY_ARRAY_CREATE_GOTO(ctx, prefixes, 0, ret, cleanup);
Radek Krejci8df109d2021-04-23 12:19:08 +0200597 *format_p = LY_VALUE_SCHEMA_RESOLVED;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100598 *prefix_data_p = prefixes;
Michal Vaskofc2cd072021-02-24 13:17:17 +0100599 } else {
600 /* reuse prefix data */
Radek Krejci8df109d2021-04-23 12:19:08 +0200601 assert(*format_p == LY_VALUE_SCHEMA_RESOLVED);
Michal Vaskofc2cd072021-02-24 13:17:17 +0100602 prefixes = *prefix_data_p;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100603 }
604
605 /* add all used prefixes */
aPiecek83436bc2021-03-30 12:20:45 +0200606 value_end = value + value_len;
607 for (value_iter = value; value_iter; value_iter = value_next) {
aPieceke3f828d2021-05-10 15:34:41 +0200608 LY_CHECK_GOTO(ret = ly_value_prefix_next(value_iter, value_end, &substr_len, &is_prefix, &value_next), cleanup);
aPiecek83436bc2021-03-30 12:20:45 +0200609 if (is_prefix) {
610 /* we have a possible prefix. Do we already have the prefix? */
611 mod = ly_resolve_prefix(ctx, value_iter, substr_len, *format_p, *prefix_data_p);
612 if (!mod) {
613 mod = ly_resolve_prefix(ctx, value_iter, substr_len, format, prefix_data);
614 if (mod) {
Radek Krejci8df109d2021-04-23 12:19:08 +0200615 assert(*format_p == LY_VALUE_SCHEMA_RESOLVED);
aPiecek83436bc2021-03-30 12:20:45 +0200616 /* store a new prefix - module pair */
617 LY_ARRAY_NEW_GOTO(ctx, prefixes, val_pref, ret, cleanup);
618 *prefix_data_p = prefixes;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100619
aPiecek83436bc2021-03-30 12:20:45 +0200620 val_pref->prefix = strndup(value_iter, substr_len);
621 LY_CHECK_ERR_GOTO(!val_pref->prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
622 val_pref->mod = mod;
623 } /* else it is not even defined */
624 } /* else the prefix is already present */
Michal Vaskofc2cd072021-02-24 13:17:17 +0100625 }
626 }
627 break;
Radek Krejci8df109d2021-04-23 12:19:08 +0200628 case LY_VALUE_XML:
Michal Vaskofc2cd072021-02-24 13:17:17 +0100629 /* copy all referenced namespaces as prefix - namespace pairs */
630 if (!*prefix_data_p) {
631 /* new prefix data */
632 LY_CHECK_GOTO(ret = ly_set_new(&ns_list), cleanup);
Radek Krejci8df109d2021-04-23 12:19:08 +0200633 *format_p = LY_VALUE_XML;
Michal Vaskofc2cd072021-02-24 13:17:17 +0100634 *prefix_data_p = ns_list;
635 } else {
636 /* reuse prefix data */
Radek Krejci8df109d2021-04-23 12:19:08 +0200637 assert(*format_p == LY_VALUE_XML);
Michal Vaskofc2cd072021-02-24 13:17:17 +0100638 ns_list = *prefix_data_p;
639 }
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100640
Michal Vaskofc2cd072021-02-24 13:17:17 +0100641 /* add all used prefixes */
aPiecek83436bc2021-03-30 12:20:45 +0200642 value_end = value + value_len;
643 for (value_iter = value; value_iter; value_iter = value_next) {
aPieceke3f828d2021-05-10 15:34:41 +0200644 LY_CHECK_GOTO(ret = ly_value_prefix_next(value_iter, value_end, &substr_len, &is_prefix, &value_next), cleanup);
aPiecek83436bc2021-03-30 12:20:45 +0200645 if (is_prefix) {
646 /* we have a possible prefix. Do we already have the prefix? */
647 ns = lyxml_ns_get(ns_list, value_iter, substr_len);
648 if (!ns) {
649 ns = lyxml_ns_get(prefix_data, value_iter, substr_len);
650 if (ns) {
651 /* store a new prefix - namespace pair */
652 new_ns = calloc(1, sizeof *new_ns);
653 LY_CHECK_ERR_GOTO(!new_ns, LOGMEM(ctx); ret = LY_EMEM, cleanup);
654 LY_CHECK_GOTO(ret = ly_set_add(ns_list, new_ns, 1, NULL), cleanup);
Michal Vaskofc2cd072021-02-24 13:17:17 +0100655
aPiecek83436bc2021-03-30 12:20:45 +0200656 new_ns->prefix = strndup(value_iter, substr_len);
657 LY_CHECK_ERR_GOTO(!new_ns->prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
658 new_ns->uri = strdup(ns->uri);
659 LY_CHECK_ERR_GOTO(!new_ns->uri, LOGMEM(ctx); ret = LY_EMEM, cleanup);
660 } /* else it is not even defined */
661 } /* else the prefix is already present */
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100662 }
663 }
664 break;
Radek Krejci224d4b42021-04-23 13:54:59 +0200665 case LY_VALUE_CANON:
Radek Krejci8df109d2021-04-23 12:19:08 +0200666 case LY_VALUE_SCHEMA_RESOLVED:
667 case LY_VALUE_JSON:
Radek Krejcif9943642021-04-26 10:18:21 +0200668 case LY_VALUE_LYB:
Michal Vaskofc2cd072021-02-24 13:17:17 +0100669 if (!*prefix_data_p) {
670 /* new prefix data - simply copy all the prefix data */
671 *format_p = format;
672 LY_CHECK_GOTO(ret = ly_dup_prefix_data(ctx, format, prefix_data, prefix_data_p), cleanup);
673 } /* else reuse prefix data - the prefix data are always the same, nothing to do */
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100674 break;
675 }
676
677cleanup:
678 if (ret) {
679 ly_free_prefix_data(*format_p, *prefix_data_p);
680 *prefix_data_p = NULL;
681 }
682 return ret;
683}
Michal Vasko7ed1fcb2020-12-03 14:15:22 +0100684
685const char *
Radek Krejci8df109d2021-04-23 12:19:08 +0200686ly_format2str(LY_VALUE_FORMAT format)
Michal Vasko7ed1fcb2020-12-03 14:15:22 +0100687{
688 switch (format) {
Radek Krejci224d4b42021-04-23 13:54:59 +0200689 case LY_VALUE_CANON:
690 return "canonical";
Radek Krejci8df109d2021-04-23 12:19:08 +0200691 case LY_VALUE_SCHEMA:
Michal Vasko7ed1fcb2020-12-03 14:15:22 +0100692 return "schema imports";
Radek Krejci8df109d2021-04-23 12:19:08 +0200693 case LY_VALUE_SCHEMA_RESOLVED:
Michal Vasko7ed1fcb2020-12-03 14:15:22 +0100694 return "schema stored mapping";
Radek Krejci8df109d2021-04-23 12:19:08 +0200695 case LY_VALUE_XML:
Michal Vasko7ed1fcb2020-12-03 14:15:22 +0100696 return "XML prefixes";
Radek Krejci8df109d2021-04-23 12:19:08 +0200697 case LY_VALUE_JSON:
Michal Vasko7ed1fcb2020-12-03 14:15:22 +0100698 return "JSON module names";
Radek Krejcif9943642021-04-26 10:18:21 +0200699 case LY_VALUE_LYB:
700 return "LYB prefixes";
Michal Vasko7ed1fcb2020-12-03 14:15:22 +0100701 default:
702 break;
703 }
704
705 return NULL;
706}