blob: 2b1b5df5907a22d11373ee261007c69e2c384eae [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;
151
Michal Vasko52927e22020-03-16 17:26:14 +0100152 if (!node || !node->schema) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100153 return NULL;
154 }
Michal Vasko9b368d32020-02-14 13:53:31 +0100155
Radek Krejci1e008d22020-08-17 11:37:37 +0200156 for (schema = node->schema; schema->parent; schema = schema->parent) {}
Michal Vasko9b368d32020-02-14 13:53:31 +0100157 return schema->module;
158}
Michal Vaskob1b5c262020-03-05 14:29:47 +0100159
Michal Vasko8207e7e2020-11-09 21:03:54 +0100160API const struct lysc_when *
161lyd_has_when(const struct lyd_node *node)
162{
163 const struct lysc_node *schema;
164
165 if (!node || !node->schema) {
166 return NULL;
167 }
168
169 schema = node->schema;
170 do {
171 if (schema->when) {
172 return *schema->when;
173 }
174 schema = schema->parent;
175 } while (schema && (schema->nodetype & (LYS_CASE | LYS_CHOICE)));
176
177 return NULL;
178}
179
Michal Vaskob1b5c262020-03-05 14:29:47 +0100180const struct lys_module *
Michal Vasko26e80012020-07-08 10:55:46 +0200181lyd_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 +0200182 struct lyd_node **first)
Michal Vaskob1b5c262020-03-05 14:29:47 +0100183{
184 struct lyd_node *iter;
185 const struct lys_module *mod;
186
187 /* get the next module */
Michal Vasko26e80012020-07-08 10:55:46 +0200188 if (module) {
189 if (*i) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100190 mod = NULL;
Michal Vasko26e80012020-07-08 10:55:46 +0200191 } else {
192 mod = module;
193 ++(*i);
Michal Vaskob1b5c262020-03-05 14:29:47 +0100194 }
195 } else {
196 do {
197 mod = ly_ctx_get_module_iter(ctx, i);
198 } while (mod && !mod->implemented);
199 }
200
201 /* find its data */
202 *first = NULL;
203 if (mod) {
204 LY_LIST_FOR(tree, iter) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100205 if (lyd_owner_module(iter) == mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100206 *first = iter;
207 break;
208 }
209 }
210 }
211
212 return mod;
213}
214
215const struct lys_module *
216lyd_data_next_module(struct lyd_node **next, struct lyd_node **first)
217{
218 const struct lys_module *mod;
219
220 if (!*next) {
221 /* all data traversed */
222 *first = NULL;
223 return NULL;
224 }
225
226 *first = *next;
227
228 /* prepare next */
Michal Vaskoc193ce92020-03-06 11:04:48 +0100229 mod = lyd_owner_module(*next);
Michal Vaskob1b5c262020-03-05 14:29:47 +0100230 LY_LIST_FOR(*next, *next) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100231 if (lyd_owner_module(*next) != mod) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100232 break;
233 }
234 }
235
236 return mod;
237}
Michal Vasko9f96a052020-03-10 09:41:45 +0100238
239LY_ERR
240lyd_parse_check_keys(struct lyd_node *node)
241{
242 const struct lysc_node *skey = NULL;
243 const struct lyd_node *key;
244
245 assert(node->schema->nodetype == LYS_LIST);
246
Radek Krejcia1c1e542020-09-29 16:06:52 +0200247 key = lyd_child(node);
Michal Vasko9f96a052020-03-10 09:41:45 +0100248 while ((skey = lys_getnext(skey, node->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
249 if (!key || (key->schema != skey)) {
Michal Vaskob7be7a82020-08-20 09:09:04 +0200250 LOGVAL(LYD_CTX(node), LY_VLOG_LYD, node, LY_VCODE_NOKEY, skey->name);
Michal Vasko9f96a052020-03-10 09:41:45 +0100251 return LY_EVALID;
252 }
253
254 key = key->next;
255 }
256
257 return LY_SUCCESS;
258}
Michal Vasko60ea6352020-06-29 13:39:39 +0200259
260void
Radek Krejci1deb5be2020-08-26 16:43:36 +0200261lyd_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 +0200262{
263 struct lyd_meta *meta2, *prev_meta = NULL;
264
265 if (!(node->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) && node->schema->when) {
Michal Vasko0f3377d2020-11-09 20:56:11 +0100266 if (!(options & LYD_PARSE_ONLY)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200267 /* remember we need to evaluate this node's when */
Radek Krejci3d92e442020-10-12 12:48:13 +0200268 LY_CHECK_RET(ly_set_add(when_check, node, 1, NULL), );
Michal Vasko60ea6352020-06-29 13:39:39 +0200269 }
270 }
271
Michal Vasko60ea6352020-06-29 13:39:39 +0200272 LY_LIST_FOR(*meta, meta2) {
Michal Vasko69730152020-10-09 16:30:07 +0200273 if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults") &&
274 meta2->value.boolean) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200275 /* node is default according to the metadata */
276 node->flags |= LYD_DEFAULT;
277
278 /* delete the metadata */
279 if (prev_meta) {
280 prev_meta->next = meta2->next;
281 } else {
282 *meta = (*meta)->next;
283 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200284 lyd_free_meta_single(meta2);
Michal Vasko60ea6352020-06-29 13:39:39 +0200285 break;
286 }
287
288 prev_meta = meta2;
289 }
290}
291
Michal Vaskoc0004272020-08-06 08:32:34 +0200292API LY_ERR
Michal Vasko61551fa2020-07-09 15:45:45 +0200293lyd_any_copy_value(struct lyd_node *trg, const union lyd_any_value *value, LYD_ANYDATA_VALUETYPE value_type)
294{
295 struct lyd_node_any *t;
Michal Vasko61551fa2020-07-09 15:45:45 +0200296
297 assert(trg->schema->nodetype & LYS_ANYDATA);
298
299 t = (struct lyd_node_any *)trg;
300
301 /* free trg */
302 switch (t->value_type) {
303 case LYD_ANYDATA_DATATREE:
304 lyd_free_all(t->value.tree);
305 break;
306 case LYD_ANYDATA_STRING:
307 case LYD_ANYDATA_XML:
308 case LYD_ANYDATA_JSON:
Michal Vaskob7be7a82020-08-20 09:09:04 +0200309 FREE_STRING(LYD_CTX(trg), t->value.str);
Michal Vasko61551fa2020-07-09 15:45:45 +0200310 break;
311 case LYD_ANYDATA_LYB:
312 free(t->value.mem);
313 break;
314 }
315 t->value.str = NULL;
316
317 if (!value) {
318 /* only free value in this case */
319 return LY_SUCCESS;
320 }
321
322 /* copy src */
323 t->value_type = value_type;
324 switch (value_type) {
325 case LYD_ANYDATA_DATATREE:
326 if (value->tree) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200327 LY_CHECK_RET(lyd_dup_siblings(value->tree, NULL, LYD_DUP_RECURSIVE, &t->value.tree));
Michal Vasko61551fa2020-07-09 15:45:45 +0200328 }
329 break;
330 case LYD_ANYDATA_STRING:
331 case LYD_ANYDATA_XML:
332 case LYD_ANYDATA_JSON:
333 if (value->str) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200334 LY_CHECK_RET(lydict_insert(LYD_CTX(trg), value->str, 0, &t->value.str));
Michal Vasko61551fa2020-07-09 15:45:45 +0200335 }
336 break;
337 case LYD_ANYDATA_LYB:
338 if (value->mem) {
Radek Krejci1deb5be2020-08-26 16:43:36 +0200339 int len = lyd_lyb_data_length(value->mem);
Radek Krejci82fa8d42020-07-11 22:00:59 +0200340 LY_CHECK_RET(len == -1, LY_EINVAL);
Michal Vasko61551fa2020-07-09 15:45:45 +0200341 t->value.mem = malloc(len);
Michal Vaskob7be7a82020-08-20 09:09:04 +0200342 LY_CHECK_ERR_RET(!t->value.mem, LOGMEM(LYD_CTX(trg)), LY_EMEM);
Michal Vasko61551fa2020-07-09 15:45:45 +0200343 memcpy(t->value.mem, value->mem, len);
344 }
345 break;
346 }
347
348 return LY_SUCCESS;
349}
350
Michal Vasko60ea6352020-06-29 13:39:39 +0200351LYB_HASH
352lyb_hash(struct lysc_node *sibling, uint8_t collision_id)
353{
354 const struct lys_module *mod;
Michal Vasko60ea6352020-06-29 13:39:39 +0200355 uint32_t full_hash;
356 LYB_HASH hash;
357
358 if ((collision_id < LYS_NODE_HASH_COUNT) && sibling->hash[collision_id]) {
359 return sibling->hash[collision_id];
360 }
361
362 mod = sibling->module;
363
364 full_hash = dict_hash_multi(0, mod->name, strlen(mod->name));
365 full_hash = dict_hash_multi(full_hash, sibling->name, strlen(sibling->name));
366 if (collision_id) {
Radek Krejci1deb5be2020-08-26 16:43:36 +0200367 size_t ext_len;
368
Michal Vasko60ea6352020-06-29 13:39:39 +0200369 if (collision_id > strlen(mod->name)) {
370 /* fine, we will not hash more bytes, just use more bits from the hash than previously */
371 ext_len = strlen(mod->name);
372 } else {
373 /* use one more byte from the module name than before */
374 ext_len = collision_id;
375 }
376 full_hash = dict_hash_multi(full_hash, mod->name, ext_len);
377 }
378 full_hash = dict_hash_multi(full_hash, NULL, 0);
379
380 /* use the shortened hash */
381 hash = full_hash & (LYB_HASH_MASK >> collision_id);
382 /* add colision identificator */
383 hash |= LYB_HASH_COLLISION_ID >> collision_id;
384
385 /* save this hash */
386 if (collision_id < LYS_NODE_HASH_COUNT) {
387 sibling->hash[collision_id] = hash;
388 }
389
390 return hash;
391}
392
Radek Krejci857189e2020-09-01 13:26:36 +0200393ly_bool
Michal Vasko60ea6352020-06-29 13:39:39 +0200394lyb_has_schema_model(const struct lysc_node *sibling, const struct lys_module **models)
395{
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200396 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +0200397
398 LY_ARRAY_FOR(models, u) {
399 if (sibling->module == models[u]) {
400 return 1;
401 }
402 }
403
404 return 0;
405}
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100406
407void
408ly_free_prefix_data(LY_PREFIX_FORMAT format, void *prefix_data)
409{
410 struct ly_set *ns_list;
411 struct lysc_prefix *prefixes;
412 uint32_t i;
413 LY_ARRAY_COUNT_TYPE u;
414
415 if (!prefix_data) {
416 return;
417 }
418
419 switch (format) {
420 case LY_PREF_XML:
421 ns_list = prefix_data;
422 for (i = 0; i < ns_list->count; ++i) {
423 free(((struct lyxml_ns *)ns_list->objs[i])->prefix);
424 free(((struct lyxml_ns *)ns_list->objs[i])->uri);
425 }
426 ly_set_free(ns_list, free);
427 break;
428 case LY_PREF_SCHEMA_RESOLVED:
429 prefixes = prefix_data;
430 LY_ARRAY_FOR(prefixes, u) {
431 free(prefixes[u].prefix);
432 }
433 LY_ARRAY_FREE(prefixes);
434 break;
435 case LY_PREF_SCHEMA:
436 case LY_PREF_JSON:
437 break;
438 }
439}
440
441LY_ERR
442ly_dup_prefix_data(const struct ly_ctx *ctx, LY_PREFIX_FORMAT format, const void *prefix_data,
443 void **prefix_data_p)
444{
445 LY_ERR ret = LY_SUCCESS;
446 struct lyxml_ns *ns;
447 struct lysc_prefix *prefixes = NULL, *orig_pref;
448 struct ly_set *ns_list, *orig_ns;
449 uint32_t i;
450 LY_ARRAY_COUNT_TYPE u;
451
452 assert(!*prefix_data_p);
453
454 switch (format) {
455 case LY_PREF_SCHEMA:
456 *prefix_data_p = (void *)prefix_data;
457 break;
458 case LY_PREF_SCHEMA_RESOLVED:
459 /* copy all the value prefixes */
460 orig_pref = (struct lysc_prefix *)prefix_data;
461 LY_ARRAY_CREATE_GOTO(ctx, prefixes, LY_ARRAY_COUNT(orig_pref), ret, cleanup);
462 *prefix_data_p = prefixes;
463
464 LY_ARRAY_FOR(orig_pref, u) {
465 if (orig_pref[u].prefix) {
466 prefixes[u].prefix = strdup(orig_pref[u].prefix);
467 LY_CHECK_ERR_GOTO(!prefixes[u].prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
468 }
469 prefixes[u].mod = orig_pref[u].mod;
470 LY_ARRAY_INCREMENT(prefixes);
471 }
472 break;
473 case LY_PREF_XML:
474 /* copy all the namespaces */
475 LY_CHECK_GOTO(ret = ly_set_new(&ns_list), cleanup);
476 *prefix_data_p = ns_list;
477
478 orig_ns = (struct ly_set *)prefix_data;
479 for (i = 0; i < orig_ns->count; ++i) {
480 ns = calloc(1, sizeof *ns);
481 LY_CHECK_ERR_GOTO(!ns, LOGMEM(ctx); ret = LY_EMEM, cleanup);
482 LY_CHECK_GOTO(ret = ly_set_add(ns_list, ns, 1, NULL), cleanup);
483
484 if (((struct lyxml_ns *)orig_ns->objs[i])->prefix) {
485 ns->prefix = strdup(((struct lyxml_ns *)orig_ns->objs[i])->prefix);
486 LY_CHECK_ERR_GOTO(!ns->prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
487 }
488 ns->uri = strdup(((struct lyxml_ns *)orig_ns->objs[i])->uri);
489 LY_CHECK_ERR_GOTO(!ns->uri, LOGMEM(ctx); ret = LY_EMEM, cleanup);
490 }
491 break;
492 case LY_PREF_JSON:
493 assert(!prefix_data);
494 *prefix_data_p = NULL;
495 break;
496 }
497
498cleanup:
499 if (ret) {
500 ly_free_prefix_data(format, *prefix_data_p);
501 *prefix_data_p = NULL;
502 }
503 return ret;
504}
505
506LY_ERR
507ly_store_prefix_data(const struct ly_ctx *ctx, const char *value, size_t value_len, LY_PREFIX_FORMAT format,
508 void *prefix_data, LY_PREFIX_FORMAT *format_p, void **prefix_data_p)
509{
510 LY_ERR ret = LY_SUCCESS;
511 const char *start, *stop;
512 const struct lys_module *mod;
513 struct lyxml_ns *ns;
514 struct ly_set *ns_list;
515 struct lysc_prefix *prefixes = NULL, *val_pref;
516
517 switch (format) {
518 case LY_PREF_SCHEMA:
519 case LY_PREF_XML:
520 /* copy all referenced modules... */
521 if (format == LY_PREF_XML) {
522 /* ...as prefix - namespace pairs */
523 LY_CHECK_GOTO(ret = ly_set_new(&ns_list), cleanup);
524 *format_p = LY_PREF_XML;
525 *prefix_data_p = ns_list;
526 } else {
527 /* ...as prefix - module pairs */
528 assert(format == LY_PREF_SCHEMA);
529 LY_ARRAY_CREATE_GOTO(ctx, prefixes, 0, ret, cleanup);
530 *format_p = LY_PREF_SCHEMA_RESOLVED;
531 *prefix_data_p = prefixes;
532 }
533
534 /* add all used prefixes */
535 for (stop = start = value; (size_t)(stop - value) < value_len; start = stop) {
536 size_t bytes;
537 uint32_t c;
538
539 ly_getutf8(&stop, &c, &bytes);
540 if (is_xmlqnamestartchar(c)) {
541 for (ly_getutf8(&stop, &c, &bytes);
542 is_xmlqnamechar(c) && (size_t)(stop - value) < value_len;
543 ly_getutf8(&stop, &c, &bytes)) {}
544 stop = stop - bytes;
545 if (*stop == ':') {
546 /* we have a possible prefix */
547 size_t len = stop - start;
548
549 /* do we already have the prefix? */
550 mod = ly_type_store_resolve_prefix(ctx, start, len, *format_p, *prefix_data_p);
551 if (!mod) {
552 mod = ly_type_store_resolve_prefix(ctx, start, len, format, prefix_data);
553 if (mod) {
554 if (*format_p == LY_PREF_XML) {
555 /* store a new prefix - namespace pair */
556 ns = calloc(1, sizeof *ns);
557 LY_CHECK_ERR_GOTO(!ns, LOGMEM(ctx); ret = LY_EMEM, cleanup);
558 LY_CHECK_GOTO(ret = ly_set_add(ns_list, ns, 1, NULL), cleanup);
559
560 ns->prefix = strndup(start, len);
561 LY_CHECK_ERR_GOTO(!ns->prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
562 ns->uri = strdup(mod->ns);
563 LY_CHECK_ERR_GOTO(!ns->uri, LOGMEM(ctx); ret = LY_EMEM, cleanup);
564 } else {
565 assert(*format_p == LY_PREF_SCHEMA_RESOLVED);
566 /* store a new prefix - module pair */
567 LY_ARRAY_NEW_GOTO(ctx, prefixes, val_pref, ret, cleanup);
568 *prefix_data_p = prefixes;
569
570 val_pref->prefix = strndup(start, len);
571 LY_CHECK_ERR_GOTO(!val_pref->prefix, LOGMEM(ctx); ret = LY_EMEM, cleanup);
572 val_pref->mod = mod;
573 }
574 } /* else it is not even defined */
575 } /* else the prefix is already present */
576 }
577 stop = stop + bytes;
578 }
579 }
580 break;
581 case LY_PREF_SCHEMA_RESOLVED:
582 case LY_PREF_JSON:
583 /* simply copy all the prefix data */
584 *format_p = format;
585 LY_CHECK_GOTO(ret = ly_dup_prefix_data(ctx, format, prefix_data, prefix_data_p), cleanup);
586 break;
587 }
588
589cleanup:
590 if (ret) {
591 ly_free_prefix_data(*format_p, *prefix_data_p);
592 *prefix_data_p = NULL;
593 }
594 return ret;
595}