blob: dbf9e6401c48085f74ef0607686d0883f1915c78 [file] [log] [blame]
Radek Krejcic6704c82015-10-06 11:12:45 +02001
Radek Krejcida04f4a2015-05-21 12:54:09 +02002/**
Michal Vasko2d162e12015-09-24 14:33:29 +02003 * @file tree_schema.c
Radek Krejcida04f4a2015-05-21 12:54:09 +02004 * @author Radek Krejci <rkrejci@cesnet.cz>
Michal Vasko2d162e12015-09-24 14:33:29 +02005 * @brief Manipulation with libyang schema data structures
Radek Krejcida04f4a2015-05-21 12:54:09 +02006 *
7 * Copyright (c) 2015 CESNET, z.s.p.o.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * 3. Neither the name of the Company nor the names of its contributors
19 * may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
21 */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020022#define _GNU_SOURCE
Radek Krejcida04f4a2015-05-21 12:54:09 +020023
Radek Krejci812b10a2015-05-28 16:48:25 +020024#include <assert.h>
Radek Krejci5a988152015-07-15 11:16:26 +020025#include <ctype.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020026#include <stdlib.h>
27#include <sys/mman.h>
Michal Vasko662610a2015-12-07 11:25:45 +010028#include <sys/types.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020029#include <sys/stat.h>
Michal Vasko662610a2015-12-07 11:25:45 +010030#include <fcntl.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020031#include <string.h>
Michal Vasko662610a2015-12-07 11:25:45 +010032#include <unistd.h>
33#include <errno.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020034
35#include "common.h"
36#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020037#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020038#include "resolve.h"
Michal Vasko88c29542015-11-27 14:57:53 +010039#include "xml.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020040#include "xml_internal.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020041#include "tree_internal.h"
Radek Krejcieab784a2015-08-27 09:56:53 +020042#include "validation.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020043
Michal Vaskoa76ee152015-08-17 15:38:22 +020044static const struct internal_modules int_mods = {
45 .modules = {
46 {"ietf-yang-types", "2013-07-15"},
47 {"ietf-inet-types", "2013-07-15"},
48 {"ietf-yang-library", "2015-07-03"}
49 },
50 .count = LY_INTERNAL_MODULE_COUNT
51};
52
Michal Vasko1e62a092015-12-01 12:27:20 +010053API const struct lys_feature *
54lys_is_disabled(const struct lys_node *node, int recursive)
Radek Krejci48061fb2015-08-05 15:41:07 +020055{
56 int i;
57
58check:
59 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
60 /* input/output does not have if-feature, so skip them */
61
62 /* check local if-features */
63 for (i = 0; i < node->features_size; i++) {
64 if (!(node->features[i]->flags & LYS_FENABLED)) {
65 return node->features[i];
66 }
67 }
68 }
69
70 if (!recursive) {
71 return NULL;
72 }
73
74 /* go through parents */
75 if (node->nodetype == LYS_AUGMENT) {
76 /* go to parent actually means go to the target node */
77 node = ((struct lys_node_augment *)node)->target;
Radek Krejci48061fb2015-08-05 15:41:07 +020078 } else if (node->parent) {
79 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020080 } else {
81 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020082 }
83
Radek Krejci074bf852015-08-19 14:22:16 +020084 if (recursive == 2) {
85 /* continue only if the node cannot have a data instance */
86 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
87 return NULL;
88 }
89 }
90 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020091}
92
Michal Vasko1dca6882015-10-22 14:29:42 +020093int
Michal Vasko36cbaa42015-12-14 13:15:48 +010094lys_get_sibling(const struct lys_node *siblings, const char *mod_name, int mod_name_len, const char *name,
95 int nam_len, LYS_NODE type, const struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +020096{
Radek Krejcic071c542016-01-27 14:57:51 +010097 const struct lys_node *node, *parent = NULL;
98 const struct lys_module *mod = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +010099 const char *node_mod_name;
Michal Vasko1dca6882015-10-22 14:29:42 +0200100
Michal Vasko36cbaa42015-12-14 13:15:48 +0100101 assert(siblings && mod_name && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +0200102 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +0200103
Michal Vasko36cbaa42015-12-14 13:15:48 +0100104 /* fill the lengths in case the caller is so indifferent */
105 if (!mod_name_len) {
106 mod_name_len = strlen(mod_name);
107 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200108 if (!nam_len) {
109 nam_len = strlen(name);
110 }
111
Michal Vasko36cbaa42015-12-14 13:15:48 +0100112 /* set mod correctly */
Radek Krejcic071c542016-01-27 14:57:51 +0100113 parent = lys_parent(siblings);
114 if (!parent) {
Michal Vasko36cbaa42015-12-14 13:15:48 +0100115 mod = siblings->module;
Michal Vasko1dca6882015-10-22 14:29:42 +0200116 }
117
Radek Krejcic071c542016-01-27 14:57:51 +0100118 /* try to find the node */
119 node = NULL;
120 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
121 if (!type || (node->nodetype & type)) {
122 /* modules need to always be checked, we want to skip augments (no other reason to check them) */
123 if (node->module->type) {
124 node_mod_name = ((struct lys_submodule *)node->module)->belongsto->name;
125 } else {
126 node_mod_name = node->module->name;
127 }
128 if (strncmp(node_mod_name, mod_name, mod_name_len) || node_mod_name[mod_name_len]) {
129 continue;
130 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200131
Radek Krejcic071c542016-01-27 14:57:51 +0100132 /* direct name check */
133 if ((node->name == name) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
134 if (ret) {
135 *ret = node;
Michal Vasko1dca6882015-10-22 14:29:42 +0200136 }
Radek Krejcic071c542016-01-27 14:57:51 +0100137 return EXIT_SUCCESS;
Michal Vasko1dca6882015-10-22 14:29:42 +0200138 }
139 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200140 }
141
142 return EXIT_FAILURE;
143}
144
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200145int
Michal Vasko1e62a092015-12-01 12:27:20 +0100146lys_get_data_sibling(const struct lys_module *mod, const struct lys_node *siblings, const char *name, LYS_NODE type,
147 const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200148{
Michal Vasko1e62a092015-12-01 12:27:20 +0100149 const struct lys_node *node;
150 const struct lys_module *cur_mod;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200151 int in_submod;
152
153 assert(siblings && name);
154 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
155
156 /* find the beginning */
157 while (siblings->prev->next) {
158 siblings = siblings->prev;
159 }
160
161 /* we start with the module itself, submodules come later */
162 in_submod = 0;
163
164 if (!mod) {
165 mod = siblings->module;
166 }
167 cur_mod = mod;
168
169 while (1) {
170 /* try to find the node */
171 node = NULL;
172 while ((node = lys_getnext(node, siblings->parent, cur_mod, 0))) {
173 if (!type || (node->nodetype & type)) {
174 /* module check */
175 if (!node->module->type) {
176 if (cur_mod != node->module) {
177 continue;
178 }
179 } else {
180 /* both are submodules */
181 if (cur_mod->type) {
182 if (cur_mod != node->module) {
183 continue;
184 }
185 } else {
186 if (cur_mod != ((struct lys_submodule *)node->module)->belongsto) {
187 continue;
188 }
189 }
190 }
191
192 /* direct name check */
193 if ((node->name == name) || !strcmp(node->name, name)) {
194 if (ret) {
195 *ret = node;
196 }
197 return EXIT_SUCCESS;
198 }
199 }
200 }
201
202 /* we're not top-level, search ended */
203 if (siblings->parent) {
204 break;
205 }
206
207 /* let's try the submodules */
Radek Krejcic071c542016-01-27 14:57:51 +0100208 while(in_submod != mod->inc_size) {
209 if (!mod->inc[in_submod].submodule) {
210 in_submod++;
211 continue;
212 }
213
214 cur_mod = (struct lys_module *)mod->inc[in_submod].submodule;
215 siblings = cur_mod->data;
216 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200217 if (in_submod == mod->inc_size) {
218 break;
219 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200220 ++in_submod;
221 }
222
223 return EXIT_FAILURE;
224}
225
Michal Vasko1e62a092015-12-01 12:27:20 +0100226API const struct lys_node *
227lys_getnext(const struct lys_node *last, const struct lys_node *parent, const struct lys_module *module, int options)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200228{
Michal Vasko1e62a092015-12-01 12:27:20 +0100229 const struct lys_node *next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200230
Radek Krejci8bc87f62015-09-02 16:19:05 +0200231 if (!last) {
232 /* first call */
233
234 /* get know where to start */
235 if (parent) {
236 /* schema subtree */
237 next = last = parent->child;
238 } else {
239 /* top level data */
240 assert(module);
241 next = last = module->data;
242 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200243 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200244 /* continue after the last returned value */
245 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200246 }
247
248repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200249 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200250 if (options & LYS_GETNEXT_WITHGROUPING) {
251 return next;
252 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200253 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200254 }
255
Radek Krejcic4ccbd92016-01-07 13:13:33 +0100256 if (!next) {
Michal Vasko7c386e72015-10-07 15:13:33 +0200257 if (lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200258 /* no next element */
259 return NULL;
260 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200261 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200262 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200263 goto repeat;
264 }
265
266 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200267 case LYS_INPUT:
268 case LYS_OUTPUT:
269 if (options & LYS_GETNEXT_WITHINOUT) {
270 return next;
271 } else {
272 next = next->child;
273 goto repeat;
274 }
275 break;
276
Michal Vaskoa5835e92015-10-20 15:07:39 +0200277 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200278 if (options & LYS_GETNEXT_WITHCASE) {
279 return next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200280 } else {
281 next = next->child;
282 goto repeat;
Michal Vasko1dca6882015-10-22 14:29:42 +0200283 }
Michal Vaskob6eedf02015-10-22 16:07:03 +0200284 break;
285
Michal Vasko1dca6882015-10-22 14:29:42 +0200286 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200287 /* go into */
288 next = next->child;
289 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200290
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200291 case LYS_RPC:
292 case LYS_NOTIF:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200293 case LYS_CONTAINER:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200294 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200295 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200296 case LYS_LIST:
297 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200298 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200299
300 case LYS_CHOICE:
301 if (options & LYS_GETNEXT_WITHCHOICE) {
302 return next;
303 } else {
304 /* go into */
305 next = next->child;
306 goto repeat;
307 }
308 break;
309
Radek Krejci7f40ce32015-08-12 20:38:46 +0200310 default:
311 /* we should not be here */
312 return NULL;
313 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200314
315
316}
317
Michal Vasko1e62a092015-12-01 12:27:20 +0100318static const struct lys_node *
Radek Krejci2342cf62016-01-29 16:48:23 +0100319check_mand_getnext(const struct lys_node *last, const struct lys_node *parent, const struct lys_module *module)
Radek Krejci8bc87f62015-09-02 16:19:05 +0200320{
Michal Vasko1e62a092015-12-01 12:27:20 +0100321 const struct lys_node *next;
322
Radek Krejci2342cf62016-01-29 16:48:23 +0100323 next = lys_getnext(last, parent, module, LYS_GETNEXT_WITHCHOICE);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200324
Radek Krejci4b6c2112015-10-06 12:48:34 +0200325repeat:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200326 if (next && next->nodetype == LYS_CONTAINER) {
327 if (((struct lys_node_container *)next)->presence) {
328 /* mandatory elements under the non-existing presence
329 * container are not mandatory - 7.6.5, rule 1 */
330 next = next->next;
331 } else {
332 /* go into */
333 next = next->child;
334 }
335 goto repeat;
336 }
337
338 return next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200339}
340
Michal Vasko1e62a092015-12-01 12:27:20 +0100341static const struct lys_node *
342check_mand_check(const struct lys_node *node, const struct lys_node *stop, const struct lyd_node *data)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200343{
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200344 struct lys_node *siter = NULL, *parent = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200345 struct lyd_node *diter = NULL;
Radek Krejcidc154432016-01-21 11:10:59 +0100346 struct ly_set *set = NULL;
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200347 unsigned int i;
Radek Krejci14a11a62015-08-17 17:27:38 +0200348 uint32_t minmax;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200349
350 if (node->flags & LYS_MAND_TRUE) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100351 if (!data) {
352 /* we have no data but a mandatory node */
353 return node;
354 }
355 switch (node->nodetype) {
356 case LYS_LEAF:
357 case LYS_ANYXML:
358 case LYS_CHOICE:
359 if (node->parent && node->parent->nodetype == LYS_CASE) {
360 /* 7.6.5, rule 2 */
361 /* 7.9.4, rule 1 */
362 if (node->parent->parent->parent == data->schema) {
363 /* the only case the node's siblings can exist is that the
364 * data node passed originally to ly_check_mandatory()
365 * had this choice as a child
366 */
367 /* try to find the node's siblings in data */
368 LY_TREE_FOR(data->child, diter) {
369 LY_TREE_FOR(node->parent->child, siter) {
370 if (siter == diter->schema) {
371 /* some sibling exists, rule applies */
372 break;
373 }
374 }
375 if (siter) {
376 break;
377 }
378 }
379 }
380 if (!siter) {
381 /* no sibling exists */
382 return NULL;
383 }
384 } else {
Radek Krejci7eb12132016-02-01 10:55:23 +0100385 for (parent = node->parent; parent && parent != stop; parent = parent->parent) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100386 if (parent->nodetype != LYS_CONTAINER) {
387 /* 7.6.5, rule 1, checking presence is not needed
388 * since it is done in check_mand_getnext()
389 */
390 ly_set_free(set);
391 return NULL;
392 }
393 /* add the parent to the list for searching in data tree */
394 if (!set) {
395 set = ly_set_new();
396 }
397 /* ignore return - memory error is logged and we will
398 * check at least the rest of nodes we have */
399 (void)ly_set_add(set, parent);
400 }
401 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200402
Radek Krejci2342cf62016-01-29 16:48:23 +0100403 /* search for instance */
404 if (set) {
405 for (i = 0; i < set->number; i++) {
406 LY_TREE_FOR(data->child, diter) {
407 if (diter->schema == set->sset[i]) {
408 break;
409 }
410 }
411 if (!diter) {
412 /* instance not found */
413 node = set->sset[i];
414 ly_set_free(set);
415 return node;
416 }
417 data = diter;
418 }
419 ly_set_free(set);
420 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200421
Radek Krejci2342cf62016-01-29 16:48:23 +0100422 LY_TREE_FOR(data->child, diter) {
423 if (diter->schema == node) {
424 return NULL;
425 }
426 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200427
Radek Krejci2342cf62016-01-29 16:48:23 +0100428 /* instance not found */
429 /* 7.6.5, rule 3 (or 2) */
430 /* 7.9.4, rule 2 */
431 return node;
432 default:
433 /* error */
434 break;
435 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200436 } else if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
437 /* search for number of instances */
438 minmax = 0;
Radek Krejci2342cf62016-01-29 16:48:23 +0100439 if (data) {
440 LY_TREE_FOR(data->child, diter) {
441 if (diter->schema == node) {
442 minmax++;
443 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200444 }
445 }
446
447 /* check the specified constraints */
448 if (node->nodetype == LYS_LIST) {
449 if (((struct lys_node_list *)node)->min && minmax < ((struct lys_node_list *)node)->min) {
450 return node;
451 }
452
453 if (((struct lys_node_list *)node)->max && minmax > ((struct lys_node_list *)node)->max) {
454 return node;
455 }
456 } else if (node->nodetype == LYS_LEAFLIST) {
457 if (((struct lys_node_leaflist *)node)->min && minmax < ((struct lys_node_leaflist *)node)->min) {
458 return node;
459 }
460
461 if (((struct lys_node_leaflist *)node)->max && minmax > ((struct lys_node_leaflist *)node)->max) {
462 return node;
463 }
464 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200465 }
466
467 return NULL;
468}
469
Michal Vasko1e62a092015-12-01 12:27:20 +0100470const struct lys_node *
Radek Krejci2342cf62016-01-29 16:48:23 +0100471ly_check_mandatory(const struct lyd_node *data, const struct lys_node *schema)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200472{
Michal Vasko1e62a092015-12-01 12:27:20 +0100473 const struct lys_node *siter, *saux, *saux2, *result, *parent = NULL, *parent2;
474 const struct lyd_node *diter;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200475 int found;
476
Radek Krejci2342cf62016-01-29 16:48:23 +0100477 assert(data || schema);
478
479 if (!data) { /* !data && schema */
480 siter = schema;
481 } else { /* data && !schema */
482 schema = siter = data->schema->child;
483 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200484
485repeat:
486 while (siter) {
Radek Krejci074bf852015-08-19 14:22:16 +0200487 if (lys_is_disabled(siter, 2)) {
488 siter = siter->next;
489 continue;
490 }
491
Radek Krejci7f40ce32015-08-12 20:38:46 +0200492 switch (siter->nodetype) {
493 case LYS_CONTAINER:
494 case LYS_LEAF:
495 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200496 case LYS_LIST:
497 case LYS_LEAFLIST:
498 /* check if there is some mandatory node; first test the siter itself ... */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200499 result = check_mand_check(siter, siter->parent, data);
500 if (result) {
501 return result;
502 }
503 /* ... and then the subtree */
Radek Krejci14a11a62015-08-17 17:27:38 +0200504 if (parent && siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
505 saux = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100506 while ((saux = check_mand_getnext(saux, siter, NULL))) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200507 result = check_mand_check(saux, siter, data);
508 if (result) {
509 return result;
510 }
511 }
512 }
513 siter = siter->next;
514 break;
515 case LYS_CHOICE:
Radek Krejci14a11a62015-08-17 17:27:38 +0200516 /* search for instance */
517 saux = siter;
518 siter = siter->child;
519 found = 0;
520 parent2 = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200521repeat_choice:
Radek Krejci2342cf62016-01-29 16:48:23 +0100522 while (siter && data) {
Radek Krejci074bf852015-08-19 14:22:16 +0200523 if (lys_is_disabled(siter, 2)) {
524 siter = siter->next;
525 continue;
526 }
527
Radek Krejci14a11a62015-08-17 17:27:38 +0200528 switch (siter->nodetype) {
529 case LYS_CONTAINER:
530 case LYS_LEAF:
531 case LYS_LEAFLIST:
532 case LYS_LIST:
533 case LYS_ANYXML:
534 LY_TREE_FOR(data->child, diter) {
535 if (diter->schema == siter) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200536 break;
537 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200538 }
539 if (diter) {
540 /* got instance */
541 /* check presence of mandatory siblings */
Radek Krejci65d0a652015-08-27 13:09:42 +0200542 if (parent2 && parent2->nodetype == LYS_CASE) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200543 saux2 = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100544 while ((saux2 = check_mand_getnext(saux2, parent2, NULL))) {
Radek Krejci37bda002015-08-27 11:23:56 +0200545 result = check_mand_check(saux2, parent2, data);
Radek Krejci14a11a62015-08-17 17:27:38 +0200546 if (result) {
547 return result;
548 }
549 }
550 }
551 siter = parent2 = NULL;
552 found = 1;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200553 break;
554 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200555 siter = siter->next;
556 break;
557 case LYS_CASE:
558 case LYS_CHOICE:
559 case LYS_USES:
560 /* go into */
Radek Krejci37bda002015-08-27 11:23:56 +0200561 if (!parent2) {
562 parent2 = siter;
563 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200564 siter = siter->child;
565 break;
566 case LYS_AUGMENT:
567 case LYS_GROUPING:
568 /* skip */
569 siter = siter->next;
570 break;
571 default:
572 /* error */
573 break;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200574 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200575 }
576
Radek Krejci14a11a62015-08-17 17:27:38 +0200577 if (parent2) {
578 siter = parent2->next;
579 if (parent2->parent == saux) {
580 parent2 = NULL;
581 } else {
582 parent2 = parent2->parent;
583 }
584 goto repeat_choice;
585 }
586
Radek Krejci074bf852015-08-19 14:22:16 +0200587 if (!found && (saux->flags & LYS_MAND_TRUE)) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200588 return saux;
589 }
590
591 /* go to next */
592 siter = saux->next;
593
Radek Krejci7f40ce32015-08-12 20:38:46 +0200594 break;
595 case LYS_USES:
596 case LYS_CASE:
597 /* go into */
598 parent = siter;
599 siter = siter->child;
600 break;
601 default:
602 /* can ignore, go to next */
603 siter = siter->next;
604 break;
605 }
606 }
607
608 if (parent) {
609 siter = parent->next;
Radek Krejci2342cf62016-01-29 16:48:23 +0100610 if (parent->parent == schema) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200611 parent = NULL;
612 } else {
613 parent = parent->parent;
614 }
615 goto repeat;
616 }
617
618 return NULL;
619}
620
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200621void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200622lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200623{
Radek Krejci76512572015-08-04 09:47:08 +0200624 struct lys_node *parent, *first;
Radek Krejcic071c542016-01-27 14:57:51 +0100625 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200626
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200627 if (!node) {
628 return;
629 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200630
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200631 /* unlink from data model if necessary */
632 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100633 /* get main module with data tree */
634 for (main_module = node->module; main_module->type; main_module = ((struct lys_submodule *)main_module)->belongsto);
635 if (main_module->data == node) {
636 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200637 }
638 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200639
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200640 /* store pointers to important nodes */
641 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200642 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200643 /* handle augments - first, unlink it from the augment parent ... */
644 if (parent->child == node) {
645 parent->child = node->next;
646 }
647 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200648 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200649 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200650
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200651 /* unlink from parent */
652 if (parent) {
653 if (parent->child == node) {
654 parent->child = node->next;
655 }
656 node->parent = NULL;
657 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200658
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200659 /* unlink from siblings */
660 if (node->prev == node) {
661 /* there are no more siblings */
662 return;
663 }
664 if (node->next) {
665 node->next->prev = node->prev;
666 } else {
667 /* unlinking the last element */
668 if (parent) {
669 first = parent->child;
670 } else {
671 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200672 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200673 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200674 }
675 }
676 first->prev = node->prev;
677 }
678 if (node->prev->next) {
679 node->prev->next = node->next;
680 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200681
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200682 /* clean up the unlinked element */
683 node->next = NULL;
684 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200685}
686
Michal Vasko563ef092015-09-04 13:17:23 +0200687struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100688lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200689{
690 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200691
692 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200693 /* top-level augment, look into module (uses augment is handled correctly below) */
694 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
695 par_iter = par_iter->parent->module->data;
696 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200697 break;
698 }
699 }
700
Michal Vasko6f929da2015-10-02 16:23:25 +0200701 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200702 continue;
703 }
704
705 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
706 if (!stop) {
707 stop = par_iter;
708 } else if (iter == stop) {
709 break;
710 }
711 if (iter->nodetype != LYS_GROUPING) {
712 continue;
713 }
714
Radek Krejcif8426a72015-10-31 23:14:03 +0100715 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200716 return (struct lys_node_grp *)iter;
717 }
718 }
719 }
720
Michal Vasko563ef092015-09-04 13:17:23 +0200721 return NULL;
722}
723
Radek Krejci10c760e2015-08-14 14:45:43 +0200724/*
725 * get next grouping in the root's subtree, in the
726 * first call, tha last is NULL
727 */
728static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200729lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200730{
Radek Krejci10c760e2015-08-14 14:45:43 +0200731 struct lys_node *last = (struct lys_node *)lastgrp;
732 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200733
Radek Krejci10c760e2015-08-14 14:45:43 +0200734 assert(root);
735
736 if (!last) {
737 last = root;
738 }
739
740 while (1) {
741 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
742 next = last->child;
743 } else {
744 next = NULL;
745 }
746 if (!next) {
747 if (last == root) {
748 /* we are done */
749 return NULL;
750 }
751
752 /* no children, go to siblings */
753 next = last->next;
754 }
755 while (!next) {
756 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100757 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200758 /* we are done */
759 return NULL;
760 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200761 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100762 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200763 }
764
765 if (next->nodetype == LYS_GROUPING) {
766 return (struct lys_node_grp *)next;
767 }
768
769 last = next;
770 }
771}
772
Michal Vasko0d343d12015-08-24 14:57:36 +0200773/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200774int
Radek Krejci07911992015-08-14 15:13:31 +0200775lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
776{
Michal Vasko563ef092015-09-04 13:17:23 +0200777 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200778 struct lys_node_grp *grp;
779 int down;
780
781 assert(node);
782
783 if (!parent) {
784 assert(module);
785 } else {
786 module = parent->module;
787 }
788
789 switch (node->nodetype) {
790 case LYS_GROUPING:
791 /* 6.2.1, rule 6 */
792 if (parent) {
793 if (parent->child) {
794 down = 1;
795 start = parent->child;
796 } else {
797 down = 0;
798 start = parent;
799 }
800 } else {
801 down = 1;
802 start = module->data;
803 }
804 /* go up */
Radek Krejcic071c542016-01-27 14:57:51 +0100805 if (lys_find_grouping_up(node->name, start)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200806 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
807 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200808 }
809 /* go down, because grouping can be defined after e.g. container in which is collision */
810 if (down) {
811 for (iter = start, stop = NULL; iter; iter = iter->prev) {
812 if (!stop) {
813 stop = start;
814 } else if (iter == stop) {
815 break;
816 }
817 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
818 continue;
819 }
820
821 grp = NULL;
822 while ((grp = lys_get_next_grouping(grp, iter))) {
823 if (node->name == grp->name) {
824 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
825 return EXIT_FAILURE;
826 }
827 }
828 }
829 }
830 break;
831 case LYS_LEAF:
832 case LYS_LEAFLIST:
833 case LYS_LIST:
834 case LYS_CONTAINER:
835 case LYS_CHOICE:
836 case LYS_ANYXML:
837 /* 6.2.1, rule 7 */
838 if (parent) {
839 iter = parent;
840 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE))) {
841 iter = iter->parent;
842 }
843 if (!iter) {
844 stop = NULL;
845 iter = module->data;
846 } else {
847 stop = iter;
848 iter = iter->child;
849 }
850 } else {
851 stop = NULL;
852 iter = module->data;
853 }
854 while (iter) {
855 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
856 iter = iter->child;
857 continue;
858 }
859
860 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
861 if (iter->module == node->module && iter->name == node->name) {
862 LOGVAL(LYE_SPEC, 0, "Duplicated child identifier \"%s\" in \"%s\".", node->name,
863 stop ? stop->name : "(sub)module");
864 return EXIT_FAILURE;
865 }
866 }
867
868 /* special case for choice - we must check the choice's name as
869 * well as the names of nodes under the choice
870 */
871 if (iter->nodetype == LYS_CHOICE) {
872 iter = iter->child;
873 continue;
874 }
875
876 /* go to siblings */
877 if (!iter->next) {
878 /* no sibling, go to parent's sibling */
879 do {
880 iter = iter->parent;
881 if (iter && iter->next) {
882 break;
883 }
884 } while (iter != stop);
885
886 if (iter == stop) {
887 break;
888 }
889 }
890 iter = iter->next;
891 }
892 break;
893 case LYS_CASE:
894 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100895 if (parent) {
896 start = parent->child;
897 } else {
898 start = module->data;
899 }
900
901 LY_TREE_FOR(start, iter) {
Radek Krejci07911992015-08-14 15:13:31 +0200902 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
903 continue;
904 }
905
906 if (iter->module == node->module && iter->name == node->name) {
907 LOGVAL(LYE_DUPID, 0, "case", node->name);
908 return EXIT_FAILURE;
909 }
910 }
911 break;
912 default:
913 /* no check needed */
914 break;
915 }
916
917 return EXIT_SUCCESS;
918}
919
Michal Vasko0d343d12015-08-24 14:57:36 +0200920/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200921int
Radek Krejci10c760e2015-08-14 14:45:43 +0200922lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
923{
Radek Krejci92720552015-10-05 15:28:27 +0200924 struct lys_node *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200925 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200926
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200927 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200928
Radek Krejci10c760e2015-08-14 14:45:43 +0200929 if (parent) {
930 type = parent->nodetype;
931 module = parent->module;
932 } else {
933 assert(module);
934 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200935 }
936
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200937 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200938 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200939 case LYS_CONTAINER:
940 case LYS_LIST:
941 case LYS_GROUPING:
942 case LYS_USES:
943 case LYS_INPUT:
944 case LYS_OUTPUT:
945 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200946 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200947 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
948 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200949 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200950 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
951 return EXIT_FAILURE;
952 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200953
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200954 break;
Radek Krejci76512572015-08-04 09:47:08 +0200955 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200956 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200957 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200958 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"choice\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200959 strnodetype(child->nodetype), parent->name);
960 return EXIT_FAILURE;
961 }
962 break;
Radek Krejci76512572015-08-04 09:47:08 +0200963 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200964 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200965 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200966 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"case\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200967 strnodetype(child->nodetype), parent->name);
968 return EXIT_FAILURE;
969 }
970 break;
Radek Krejci76512572015-08-04 09:47:08 +0200971 case LYS_RPC:
972 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200973 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"rpc\" %s.",
Michal Vasko38d01f72015-06-15 09:41:06 +0200974 strnodetype(child->nodetype), parent->name);
975 return EXIT_FAILURE;
976 }
977 break;
Radek Krejci76512572015-08-04 09:47:08 +0200978 case LYS_LEAF:
979 case LYS_LEAFLIST:
980 case LYS_ANYXML:
Radek Krejci10c760e2015-08-14 14:45:43 +0200981 LOGVAL(LYE_SPEC, 0, "The \"%s\" statement (%s) cannot have any data substatement.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200982 strnodetype(parent->nodetype), parent->name);
983 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200984 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200985 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200986 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
987 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200988 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200989 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
990 return EXIT_FAILURE;
991 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200992 break;
993 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200994 /* top level */
995 if (!(child->nodetype &
996 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
997 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci2c0ca272015-08-14 15:31:01 +0200998 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in (sub)module \"%s\"",
999 strnodetype(child->nodetype), module->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02001000 return EXIT_FAILURE;
1001 }
1002
Radek Krejcic071c542016-01-27 14:57:51 +01001003 break;
Radek Krejci10c760e2015-08-14 14:45:43 +02001004 }
1005
1006 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +02001007 if (lys_check_id(child, parent, module)) {
1008 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001009 }
Radek Krejcib7155b52015-06-10 17:03:01 +02001010
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001011 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001012 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001013 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001014
Radek Krejci10c760e2015-08-14 14:45:43 +02001015 if (!parent) {
Radek Krejci92720552015-10-05 15:28:27 +02001016 if (module->data) {
1017 module->data->prev->next = child;
1018 child->prev = module->data->prev;
1019 module->data->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +02001020 } else {
Radek Krejci92720552015-10-05 15:28:27 +02001021 module->data = child;
Radek Krejci10c760e2015-08-14 14:45:43 +02001022 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001023 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +02001024 if (!parent->child) {
1025 /* the only/first child of the parent */
1026 parent->child = child;
1027 child->parent = parent;
1028 iter = child;
1029 } else {
1030 /* add a new child at the end of parent's child list */
1031 iter = parent->child->prev;
1032 iter->next = child;
1033 child->prev = iter;
1034 }
1035 while (iter->next) {
1036 iter = iter->next;
1037 iter->parent = parent;
1038 }
1039 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001040 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001041
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001042 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001043}
1044
Michal Vasko1e62a092015-12-01 12:27:20 +01001045API const struct lys_module *
Radek Krejci722b0072016-02-01 17:09:45 +01001046lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001047{
Radek Krejci0b5805d2015-08-13 09:38:02 +02001048 struct lys_module *mod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001049
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001050 if (!ctx || !data) {
1051 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1052 return NULL;
1053 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001054
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001055 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001056 case LYS_IN_YIN:
Radek Krejcic071c542016-01-27 14:57:51 +01001057 mod = yin_read_module(ctx, data, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001058 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001059 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001060 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001061 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001062 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001063 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001064
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001065 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001066}
1067
Radek Krejcib8048692015-08-05 13:36:34 +02001068struct lys_submodule *
Radek Krejcic071c542016-01-27 14:57:51 +01001069lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001070{
Radek Krejci0b5805d2015-08-13 09:38:02 +02001071 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001073 assert(module);
1074 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001075
Radek Krejcic071c542016-01-27 14:57:51 +01001076 /* get the main module */
1077 while(module->type) {
1078 module = ((struct lys_submodule *)module)->belongsto;
Michal Vasko253035f2015-12-17 16:58:13 +01001079 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001080
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001081 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001082 case LYS_IN_YIN:
Radek Krejcic071c542016-01-27 14:57:51 +01001083 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001084 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001085 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001086 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001087 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001088 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001089 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001090
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001091 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001092}
1093
Michal Vasko1e62a092015-12-01 12:27:20 +01001094API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +01001095lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1096{
1097 int fd;
1098 const struct lys_module *ret;
1099
1100 if (!ctx || !path) {
1101 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1102 return NULL;
1103 }
1104
1105 fd = open(path, O_RDONLY);
1106 if (fd == -1) {
1107 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
1108 return NULL;
1109 }
1110
1111 ret = lys_parse_fd(ctx, fd, format);
1112 close(fd);
1113 return ret;
1114}
1115
1116API const struct lys_module *
1117lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001118{
Michal Vasko1e62a092015-12-01 12:27:20 +01001119 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +02001120 struct stat sb;
1121 char *addr;
1122
1123 if (!ctx || fd < 0) {
1124 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1125 return NULL;
1126 }
1127
Radek Krejci10a833c2015-12-16 15:28:37 +01001128 if (fstat(fd, &sb) == -1) {
1129 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
1130 return NULL;
1131 }
Radek Krejci3006be02015-12-17 11:24:33 +01001132 addr = mmap(NULL, sb.st_size + 1, PROT_READ, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001133 if (addr == MAP_FAILED) {
Michal Vasko662610a2015-12-07 11:25:45 +01001134 LOGERR(LY_EMEM, "Map file into memory failed (%s()).",__func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001135 return NULL;
1136 }
Radek Krejci722b0072016-02-01 17:09:45 +01001137 module = lys_parse_mem(ctx, addr, format);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001138 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001139
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001140 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001141}
1142
Radek Krejcib8048692015-08-05 13:36:34 +02001143struct lys_submodule *
Radek Krejcic071c542016-01-27 14:57:51 +01001144lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001145{
Radek Krejcib8048692015-08-05 13:36:34 +02001146 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001147 struct stat sb;
1148 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001150 assert(module);
1151 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001152
Radek Krejci10a833c2015-12-16 15:28:37 +01001153 if (fstat(fd, &sb) == -1) {
1154 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
1155 return NULL;
1156 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001157 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001158 if (addr == MAP_FAILED) {
1159 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
1160 return NULL;
1161 }
Radek Krejcic071c542016-01-27 14:57:51 +01001162 submodule = lys_submodule_parse(module, addr, format, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001163 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +02001164
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001165 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02001166
1167}
1168
Radek Krejci1d82ef62015-08-07 14:44:40 +02001169static struct lys_restr *
1170lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001171{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001172 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001173 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001174
Radek Krejci3733a802015-06-19 13:43:21 +02001175 if (!size) {
1176 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001177 }
Radek Krejci3733a802015-06-19 13:43:21 +02001178
1179 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001180 if (!result) {
1181 return NULL;
1182 }
Radek Krejci3733a802015-06-19 13:43:21 +02001183 for (i = 0; i < size; i++) {
1184 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1185 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1186 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1187 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1188 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1189 }
1190
1191 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001192}
1193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001194void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001195lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001196{
1197 assert(ctx);
1198 if (!restr) {
1199 return;
1200 }
1201
1202 lydict_remove(ctx, restr->expr);
1203 lydict_remove(ctx, restr->dsc);
1204 lydict_remove(ctx, restr->ref);
1205 lydict_remove(ctx, restr->eapptag);
1206 lydict_remove(ctx, restr->emsg);
1207}
1208
Michal Vaskob84f88a2015-09-24 13:16:10 +02001209static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001210lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Michal Vaskof02e3742015-08-05 16:27:02 +02001211 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001212{
1213 int i;
1214
Michal Vasko1dca6882015-10-22 14:29:42 +02001215 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001216 new->base = old->base;
1217 new->der = old->der;
1218
Michal Vasko0bd29d12015-08-19 11:45:49 +02001219 i = unres_schema_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001220 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001221 /* HACK (serious one) for unres */
1222 /* nothing else we can do but duplicate it immediately */
1223 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
Radek Krejcic071c542016-01-27 14:57:51 +01001224 new->parent = (struct lys_tpdf *)parent;
Michal Vaskob84f88a2015-09-24 13:16:10 +02001225 /* all these unres additions can fail even though they did not before */
Michal Vasko88c29542015-11-27 14:57:53 +01001226 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_DER, parent, 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001227 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001228 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001229 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001230 }
1231
Radek Krejci3733a802015-06-19 13:43:21 +02001232 switch (new->base) {
1233 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +02001234 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001235 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001236 }
Radek Krejci3733a802015-06-19 13:43:21 +02001237 break;
1238
1239 case LY_TYPE_BITS:
1240 new->info.bits.count = old->info.bits.count;
1241 if (new->info.bits.count) {
1242 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +01001243 if (!new->info.bits.bit) {
1244 LOGMEM;
1245 return -1;
1246 }
Radek Krejci3733a802015-06-19 13:43:21 +02001247 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001248 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1249 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1250 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001251 new->info.bits.bit[i].status = old->info.bits.bit[i].status;
1252 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1253 }
1254 }
1255 break;
1256
Radek Krejcif9401c32015-06-26 16:47:36 +02001257 case LY_TYPE_DEC64:
1258 new->info.dec64.dig = old->info.dec64.dig;
1259 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001260 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +02001261 }
1262 break;
1263
Radek Krejci3733a802015-06-19 13:43:21 +02001264 case LY_TYPE_ENUM:
1265 new->info.enums.count = old->info.enums.count;
1266 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001267 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +01001268 if (!new->info.enums.enm) {
1269 LOGMEM;
1270 return -1;
1271 }
Radek Krejci3733a802015-06-19 13:43:21 +02001272 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001273 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1274 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1275 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1276 new->info.enums.enm[i].status = old->info.enums.enm[i].status;
1277 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +02001278 }
1279 }
1280 break;
1281
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001282 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001283 if (old->info.ident.ref) {
1284 new->info.ident.ref = old->info.ident.ref;
1285 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001286 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001287 assert(i != -1);
Michal Vasko88c29542015-11-27 14:57:53 +01001288 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i], 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001289 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001290 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001291 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001292 break;
1293
Radek Krejciaf351422015-06-19 14:49:38 +02001294 case LY_TYPE_INST:
1295 new->info.inst.req = old->info.inst.req;
1296 break;
1297
Radek Krejcif2860132015-06-20 12:37:20 +02001298 case LY_TYPE_INT8:
1299 case LY_TYPE_INT16:
1300 case LY_TYPE_INT32:
1301 case LY_TYPE_INT64:
1302 case LY_TYPE_UINT8:
1303 case LY_TYPE_UINT16:
1304 case LY_TYPE_UINT32:
1305 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +02001306 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001307 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001308 }
Radek Krejcif2860132015-06-20 12:37:20 +02001309 break;
1310
Radek Krejcidc4c1412015-06-19 15:39:54 +02001311 case LY_TYPE_LEAFREF:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001312 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko88c29542015-11-27 14:57:53 +01001313 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001314 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001315 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001316 break;
1317
Radek Krejci3733a802015-06-19 13:43:21 +02001318 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +02001319 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001320 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001321 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001322 new->info.str.patterns = lys_restr_dup(mod->ctx, old->info.str.patterns, old->info.str.pat_count);
Radek Krejci3733a802015-06-19 13:43:21 +02001323 break;
1324
Radek Krejcie4c366b2015-07-02 10:11:31 +02001325 case LY_TYPE_UNION:
1326 new->info.uni.count = old->info.uni.count;
1327 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001328 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +01001329 if (!new->info.uni.types) {
1330 LOGMEM;
1331 return -1;
1332 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001333 for (i = 0; i < new->info.uni.count; i++) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001334 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres)) {
1335 return -1;
1336 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001337 }
1338 }
1339 break;
1340
Radek Krejci3733a802015-06-19 13:43:21 +02001341 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001342 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001343 break;
1344 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001345
1346 return EXIT_SUCCESS;
Radek Krejci3733a802015-06-19 13:43:21 +02001347}
1348
1349void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001350lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001351{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001352 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001353
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001354 assert(ctx);
1355 if (!type) {
1356 return;
1357 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001358
Michal Vasko1dca6882015-10-22 14:29:42 +02001359 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001360
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001361 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001362 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001363 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001364 free(type->info.binary.length);
1365 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001366 case LY_TYPE_BITS:
1367 for (i = 0; i < type->info.bits.count; i++) {
1368 lydict_remove(ctx, type->info.bits.bit[i].name);
1369 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1370 lydict_remove(ctx, type->info.bits.bit[i].ref);
1371 }
1372 free(type->info.bits.bit);
1373 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001374
1375 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001376 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001377 free(type->info.dec64.range);
1378 break;
1379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001380 case LY_TYPE_ENUM:
1381 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001382 lydict_remove(ctx, type->info.enums.enm[i].name);
1383 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1384 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001385 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001386 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001387 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001388
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001389 case LY_TYPE_INT8:
1390 case LY_TYPE_INT16:
1391 case LY_TYPE_INT32:
1392 case LY_TYPE_INT64:
1393 case LY_TYPE_UINT8:
1394 case LY_TYPE_UINT16:
1395 case LY_TYPE_UINT32:
1396 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001397 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001398 free(type->info.num.range);
1399 break;
1400
Radek Krejcidc4c1412015-06-19 15:39:54 +02001401 case LY_TYPE_LEAFREF:
1402 lydict_remove(ctx, type->info.lref.path);
1403 break;
1404
Radek Krejci3733a802015-06-19 13:43:21 +02001405 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001406 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001407 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001408 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001409 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001410 }
1411 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001412 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001413
Radek Krejcie4c366b2015-07-02 10:11:31 +02001414 case LY_TYPE_UNION:
1415 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001416 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001417 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001418 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001419 break;
1420
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001421 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001422 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001423 break;
1424 }
Radek Krejci5a065542015-05-22 15:02:07 +02001425}
1426
Radek Krejci1d82ef62015-08-07 14:44:40 +02001427static void
1428lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001429{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001430 assert(ctx);
1431 if (!tpdf) {
1432 return;
1433 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001434
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001435 lydict_remove(ctx, tpdf->name);
1436 lydict_remove(ctx, tpdf->dsc);
1437 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001438
Radek Krejci1d82ef62015-08-07 14:44:40 +02001439 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001440
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001441 lydict_remove(ctx, tpdf->units);
1442 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001443}
1444
Michal Vaskob84f88a2015-09-24 13:16:10 +02001445static struct lys_tpdf *
1446lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1447{
1448 struct lys_tpdf *result;
1449 int i, j;
1450
1451 if (!size) {
1452 return NULL;
1453 }
1454
1455 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001456 if (!result) {
1457 LOGMEM;
1458 return NULL;
1459 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001460 for (i = 0; i < size; i++) {
1461 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1462 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1463 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1464 result[i].flags = old[i].flags;
1465 result[i].module = old[i].module;
1466
1467 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres)) {
1468 for (j = 0; j <= i; ++j) {
1469 lys_tpdf_free(mod->ctx, &result[j]);
1470 }
1471 free(result);
1472 return NULL;
1473 }
1474
1475 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1476 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1477 }
1478
1479 return result;
1480}
1481
Radek Krejci1d82ef62015-08-07 14:44:40 +02001482static struct lys_when *
1483lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001484{
Radek Krejci76512572015-08-04 09:47:08 +02001485 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001486
1487 if (!old) {
1488 return NULL;
1489 }
1490
1491 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001492 if (!new) {
1493 LOGMEM;
1494 return NULL;
1495 }
Radek Krejci00768f42015-06-18 17:04:04 +02001496 new->cond = lydict_insert(ctx, old->cond, 0);
1497 new->dsc = lydict_insert(ctx, old->dsc, 0);
1498 new->ref = lydict_insert(ctx, old->ref, 0);
1499
1500 return new;
1501}
1502
Michal Vasko0308dd62015-10-07 09:14:40 +02001503void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001504lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001505{
1506 if (!w) {
1507 return;
1508 }
1509
1510 lydict_remove(ctx, w->cond);
1511 lydict_remove(ctx, w->dsc);
1512 lydict_remove(ctx, w->ref);
1513
1514 free(w);
1515}
1516
Radek Krejcib7f5e412015-08-13 10:15:51 +02001517static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001518lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment aug, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcib7f5e412015-08-13 10:15:51 +02001519{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001520 struct lys_node *next, *sub;
1521
Radek Krejcic071c542016-01-27 14:57:51 +01001522 /* children from a resolved augment are freed under the target node */
1523 if (!aug.target) {
1524 LY_TREE_FOR_SAFE(aug.child, next, sub) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001525 lys_node_free(sub, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01001526 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001527 }
1528
Radek Krejcib7f5e412015-08-13 10:15:51 +02001529 lydict_remove(ctx, aug.target_name);
1530 lydict_remove(ctx, aug.dsc);
1531 lydict_remove(ctx, aug.ref);
1532
1533 free(aug.features);
1534
1535 lys_when_free(ctx, aug.when);
1536
Michal Vasko7d356a52015-08-19 15:06:31 +02001537 /* Do not free the children, they were appended somewhere and their
1538 * new parent will take care of them.
1539 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001540}
1541
Radek Krejci76512572015-08-04 09:47:08 +02001542static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001543lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001544{
Radek Krejci76512572015-08-04 09:47:08 +02001545 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001546 struct lys_node *old_child, *new_child;
1547 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001548
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001549 if (!size) {
1550 return NULL;
1551 }
Radek Krejci106efc02015-06-10 14:36:27 +02001552
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001553 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001554 if (!new) {
1555 LOGMEM;
1556 return NULL;
1557 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001558 for (i = 0; i < size; i++) {
1559 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1560 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1561 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1562 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001563 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001564 new[i].nodetype = old[i].nodetype;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001565 /* this must succeed, it was already resolved once */
Michal Vasko1e62a092015-12-01 12:27:20 +01001566 if (resolve_schema_nodeid(new[i].target_name, parent->child, new[i].module, LYS_AUGMENT,
1567 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001568 LOGINT;
1569 free(new);
1570 return NULL;
1571 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001572 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001573
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001574 /* Correct the augment nodes.
1575 * This function can only be called from lys_node_dup() with uses
1576 * being the node duplicated, so we must have a case of grouping
1577 * with a uses with augments. The augmented nodes have already been
1578 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001579 * (it was set to their actual data parent, not an augment), and
1580 * the new augment does not have child pointer to its augment nodes,
1581 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001582 */
1583 LY_TREE_FOR(new[i].target->child, new_child) {
1584 if (new_child->name == old[i].child->name) {
1585 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001586 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001587 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001588 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001589 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001590 LY_TREE_FOR(old[i].child, old_child) {
1591 /* all augment nodes were connected as siblings, there can be no more after this */
1592 if (old_child->parent != (struct lys_node *)&old[i]) {
1593 break;
1594 }
1595
1596 assert(old_child->name == new_child->name);
1597
1598 new_child->parent = (struct lys_node *)&new[i];
1599 new_child = new_child->next;
1600 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001601 }
Radek Krejci106efc02015-06-10 14:36:27 +02001602
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001603 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001604}
1605
Radek Krejci76512572015-08-04 09:47:08 +02001606static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001607lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001608{
Radek Krejci76512572015-08-04 09:47:08 +02001609 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001610 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001611
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001612 if (!size) {
1613 return NULL;
1614 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001615
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001616 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001617 if (!result) {
1618 LOGMEM;
1619 return NULL;
1620 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001621 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001622 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001623 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1624 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001625 result[i].flags = old[i].flags;
1626 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001627
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001628 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001629 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001630
Radek Krejci76512572015-08-04 09:47:08 +02001631 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001632 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001633 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001634 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001635 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001636 result[i].mod.list = old[i].mod.list;
1637 }
1638 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001639
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001640 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001641}
1642
Radek Krejci1d82ef62015-08-07 14:44:40 +02001643static void
1644lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001645{
Radek Krejcia52656e2015-08-05 13:41:50 +02001646 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001647
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001648 assert(ctx);
1649 if (!ident) {
1650 return;
1651 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001652
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001653 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001654 * if caller free only a single data model which is used (its identity is
1655 * reference from identity in another module), this silly freeing can lead
1656 * to segmentation fault. But without noting if the module is used by some
1657 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001658 *
1659 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001660 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001661 */
1662 while (ident->der) {
1663 der = ident->der;
1664 ident->der = der->next;
1665 free(der);
1666 }
Radek Krejci6793db02015-05-22 17:49:54 +02001667
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001668 lydict_remove(ctx, ident->name);
1669 lydict_remove(ctx, ident->dsc);
1670 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001671
1672}
1673
Radek Krejci1d82ef62015-08-07 14:44:40 +02001674static void
1675lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001676{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001677 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001678
Radek Krejcid12f57b2015-08-06 10:43:39 +02001679 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001680 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001681 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001682 }
1683 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001684}
1685
Radek Krejci1d82ef62015-08-07 14:44:40 +02001686static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001687lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1688{
1689 int i;
1690
1691 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1692 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001693 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001694 }
1695 free(io->tpdf);
1696}
1697
Radek Krejci1d82ef62015-08-07 14:44:40 +02001698static void
1699lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001700{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001701 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001702
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001703 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001704 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001705 }
1706 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001707
Radek Krejci1d82ef62015-08-07 14:44:40 +02001708 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001709}
1710
Radek Krejci1d82ef62015-08-07 14:44:40 +02001711static void
1712lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001713{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001714 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001715
Radek Krejci46c4cd72016-01-21 15:13:52 +01001716 if (leaf->child) {
1717 /* leafref backlinks */
1718 ly_set_free((struct ly_set *)leaf->child);
1719 }
1720
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001721 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001722 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001723 }
1724 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001725
Radek Krejci1d82ef62015-08-07 14:44:40 +02001726 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001727
Radek Krejci1d82ef62015-08-07 14:44:40 +02001728 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001729 lydict_remove(ctx, leaf->units);
1730 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001731}
1732
Radek Krejci1d82ef62015-08-07 14:44:40 +02001733static void
1734lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001735{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001736 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001737
Radek Krejci46c4cd72016-01-21 15:13:52 +01001738 if (llist->child) {
1739 /* leafref backlinks */
1740 ly_set_free((struct ly_set *)llist->child);
1741 }
1742
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001743 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001744 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001745 }
1746 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001747
Radek Krejci1d82ef62015-08-07 14:44:40 +02001748 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001749
Radek Krejci1d82ef62015-08-07 14:44:40 +02001750 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001751 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001752}
1753
Radek Krejci1d82ef62015-08-07 14:44:40 +02001754static void
1755lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001756{
Radek Krejci581ce772015-11-10 17:22:40 +01001757 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001758
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001759 /* handle only specific parts for LY_NODE_LIST */
1760 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001761 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001762 }
1763 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001764
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001765 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001766 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001767 }
1768 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001769
Radek Krejci1d82ef62015-08-07 14:44:40 +02001770 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001771
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001772 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001773 for (j = 0; j > list->unique[i].expr_size; j++) {
1774 lydict_remove(ctx, list->unique[i].expr[j]);
1775 }
1776 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001777 }
1778 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001779
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001780 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001781}
1782
Radek Krejci1d82ef62015-08-07 14:44:40 +02001783static void
1784lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001785{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001786 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001787
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001788 /* handle only specific parts for LY_NODE_CONTAINER */
1789 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001790
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001791 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001792 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001793 }
1794 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001795
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001796 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001797 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001798 }
1799 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001800
Radek Krejci1d82ef62015-08-07 14:44:40 +02001801 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001802}
1803
Radek Krejci1d82ef62015-08-07 14:44:40 +02001804static void
1805lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001806{
1807 lydict_remove(ctx, f->name);
1808 lydict_remove(ctx, f->dsc);
1809 lydict_remove(ctx, f->ref);
1810 free(f->features);
1811}
1812
Radek Krejci1d82ef62015-08-07 14:44:40 +02001813static void
1814lys_deviation_free(struct ly_ctx *ctx, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001815{
Radek Krejci581ce772015-11-10 17:22:40 +01001816 int i, j, k;
Radek Krejcieb00f512015-07-01 16:44:58 +02001817
1818 lydict_remove(ctx, dev->target_name);
1819 lydict_remove(ctx, dev->dsc);
1820 lydict_remove(ctx, dev->ref);
1821
1822 for (i = 0; i < dev->deviate_size; i++) {
1823 lydict_remove(ctx, dev->deviate[i].dflt);
1824 lydict_remove(ctx, dev->deviate[i].units);
1825
1826 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1827 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001828 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001829 }
1830 free(dev->deviate[i].must);
1831
1832 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001833 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1834 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1835 }
1836 free(dev->deviate[j].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001837 }
1838 free(dev->deviate[i].unique);
1839 }
1840 }
1841 free(dev->deviate);
1842}
1843
Radek Krejci1d82ef62015-08-07 14:44:40 +02001844static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001845lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcie1fa8582015-06-08 09:46:45 +02001846{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001847 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001848
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001849 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001850 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001851 lydict_remove(ctx, uses->refine[i].dsc);
1852 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001853
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001854 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001855 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001856 }
1857 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001858
Radek Krejci76512572015-08-04 09:47:08 +02001859 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001860 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001861 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001862 lydict_remove(ctx, uses->refine[i].mod.presence);
1863 }
1864 }
1865 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001866
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001867 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001868 lys_augment_free(ctx, uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001869 }
1870 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001871
Radek Krejci1d82ef62015-08-07 14:44:40 +02001872 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001873}
1874
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001875void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001876lys_node_free(struct lys_node *node, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02001877{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001878 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001879 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001880
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001881 if (!node) {
1882 return;
1883 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001884
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001885 assert(node->module);
1886 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001887
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001888 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001889
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001890 /* remove private object */
1891 if (node->private && private_destructor) {
1892 private_destructor(node, node->private);
1893 }
1894
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001895 /* common part */
Radek Krejcid12f57b2015-08-06 10:43:39 +02001896 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1897 free(node->features);
1898 lydict_remove(ctx, node->name);
1899 lydict_remove(ctx, node->dsc);
1900 lydict_remove(ctx, node->ref);
1901 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001902
Radek Krejci46c4cd72016-01-21 15:13:52 +01001903 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
1904 LY_TREE_FOR_SAFE(node->child, next, sub) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001905 lys_node_free(sub, private_destructor);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001906 }
1907 }
1908
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001909 /* specific part */
1910 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001911 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001912 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001913 break;
Radek Krejci76512572015-08-04 09:47:08 +02001914 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001915 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001916 break;
Radek Krejci76512572015-08-04 09:47:08 +02001917 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001918 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001919 break;
Radek Krejci76512572015-08-04 09:47:08 +02001920 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001921 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001922 break;
Radek Krejci76512572015-08-04 09:47:08 +02001923 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001924 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001925 break;
Radek Krejci76512572015-08-04 09:47:08 +02001926 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001927 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001928 break;
Radek Krejci76512572015-08-04 09:47:08 +02001929 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001930 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001931 break;
Radek Krejci76512572015-08-04 09:47:08 +02001932 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001933 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001934 break;
Radek Krejci76512572015-08-04 09:47:08 +02001935 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001936 /* do nothing */
1937 break;
Radek Krejci76512572015-08-04 09:47:08 +02001938 case LYS_GROUPING:
1939 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001940 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001941 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001942 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001943
1944 case LYS_INPUT:
1945 case LYS_OUTPUT:
1946 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1947 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001948 case LYS_UNKNOWN:
1949 LOGINT;
1950 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001951 }
Radek Krejci5a065542015-05-22 15:02:07 +02001952
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001953 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001954 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001955 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001956}
1957
Michal Vasko1e62a092015-12-01 12:27:20 +01001958const struct lys_module *
1959lys_get_import_module(const struct lys_module *module, const char *prefix, int pref_len, const char *name, int name_len)
Michal Vasko8ce24d72015-10-21 11:27:26 +02001960{
Radek Krejcic071c542016-01-27 14:57:51 +01001961 const struct lys_module *main_module;
Michal Vaskob6729c62015-10-21 12:09:47 +02001962 int i, match;
1963
Michal Vaskob6729c62015-10-21 12:09:47 +02001964 if (prefix && !pref_len) {
1965 pref_len = strlen(prefix);
1966 }
1967 if (name && !name_len) {
1968 name_len = strlen(name);
1969 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02001970
Radek Krejcic071c542016-01-27 14:57:51 +01001971 main_module = module->type ? ((struct lys_submodule *)module)->belongsto : module;
1972 if ((!prefix || (!strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])) && (!name
1973 || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
1974 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02001975 }
1976
Michal Vasko8ce24d72015-10-21 11:27:26 +02001977 for (i = 0; i < module->imp_size; ++i) {
Michal Vaskob6729c62015-10-21 12:09:47 +02001978 match = 0;
1979 if (!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len])) {
1980 match = 1;
1981 }
1982 if (match && (!name
1983 || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02001984 return module->imp[i].module;
1985 }
1986 }
1987
1988 return NULL;
1989}
1990
Michal Vasko13b15832015-08-19 11:04:48 +02001991/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001992static void
Michal Vaskob746fff2016-02-11 11:37:50 +01001993module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02001994{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001995 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01001996 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001997 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001998
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001999 assert(module->ctx);
2000 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002001
Michal Vaskob746fff2016-02-11 11:37:50 +01002002 /* just free the import array, imported modules will stay in the context */
Radek Krejcidce51452015-06-16 15:20:08 +02002003 free(module->imp);
2004
Radek Krejcic071c542016-01-27 14:57:51 +01002005 /* submodules don't have data tree, the data nodes
2006 * are placed in the main module altogether */
2007 if (!module->type) {
2008 LY_TREE_FOR_SAFE(module->data, next, iter) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002009 lys_node_free(iter, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002010 }
Radek Krejci21181962015-06-30 14:11:00 +02002011 }
Radek Krejci5a065542015-05-22 15:02:07 +02002012
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002013 lydict_remove(ctx, module->dsc);
2014 lydict_remove(ctx, module->ref);
2015 lydict_remove(ctx, module->org);
2016 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002017
Radek Krejcieb00f512015-07-01 16:44:58 +02002018 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002019 for (i = 0; i < module->rev_size; i++) {
2020 lydict_remove(ctx, module->rev[i].dsc);
2021 lydict_remove(ctx, module->rev[i].ref);
2022 }
2023 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002024
Radek Krejcieb00f512015-07-01 16:44:58 +02002025 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002026 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002027 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002028 }
2029 module->ident_size = 0;
2030 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002031
Radek Krejcieb00f512015-07-01 16:44:58 +02002032 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002033 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002034 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002035 }
2036 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002037
Radek Krejcieb00f512015-07-01 16:44:58 +02002038 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002039 for (i = 0; i < module->inc_size; i++) {
Radek Krejcic071c542016-01-27 14:57:51 +01002040 /* complete submodule free is done only from main module since
2041 * submodules propagate their includes to the main module */
2042 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002043 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002044 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002045 }
2046 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002047
Radek Krejcieb00f512015-07-01 16:44:58 +02002048 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002049 for (i = 0; i < module->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002050 lys_augment_free(ctx, module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002051 }
2052 free(module->augment);
2053
Radek Krejcieb00f512015-07-01 16:44:58 +02002054 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002055 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002056 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002057 }
2058 free(module->features);
2059
Radek Krejcieb00f512015-07-01 16:44:58 +02002060 /* deviations */
2061 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002062 lys_deviation_free(ctx, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002063 }
2064 free(module->deviation);
2065
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002066 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02002067}
2068
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002069void
Michal Vaskob746fff2016-02-11 11:37:50 +01002070lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002071{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002072 if (!submodule) {
2073 return;
2074 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002076 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002077 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002078
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002079 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002080
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002081 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002082}
2083
Radek Krejci76512572015-08-04 09:47:08 +02002084struct lys_node *
Radek Krejcic071c542016-01-27 14:57:51 +01002085lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node, uint8_t flags,
2086 uint8_t nacm, struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002087{
Radek Krejcic071c542016-01-27 14:57:51 +01002088 struct lys_node *retval = NULL, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002089 struct ly_ctx *ctx = module->ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002090 const char *modname;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002091 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002092
Michal Vaskoc07187d2015-08-13 15:20:57 +02002093 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002094 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002095 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002096 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002097 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002098 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002099 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002100 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002101 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002102 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002103 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002104 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002105 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002106 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002107 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002108 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002109 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002110 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002111 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002112 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002113 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002114 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002115 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002116 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002117
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002118 /* we cannot just duplicate memory since the strings are stored in
2119 * dictionary and we need to update dictionary counters.
2120 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002121
Radek Krejci1d82ef62015-08-07 14:44:40 +02002122 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002123 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002124 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002125 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002126 break;
2127
Radek Krejci76512572015-08-04 09:47:08 +02002128 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002129 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002130 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002131 break;
2132
Radek Krejci76512572015-08-04 09:47:08 +02002133 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002134 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002135 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002136 break;
2137
Radek Krejci76512572015-08-04 09:47:08 +02002138 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002139 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002140 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002141 break;
2142
Radek Krejci76512572015-08-04 09:47:08 +02002143 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002144 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002145 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002146 break;
2147
Radek Krejci76512572015-08-04 09:47:08 +02002148 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002149 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002150 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002151 break;
2152
Radek Krejci76512572015-08-04 09:47:08 +02002153 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002154 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002155 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002156 break;
2157
Radek Krejci76512572015-08-04 09:47:08 +02002158 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002159 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002160 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002161 break;
2162
Radek Krejci76512572015-08-04 09:47:08 +02002163 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002164 grp = calloc(1, sizeof *grp);
2165 retval = (struct lys_node *)grp;
2166 break;
2167
Radek Krejci76512572015-08-04 09:47:08 +02002168 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002169 rpc = calloc(1, sizeof *rpc);
2170 retval = (struct lys_node *)rpc;
2171 break;
2172
Radek Krejci76512572015-08-04 09:47:08 +02002173 case LYS_INPUT:
2174 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002175 io = calloc(1, sizeof *io);
2176 retval = (struct lys_node *)io;
2177 break;
2178
Radek Krejci76512572015-08-04 09:47:08 +02002179 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002180 ntf = calloc(1, sizeof *ntf);
2181 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002182 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002183
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002184 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002185 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002186 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002187 }
Radek Krejcib388c152015-06-04 17:03:03 +02002188
Michal Vasko253035f2015-12-17 16:58:13 +01002189 if (!retval) {
2190 LOGMEM;
2191 return NULL;
2192 }
2193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002194 /*
2195 * duplicate generic part of the structure
2196 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002197 retval->name = lydict_insert(ctx, node->name, 0);
2198 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2199 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002200 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002201 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002202 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002203 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002204 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002205 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002206
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002207 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002208 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002209
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002210 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002211
Radek Krejci1d82ef62015-08-07 14:44:40 +02002212 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002213 retval->features = calloc(retval->features_size, sizeof *retval->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002214 if (!retval->features) {
2215 LOGMEM;
2216 goto error;
2217 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002218 for (i = 0; i < node->features_size; ++i) {
Radek Krejcicf509982015-12-15 09:22:44 +01002219 retval->features[i] = (struct lys_feature *)retval;
Michal Vasko0bd29d12015-08-19 11:45:49 +02002220 if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002221 retval->features[i] = node->features[i];
Michal Vaskod23ce592015-08-06 09:55:37 +02002222 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002223 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002224
Radek Krejcic071c542016-01-27 14:57:51 +01002225 /* connect it to the parent */
2226 if (lys_node_addchild(parent, retval->module, retval)) {
2227 goto error;
2228 }
2229
2230 /* go recursively */
2231 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002232 LY_TREE_FOR(node->child, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01002233 if (!lys_node_dup(module, retval, child, retval->flags, retval->nacm, unres)) {
Michal Vasko49168a22015-08-17 16:35:41 +02002234 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002235 }
2236 }
2237 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002238
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002239 /*
2240 * duplicate specific part of the structure
2241 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002242 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002243 case LYS_CONTAINER:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002244 if (cont_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002245 cont->when = lys_when_dup(ctx, cont_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002246 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002247 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002248
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002249 cont->must_size = cont_orig->must_size;
2250 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002251
Radek Krejci1d82ef62015-08-07 14:44:40 +02002252 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci1d82ef62015-08-07 14:44:40 +02002253 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002254 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002255
Radek Krejci76512572015-08-04 09:47:08 +02002256 case LYS_CHOICE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002257 if (choice_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002258 choice->when = lys_when_dup(ctx, choice_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002259 }
2260
2261 if (choice_orig->dflt) {
Radek Krejcif70a3a62016-01-27 16:39:58 +01002262 modname = choice->module->type ? ((struct lys_submodule *)choice->module)->belongsto->name : choice->module->name;
Radek Krejcic071c542016-01-27 14:57:51 +01002263 rc = lys_get_sibling(choice->child, modname, 0, choice_orig->dflt->name, 0, LYS_ANYXML
Radek Krejci76512572015-08-04 09:47:08 +02002264 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
Michal Vasko1e62a092015-12-01 12:27:20 +01002265 | LYS_LIST, (const struct lys_node **)&choice->dflt);
Michal Vasko49168a22015-08-17 16:35:41 +02002266 if (rc) {
2267 if (rc == EXIT_FAILURE) {
2268 LOGINT;
2269 }
2270 goto error;
2271 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002272 } else {
Michal Vaskoc68a2a22015-08-06 09:57:24 +02002273 /* useless to check return value, we don't know whether
2274 * there really wasn't any default defined or it just hasn't
2275 * been resolved, we just hope for the best :)
2276 */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002277 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002278 }
2279 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002280
Radek Krejci76512572015-08-04 09:47:08 +02002281 case LYS_LEAF:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002282 if (lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres)) {
2283 goto error;
2284 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002285 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2286
2287 if (leaf_orig->dflt) {
2288 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002289 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002290 goto error;
2291 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002292 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002293
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002294 leaf->must_size = leaf_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002295 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002296
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002297 if (leaf_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002298 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002299 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002300 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002301
Radek Krejci76512572015-08-04 09:47:08 +02002302 case LYS_LEAFLIST:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002303 if (lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres)) {
2304 goto error;
2305 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002306 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002307
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002308 llist->min = llist_orig->min;
2309 llist->max = llist_orig->max;
2310
2311 llist->must_size = llist_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002312 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002313
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002314 if (llist_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002315 llist->when = lys_when_dup(ctx, llist_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002316 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002317 break;
2318
Radek Krejci76512572015-08-04 09:47:08 +02002319 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002320 list->min = list_orig->min;
2321 list->max = list_orig->max;
2322
2323 list->must_size = list_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002324 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002325
Radek Krejci581ce772015-11-10 17:22:40 +01002326 list->tpdf_size = list_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002327 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002328
Radek Krejci581ce772015-11-10 17:22:40 +01002329 list->keys_size = list_orig->keys_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002330 if (list->keys_size) {
2331 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01002332 if (!list->keys) {
2333 LOGMEM;
2334 goto error;
2335 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002336
2337 /* we managed to resolve it before, resolve it again manually */
2338 if (list_orig->keys[0]) {
Radek Krejcic071c542016-01-27 14:57:51 +01002339 modname = list->module->type ? ((struct lys_submodule *)list->module)->belongsto->name : list->module->name;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002340 for (i = 0; i < list->keys_size; ++i) {
Radek Krejcic071c542016-01-27 14:57:51 +01002341 rc = lys_get_sibling(list->child, modname, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
Michal Vasko1e62a092015-12-01 12:27:20 +01002342 (const struct lys_node **)&list->keys[i]);
Michal Vasko49168a22015-08-17 16:35:41 +02002343 if (rc) {
2344 if (rc == EXIT_FAILURE) {
2345 LOGINT;
2346 }
2347 goto error;
2348 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002349 }
2350 /* it was not resolved yet, add unres copy */
2351 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002352 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02002353 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002354 goto error;
Michal Vaskod23ce592015-08-06 09:55:37 +02002355 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002356 }
2357 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002358
Radek Krejci581ce772015-11-10 17:22:40 +01002359 list->unique_size = list_orig->unique_size;
2360 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002361 if (!list->unique) {
2362 LOGMEM;
2363 goto error;
2364 }
Radek Krejci581ce772015-11-10 17:22:40 +01002365 for (i = 0; i < list->unique_size; ++i) {
2366 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2367 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002368 if (!list->unique[i].expr) {
2369 LOGMEM;
2370 goto error;
2371 }
Radek Krejci581ce772015-11-10 17:22:40 +01002372 for (j = 0; j < list->unique[i].expr_size; j++) {
2373 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2374
2375 /* if it stays in unres list, duplicate it also there */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002376 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002377 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002378 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002379
2380 if (list_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002381 list->when = lys_when_dup(ctx, list_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002382 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002383 break;
2384
Radek Krejci76512572015-08-04 09:47:08 +02002385 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002386 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002387 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002388
2389 if (anyxml_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002390 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002391 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002392 break;
2393
Radek Krejci76512572015-08-04 09:47:08 +02002394 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002395 uses->grp = uses_orig->grp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002396
2397 if (uses_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002398 uses->when = lys_when_dup(ctx, uses_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002399 }
2400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002401 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002402 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002403 uses->augment_size = uses_orig->augment_size;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02002404 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Michal Vaskof8c128d2015-08-06 15:25:28 +02002405 if (!uses->child) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002406 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002407 goto error;
2408 }
Michal Vaskof8c128d2015-08-06 15:25:28 +02002409 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002410 break;
2411
Radek Krejci76512572015-08-04 09:47:08 +02002412 case LYS_CASE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002413 if (cs_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002414 cs->when = lys_when_dup(ctx, cs_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002415 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002416 break;
2417
Radek Krejci76512572015-08-04 09:47:08 +02002418 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002419 grp->tpdf_size = grp_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002420 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002421 break;
2422
Radek Krejci76512572015-08-04 09:47:08 +02002423 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002424 rpc->tpdf_size = rpc_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002425 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002426 break;
2427
Radek Krejci76512572015-08-04 09:47:08 +02002428 case LYS_INPUT:
2429 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002430 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002431 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002432 break;
2433
Radek Krejci76512572015-08-04 09:47:08 +02002434 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002435 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002436 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcia01e5432015-06-16 10:35:25 +02002437 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002438
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002439 default:
Radek Krejci00768f42015-06-18 17:04:04 +02002440 /* LY_NODE_AUGMENT */
Michal Vaskod23ce592015-08-06 09:55:37 +02002441 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002442 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002443 }
2444
2445 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002446
2447error:
2448
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002449 lys_node_free(retval, NULL);
Michal Vasko49168a22015-08-17 16:35:41 +02002450 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002451}
2452
Michal Vasko13b15832015-08-19 11:04:48 +02002453void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002454lys_free(struct lys_module *module, int free_int_mods, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002455{
Radek Krejcidce51452015-06-16 15:20:08 +02002456 struct ly_ctx *ctx;
2457 int i;
2458
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002459 if (!module) {
2460 return;
2461 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002462
Radek Krejcidce51452015-06-16 15:20:08 +02002463 /* remove schema from the context */
2464 ctx = module->ctx;
2465 if (ctx->models.used) {
2466 for (i = 0; i < ctx->models.used; i++) {
2467 if (ctx->models.list[i] == module) {
2468 /* replace the position in the list by the last module in the list */
2469 ctx->models.used--;
2470 ctx->models.list[i] = ctx->models.list[ctx->models.used];
2471 ctx->models.list[ctx->models.used] = NULL;
2472 /* we are done */
2473 break;
2474 }
2475 }
2476 }
2477
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002478 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01002479 module_free_common(module, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002480
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002481 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01002482 lydict_remove(ctx, module->ns);
2483 lydict_remove(ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02002484
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002485 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002486}
Radek Krejci7e97c352015-06-19 16:26:34 +02002487
2488/*
2489 * op: 1 - enable, 0 - disable
2490 */
2491static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002492lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002493{
2494 int all = 0;
2495 int i, j, k;
2496
2497 if (!module || !name || !strlen(name)) {
2498 return EXIT_FAILURE;
2499 }
2500
2501 if (!strcmp(name, "*")) {
2502 /* enable all */
2503 all = 1;
2504 }
2505
2506 /* module itself */
2507 for (i = 0; i < module->features_size; i++) {
2508 if (all || !strcmp(module->features[i].name, name)) {
2509 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002510 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002511 /* enable referenced features (recursion) */
2512 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002513 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002514 module->features[i].features[k]->name, op);
2515 }
2516 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002517 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002518 }
2519 if (!all) {
2520 return EXIT_SUCCESS;
2521 }
2522 }
2523 }
2524
2525 /* submodules */
2526 for (j = 0; j < module->inc_size; j++) {
2527 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2528 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2529 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002530 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002531 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002532 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002533 }
2534 if (!all) {
2535 return EXIT_SUCCESS;
2536 }
2537 }
2538 }
2539 }
2540
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002541 /* TODO submodules of submodules ... */
2542
Radek Krejci7e97c352015-06-19 16:26:34 +02002543 if (all) {
2544 return EXIT_SUCCESS;
2545 } else {
2546 return EXIT_FAILURE;
2547 }
2548}
2549
2550API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002551lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002552{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002553 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002554}
2555
2556API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002557lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002558{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002559 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002560}
2561
2562API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002563lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002564{
2565 int i, j;
2566
2567 if (!module || !feature) {
2568 return -1;
2569 }
2570
2571 /* search for the specified feature */
2572 /* module itself */
2573 for (i = 0; i < module->features_size; i++) {
2574 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002575 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002576 return 1;
2577 } else {
2578 return 0;
2579 }
2580 }
2581 }
2582
2583 /* submodules */
2584 for (j = 0; j < module->inc_size; j++) {
2585 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2586 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002587 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002588 return 1;
2589 } else {
2590 return 0;
2591 }
2592 }
2593 }
2594 }
2595
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002596 /* feature definition not found */
2597 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002598}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002599
Radek Krejci96a10da2015-07-30 11:00:14 +02002600API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01002601lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002602{
Radek Krejci96a10da2015-07-30 11:00:14 +02002603 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002604 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002605 unsigned int count;
2606
2607 if (!module) {
2608 return NULL;
2609 }
2610
2611 count = module->features_size;
2612 for (i = 0; i < module->inc_size; i++) {
2613 count += module->inc[i].submodule->features_size;
2614 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002615 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01002616 if (!result) {
2617 LOGMEM;
2618 return NULL;
2619 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002620 if (states) {
2621 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01002622 if (!(*states)) {
2623 LOGMEM;
2624 free(result);
2625 return NULL;
2626 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002627 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002628 count = 0;
2629
2630 /* module itself */
2631 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002632 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002633 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002634 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002635 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002636 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002637 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002638 }
2639 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002640 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002641 }
2642
2643 /* submodules */
2644 for (j = 0; j < module->inc_size; j++) {
2645 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002646 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002647 if (states) {
2648 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2649 (*states)[count] = 1;
2650 } else {
2651 (*states)[count] = 0;
2652 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002653 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002654 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002655 }
2656 }
2657
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002658 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002659 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002660
2661 return result;
2662}
Michal Vaskobaefb032015-09-24 14:52:10 +02002663
Radek Krejcic071c542016-01-27 14:57:51 +01002664struct lys_module *
2665lys_mainmodule(const struct lys_node *node)
2666{
2667 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
2668}
2669
Michal Vaskobaefb032015-09-24 14:52:10 +02002670API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002671lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02002672{
2673 if (!node || !node->parent) {
2674 return NULL;
2675 }
2676
2677 if (node->parent->nodetype == LYS_AUGMENT) {
2678 return ((struct lys_node_augment *)node->parent)->target;
2679 }
2680
2681 return node->parent;
2682}
Michal Vasko1b229152016-01-13 11:28:38 +01002683
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002684API void *
Michal Vasko1b229152016-01-13 11:28:38 +01002685lys_set_private(const struct lys_node *node, void *priv)
2686{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002687 void *prev;
2688
Michal Vasko1b229152016-01-13 11:28:38 +01002689 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002690 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2691 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01002692 }
2693
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002694 prev = node->private;
Michal Vasko1b229152016-01-13 11:28:38 +01002695 ((struct lys_node *)node)->private = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002696
2697 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01002698}
Michal Vasko86252b32016-01-19 09:00:56 +01002699
2700API const struct lys_node *
2701lys_get_node(const struct lys_module *module, const char *nodeid)
2702{
2703 const struct lys_node *ret;
2704
2705 if (!module || !nodeid) {
2706 ly_errno = LY_EINVAL;
2707 return NULL;
2708 }
2709
2710 if (nodeid[0] != '/') {
2711 ly_errno = LY_EINVAL;
2712 return NULL;
2713 }
2714
2715 if (resolve_schema_nodeid(nodeid, NULL, module, LYS_AUGMENT, &ret)) {
2716 ly_errno = LY_EINVAL;
2717 return NULL;
2718 }
2719
2720 return ret;
2721}