blob: c2134c0633246300aeaae45b6ad9dd13fc888257 [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 */
Michal Vasko6b5cb2a2020-11-11 19:11:21 +010014#define _XOPEN_SOURCE 500 /* strdup */
15#define _POSIX_C_SOURCE 200809L /*strndup */
Radek Krejcie7b95092019-05-15 11:03:07 +020016
17#include <assert.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020018#include <stdint.h>
Radek Krejcie7b95092019-05-15 11:03:07 +020019#include <stdlib.h>
Radek Krejciad97c5f2020-06-30 09:19:28 +020020#include <string.h>
Radek Krejcie7b95092019-05-15 11:03:07 +020021
Radek Krejci535ea9f2020-05-29 16:01:05 +020022#include "common.h"
Michal Vasko6b5cb2a2020-11-11 19:11:21 +010023#include "compat.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020024#include "context.h"
Radek Krejci47fab892020-11-05 17:02:41 +010025#include "dict.h"
Radek Krejciad97c5f2020-06-30 09:19:28 +020026#include "hash_table.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020027#include "log.h"
Radek Krejciad97c5f2020-06-30 09:19:28 +020028#include "lyb.h"
Radek Krejci7931b192020-06-25 17:05:03 +020029#include "parser_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 Krejcie7b95092019-05-15 11:03:07 +020034#include "tree_schema.h"
35
Michal Vaskoa6669ba2020-08-06 16:14:26 +020036struct lyd_node *
37lys_getnext_data(const struct lyd_node *last, const struct lyd_node *sibling, const struct lysc_node **slast,
Radek Krejci0f969882020-08-21 16:56:47 +020038 const struct lysc_node *parent, const struct lysc_module *module)
Michal Vaskoa6669ba2020-08-06 16:14:26 +020039{
40 const struct lysc_node *siter = NULL;
41 struct lyd_node *match = NULL;
42
43 assert(parent || module);
44 assert(!last || (slast && *slast));
45
46 if (slast) {
47 siter = *slast;
48 }
49
50 if (last && last->next && (last->next->schema == siter)) {
51 /* return next data instance */
52 return last->next;
53 }
54
55 /* find next schema node data instance */
56 while ((siter = lys_getnext(siter, parent, module, 0))) {
57 if (!lyd_find_sibling_val(sibling, siter, NULL, 0, &match)) {
58 break;
59 }
60 }
61
62 if (slast) {
63 *slast = siter;
64 }
65 return match;
66}
67
Radek Krejcie7b95092019-05-15 11:03:07 +020068struct lyd_node **
69lyd_node_children_p(struct lyd_node *node)
70{
71 assert(node);
Michal Vasko52927e22020-03-16 17:26:14 +010072
73 if (!node->schema) {
74 return &((struct lyd_node_opaq *)node)->child;
75 } else {
76 switch (node->schema->nodetype) {
77 case LYS_CONTAINER:
78 case LYS_LIST:
Michal Vasko1bf09392020-03-27 12:38:10 +010079 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +010080 case LYS_ACTION:
81 case LYS_NOTIF:
82 return &((struct lyd_node_inner *)node)->child;
83 default:
84 return NULL;
85 }
Radek Krejcie7b95092019-05-15 11:03:07 +020086 }
87}
88
Radek Krejcidae0ee82020-05-06 16:53:24 +020089API struct lyd_node *
Radek Krejcia1c1e542020-09-29 16:06:52 +020090lyd_parent(const struct lyd_node *node)
Radek Krejcie7b95092019-05-15 11:03:07 +020091{
Radek Krejcia1c1e542020-09-29 16:06:52 +020092 if (!node) {
93 return NULL;
94 }
95
96 return (struct lyd_node *)(node)->parent;
97}
98
99API struct lyd_node *
100lyd_child(const struct lyd_node *node)
101{
102 struct lyd_node **children;
Radek Krejcie7b95092019-05-15 11:03:07 +0200103
104 if (!node) {
105 return NULL;
106 }
107
Radek Krejcia1c1e542020-09-29 16:06:52 +0200108 if (!node->schema) {
109 /* opaq node */
110 return ((struct lyd_node_opaq *)(node))->child;
111 }
112
Michal Vasko5bfd4be2020-06-23 13:26:19 +0200113 children = lyd_node_children_p((struct lyd_node *)node);
Radek Krejcie7b95092019-05-15 11:03:07 +0200114 if (children) {
Radek Krejcia1c1e542020-09-29 16:06:52 +0200115 return *children;
116 } else {
117 return NULL;
118 }
119}
120
121API struct lyd_node *
122lyd_child_no_keys(const struct lyd_node *node)
123{
124 struct lyd_node **children;
125
126 if (!node) {
127 return NULL;
128 }
129
130 if (!node->schema) {
131 /* opaq node */
132 return ((struct lyd_node_opaq *)(node))->child;
133 }
134
135 children = lyd_node_children_p((struct lyd_node *)node);
136 if (children) {
137 struct lyd_node *child = *children;
138 while (child && child->schema && (child->schema->flags & LYS_KEY)) {
139 child = child->next;
Michal Vasko5bfd4be2020-06-23 13:26:19 +0200140 }
141 return child;
Radek Krejcie7b95092019-05-15 11:03:07 +0200142 } else {
143 return NULL;
144 }
145}
Michal Vasko9b368d32020-02-14 13:53:31 +0100146
Michal Vaskoc193ce92020-03-06 11:04:48 +0100147API const struct lys_module *
148lyd_owner_module(const struct lyd_node *node)
Michal Vasko9b368d32020-02-14 13:53:31 +0100149{
150 const struct lysc_node *schema;
Michal Vaskod5cfa6e2020-11-23 16:56:08 +0100151 const struct lyd_node_opaq *opaq;
Michal Vasko9b368d32020-02-14 13:53:31 +0100152
Michal Vaskod5cfa6e2020-11-23 16:56:08 +0100153 if (!node) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100154 return NULL;
155 }
Michal Vasko9b368d32020-02-14 13:53:31 +0100156
Michal Vaskod5cfa6e2020-11-23 16:56:08 +0100157 if (!node->schema) {
158 opaq = (struct lyd_node_opaq *)node;
159 switch (opaq->format) {
160 case LY_PREF_XML:
161 return ly_ctx_get_module_implemented_ns(LYD_CTX(node), opaq->name.module_ns);
162 case LY_PREF_JSON:
163 return ly_ctx_get_module_implemented(LYD_CTX(node), opaq->name.module_name);
164 default:
165 return NULL;
166 }
167 }
168
Radek Krejci1e008d22020-08-17 11:37:37 +0200169 for (schema = node->schema; schema->parent; schema = schema->parent) {}
Michal Vasko9b368d32020-02-14 13:53:31 +0100170 return schema->module;
171}
Michal Vaskob1b5c262020-03-05 14:29:47 +0100172
173const struct lys_module *
Michal Vasko26e80012020-07-08 10:55:46 +0200174lyd_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 +0200175 struct lyd_node **first)
Michal Vaskob1b5c262020-03-05 14:29:47 +0100176{
177 struct lyd_node *iter;
178 const struct lys_module *mod;
179
180 /* get the next module */
Michal Vasko26e80012020-07-08 10:55:46 +0200181 if (module) {
182 if (*i) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100183 mod = NULL;
Michal Vasko26e80012020-07-08 10:55:46 +0200184 } else {
185 mod = module;
186 ++(*i);
Michal Vaskob1b5c262020-03-05 14:29:47 +0100187 }
188 } else {
189 do {
190 mod = ly_ctx_get_module_iter(ctx, i);
191 } while (mod && !mod->implemented);
192 }
193
194 /* find its data */
195 *first = NULL;
196 if (mod) {
197 LY_LIST_FOR(tree, iter) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100198 if (lyd_owner_module(iter) == mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100199 *first = iter;
200 break;
201 }
202 }
203 }
204
205 return mod;
206}
207
208const struct lys_module *
209lyd_data_next_module(struct lyd_node **next, struct lyd_node **first)
210{
211 const struct lys_module *mod;
212
213 if (!*next) {
214 /* all data traversed */
215 *first = NULL;
216 return NULL;
217 }
218
219 *first = *next;
220
221 /* prepare next */
Michal Vaskoc193ce92020-03-06 11:04:48 +0100222 mod = lyd_owner_module(*next);
Michal Vaskob1b5c262020-03-05 14:29:47 +0100223 LY_LIST_FOR(*next, *next) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100224 if (lyd_owner_module(*next) != mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100225 break;
226 }
227 }
228
229 return mod;
230}
Michal Vasko9f96a052020-03-10 09:41:45 +0100231
232LY_ERR
233lyd_parse_check_keys(struct lyd_node *node)
234{
235 const struct lysc_node *skey = NULL;
236 const struct lyd_node *key;
237
238 assert(node->schema->nodetype == LYS_LIST);
239
Radek Krejcia1c1e542020-09-29 16:06:52 +0200240 key = lyd_child(node);
Michal Vasko9f96a052020-03-10 09:41:45 +0100241 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
242 if (!key || (key->schema != skey)) {
Michal Vaskob7be7a82020-08-20 09:09:04 +0200243 LOGVAL(LYD_CTX(node), LY_VLOG_LYD, node, LY_VCODE_NOKEY, skey->name);
Michal Vasko9f96a052020-03-10 09:41:45 +0100244 return LY_EVALID;
245 }
246
247 key = key->next;
248 }
249
250 return LY_SUCCESS;
251}
Michal Vasko60ea6352020-06-29 13:39:39 +0200252
253void
Radek Krejci1deb5be2020-08-26 16:43:36 +0200254lyd_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 +0200255{
256 struct lyd_meta *meta2, *prev_meta = NULL;
257
258 if (!(node->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) && node->schema->when) {
Michal Vasko0f3377d2020-11-09 20:56:11 +0100259 if (!(options & LYD_PARSE_ONLY)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200260 /* remember we need to evaluate this node's when */
Radek Krejci3d92e442020-10-12 12:48:13 +0200261 LY_CHECK_RET(ly_set_add(when_check, node, 1, NULL), );
Michal Vasko60ea6352020-06-29 13:39:39 +0200262 }
263 }
264
Michal Vasko60ea6352020-06-29 13:39:39 +0200265 LY_LIST_FOR(*meta, meta2) {
Michal Vasko69730152020-10-09 16:30:07 +0200266 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults") &&
267 meta2->value.boolean) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200268 /* node is default according to the metadata */
269 node->flags |= LYD_DEFAULT;
270
271 /* delete the metadata */
272 if (prev_meta) {
273 prev_meta->next = meta2->next;
274 } else {
275 *meta = (*meta)->next;
276 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200277 lyd_free_meta_single(meta2);
Michal Vasko60ea6352020-06-29 13:39:39 +0200278 break;
279 }
280
281 prev_meta = meta2;
282 }
283}
284
Michal Vaskoc0004272020-08-06 08:32:34 +0200285API LY_ERR
Michal Vasko61551fa2020-07-09 15:45:45 +0200286lyd_any_copy_value(struct lyd_node *trg, const union lyd_any_value *value, LYD_ANYDATA_VALUETYPE value_type)
287{
288 struct lyd_node_any *t;
Michal Vasko61551fa2020-07-09 15:45:45 +0200289
290 assert(trg->schema->nodetype & LYS_ANYDATA);
291
292 t = (struct lyd_node_any *)trg;
293
294 /* free trg */
295 switch (t->value_type) {
296 case LYD_ANYDATA_DATATREE:
297 lyd_free_all(t->value.tree);
298 break;
299 case LYD_ANYDATA_STRING:
300 case LYD_ANYDATA_XML:
301 case LYD_ANYDATA_JSON:
Michal Vaskob7be7a82020-08-20 09:09:04 +0200302 FREE_STRING(LYD_CTX(trg), t->value.str);
Michal Vasko61551fa2020-07-09 15:45:45 +0200303 break;
304 case LYD_ANYDATA_LYB:
305 free(t->value.mem);
306 break;
307 }
308 t->value.str = NULL;
309
310 if (!value) {
311 /* only free value in this case */
312 return LY_SUCCESS;
313 }
314
315 /* copy src */
316 t->value_type = value_type;
317 switch (value_type) {
318 case LYD_ANYDATA_DATATREE:
319 if (value->tree) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200320 LY_CHECK_RET(lyd_dup_siblings(value->tree, NULL, LYD_DUP_RECURSIVE, &t->value.tree));
Michal Vasko61551fa2020-07-09 15:45:45 +0200321 }
322 break;
323 case LYD_ANYDATA_STRING:
324 case LYD_ANYDATA_XML:
325 case LYD_ANYDATA_JSON:
326 if (value->str) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200327 LY_CHECK_RET(lydict_insert(LYD_CTX(trg), value->str, 0, &t->value.str));
Michal Vasko61551fa2020-07-09 15:45:45 +0200328 }
329 break;
330 case LYD_ANYDATA_LYB:
331 if (value->mem) {
Radek Krejci1deb5be2020-08-26 16:43:36 +0200332 int len = lyd_lyb_data_length(value->mem);
Radek Krejci82fa8d42020-07-11 22:00:59 +0200333 LY_CHECK_RET(len == -1, LY_EINVAL);
Michal Vasko61551fa2020-07-09 15:45:45 +0200334 t->value.mem = malloc(len);
Michal Vaskob7be7a82020-08-20 09:09:04 +0200335 LY_CHECK_ERR_RET(!t->value.mem, LOGMEM(LYD_CTX(trg)), LY_EMEM);
Michal Vasko61551fa2020-07-09 15:45:45 +0200336 memcpy(t->value.mem, value->mem, len);
337 }
338 break;
339 }
340
341 return LY_SUCCESS;
342}
343
Michal Vasko60ea6352020-06-29 13:39:39 +0200344LYB_HASH
345lyb_hash(struct lysc_node *sibling, uint8_t collision_id)
346{
347 const struct lys_module *mod;
Michal Vasko60ea6352020-06-29 13:39:39 +0200348 uint32_t full_hash;
349 LYB_HASH hash;
350
351 if ((collision_id < LYS_NODE_HASH_COUNT) && sibling->hash[collision_id]) {
352 return sibling->hash[collision_id];
353 }
354
355 mod = sibling->module;
356
357 full_hash = dict_hash_multi(0, mod->name, strlen(mod->name));
358 full_hash = dict_hash_multi(full_hash, sibling->name, strlen(sibling->name));
359 if (collision_id) {
Radek Krejci1deb5be2020-08-26 16:43:36 +0200360 size_t ext_len;
361
Michal Vasko60ea6352020-06-29 13:39:39 +0200362 if (collision_id > strlen(mod->name)) {
363 /* fine, we will not hash more bytes, just use more bits from the hash than previously */
364 ext_len = strlen(mod->name);
365 } else {
366 /* use one more byte from the module name than before */
367 ext_len = collision_id;
368 }
369 full_hash = dict_hash_multi(full_hash, mod->name, ext_len);
370 }
371 full_hash = dict_hash_multi(full_hash, NULL, 0);
372
373 /* use the shortened hash */
374 hash = full_hash & (LYB_HASH_MASK >> collision_id);
375 /* add colision identificator */
376 hash |= LYB_HASH_COLLISION_ID >> collision_id;
377
378 /* save this hash */
379 if (collision_id < LYS_NODE_HASH_COUNT) {
380 sibling->hash[collision_id] = hash;
381 }
382
383 return hash;
384}
385
Radek Krejci857189e2020-09-01 13:26:36 +0200386ly_bool
Michal Vasko60ea6352020-06-29 13:39:39 +0200387lyb_has_schema_model(const struct lysc_node *sibling, const struct lys_module **models)
388{
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200389 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +0200390
391 LY_ARRAY_FOR(models, u) {
392 if (sibling->module == models[u]) {
393 return 1;
394 }
395 }
396
397 return 0;
398}
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100399
400void
401ly_free_prefix_data(LY_PREFIX_FORMAT format, void *prefix_data)
402{
403 struct ly_set *ns_list;
404 struct lysc_prefix *prefixes;
405 uint32_t i;
406 LY_ARRAY_COUNT_TYPE u;
407
408 if (!prefix_data) {
409 return;
410 }
411
412 switch (format) {
413 case LY_PREF_XML:
414 ns_list = prefix_data;
415 for (i = 0; i < ns_list->count; ++i) {
416 free(((struct lyxml_ns *)ns_list->objs[i])->prefix);
417 free(((struct lyxml_ns *)ns_list->objs[i])->uri);
418 }
419 ly_set_free(ns_list, free);
420 break;
421 case LY_PREF_SCHEMA_RESOLVED:
422 prefixes = prefix_data;
423 LY_ARRAY_FOR(prefixes, u) {
424 free(prefixes[u].prefix);
425 }
426 LY_ARRAY_FREE(prefixes);
427 break;
428 case LY_PREF_SCHEMA:
429 case LY_PREF_JSON:
430 break;
431 }
432}
433
434LY_ERR
435ly_dup_prefix_data(const struct ly_ctx *ctx, LY_PREFIX_FORMAT format, const void *prefix_data,
436 void **prefix_data_p)
437{
438 LY_ERR ret = LY_SUCCESS;
439 struct lyxml_ns *ns;
440 struct lysc_prefix *prefixes = NULL, *orig_pref;
441 struct ly_set *ns_list, *orig_ns;
442 uint32_t i;
443 LY_ARRAY_COUNT_TYPE u;
444
445 assert(!*prefix_data_p);
446
447 switch (format) {
448 case LY_PREF_SCHEMA:
449 *prefix_data_p = (void *)prefix_data;
450 break;
451 case LY_PREF_SCHEMA_RESOLVED:
452 /* copy all the value prefixes */
453 orig_pref = (struct lysc_prefix *)prefix_data;
454 LY_ARRAY_CREATE_GOTO(ctx, prefixes, LY_ARRAY_COUNT(orig_pref), ret, cleanup);
455 *prefix_data_p = prefixes;
456
457 LY_ARRAY_FOR(orig_pref, u) {
458 if (orig_pref[u].prefix) {
459 prefixes[u].prefix = strdup(orig_pref[u].prefix);
460 LY_CHECK_ERR_GOTO(!prefixes[u].prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
461 }
462 prefixes[u].mod = orig_pref[u].mod;
463 LY_ARRAY_INCREMENT(prefixes);
464 }
465 break;
466 case LY_PREF_XML:
467 /* copy all the namespaces */
468 LY_CHECK_GOTO(ret = ly_set_new(&ns_list), cleanup);
469 *prefix_data_p = ns_list;
470
471 orig_ns = (struct ly_set *)prefix_data;
472 for (i = 0; i < orig_ns->count; ++i) {
473 ns = calloc(1, sizeof *ns);
474 LY_CHECK_ERR_GOTO(!ns, LOGMEM(ctx); ret = LY_EMEM, cleanup);
475 LY_CHECK_GOTO(ret = ly_set_add(ns_list, ns, 1, NULL), cleanup);
476
477 if (((struct lyxml_ns *)orig_ns->objs[i])->prefix) {
478 ns->prefix = strdup(((struct lyxml_ns *)orig_ns->objs[i])->prefix);
479 LY_CHECK_ERR_GOTO(!ns->prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
480 }
481 ns->uri = strdup(((struct lyxml_ns *)orig_ns->objs[i])->uri);
482 LY_CHECK_ERR_GOTO(!ns->uri, LOGMEM(ctx); ret = LY_EMEM, cleanup);
483 }
484 break;
485 case LY_PREF_JSON:
486 assert(!prefix_data);
487 *prefix_data_p = NULL;
488 break;
489 }
490
491cleanup:
492 if (ret) {
493 ly_free_prefix_data(format, *prefix_data_p);
494 *prefix_data_p = NULL;
495 }
496 return ret;
497}
498
499LY_ERR
500ly_store_prefix_data(const struct ly_ctx *ctx, const char *value, size_t value_len, LY_PREFIX_FORMAT format,
501 void *prefix_data, LY_PREFIX_FORMAT *format_p, void **prefix_data_p)
502{
503 LY_ERR ret = LY_SUCCESS;
504 const char *start, *stop;
505 const struct lys_module *mod;
506 struct lyxml_ns *ns;
507 struct ly_set *ns_list;
508 struct lysc_prefix *prefixes = NULL, *val_pref;
509
510 switch (format) {
511 case LY_PREF_SCHEMA:
512 case LY_PREF_XML:
513 /* copy all referenced modules... */
514 if (format == LY_PREF_XML) {
515 /* ...as prefix - namespace pairs */
516 LY_CHECK_GOTO(ret = ly_set_new(&ns_list), cleanup);
517 *format_p = LY_PREF_XML;
518 *prefix_data_p = ns_list;
519 } else {
520 /* ...as prefix - module pairs */
521 assert(format == LY_PREF_SCHEMA);
522 LY_ARRAY_CREATE_GOTO(ctx, prefixes, 0, ret, cleanup);
523 *format_p = LY_PREF_SCHEMA_RESOLVED;
524 *prefix_data_p = prefixes;
525 }
526
527 /* add all used prefixes */
528 for (stop = start = value; (size_t)(stop - value) < value_len; start = stop) {
529 size_t bytes;
530 uint32_t c;
531
532 ly_getutf8(&stop, &c, &bytes);
533 if (is_xmlqnamestartchar(c)) {
534 for (ly_getutf8(&stop, &c, &bytes);
535 is_xmlqnamechar(c) && (size_t)(stop - value) < value_len;
536 ly_getutf8(&stop, &c, &bytes)) {}
537 stop = stop - bytes;
538 if (*stop == ':') {
539 /* we have a possible prefix */
540 size_t len = stop - start;
541
542 /* do we already have the prefix? */
543 mod = ly_type_store_resolve_prefix(ctx, start, len, *format_p, *prefix_data_p);
544 if (!mod) {
545 mod = ly_type_store_resolve_prefix(ctx, start, len, format, prefix_data);
546 if (mod) {
547 if (*format_p == LY_PREF_XML) {
548 /* store a new prefix - namespace pair */
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 ns->prefix = strndup(start, len);
554 LY_CHECK_ERR_GOTO(!ns->prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
555 ns->uri = strdup(mod->ns);
556 LY_CHECK_ERR_GOTO(!ns->uri, LOGMEM(ctx); ret = LY_EMEM, cleanup);
557 } else {
558 assert(*format_p == LY_PREF_SCHEMA_RESOLVED);
559 /* store a new prefix - module pair */
560 LY_ARRAY_NEW_GOTO(ctx, prefixes, val_pref, ret, cleanup);
561 *prefix_data_p = prefixes;
562
563 val_pref->prefix = strndup(start, len);
564 LY_CHECK_ERR_GOTO(!val_pref->prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
565 val_pref->mod = mod;
566 }
567 } /* else it is not even defined */
568 } /* else the prefix is already present */
569 }
570 stop = stop + bytes;
571 }
572 }
573 break;
574 case LY_PREF_SCHEMA_RESOLVED:
575 case LY_PREF_JSON:
576 /* simply copy all the prefix data */
577 *format_p = format;
578 LY_CHECK_GOTO(ret = ly_dup_prefix_data(ctx, format, prefix_data, prefix_data_p), cleanup);
579 break;
580 }
581
582cleanup:
583 if (ret) {
584 ly_free_prefix_data(*format_p, *prefix_data_p);
585 *prefix_data_p = NULL;
586 }
587 return ret;
588}