blob: 78f53aff713127435397bf6d23bf92fd4a577c23 [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"
Radek Krejciad97c5f2020-06-30 09:19:28 +020029#include "set.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020030#include "tree.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020031#include "tree_data.h"
Michal Vasko60ea6352020-06-29 13:39:39 +020032#include "tree_data_internal.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020033#include "tree_schema.h"
34
Michal Vaskoa6669ba2020-08-06 16:14:26 +020035struct lyd_node *
36lys_getnext_data(const struct lyd_node *last, const struct lyd_node *sibling, const struct lysc_node **slast,
Radek Krejci0f969882020-08-21 16:56:47 +020037 const struct lysc_node *parent, const struct lysc_module *module)
Michal Vaskoa6669ba2020-08-06 16:14:26 +020038{
39 const struct lysc_node *siter = NULL;
40 struct lyd_node *match = NULL;
41
42 assert(parent || module);
43 assert(!last || (slast && *slast));
44
45 if (slast) {
46 siter = *slast;
47 }
48
49 if (last && last->next && (last->next->schema == siter)) {
50 /* return next data instance */
51 return last->next;
52 }
53
54 /* find next schema node data instance */
55 while ((siter = lys_getnext(siter, parent, module, 0))) {
56 if (!lyd_find_sibling_val(sibling, siter, NULL, 0, &match)) {
57 break;
58 }
59 }
60
61 if (slast) {
62 *slast = siter;
63 }
64 return match;
65}
66
Radek Krejcie7b95092019-05-15 11:03:07 +020067struct lyd_node **
68lyd_node_children_p(struct lyd_node *node)
69{
70 assert(node);
Michal Vasko52927e22020-03-16 17:26:14 +010071
72 if (!node->schema) {
73 return &((struct lyd_node_opaq *)node)->child;
74 } else {
75 switch (node->schema->nodetype) {
76 case LYS_CONTAINER:
77 case LYS_LIST:
Michal Vasko1bf09392020-03-27 12:38:10 +010078 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +010079 case LYS_ACTION:
80 case LYS_NOTIF:
81 return &((struct lyd_node_inner *)node)->child;
82 default:
83 return NULL;
84 }
Radek Krejcie7b95092019-05-15 11:03:07 +020085 }
86}
87
Radek Krejcidae0ee82020-05-06 16:53:24 +020088API struct lyd_node *
Radek Krejcia1c1e542020-09-29 16:06:52 +020089lyd_parent(const struct lyd_node *node)
Radek Krejcie7b95092019-05-15 11:03:07 +020090{
Radek Krejcia1c1e542020-09-29 16:06:52 +020091 if (!node) {
92 return NULL;
93 }
94
95 return (struct lyd_node *)(node)->parent;
96}
97
98API struct lyd_node *
99lyd_child(const struct lyd_node *node)
100{
101 struct lyd_node **children;
Radek Krejcie7b95092019-05-15 11:03:07 +0200102
103 if (!node) {
104 return NULL;
105 }
106
Radek Krejcia1c1e542020-09-29 16:06:52 +0200107 if (!node->schema) {
108 /* opaq node */
109 return ((struct lyd_node_opaq *)(node))->child;
110 }
111
Michal Vasko5bfd4be2020-06-23 13:26:19 +0200112 children = lyd_node_children_p((struct lyd_node *)node);
Radek Krejcie7b95092019-05-15 11:03:07 +0200113 if (children) {
Radek Krejcia1c1e542020-09-29 16:06:52 +0200114 return *children;
115 } else {
116 return NULL;
117 }
118}
119
120API struct lyd_node *
121lyd_child_no_keys(const struct lyd_node *node)
122{
123 struct lyd_node **children;
124
125 if (!node) {
126 return NULL;
127 }
128
129 if (!node->schema) {
130 /* opaq node */
131 return ((struct lyd_node_opaq *)(node))->child;
132 }
133
134 children = lyd_node_children_p((struct lyd_node *)node);
135 if (children) {
136 struct lyd_node *child = *children;
137 while (child && child->schema && (child->schema->flags & LYS_KEY)) {
138 child = child->next;
Michal Vasko5bfd4be2020-06-23 13:26:19 +0200139 }
140 return child;
Radek Krejcie7b95092019-05-15 11:03:07 +0200141 } else {
142 return NULL;
143 }
144}
Michal Vasko9b368d32020-02-14 13:53:31 +0100145
Michal Vaskoc193ce92020-03-06 11:04:48 +0100146API const struct lys_module *
147lyd_owner_module(const struct lyd_node *node)
Michal Vasko9b368d32020-02-14 13:53:31 +0100148{
149 const struct lysc_node *schema;
Michal Vaskod5cfa6e2020-11-23 16:56:08 +0100150 const struct lyd_node_opaq *opaq;
Michal Vasko9b368d32020-02-14 13:53:31 +0100151
Michal Vaskod5cfa6e2020-11-23 16:56:08 +0100152 if (!node) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100153 return NULL;
154 }
Michal Vasko9b368d32020-02-14 13:53:31 +0100155
Michal Vaskod5cfa6e2020-11-23 16:56:08 +0100156 if (!node->schema) {
157 opaq = (struct lyd_node_opaq *)node;
158 switch (opaq->format) {
159 case LY_PREF_XML:
160 return ly_ctx_get_module_implemented_ns(LYD_CTX(node), opaq->name.module_ns);
161 case LY_PREF_JSON:
162 return ly_ctx_get_module_implemented(LYD_CTX(node), opaq->name.module_name);
163 default:
164 return NULL;
165 }
166 }
167
Radek Krejci1e008d22020-08-17 11:37:37 +0200168 for (schema = node->schema; schema->parent; schema = schema->parent) {}
Michal Vasko9b368d32020-02-14 13:53:31 +0100169 return schema->module;
170}
Michal Vaskob1b5c262020-03-05 14:29:47 +0100171
172const struct lys_module *
Michal Vasko26e80012020-07-08 10:55:46 +0200173lyd_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 +0200174 struct lyd_node **first)
Michal Vaskob1b5c262020-03-05 14:29:47 +0100175{
176 struct lyd_node *iter;
177 const struct lys_module *mod;
178
179 /* get the next module */
Michal Vasko26e80012020-07-08 10:55:46 +0200180 if (module) {
181 if (*i) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100182 mod = NULL;
Michal Vasko26e80012020-07-08 10:55:46 +0200183 } else {
184 mod = module;
185 ++(*i);
Michal Vaskob1b5c262020-03-05 14:29:47 +0100186 }
187 } else {
188 do {
189 mod = ly_ctx_get_module_iter(ctx, i);
190 } while (mod && !mod->implemented);
191 }
192
193 /* find its data */
194 *first = NULL;
195 if (mod) {
196 LY_LIST_FOR(tree, iter) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100197 if (lyd_owner_module(iter) == mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100198 *first = iter;
199 break;
200 }
201 }
202 }
203
204 return mod;
205}
206
207const struct lys_module *
208lyd_data_next_module(struct lyd_node **next, struct lyd_node **first)
209{
210 const struct lys_module *mod;
211
212 if (!*next) {
213 /* all data traversed */
214 *first = NULL;
215 return NULL;
216 }
217
218 *first = *next;
219
220 /* prepare next */
Michal Vaskoc193ce92020-03-06 11:04:48 +0100221 mod = lyd_owner_module(*next);
Michal Vaskob1b5c262020-03-05 14:29:47 +0100222 LY_LIST_FOR(*next, *next) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100223 if (lyd_owner_module(*next) != mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100224 break;
225 }
226 }
227
228 return mod;
229}
Michal Vasko9f96a052020-03-10 09:41:45 +0100230
231LY_ERR
232lyd_parse_check_keys(struct lyd_node *node)
233{
234 const struct lysc_node *skey = NULL;
235 const struct lyd_node *key;
236
237 assert(node->schema->nodetype == LYS_LIST);
238
Radek Krejcia1c1e542020-09-29 16:06:52 +0200239 key = lyd_child(node);
Michal Vasko9f96a052020-03-10 09:41:45 +0100240 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
241 if (!key || (key->schema != skey)) {
Radek Krejci2efc45b2020-12-22 16:25:44 +0100242 LOGVAL(LYD_CTX(node), LY_VCODE_NOKEY, skey->name);
Michal Vasko9f96a052020-03-10 09:41:45 +0100243 return LY_EVALID;
244 }
245
246 key = key->next;
247 }
248
249 return LY_SUCCESS;
250}
Michal Vasko60ea6352020-06-29 13:39:39 +0200251
252void
Radek Krejci1deb5be2020-08-26 16:43:36 +0200253lyd_parse_set_data_flags(struct lyd_node *node, struct ly_set *when_check, struct lyd_meta **meta, uint32_t options)
Michal Vasko60ea6352020-06-29 13:39:39 +0200254{
255 struct lyd_meta *meta2, *prev_meta = NULL;
256
Michal Vaskoa5705e52020-12-09 18:15:14 +0100257 if (lysc_has_when(node->schema)) {
Michal Vasko0f3377d2020-11-09 20:56:11 +0100258 if (!(options & LYD_PARSE_ONLY)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200259 /* remember we need to evaluate this node's when */
Radek Krejci3d92e442020-10-12 12:48:13 +0200260 LY_CHECK_RET(ly_set_add(when_check, node, 1, NULL), );
Michal Vasko60ea6352020-06-29 13:39:39 +0200261 }
262 }
263
Michal Vasko60ea6352020-06-29 13:39:39 +0200264 LY_LIST_FOR(*meta, meta2) {
Michal Vasko69730152020-10-09 16:30:07 +0200265 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults") &&
266 meta2->value.boolean) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200267 /* node is default according to the metadata */
268 node->flags |= LYD_DEFAULT;
269
270 /* delete the metadata */
271 if (prev_meta) {
272 prev_meta->next = meta2->next;
273 } else {
274 *meta = (*meta)->next;
275 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200276 lyd_free_meta_single(meta2);
Michal Vasko60ea6352020-06-29 13:39:39 +0200277 break;
278 }
279
280 prev_meta = meta2;
281 }
282}
283
Michal Vaskoc0004272020-08-06 08:32:34 +0200284API LY_ERR
Michal Vasko61551fa2020-07-09 15:45:45 +0200285lyd_any_copy_value(struct lyd_node *trg, const union lyd_any_value *value, LYD_ANYDATA_VALUETYPE value_type)
286{
287 struct lyd_node_any *t;
Michal Vasko61551fa2020-07-09 15:45:45 +0200288
289 assert(trg->schema->nodetype & LYS_ANYDATA);
290
291 t = (struct lyd_node_any *)trg;
292
293 /* free trg */
294 switch (t->value_type) {
295 case LYD_ANYDATA_DATATREE:
296 lyd_free_all(t->value.tree);
297 break;
298 case LYD_ANYDATA_STRING:
299 case LYD_ANYDATA_XML:
300 case LYD_ANYDATA_JSON:
Michal Vaskob7be7a82020-08-20 09:09:04 +0200301 FREE_STRING(LYD_CTX(trg), t->value.str);
Michal Vasko61551fa2020-07-09 15:45:45 +0200302 break;
303 case LYD_ANYDATA_LYB:
304 free(t->value.mem);
305 break;
306 }
307 t->value.str = NULL;
308
309 if (!value) {
310 /* only free value in this case */
311 return LY_SUCCESS;
312 }
313
314 /* copy src */
315 t->value_type = value_type;
316 switch (value_type) {
317 case LYD_ANYDATA_DATATREE:
318 if (value->tree) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200319 LY_CHECK_RET(lyd_dup_siblings(value->tree, NULL, LYD_DUP_RECURSIVE, &t->value.tree));
Michal Vasko61551fa2020-07-09 15:45:45 +0200320 }
321 break;
322 case LYD_ANYDATA_STRING:
323 case LYD_ANYDATA_XML:
324 case LYD_ANYDATA_JSON:
325 if (value->str) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200326 LY_CHECK_RET(lydict_insert(LYD_CTX(trg), value->str, 0, &t->value.str));
Michal Vasko61551fa2020-07-09 15:45:45 +0200327 }
328 break;
329 case LYD_ANYDATA_LYB:
330 if (value->mem) {
Radek Krejci1deb5be2020-08-26 16:43:36 +0200331 int len = lyd_lyb_data_length(value->mem);
Radek Krejci82fa8d42020-07-11 22:00:59 +0200332 LY_CHECK_RET(len == -1, LY_EINVAL);
Michal Vasko61551fa2020-07-09 15:45:45 +0200333 t->value.mem = malloc(len);
Michal Vaskob7be7a82020-08-20 09:09:04 +0200334 LY_CHECK_ERR_RET(!t->value.mem, LOGMEM(LYD_CTX(trg)), LY_EMEM);
Michal Vasko61551fa2020-07-09 15:45:45 +0200335 memcpy(t->value.mem, value->mem, len);
336 }
337 break;
338 }
339
340 return LY_SUCCESS;
341}
342
Michal Vasko60ea6352020-06-29 13:39:39 +0200343LYB_HASH
344lyb_hash(struct lysc_node *sibling, uint8_t collision_id)
345{
346 const struct lys_module *mod;
Michal Vasko60ea6352020-06-29 13:39:39 +0200347 uint32_t full_hash;
348 LYB_HASH hash;
349
350 if ((collision_id < LYS_NODE_HASH_COUNT) && sibling->hash[collision_id]) {
351 return sibling->hash[collision_id];
352 }
353
354 mod = sibling->module;
355
356 full_hash = dict_hash_multi(0, mod->name, strlen(mod->name));
357 full_hash = dict_hash_multi(full_hash, sibling->name, strlen(sibling->name));
358 if (collision_id) {
Radek Krejci1deb5be2020-08-26 16:43:36 +0200359 size_t ext_len;
360
Michal Vasko60ea6352020-06-29 13:39:39 +0200361 if (collision_id > strlen(mod->name)) {
362 /* fine, we will not hash more bytes, just use more bits from the hash than previously */
363 ext_len = strlen(mod->name);
364 } else {
365 /* use one more byte from the module name than before */
366 ext_len = collision_id;
367 }
368 full_hash = dict_hash_multi(full_hash, mod->name, ext_len);
369 }
370 full_hash = dict_hash_multi(full_hash, NULL, 0);
371
372 /* use the shortened hash */
373 hash = full_hash & (LYB_HASH_MASK >> collision_id);
374 /* add colision identificator */
375 hash |= LYB_HASH_COLLISION_ID >> collision_id;
376
377 /* save this hash */
378 if (collision_id < LYS_NODE_HASH_COUNT) {
379 sibling->hash[collision_id] = hash;
380 }
381
382 return hash;
383}
384
Radek Krejci857189e2020-09-01 13:26:36 +0200385ly_bool
Michal Vasko60ea6352020-06-29 13:39:39 +0200386lyb_has_schema_model(const struct lysc_node *sibling, const struct lys_module **models)
387{
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200388 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +0200389
390 LY_ARRAY_FOR(models, u) {
391 if (sibling->module == models[u]) {
392 return 1;
393 }
394 }
395
396 return 0;
397}
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100398
399void
Michal Vaskod3bb12f2020-12-04 14:33:09 +0100400lyd_del_move_root(struct lyd_node **root, const struct lyd_node *to_del, const struct lys_module *mod)
401{
402 if (*root && (lyd_owner_module(*root) != mod)) {
403 /* there are no data of mod so this is simply the first top-level sibling */
404 mod = NULL;
405 }
406
407 if ((*root != to_del) || (*root)->parent) {
408 return;
409 }
410
411 *root = (*root)->next;
412 if (mod && *root && (lyd_owner_module(to_del) != lyd_owner_module(*root))) {
413 /* there are no more nodes from mod */
414 *root = lyd_first_sibling(*root);
415 }
416}
417
418void
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100419ly_free_prefix_data(LY_PREFIX_FORMAT format, void *prefix_data)
420{
421 struct ly_set *ns_list;
422 struct lysc_prefix *prefixes;
423 uint32_t i;
424 LY_ARRAY_COUNT_TYPE u;
425
426 if (!prefix_data) {
427 return;
428 }
429
430 switch (format) {
431 case LY_PREF_XML:
432 ns_list = prefix_data;
433 for (i = 0; i < ns_list->count; ++i) {
434 free(((struct lyxml_ns *)ns_list->objs[i])->prefix);
435 free(((struct lyxml_ns *)ns_list->objs[i])->uri);
436 }
437 ly_set_free(ns_list, free);
438 break;
439 case LY_PREF_SCHEMA_RESOLVED:
440 prefixes = prefix_data;
441 LY_ARRAY_FOR(prefixes, u) {
442 free(prefixes[u].prefix);
443 }
444 LY_ARRAY_FREE(prefixes);
445 break;
446 case LY_PREF_SCHEMA:
447 case LY_PREF_JSON:
448 break;
449 }
450}
451
452LY_ERR
453ly_dup_prefix_data(const struct ly_ctx *ctx, LY_PREFIX_FORMAT format, const void *prefix_data,
454 void **prefix_data_p)
455{
456 LY_ERR ret = LY_SUCCESS;
457 struct lyxml_ns *ns;
458 struct lysc_prefix *prefixes = NULL, *orig_pref;
459 struct ly_set *ns_list, *orig_ns;
460 uint32_t i;
461 LY_ARRAY_COUNT_TYPE u;
462
463 assert(!*prefix_data_p);
464
465 switch (format) {
466 case LY_PREF_SCHEMA:
467 *prefix_data_p = (void *)prefix_data;
468 break;
469 case LY_PREF_SCHEMA_RESOLVED:
470 /* copy all the value prefixes */
471 orig_pref = (struct lysc_prefix *)prefix_data;
472 LY_ARRAY_CREATE_GOTO(ctx, prefixes, LY_ARRAY_COUNT(orig_pref), ret, cleanup);
473 *prefix_data_p = prefixes;
474
475 LY_ARRAY_FOR(orig_pref, u) {
476 if (orig_pref[u].prefix) {
477 prefixes[u].prefix = strdup(orig_pref[u].prefix);
478 LY_CHECK_ERR_GOTO(!prefixes[u].prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
479 }
480 prefixes[u].mod = orig_pref[u].mod;
481 LY_ARRAY_INCREMENT(prefixes);
482 }
483 break;
484 case LY_PREF_XML:
485 /* copy all the namespaces */
486 LY_CHECK_GOTO(ret = ly_set_new(&ns_list), cleanup);
487 *prefix_data_p = ns_list;
488
489 orig_ns = (struct ly_set *)prefix_data;
490 for (i = 0; i < orig_ns->count; ++i) {
491 ns = calloc(1, sizeof *ns);
492 LY_CHECK_ERR_GOTO(!ns, LOGMEM(ctx); ret = LY_EMEM, cleanup);
493 LY_CHECK_GOTO(ret = ly_set_add(ns_list, ns, 1, NULL), cleanup);
494
495 if (((struct lyxml_ns *)orig_ns->objs[i])->prefix) {
496 ns->prefix = strdup(((struct lyxml_ns *)orig_ns->objs[i])->prefix);
497 LY_CHECK_ERR_GOTO(!ns->prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
498 }
499 ns->uri = strdup(((struct lyxml_ns *)orig_ns->objs[i])->uri);
500 LY_CHECK_ERR_GOTO(!ns->uri, LOGMEM(ctx); ret = LY_EMEM, cleanup);
501 }
502 break;
503 case LY_PREF_JSON:
504 assert(!prefix_data);
505 *prefix_data_p = NULL;
506 break;
507 }
508
509cleanup:
510 if (ret) {
511 ly_free_prefix_data(format, *prefix_data_p);
512 *prefix_data_p = NULL;
513 }
514 return ret;
515}
516
517LY_ERR
518ly_store_prefix_data(const struct ly_ctx *ctx, const char *value, size_t value_len, LY_PREFIX_FORMAT format,
519 void *prefix_data, LY_PREFIX_FORMAT *format_p, void **prefix_data_p)
520{
521 LY_ERR ret = LY_SUCCESS;
522 const char *start, *stop;
523 const struct lys_module *mod;
524 struct lyxml_ns *ns;
525 struct ly_set *ns_list;
526 struct lysc_prefix *prefixes = NULL, *val_pref;
527
528 switch (format) {
529 case LY_PREF_SCHEMA:
530 case LY_PREF_XML:
531 /* copy all referenced modules... */
532 if (format == LY_PREF_XML) {
533 /* ...as prefix - namespace pairs */
534 LY_CHECK_GOTO(ret = ly_set_new(&ns_list), cleanup);
535 *format_p = LY_PREF_XML;
536 *prefix_data_p = ns_list;
537 } else {
538 /* ...as prefix - module pairs */
539 assert(format == LY_PREF_SCHEMA);
540 LY_ARRAY_CREATE_GOTO(ctx, prefixes, 0, ret, cleanup);
541 *format_p = LY_PREF_SCHEMA_RESOLVED;
542 *prefix_data_p = prefixes;
543 }
544
545 /* add all used prefixes */
546 for (stop = start = value; (size_t)(stop - value) < value_len; start = stop) {
547 size_t bytes;
548 uint32_t c;
549
550 ly_getutf8(&stop, &c, &bytes);
551 if (is_xmlqnamestartchar(c)) {
552 for (ly_getutf8(&stop, &c, &bytes);
553 is_xmlqnamechar(c) && (size_t)(stop - value) < value_len;
554 ly_getutf8(&stop, &c, &bytes)) {}
555 stop = stop - bytes;
556 if (*stop == ':') {
557 /* we have a possible prefix */
558 size_t len = stop - start;
559
560 /* do we already have the prefix? */
561 mod = ly_type_store_resolve_prefix(ctx, start, len, *format_p, *prefix_data_p);
562 if (!mod) {
563 mod = ly_type_store_resolve_prefix(ctx, start, len, format, prefix_data);
564 if (mod) {
565 if (*format_p == LY_PREF_XML) {
566 /* store a new prefix - namespace pair */
567 ns = calloc(1, sizeof *ns);
568 LY_CHECK_ERR_GOTO(!ns, LOGMEM(ctx); ret = LY_EMEM, cleanup);
569 LY_CHECK_GOTO(ret = ly_set_add(ns_list, ns, 1, NULL), cleanup);
570
571 ns->prefix = strndup(start, len);
572 LY_CHECK_ERR_GOTO(!ns->prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
573 ns->uri = strdup(mod->ns);
574 LY_CHECK_ERR_GOTO(!ns->uri, LOGMEM(ctx); ret = LY_EMEM, cleanup);
575 } else {
576 assert(*format_p == LY_PREF_SCHEMA_RESOLVED);
577 /* store a new prefix - module pair */
578 LY_ARRAY_NEW_GOTO(ctx, prefixes, val_pref, ret, cleanup);
579 *prefix_data_p = prefixes;
580
581 val_pref->prefix = strndup(start, len);
582 LY_CHECK_ERR_GOTO(!val_pref->prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
583 val_pref->mod = mod;
584 }
585 } /* else it is not even defined */
586 } /* else the prefix is already present */
587 }
588 stop = stop + bytes;
589 }
590 }
591 break;
592 case LY_PREF_SCHEMA_RESOLVED:
593 case LY_PREF_JSON:
594 /* simply copy all the prefix data */
595 *format_p = format;
596 LY_CHECK_GOTO(ret = ly_dup_prefix_data(ctx, format, prefix_data, prefix_data_p), cleanup);
597 break;
598 }
599
600cleanup:
601 if (ret) {
602 ly_free_prefix_data(*format_p, *prefix_data_p);
603 *prefix_data_p = NULL;
604 }
605 return ret;
606}
Michal Vasko7ed1fcb2020-12-03 14:15:22 +0100607
608const char *
609ly_format2str(LY_PREFIX_FORMAT format)
610{
611 switch (format) {
612 case LY_PREF_SCHEMA:
613 return "schema imports";
614 case LY_PREF_SCHEMA_RESOLVED:
615 return "schema stored mapping";
616 case LY_PREF_XML:
617 return "XML prefixes";
618 case LY_PREF_JSON:
619 return "JSON module names";
620 default:
621 break;
622 }
623
624 return NULL;
625}