blob: a6a26b4e4584da51d44cb9218c3204a11f017cdc [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{
Michal Vasko1e62a092015-12-01 12:27:20 +010097 const struct lys_node *node, *old_siblings = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +010098 const struct lys_module *mod;
99 const char *node_mod_name;
Michal Vasko1dca6882015-10-22 14:29:42 +0200100 int in_submod;
Michal Vasko1dca6882015-10-22 14:29:42 +0200101
Michal Vasko36cbaa42015-12-14 13:15:48 +0100102 assert(siblings && mod_name && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +0200103 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +0200104
105 /* find the beginning */
106 while (siblings->prev->next) {
107 siblings = siblings->prev;
108 }
109
Michal Vasko36cbaa42015-12-14 13:15:48 +0100110 /* fill the lengths in case the caller is so indifferent */
111 if (!mod_name_len) {
112 mod_name_len = strlen(mod_name);
113 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200114 if (!nam_len) {
115 nam_len = strlen(name);
116 }
117
118 /* we start with the module itself, submodules come later */
119 in_submod = 0;
120
Michal Vasko36cbaa42015-12-14 13:15:48 +0100121 /* set mod correctly */
122 if (!siblings->parent) {
123 mod = lys_get_import_module(siblings->module, NULL, 0, mod_name, mod_name_len);
124 if (mod) {
125 old_siblings = siblings;
126 siblings = mod->data;
127 } else if (type & LYS_AUGMENT) {
128 mod = siblings->module;
129 } else {
Michal Vasko1dca6882015-10-22 14:29:42 +0200130 return -1;
131 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200132 } else {
Michal Vasko36cbaa42015-12-14 13:15:48 +0100133 mod = siblings->module;
Michal Vasko1dca6882015-10-22 14:29:42 +0200134 }
135
136 while (1) {
137 /* try to find the node */
138 node = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +0100139 while ((node = lys_getnext(node, siblings->parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
Michal Vasko1dca6882015-10-22 14:29:42 +0200140 if (!type || (node->nodetype & type)) {
Michal Vasko36cbaa42015-12-14 13:15:48 +0100141 /* modules need to always be checked, we want to skip augments (no other reason to check them) */
142 if (node->module->type) {
143 node_mod_name = ((struct lys_submodule *)node->module)->belongsto->name;
Michal Vasko1dca6882015-10-22 14:29:42 +0200144 } else {
Michal Vasko36cbaa42015-12-14 13:15:48 +0100145 node_mod_name = node->module->name;
146 }
147 if ((node_mod_name != mod_name) && (strncmp(node_mod_name, mod_name, mod_name_len) || node_mod_name[mod_name_len])) {
148 continue;
Michal Vasko1dca6882015-10-22 14:29:42 +0200149 }
150
151 /* direct name check */
152 if ((node->name == name) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
153 if (ret) {
154 *ret = node;
155 }
156 return EXIT_SUCCESS;
157 }
158 }
159 }
160
161 /* The original siblings may be valid,
162 * it's a special case when we're looking
163 * for a node from an augment.
164 */
Michal Vasko165dc4a2015-10-23 09:44:27 +0200165 if ((type & LYS_AUGMENT) && old_siblings) {
Michal Vasko1dca6882015-10-22 14:29:42 +0200166 siblings = old_siblings;
167 old_siblings = NULL;
168 continue;
169 }
170
171 /* we're not top-level, search ended */
172 if (siblings->parent) {
173 break;
174 }
175
176 /* let's try the submodules */
Michal Vasko36cbaa42015-12-14 13:15:48 +0100177 if (in_submod == mod->inc_size) {
Michal Vasko1dca6882015-10-22 14:29:42 +0200178 break;
179 }
Michal Vasko36cbaa42015-12-14 13:15:48 +0100180 siblings = mod->inc[in_submod].submodule->data;
Michal Vasko1dca6882015-10-22 14:29:42 +0200181 ++in_submod;
182 }
183
184 return EXIT_FAILURE;
185}
186
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200187int
Michal Vasko1e62a092015-12-01 12:27:20 +0100188lys_get_data_sibling(const struct lys_module *mod, const struct lys_node *siblings, const char *name, LYS_NODE type,
189 const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200190{
Michal Vasko1e62a092015-12-01 12:27:20 +0100191 const struct lys_node *node;
192 const struct lys_module *cur_mod;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200193 int in_submod;
194
195 assert(siblings && name);
196 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
197
198 /* find the beginning */
199 while (siblings->prev->next) {
200 siblings = siblings->prev;
201 }
202
203 /* we start with the module itself, submodules come later */
204 in_submod = 0;
205
206 if (!mod) {
207 mod = siblings->module;
208 }
209 cur_mod = mod;
210
211 while (1) {
212 /* try to find the node */
213 node = NULL;
214 while ((node = lys_getnext(node, siblings->parent, cur_mod, 0))) {
215 if (!type || (node->nodetype & type)) {
216 /* module check */
217 if (!node->module->type) {
218 if (cur_mod != node->module) {
219 continue;
220 }
221 } else {
222 /* both are submodules */
223 if (cur_mod->type) {
224 if (cur_mod != node->module) {
225 continue;
226 }
227 } else {
228 if (cur_mod != ((struct lys_submodule *)node->module)->belongsto) {
229 continue;
230 }
231 }
232 }
233
234 /* direct name check */
235 if ((node->name == name) || !strcmp(node->name, name)) {
236 if (ret) {
237 *ret = node;
238 }
239 return EXIT_SUCCESS;
240 }
241 }
242 }
243
244 /* we're not top-level, search ended */
245 if (siblings->parent) {
246 break;
247 }
248
249 /* let's try the submodules */
250 if (in_submod == mod->inc_size) {
251 break;
252 }
253 cur_mod = (struct lys_module *)mod->inc[in_submod].submodule;
254 siblings = cur_mod->data;
255 ++in_submod;
256 }
257
258 return EXIT_FAILURE;
259}
260
Michal Vasko1e62a092015-12-01 12:27:20 +0100261API const struct lys_node *
262lys_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 +0200263{
Michal Vasko1e62a092015-12-01 12:27:20 +0100264 const struct lys_node *next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200265
Radek Krejci8bc87f62015-09-02 16:19:05 +0200266 if (!last) {
267 /* first call */
268
269 /* get know where to start */
270 if (parent) {
271 /* schema subtree */
272 next = last = parent->child;
273 } else {
274 /* top level data */
275 assert(module);
276 next = last = module->data;
277 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200278 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200279 /* continue after the last returned value */
280 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200281 }
282
283repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200284 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200285 if (options & LYS_GETNEXT_WITHGROUPING) {
286 return next;
287 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200288 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200289 }
290
Radek Krejcic4ccbd92016-01-07 13:13:33 +0100291 if (!next) {
Michal Vasko7c386e72015-10-07 15:13:33 +0200292 if (lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200293 /* no next element */
294 return NULL;
295 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200296 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200297 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200298 goto repeat;
299 }
300
301 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200302 case LYS_INPUT:
303 case LYS_OUTPUT:
304 if (options & LYS_GETNEXT_WITHINOUT) {
305 return next;
306 } else {
307 next = next->child;
308 goto repeat;
309 }
310 break;
311
Michal Vaskoa5835e92015-10-20 15:07:39 +0200312 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200313 if (options & LYS_GETNEXT_WITHCASE) {
314 return next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200315 } else {
316 next = next->child;
317 goto repeat;
Michal Vasko1dca6882015-10-22 14:29:42 +0200318 }
Michal Vaskob6eedf02015-10-22 16:07:03 +0200319 break;
320
Michal Vasko1dca6882015-10-22 14:29:42 +0200321 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200322 /* go into */
323 next = next->child;
324 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200325
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200326 case LYS_RPC:
327 case LYS_NOTIF:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200328 case LYS_CONTAINER:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200329 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200330 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200331 case LYS_LIST:
332 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200333 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200334
335 case LYS_CHOICE:
336 if (options & LYS_GETNEXT_WITHCHOICE) {
337 return next;
338 } else {
339 /* go into */
340 next = next->child;
341 goto repeat;
342 }
343 break;
344
Radek Krejci7f40ce32015-08-12 20:38:46 +0200345 default:
346 /* we should not be here */
347 return NULL;
348 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200349
350
351}
352
Michal Vasko1e62a092015-12-01 12:27:20 +0100353static const struct lys_node *
354check_mand_getnext(const struct lys_node *last, const struct lys_node *parent)
Radek Krejci8bc87f62015-09-02 16:19:05 +0200355{
Michal Vasko1e62a092015-12-01 12:27:20 +0100356 const struct lys_node *next;
357
Radek Krejci8bc87f62015-09-02 16:19:05 +0200358 next = lys_getnext(last, parent, NULL, LYS_GETNEXT_WITHCHOICE);
359
Radek Krejci4b6c2112015-10-06 12:48:34 +0200360repeat:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200361 if (next && next->nodetype == LYS_CONTAINER) {
362 if (((struct lys_node_container *)next)->presence) {
363 /* mandatory elements under the non-existing presence
364 * container are not mandatory - 7.6.5, rule 1 */
365 next = next->next;
366 } else {
367 /* go into */
368 next = next->child;
369 }
370 goto repeat;
371 }
372
373 return next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200374}
375
Michal Vasko1e62a092015-12-01 12:27:20 +0100376static const struct lys_node *
377check_mand_check(const struct lys_node *node, const struct lys_node *stop, const struct lyd_node *data)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200378{
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200379 struct lys_node *siter = NULL, *parent = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200380 struct lyd_node *diter = NULL;
Radek Krejcidc154432016-01-21 11:10:59 +0100381 struct ly_set *set = NULL;
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200382 unsigned int i;
Radek Krejci14a11a62015-08-17 17:27:38 +0200383 uint32_t minmax;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200384
385 if (node->flags & LYS_MAND_TRUE) {
386 switch (node->nodetype) {
387 case LYS_LEAF:
388 case LYS_ANYXML:
389 case LYS_CHOICE:
390 if (node->parent->nodetype == LYS_CASE) {
391 /* 7.6.5, rule 2 */
392 /* 7.9.4, rule 1 */
393 if (node->parent->parent->parent == data->schema) {
394 /* the only case the node's siblings can exist is that the
395 * data node passed originaly to ly_check_mandatory()
396 * had this choice as a child
397 */
398 /* try to find the node's siblings in data */
399 LY_TREE_FOR(data->child, diter) {
400 LY_TREE_FOR(node->parent->child, siter) {
401 if (siter == diter->schema) {
402 /* some sibling exists, rule applies */
403 break;
404 }
405 }
406 if (siter) {
407 break;
408 }
409 }
410 }
411 if (!siter) {
412 /* no sibling exists */
413 return NULL;
414 }
415 } else {
416 for(parent = node->parent; parent != stop; parent = parent->parent) {
417 if (parent->nodetype != LYS_CONTAINER) {
418 /* 7.6.5, rule 1, checking presence is not needed
419 * since it is done in check_mand_getnext()
420 */
Radek Krejcidc154432016-01-21 11:10:59 +0100421 ly_set_free(set);
Radek Krejci7f40ce32015-08-12 20:38:46 +0200422 return NULL;
423 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200424 /* add the parent to the list for searching in data tree */
425 if (!set) {
Radek Krejcidc154432016-01-21 11:10:59 +0100426 set = ly_set_new();
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200427 }
Radek Krejci592f45c2016-01-08 09:38:06 +0100428 /* ignore return - memory error is logged and we will
429 * check at least the rest of nodes we have */
Radek Krejcidc154432016-01-21 11:10:59 +0100430 (void) ly_set_add(set, parent);
Radek Krejci7f40ce32015-08-12 20:38:46 +0200431 }
432 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200433
434 /* search for instance */
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200435 if (set) {
436 for (i = 0; i < set->number; i++) {
437 LY_TREE_FOR(data->child, diter) {
Radek Krejcidc154432016-01-21 11:10:59 +0100438 if (diter->schema == set->sset[i]) {
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200439 break;
440 }
441 }
442 if (!diter) {
443 /* instance not found */
Radek Krejcidc154432016-01-21 11:10:59 +0100444 node = set->sset[i];
445 ly_set_free(set);
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200446 return node;
447 }
448 data = diter;
449 }
Radek Krejcidc154432016-01-21 11:10:59 +0100450 ly_set_free(set);
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200451 }
452
Radek Krejci14a11a62015-08-17 17:27:38 +0200453 LY_TREE_FOR(data->child, diter) {
454 if (diter->schema == node) {
455 return NULL;
456 }
457 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200458
Radek Krejci14a11a62015-08-17 17:27:38 +0200459 /* instance not found */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200460 /* 7.6.5, rule 3 (or 2) */
461 /* 7.9.4, rule 2 */
462 return node;
463 default:
464 /* error */
465 break;
466 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200467 } else if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
468 /* search for number of instances */
469 minmax = 0;
470 LY_TREE_FOR(data->child, diter) {
471 if (diter->schema == node) {
472 minmax++;
473 }
474 }
475
476 /* check the specified constraints */
477 if (node->nodetype == LYS_LIST) {
478 if (((struct lys_node_list *)node)->min && minmax < ((struct lys_node_list *)node)->min) {
479 return node;
480 }
481
482 if (((struct lys_node_list *)node)->max && minmax > ((struct lys_node_list *)node)->max) {
483 return node;
484 }
485 } else if (node->nodetype == LYS_LEAFLIST) {
486 if (((struct lys_node_leaflist *)node)->min && minmax < ((struct lys_node_leaflist *)node)->min) {
487 return node;
488 }
489
490 if (((struct lys_node_leaflist *)node)->max && minmax > ((struct lys_node_leaflist *)node)->max) {
491 return node;
492 }
493 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200494 }
495
496 return NULL;
497}
498
Michal Vasko1e62a092015-12-01 12:27:20 +0100499const struct lys_node *
500ly_check_mandatory(const struct lyd_node *data)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200501{
Michal Vasko1e62a092015-12-01 12:27:20 +0100502 const struct lys_node *siter, *saux, *saux2, *result, *parent = NULL, *parent2;
503 const struct lyd_node *diter;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200504 int found;
505
506 siter = data->schema->child;
507
508repeat:
509 while (siter) {
Radek Krejci074bf852015-08-19 14:22:16 +0200510 if (lys_is_disabled(siter, 2)) {
511 siter = siter->next;
512 continue;
513 }
514
Radek Krejci7f40ce32015-08-12 20:38:46 +0200515 switch (siter->nodetype) {
516 case LYS_CONTAINER:
517 case LYS_LEAF:
518 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200519 case LYS_LIST:
520 case LYS_LEAFLIST:
521 /* check if there is some mandatory node; first test the siter itself ... */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200522 result = check_mand_check(siter, siter->parent, data);
523 if (result) {
524 return result;
525 }
526 /* ... and then the subtree */
Radek Krejci14a11a62015-08-17 17:27:38 +0200527 if (parent && siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
528 saux = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200529 while ((saux = check_mand_getnext(saux, siter))) {
530 result = check_mand_check(saux, siter, data);
531 if (result) {
532 return result;
533 }
534 }
535 }
536 siter = siter->next;
537 break;
538 case LYS_CHOICE:
Radek Krejci14a11a62015-08-17 17:27:38 +0200539 /* search for instance */
540 saux = siter;
541 siter = siter->child;
542 found = 0;
543 parent2 = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200544repeat_choice:
Radek Krejci074bf852015-08-19 14:22:16 +0200545 while (siter) {
546 if (lys_is_disabled(siter, 2)) {
547 siter = siter->next;
548 continue;
549 }
550
Radek Krejci14a11a62015-08-17 17:27:38 +0200551 switch (siter->nodetype) {
552 case LYS_CONTAINER:
553 case LYS_LEAF:
554 case LYS_LEAFLIST:
555 case LYS_LIST:
556 case LYS_ANYXML:
557 LY_TREE_FOR(data->child, diter) {
558 if (diter->schema == siter) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200559 break;
560 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200561 }
562 if (diter) {
563 /* got instance */
564 /* check presence of mandatory siblings */
Radek Krejci65d0a652015-08-27 13:09:42 +0200565 if (parent2 && parent2->nodetype == LYS_CASE) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200566 saux2 = NULL;
Radek Krejci37bda002015-08-27 11:23:56 +0200567 while ((saux2 = check_mand_getnext(saux2, parent2))) {
568 result = check_mand_check(saux2, parent2, data);
Radek Krejci14a11a62015-08-17 17:27:38 +0200569 if (result) {
570 return result;
571 }
572 }
573 }
574 siter = parent2 = NULL;
575 found = 1;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200576 break;
577 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200578 siter = siter->next;
579 break;
580 case LYS_CASE:
581 case LYS_CHOICE:
582 case LYS_USES:
583 /* go into */
Radek Krejci37bda002015-08-27 11:23:56 +0200584 if (!parent2) {
585 parent2 = siter;
586 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200587 siter = siter->child;
588 break;
589 case LYS_AUGMENT:
590 case LYS_GROUPING:
591 /* skip */
592 siter = siter->next;
593 break;
594 default:
595 /* error */
596 break;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200597 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200598 }
599
Radek Krejci14a11a62015-08-17 17:27:38 +0200600 if (parent2) {
601 siter = parent2->next;
602 if (parent2->parent == saux) {
603 parent2 = NULL;
604 } else {
605 parent2 = parent2->parent;
606 }
607 goto repeat_choice;
608 }
609
Radek Krejci074bf852015-08-19 14:22:16 +0200610 if (!found && (saux->flags & LYS_MAND_TRUE)) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200611 return saux;
612 }
613
614 /* go to next */
615 siter = saux->next;
616
Radek Krejci7f40ce32015-08-12 20:38:46 +0200617 break;
618 case LYS_USES:
619 case LYS_CASE:
620 /* go into */
621 parent = siter;
622 siter = siter->child;
623 break;
624 default:
625 /* can ignore, go to next */
626 siter = siter->next;
627 break;
628 }
629 }
630
631 if (parent) {
632 siter = parent->next;
633 if (parent->parent == data->schema) {
634 parent = NULL;
635 } else {
636 parent = parent->parent;
637 }
638 goto repeat;
639 }
640
641 return NULL;
642}
643
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200644void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200645lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200646{
Radek Krejci76512572015-08-04 09:47:08 +0200647 struct lys_node *parent, *first;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200648
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200649 if (!node) {
650 return;
651 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200652
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200653 /* unlink from data model if necessary */
654 if (node->module) {
655 if (node->module->data == node) {
656 node->module->data = node->next;
657 }
658 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200659
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200660 /* store pointers to important nodes */
661 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200662 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200663 /* handle augments - first, unlink it from the augment parent ... */
664 if (parent->child == node) {
665 parent->child = node->next;
666 }
667 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200668 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200669 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200670
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200671 /* unlink from parent */
672 if (parent) {
673 if (parent->child == node) {
674 parent->child = node->next;
675 }
676 node->parent = NULL;
677 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200678
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200679 /* unlink from siblings */
680 if (node->prev == node) {
681 /* there are no more siblings */
682 return;
683 }
684 if (node->next) {
685 node->next->prev = node->prev;
686 } else {
687 /* unlinking the last element */
688 if (parent) {
689 first = parent->child;
690 } else {
691 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200692 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200693 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200694 }
695 }
696 first->prev = node->prev;
697 }
698 if (node->prev->next) {
699 node->prev->next = node->next;
700 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200701
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200702 /* clean up the unlinked element */
703 node->next = NULL;
704 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200705}
706
Michal Vasko563ef092015-09-04 13:17:23 +0200707struct lys_node_grp *
708lys_find_grouping_up(const char *name, struct lys_node *start, int in_submodules)
709{
710 struct lys_node *par_iter, *iter, *stop;
711 int i;
712
713 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200714 /* top-level augment, look into module (uses augment is handled correctly below) */
715 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
716 par_iter = par_iter->parent->module->data;
717 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200718 break;
719 }
720 }
721
Michal Vasko6f929da2015-10-02 16:23:25 +0200722 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200723 continue;
724 }
725
726 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
727 if (!stop) {
728 stop = par_iter;
729 } else if (iter == stop) {
730 break;
731 }
732 if (iter->nodetype != LYS_GROUPING) {
733 continue;
734 }
735
Radek Krejcif8426a72015-10-31 23:14:03 +0100736 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200737 return (struct lys_node_grp *)iter;
738 }
739 }
740 }
741
742 if (in_submodules) {
743 for (i = 0; i < start->module->inc_size; ++i) {
744 for (iter = start->module->inc[i].submodule->data; iter; iter = iter->next) {
745 if (iter->nodetype != LYS_GROUPING) {
746 continue;
747 }
748
Radek Krejcif8426a72015-10-31 23:14:03 +0100749 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200750 return (struct lys_node_grp *)iter;
751 }
752 }
753 }
754 }
755
756 return NULL;
757}
758
Radek Krejci10c760e2015-08-14 14:45:43 +0200759/*
760 * get next grouping in the root's subtree, in the
761 * first call, tha last is NULL
762 */
763static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200764lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200765{
Radek Krejci10c760e2015-08-14 14:45:43 +0200766 struct lys_node *last = (struct lys_node *)lastgrp;
767 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200768
Radek Krejci10c760e2015-08-14 14:45:43 +0200769 assert(root);
770
771 if (!last) {
772 last = root;
773 }
774
775 while (1) {
776 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
777 next = last->child;
778 } else {
779 next = NULL;
780 }
781 if (!next) {
782 if (last == root) {
783 /* we are done */
784 return NULL;
785 }
786
787 /* no children, go to siblings */
788 next = last->next;
789 }
790 while (!next) {
791 /* go back through parents */
792 if (last->parent == root) {
793 /* we are done */
794 return NULL;
795 }
796 last = last->parent;
797 next = last->next;
798 }
799
800 if (next->nodetype == LYS_GROUPING) {
801 return (struct lys_node_grp *)next;
802 }
803
804 last = next;
805 }
806}
807
Michal Vasko0d343d12015-08-24 14:57:36 +0200808/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200809int
Radek Krejci07911992015-08-14 15:13:31 +0200810lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
811{
Michal Vasko563ef092015-09-04 13:17:23 +0200812 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200813 struct lys_node_grp *grp;
814 int down;
815
816 assert(node);
817
818 if (!parent) {
819 assert(module);
820 } else {
821 module = parent->module;
822 }
823
824 switch (node->nodetype) {
825 case LYS_GROUPING:
826 /* 6.2.1, rule 6 */
827 if (parent) {
828 if (parent->child) {
829 down = 1;
830 start = parent->child;
831 } else {
832 down = 0;
833 start = parent;
834 }
835 } else {
836 down = 1;
837 start = module->data;
838 }
839 /* go up */
Michal Vasko563ef092015-09-04 13:17:23 +0200840 if (lys_find_grouping_up(node->name, start, 0)) {
841 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
842 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200843 }
844 /* go down, because grouping can be defined after e.g. container in which is collision */
845 if (down) {
846 for (iter = start, stop = NULL; iter; iter = iter->prev) {
847 if (!stop) {
848 stop = start;
849 } else if (iter == stop) {
850 break;
851 }
852 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
853 continue;
854 }
855
856 grp = NULL;
857 while ((grp = lys_get_next_grouping(grp, iter))) {
858 if (node->name == grp->name) {
859 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
860 return EXIT_FAILURE;
861 }
862 }
863 }
864 }
865 break;
866 case LYS_LEAF:
867 case LYS_LEAFLIST:
868 case LYS_LIST:
869 case LYS_CONTAINER:
870 case LYS_CHOICE:
871 case LYS_ANYXML:
872 /* 6.2.1, rule 7 */
873 if (parent) {
874 iter = parent;
875 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE))) {
876 iter = iter->parent;
877 }
878 if (!iter) {
879 stop = NULL;
880 iter = module->data;
881 } else {
882 stop = iter;
883 iter = iter->child;
884 }
885 } else {
886 stop = NULL;
887 iter = module->data;
888 }
889 while (iter) {
890 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
891 iter = iter->child;
892 continue;
893 }
894
895 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
896 if (iter->module == node->module && iter->name == node->name) {
897 LOGVAL(LYE_SPEC, 0, "Duplicated child identifier \"%s\" in \"%s\".", node->name,
898 stop ? stop->name : "(sub)module");
899 return EXIT_FAILURE;
900 }
901 }
902
903 /* special case for choice - we must check the choice's name as
904 * well as the names of nodes under the choice
905 */
906 if (iter->nodetype == LYS_CHOICE) {
907 iter = iter->child;
908 continue;
909 }
910
911 /* go to siblings */
912 if (!iter->next) {
913 /* no sibling, go to parent's sibling */
914 do {
915 iter = iter->parent;
916 if (iter && iter->next) {
917 break;
918 }
919 } while (iter != stop);
920
921 if (iter == stop) {
922 break;
923 }
924 }
925 iter = iter->next;
926 }
927 break;
928 case LYS_CASE:
929 /* 6.2.1, rule 8 */
930 LY_TREE_FOR(parent->child, iter) {
931 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
932 continue;
933 }
934
935 if (iter->module == node->module && iter->name == node->name) {
936 LOGVAL(LYE_DUPID, 0, "case", node->name);
937 return EXIT_FAILURE;
938 }
939 }
940 break;
941 default:
942 /* no check needed */
943 break;
944 }
945
946 return EXIT_SUCCESS;
947}
948
Michal Vasko0d343d12015-08-24 14:57:36 +0200949/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200950int
Radek Krejci10c760e2015-08-14 14:45:43 +0200951lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
952{
Radek Krejci92720552015-10-05 15:28:27 +0200953 struct lys_node *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200954 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200955
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200956 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200957
Radek Krejci10c760e2015-08-14 14:45:43 +0200958 if (parent) {
959 type = parent->nodetype;
960 module = parent->module;
961 } else {
962 assert(module);
963 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200964 }
965
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200966 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200967 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200968 case LYS_CONTAINER:
969 case LYS_LIST:
970 case LYS_GROUPING:
971 case LYS_USES:
972 case LYS_INPUT:
973 case LYS_OUTPUT:
974 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200975 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200976 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
977 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200978 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200979 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
980 return EXIT_FAILURE;
981 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200982
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200983 break;
Radek Krejci76512572015-08-04 09:47:08 +0200984 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200985 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200986 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200987 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"choice\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200988 strnodetype(child->nodetype), parent->name);
989 return EXIT_FAILURE;
990 }
991 break;
Radek Krejci76512572015-08-04 09:47:08 +0200992 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200993 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200994 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200995 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"case\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200996 strnodetype(child->nodetype), parent->name);
997 return EXIT_FAILURE;
998 }
999 break;
Radek Krejci76512572015-08-04 09:47:08 +02001000 case LYS_RPC:
1001 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001002 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"rpc\" %s.",
Michal Vasko38d01f72015-06-15 09:41:06 +02001003 strnodetype(child->nodetype), parent->name);
1004 return EXIT_FAILURE;
1005 }
1006 break;
Radek Krejci76512572015-08-04 09:47:08 +02001007 case LYS_LEAF:
1008 case LYS_LEAFLIST:
1009 case LYS_ANYXML:
Radek Krejci10c760e2015-08-14 14:45:43 +02001010 LOGVAL(LYE_SPEC, 0, "The \"%s\" statement (%s) cannot have any data substatement.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001011 strnodetype(parent->nodetype), parent->name);
1012 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +02001013 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001014 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +02001015 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
1016 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001017 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001018 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
1019 return EXIT_FAILURE;
1020 }
Michal Vasko591e0b22015-08-13 13:53:43 +02001021 break;
1022 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +02001023 /* top level */
1024 if (!(child->nodetype &
1025 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
1026 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci2c0ca272015-08-14 15:31:01 +02001027 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in (sub)module \"%s\"",
1028 strnodetype(child->nodetype), module->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02001029 return EXIT_FAILURE;
1030 }
1031
1032 break;;
1033 }
1034
1035 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +02001036 if (lys_check_id(child, parent, module)) {
1037 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001038 }
Radek Krejcib7155b52015-06-10 17:03:01 +02001039
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001040 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001041 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001042 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001043
Radek Krejci10c760e2015-08-14 14:45:43 +02001044 if (!parent) {
Radek Krejci92720552015-10-05 15:28:27 +02001045 if (module->data) {
1046 module->data->prev->next = child;
1047 child->prev = module->data->prev;
1048 module->data->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +02001049 } else {
Radek Krejci92720552015-10-05 15:28:27 +02001050 module->data = child;
Radek Krejci10c760e2015-08-14 14:45:43 +02001051 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001052 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +02001053 if (!parent->child) {
1054 /* the only/first child of the parent */
1055 parent->child = child;
1056 child->parent = parent;
1057 iter = child;
1058 } else {
1059 /* add a new child at the end of parent's child list */
1060 iter = parent->child->prev;
1061 iter->next = child;
1062 child->prev = iter;
1063 }
1064 while (iter->next) {
1065 iter = iter->next;
1066 iter->parent = parent;
1067 }
1068 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001069 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001070
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001071 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001072}
1073
Michal Vasko1e62a092015-12-01 12:27:20 +01001074API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +01001075lys_parse_data(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001076{
Michal Vaskof02e3742015-08-05 16:27:02 +02001077 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +02001078 struct lys_module *mod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001079
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001080 if (!ctx || !data) {
1081 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1082 return NULL;
1083 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001084
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001085 unres = calloc(1, sizeof *unres);
Michal Vasko253035f2015-12-17 16:58:13 +01001086 if (!unres) {
1087 LOGMEM;
1088 return NULL;
1089 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001090
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001091 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001092 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001093 mod = yin_read_module(ctx, data, 1, unres);
1094 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001095 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001096 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001097 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001098 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001099 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001100
Michal Vasko0bd29d12015-08-19 11:45:49 +02001101 if (mod && unres->count && resolve_unres_schema(mod, unres)) {
Radek Krejcif7101ce2015-12-15 11:39:56 +01001102 unres_schema_free(ctx, unres);
Michal Vasko13b15832015-08-19 11:04:48 +02001103 lys_free(mod, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001104 mod = NULL;
Radek Krejcif7101ce2015-12-15 11:39:56 +01001105 } else {
1106 unres_schema_free(ctx, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001107 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001108
1109 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001110}
1111
Radek Krejcib8048692015-08-05 13:36:34 +02001112struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001113lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02001114{
Michal Vaskof02e3742015-08-05 16:27:02 +02001115 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +02001116 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001117
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001118 assert(module);
1119 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001120
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001121 unres = calloc(1, sizeof *unres);
Michal Vasko253035f2015-12-17 16:58:13 +01001122 if (!unres) {
1123 LOGMEM;
1124 return NULL;
1125 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001126
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001127 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001128 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001129 submod = yin_read_submodule(module, data, implement, unres);
1130 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001131 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001132 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001133 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001134 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001135 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001136
Michal Vasko0bd29d12015-08-19 11:45:49 +02001137 if (submod && unres->count && resolve_unres_schema((struct lys_module *)submod, unres)) {
Radek Krejcif7101ce2015-12-15 11:39:56 +01001138 unres_schema_free(module->ctx, unres);
Michal Vasko13b15832015-08-19 11:04:48 +02001139 lys_submodule_free(submod, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001140 submod = NULL;
Radek Krejcif7101ce2015-12-15 11:39:56 +01001141 } else {
1142 unres_schema_free(module->ctx, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001143 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001144
1145 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001146}
1147
Michal Vasko1e62a092015-12-01 12:27:20 +01001148API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +01001149lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1150{
1151 int fd;
1152 const struct lys_module *ret;
1153
1154 if (!ctx || !path) {
1155 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1156 return NULL;
1157 }
1158
1159 fd = open(path, O_RDONLY);
1160 if (fd == -1) {
1161 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
1162 return NULL;
1163 }
1164
1165 ret = lys_parse_fd(ctx, fd, format);
1166 close(fd);
1167 return ret;
1168}
1169
1170API const struct lys_module *
1171lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001172{
Michal Vasko1e62a092015-12-01 12:27:20 +01001173 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +02001174 struct stat sb;
1175 char *addr;
1176
1177 if (!ctx || fd < 0) {
1178 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1179 return NULL;
1180 }
1181
Radek Krejci10a833c2015-12-16 15:28:37 +01001182 if (fstat(fd, &sb) == -1) {
1183 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
1184 return NULL;
1185 }
Radek Krejci3006be02015-12-17 11:24:33 +01001186 addr = mmap(NULL, sb.st_size + 1, PROT_READ, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001187 if (addr == MAP_FAILED) {
Michal Vasko662610a2015-12-07 11:25:45 +01001188 LOGERR(LY_EMEM, "Map file into memory failed (%s()).",__func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001189 return NULL;
1190 }
Michal Vasko662610a2015-12-07 11:25:45 +01001191 module = lys_parse_data(ctx, addr, format);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001192 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001194 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001195}
1196
Radek Krejcib8048692015-08-05 13:36:34 +02001197struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001198lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02001199{
Radek Krejcib8048692015-08-05 13:36:34 +02001200 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001201 struct stat sb;
1202 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001203
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001204 assert(module);
1205 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001206
Radek Krejci10a833c2015-12-16 15:28:37 +01001207 if (fstat(fd, &sb) == -1) {
1208 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
1209 return NULL;
1210 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001211 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001212 if (addr == MAP_FAILED) {
1213 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
1214 return NULL;
1215 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001216 submodule = lys_submodule_parse(module, addr, format, implement);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001217 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +02001218
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001219 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02001220
1221}
1222
Radek Krejci1d82ef62015-08-07 14:44:40 +02001223static struct lys_restr *
1224lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001225{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001226 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001227 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001228
Radek Krejci3733a802015-06-19 13:43:21 +02001229 if (!size) {
1230 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001231 }
Radek Krejci3733a802015-06-19 13:43:21 +02001232
1233 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001234 if (!result) {
1235 return NULL;
1236 }
Radek Krejci3733a802015-06-19 13:43:21 +02001237 for (i = 0; i < size; i++) {
1238 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1239 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1240 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1241 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1242 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1243 }
1244
1245 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001246}
1247
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001248void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001249lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001250{
1251 assert(ctx);
1252 if (!restr) {
1253 return;
1254 }
1255
1256 lydict_remove(ctx, restr->expr);
1257 lydict_remove(ctx, restr->dsc);
1258 lydict_remove(ctx, restr->ref);
1259 lydict_remove(ctx, restr->eapptag);
1260 lydict_remove(ctx, restr->emsg);
1261}
1262
Michal Vaskob84f88a2015-09-24 13:16:10 +02001263static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001264lys_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 +02001265 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001266{
1267 int i;
1268
Michal Vasko1dca6882015-10-22 14:29:42 +02001269 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001270 new->base = old->base;
1271 new->der = old->der;
1272
Michal Vasko0bd29d12015-08-19 11:45:49 +02001273 i = unres_schema_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001274 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001275 /* HACK (serious one) for unres */
1276 /* nothing else we can do but duplicate it immediately */
1277 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
Michal Vaskob84f88a2015-09-24 13:16:10 +02001278 /* all these unres additions can fail even though they did not before */
Michal Vasko88c29542015-11-27 14:57:53 +01001279 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_DER, parent, 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001280 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001281 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001282 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001283 }
1284
Radek Krejci3733a802015-06-19 13:43:21 +02001285 switch (new->base) {
1286 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +02001287 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001288 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001289 }
Radek Krejci3733a802015-06-19 13:43:21 +02001290 break;
1291
1292 case LY_TYPE_BITS:
1293 new->info.bits.count = old->info.bits.count;
1294 if (new->info.bits.count) {
1295 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +01001296 if (!new->info.bits.bit) {
1297 LOGMEM;
1298 return -1;
1299 }
Radek Krejci3733a802015-06-19 13:43:21 +02001300 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001301 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1302 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1303 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001304 new->info.bits.bit[i].status = old->info.bits.bit[i].status;
1305 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1306 }
1307 }
1308 break;
1309
Radek Krejcif9401c32015-06-26 16:47:36 +02001310 case LY_TYPE_DEC64:
1311 new->info.dec64.dig = old->info.dec64.dig;
1312 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001313 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +02001314 }
1315 break;
1316
Radek Krejci3733a802015-06-19 13:43:21 +02001317 case LY_TYPE_ENUM:
1318 new->info.enums.count = old->info.enums.count;
1319 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001320 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +01001321 if (!new->info.enums.enm) {
1322 LOGMEM;
1323 return -1;
1324 }
Radek Krejci3733a802015-06-19 13:43:21 +02001325 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001326 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1327 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1328 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1329 new->info.enums.enm[i].status = old->info.enums.enm[i].status;
1330 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +02001331 }
1332 }
1333 break;
1334
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001335 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001336 if (old->info.ident.ref) {
1337 new->info.ident.ref = old->info.ident.ref;
1338 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001339 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001340 assert(i != -1);
Michal Vasko88c29542015-11-27 14:57:53 +01001341 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i], 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001342 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001343 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001344 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001345 break;
1346
Radek Krejciaf351422015-06-19 14:49:38 +02001347 case LY_TYPE_INST:
1348 new->info.inst.req = old->info.inst.req;
1349 break;
1350
Radek Krejcif2860132015-06-20 12:37:20 +02001351 case LY_TYPE_INT8:
1352 case LY_TYPE_INT16:
1353 case LY_TYPE_INT32:
1354 case LY_TYPE_INT64:
1355 case LY_TYPE_UINT8:
1356 case LY_TYPE_UINT16:
1357 case LY_TYPE_UINT32:
1358 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +02001359 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001360 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001361 }
Radek Krejcif2860132015-06-20 12:37:20 +02001362 break;
1363
Radek Krejcidc4c1412015-06-19 15:39:54 +02001364 case LY_TYPE_LEAFREF:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001365 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko88c29542015-11-27 14:57:53 +01001366 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001367 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001368 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001369 break;
1370
Radek Krejci3733a802015-06-19 13:43:21 +02001371 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +02001372 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001373 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001374 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001375 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 +02001376 break;
1377
Radek Krejcie4c366b2015-07-02 10:11:31 +02001378 case LY_TYPE_UNION:
1379 new->info.uni.count = old->info.uni.count;
1380 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001381 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +01001382 if (!new->info.uni.types) {
1383 LOGMEM;
1384 return -1;
1385 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001386 for (i = 0; i < new->info.uni.count; i++) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001387 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres)) {
1388 return -1;
1389 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001390 }
1391 }
1392 break;
1393
Radek Krejci3733a802015-06-19 13:43:21 +02001394 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001395 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001396 break;
1397 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001398
1399 return EXIT_SUCCESS;
Radek Krejci3733a802015-06-19 13:43:21 +02001400}
1401
1402void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001403lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001404{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001405 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001406
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001407 assert(ctx);
1408 if (!type) {
1409 return;
1410 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001411
Michal Vasko1dca6882015-10-22 14:29:42 +02001412 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001413
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001414 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001415 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001416 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001417 free(type->info.binary.length);
1418 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001419 case LY_TYPE_BITS:
1420 for (i = 0; i < type->info.bits.count; i++) {
1421 lydict_remove(ctx, type->info.bits.bit[i].name);
1422 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1423 lydict_remove(ctx, type->info.bits.bit[i].ref);
1424 }
1425 free(type->info.bits.bit);
1426 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001427
1428 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001429 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001430 free(type->info.dec64.range);
1431 break;
1432
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001433 case LY_TYPE_ENUM:
1434 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001435 lydict_remove(ctx, type->info.enums.enm[i].name);
1436 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1437 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001438 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001439 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001440 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001441
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001442 case LY_TYPE_INT8:
1443 case LY_TYPE_INT16:
1444 case LY_TYPE_INT32:
1445 case LY_TYPE_INT64:
1446 case LY_TYPE_UINT8:
1447 case LY_TYPE_UINT16:
1448 case LY_TYPE_UINT32:
1449 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001450 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001451 free(type->info.num.range);
1452 break;
1453
Radek Krejcidc4c1412015-06-19 15:39:54 +02001454 case LY_TYPE_LEAFREF:
1455 lydict_remove(ctx, type->info.lref.path);
1456 break;
1457
Radek Krejci3733a802015-06-19 13:43:21 +02001458 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001459 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001460 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001461 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001462 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001463 }
1464 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001465 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001466
Radek Krejcie4c366b2015-07-02 10:11:31 +02001467 case LY_TYPE_UNION:
1468 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001469 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001470 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001471 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001472 break;
1473
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001474 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001475 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001476 break;
1477 }
Radek Krejci5a065542015-05-22 15:02:07 +02001478}
1479
Radek Krejci1d82ef62015-08-07 14:44:40 +02001480static void
1481lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001482{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001483 assert(ctx);
1484 if (!tpdf) {
1485 return;
1486 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001487
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001488 lydict_remove(ctx, tpdf->name);
1489 lydict_remove(ctx, tpdf->dsc);
1490 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001491
Radek Krejci1d82ef62015-08-07 14:44:40 +02001492 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001493
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001494 lydict_remove(ctx, tpdf->units);
1495 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001496}
1497
Michal Vaskob84f88a2015-09-24 13:16:10 +02001498static struct lys_tpdf *
1499lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1500{
1501 struct lys_tpdf *result;
1502 int i, j;
1503
1504 if (!size) {
1505 return NULL;
1506 }
1507
1508 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001509 if (!result) {
1510 LOGMEM;
1511 return NULL;
1512 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001513 for (i = 0; i < size; i++) {
1514 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1515 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1516 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1517 result[i].flags = old[i].flags;
1518 result[i].module = old[i].module;
1519
1520 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres)) {
1521 for (j = 0; j <= i; ++j) {
1522 lys_tpdf_free(mod->ctx, &result[j]);
1523 }
1524 free(result);
1525 return NULL;
1526 }
1527
1528 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1529 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1530 }
1531
1532 return result;
1533}
1534
Radek Krejci1d82ef62015-08-07 14:44:40 +02001535static struct lys_when *
1536lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001537{
Radek Krejci76512572015-08-04 09:47:08 +02001538 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001539
1540 if (!old) {
1541 return NULL;
1542 }
1543
1544 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001545 if (!new) {
1546 LOGMEM;
1547 return NULL;
1548 }
Radek Krejci00768f42015-06-18 17:04:04 +02001549 new->cond = lydict_insert(ctx, old->cond, 0);
1550 new->dsc = lydict_insert(ctx, old->dsc, 0);
1551 new->ref = lydict_insert(ctx, old->ref, 0);
1552
1553 return new;
1554}
1555
Michal Vasko0308dd62015-10-07 09:14:40 +02001556void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001557lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001558{
1559 if (!w) {
1560 return;
1561 }
1562
1563 lydict_remove(ctx, w->cond);
1564 lydict_remove(ctx, w->dsc);
1565 lydict_remove(ctx, w->ref);
1566
1567 free(w);
1568}
1569
Radek Krejcib7f5e412015-08-13 10:15:51 +02001570static void
1571lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment aug)
1572{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001573 struct lys_node *next, *sub;
1574
1575 /* children from a resolved uses */
1576 LY_TREE_FOR_SAFE(aug.child, next, sub) {
1577 lys_node_free(sub);
1578 }
1579
Radek Krejcib7f5e412015-08-13 10:15:51 +02001580 lydict_remove(ctx, aug.target_name);
1581 lydict_remove(ctx, aug.dsc);
1582 lydict_remove(ctx, aug.ref);
1583
1584 free(aug.features);
1585
1586 lys_when_free(ctx, aug.when);
1587
Michal Vasko7d356a52015-08-19 15:06:31 +02001588 /* Do not free the children, they were appended somewhere and their
1589 * new parent will take care of them.
1590 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001591}
1592
Radek Krejci76512572015-08-04 09:47:08 +02001593static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001594lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001595{
Radek Krejci76512572015-08-04 09:47:08 +02001596 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001597 struct lys_node *old_child, *new_child;
1598 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001599
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001600 if (!size) {
1601 return NULL;
1602 }
Radek Krejci106efc02015-06-10 14:36:27 +02001603
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001604 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001605 if (!new) {
1606 LOGMEM;
1607 return NULL;
1608 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001609 for (i = 0; i < size; i++) {
1610 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1611 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1612 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1613 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001614 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001615 new[i].nodetype = old[i].nodetype;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001616 /* this must succeed, it was already resolved once */
Michal Vasko1e62a092015-12-01 12:27:20 +01001617 if (resolve_schema_nodeid(new[i].target_name, parent->child, new[i].module, LYS_AUGMENT,
1618 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001619 LOGINT;
1620 free(new);
1621 return NULL;
1622 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001623 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001624
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001625 /* Correct the augment nodes.
1626 * This function can only be called from lys_node_dup() with uses
1627 * being the node duplicated, so we must have a case of grouping
1628 * with a uses with augments. The augmented nodes have already been
1629 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001630 * (it was set to their actual data parent, not an augment), and
1631 * the new augment does not have child pointer to its augment nodes,
1632 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001633 */
1634 LY_TREE_FOR(new[i].target->child, new_child) {
1635 if (new_child->name == old[i].child->name) {
1636 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001637 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001638 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001639 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001640 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001641 LY_TREE_FOR(old[i].child, old_child) {
1642 /* all augment nodes were connected as siblings, there can be no more after this */
1643 if (old_child->parent != (struct lys_node *)&old[i]) {
1644 break;
1645 }
1646
1647 assert(old_child->name == new_child->name);
1648
1649 new_child->parent = (struct lys_node *)&new[i];
1650 new_child = new_child->next;
1651 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001652 }
Radek Krejci106efc02015-06-10 14:36:27 +02001653
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001654 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001655}
1656
Radek Krejci76512572015-08-04 09:47:08 +02001657static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001658lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001659{
Radek Krejci76512572015-08-04 09:47:08 +02001660 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001661 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001662
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001663 if (!size) {
1664 return NULL;
1665 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001666
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001667 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001668 if (!result) {
1669 LOGMEM;
1670 return NULL;
1671 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001672 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001673 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001674 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1675 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001676 result[i].flags = old[i].flags;
1677 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001678
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001679 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001680 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001681
Radek Krejci76512572015-08-04 09:47:08 +02001682 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001683 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001684 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001685 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001686 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001687 result[i].mod.list = old[i].mod.list;
1688 }
1689 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001690
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001691 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001692}
1693
Radek Krejci1d82ef62015-08-07 14:44:40 +02001694static void
1695lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001696{
Radek Krejcia52656e2015-08-05 13:41:50 +02001697 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001698
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001699 assert(ctx);
1700 if (!ident) {
1701 return;
1702 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001703
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001704 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001705 * if caller free only a single data model which is used (its identity is
1706 * reference from identity in another module), this silly freeing can lead
1707 * to segmentation fault. But without noting if the module is used by some
1708 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001709 *
1710 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001711 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001712 */
1713 while (ident->der) {
1714 der = ident->der;
1715 ident->der = der->next;
1716 free(der);
1717 }
Radek Krejci6793db02015-05-22 17:49:54 +02001718
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001719 lydict_remove(ctx, ident->name);
1720 lydict_remove(ctx, ident->dsc);
1721 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001722
1723}
1724
Radek Krejci1d82ef62015-08-07 14:44:40 +02001725static void
1726lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001727{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001728 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001729
Radek Krejcid12f57b2015-08-06 10:43:39 +02001730 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001731 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001732 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001733 }
1734 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001735}
1736
Radek Krejci1d82ef62015-08-07 14:44:40 +02001737static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001738lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1739{
1740 int i;
1741
1742 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1743 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001744 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001745 }
1746 free(io->tpdf);
1747}
1748
Radek Krejci1d82ef62015-08-07 14:44:40 +02001749static void
1750lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001751{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001752 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001753
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001754 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001755 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001756 }
1757 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001758
Radek Krejci1d82ef62015-08-07 14:44:40 +02001759 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001760}
1761
Radek Krejci1d82ef62015-08-07 14:44:40 +02001762static void
1763lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001764{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001765 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001766
Radek Krejci46c4cd72016-01-21 15:13:52 +01001767 if (leaf->child) {
1768 /* leafref backlinks */
1769 ly_set_free((struct ly_set *)leaf->child);
1770 }
1771
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001772 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001773 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001774 }
1775 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001776
Radek Krejci1d82ef62015-08-07 14:44:40 +02001777 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001778
Radek Krejci1d82ef62015-08-07 14:44:40 +02001779 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001780 lydict_remove(ctx, leaf->units);
1781 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001782}
1783
Radek Krejci1d82ef62015-08-07 14:44:40 +02001784static void
1785lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001786{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001787 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001788
Radek Krejci46c4cd72016-01-21 15:13:52 +01001789 if (llist->child) {
1790 /* leafref backlinks */
1791 ly_set_free((struct ly_set *)llist->child);
1792 }
1793
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001794 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001795 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001796 }
1797 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001798
Radek Krejci1d82ef62015-08-07 14:44:40 +02001799 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001800
Radek Krejci1d82ef62015-08-07 14:44:40 +02001801 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001802 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001803}
1804
Radek Krejci1d82ef62015-08-07 14:44:40 +02001805static void
1806lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001807{
Radek Krejci581ce772015-11-10 17:22:40 +01001808 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001809
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001810 /* handle only specific parts for LY_NODE_LIST */
1811 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001812 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001813 }
1814 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001815
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001816 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001817 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001818 }
1819 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001820
Radek Krejci1d82ef62015-08-07 14:44:40 +02001821 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001822
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001823 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001824 for (j = 0; j > list->unique[i].expr_size; j++) {
1825 lydict_remove(ctx, list->unique[i].expr[j]);
1826 }
1827 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001828 }
1829 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001830
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001831 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001832}
1833
Radek Krejci1d82ef62015-08-07 14:44:40 +02001834static void
1835lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001836{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001837 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001838
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001839 /* handle only specific parts for LY_NODE_CONTAINER */
1840 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001841
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001842 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001843 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001844 }
1845 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001846
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001847 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001848 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001849 }
1850 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001851
Radek Krejci1d82ef62015-08-07 14:44:40 +02001852 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001853}
1854
Radek Krejci1d82ef62015-08-07 14:44:40 +02001855static void
1856lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001857{
1858 lydict_remove(ctx, f->name);
1859 lydict_remove(ctx, f->dsc);
1860 lydict_remove(ctx, f->ref);
1861 free(f->features);
1862}
1863
Radek Krejci1d82ef62015-08-07 14:44:40 +02001864static void
1865lys_deviation_free(struct ly_ctx *ctx, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001866{
Radek Krejci581ce772015-11-10 17:22:40 +01001867 int i, j, k;
Radek Krejcieb00f512015-07-01 16:44:58 +02001868
1869 lydict_remove(ctx, dev->target_name);
1870 lydict_remove(ctx, dev->dsc);
1871 lydict_remove(ctx, dev->ref);
1872
1873 for (i = 0; i < dev->deviate_size; i++) {
1874 lydict_remove(ctx, dev->deviate[i].dflt);
1875 lydict_remove(ctx, dev->deviate[i].units);
1876
1877 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1878 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001879 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001880 }
1881 free(dev->deviate[i].must);
1882
1883 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001884 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1885 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1886 }
1887 free(dev->deviate[j].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001888 }
1889 free(dev->deviate[i].unique);
1890 }
1891 }
1892 free(dev->deviate);
1893}
1894
Radek Krejci1d82ef62015-08-07 14:44:40 +02001895static void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001896lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +02001897{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001898 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001899
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001900 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001901 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001902 lydict_remove(ctx, uses->refine[i].dsc);
1903 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001904
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001905 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001906 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001907 }
1908 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001909
Radek Krejci76512572015-08-04 09:47:08 +02001910 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001911 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001912 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001913 lydict_remove(ctx, uses->refine[i].mod.presence);
1914 }
1915 }
1916 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001917
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001918 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001919 lys_augment_free(ctx, uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001920 }
1921 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001922
Radek Krejci1d82ef62015-08-07 14:44:40 +02001923 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001924}
1925
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001926void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001927lys_node_free(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001928{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001929 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001930 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001931
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001932 if (!node) {
1933 return;
1934 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001935
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001936 assert(node->module);
1937 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001938
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001939 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001940
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001941 /* common part */
Radek Krejcid12f57b2015-08-06 10:43:39 +02001942 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1943 free(node->features);
1944 lydict_remove(ctx, node->name);
1945 lydict_remove(ctx, node->dsc);
1946 lydict_remove(ctx, node->ref);
1947 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001948
Radek Krejci46c4cd72016-01-21 15:13:52 +01001949 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
1950 LY_TREE_FOR_SAFE(node->child, next, sub) {
1951 lys_node_free(sub);
1952 }
1953 }
1954
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001955 /* specific part */
1956 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001957 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001958 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001959 break;
Radek Krejci76512572015-08-04 09:47:08 +02001960 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001961 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001962 break;
Radek Krejci76512572015-08-04 09:47:08 +02001963 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001964 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001965 break;
Radek Krejci76512572015-08-04 09:47:08 +02001966 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001967 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001968 break;
Radek Krejci76512572015-08-04 09:47:08 +02001969 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001970 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001971 break;
Radek Krejci76512572015-08-04 09:47:08 +02001972 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001973 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001974 break;
Radek Krejci76512572015-08-04 09:47:08 +02001975 case LYS_USES:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001976 lys_uses_free(ctx, (struct lys_node_uses *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001977 break;
Radek Krejci76512572015-08-04 09:47:08 +02001978 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001979 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001980 break;
Radek Krejci76512572015-08-04 09:47:08 +02001981 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001982 /* do nothing */
1983 break;
Radek Krejci76512572015-08-04 09:47:08 +02001984 case LYS_GROUPING:
1985 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001986 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001987 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001988 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001989
1990 case LYS_INPUT:
1991 case LYS_OUTPUT:
1992 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1993 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001994 case LYS_UNKNOWN:
1995 LOGINT;
1996 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001997 }
Radek Krejci5a065542015-05-22 15:02:07 +02001998
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001999 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002000 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002001 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002002}
2003
Michal Vasko1e62a092015-12-01 12:27:20 +01002004const struct lys_module *
2005lys_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 +02002006{
Michal Vaskob6729c62015-10-21 12:09:47 +02002007 int i, match;
Michal Vasko8afe75e2015-12-11 12:02:20 +01002008 struct lys_submodule *submodule = (struct lys_submodule *)module;
Michal Vaskob6729c62015-10-21 12:09:47 +02002009
2010 assert(prefix || name);
2011 if (prefix && !pref_len) {
2012 pref_len = strlen(prefix);
2013 }
2014 if (name && !name_len) {
2015 name_len = strlen(name);
2016 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02002017
Michal Vasko8afe75e2015-12-11 12:02:20 +01002018 /* special case, in submodule we pretend the (JSON) module name is the name of the belongs-to module */
2019 if (module->type) {
2020 if ((!prefix || (!strncmp(submodule->prefix, prefix, pref_len) && !submodule->prefix[pref_len]))
2021 && (!name || (!strncmp(submodule->belongsto->name, name, name_len) && !submodule->belongsto->name[name_len]))) {
2022 return module;
2023 }
2024 } else {
2025 if ((!prefix || (!strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
2026 && (!name || (!strncmp(module->name, name, name_len) && !module->name[name_len]))) {
2027 return module;
2028 }
Michal Vaskod8da86b2015-10-21 13:35:37 +02002029 }
2030
Michal Vasko8ce24d72015-10-21 11:27:26 +02002031 for (i = 0; i < module->imp_size; ++i) {
Michal Vaskob6729c62015-10-21 12:09:47 +02002032 match = 0;
2033 if (!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len])) {
2034 match = 1;
2035 }
2036 if (match && (!name
2037 || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02002038 return module->imp[i].module;
2039 }
2040 }
2041
2042 return NULL;
2043}
2044
Michal Vasko13b15832015-08-19 11:04:48 +02002045/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002046static void
Michal Vasko13b15832015-08-19 11:04:48 +02002047module_free_common(struct lys_module *module, int free_int_mods)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002048{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002049 struct ly_ctx *ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002050 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02002051 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002052
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002053 assert(module->ctx);
2054 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002055
Radek Krejcidce51452015-06-16 15:20:08 +02002056 /* as first step, free the imported modules */
2057 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa76ee152015-08-17 15:38:22 +02002058 /* do not free internal modules */
Michal Vasko18bd09b2015-08-19 15:07:00 +02002059 if (!free_int_mods) {
2060 for (j = 0; j < int_mods.count; ++j) {
Michal Vaskod83c03a2015-08-21 09:09:24 +02002061 if (module->imp[i].module && !strcmp(int_mods.modules[j].name, module->imp[i].module->name)
Michal Vasko18bd09b2015-08-19 15:07:00 +02002062 && module->imp[i].module->rev
2063 && !strcmp(int_mods.modules[j].revision, module->imp[i].module->rev[0].date)) {
2064 break;
2065 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02002066 }
Michal Vasko18bd09b2015-08-19 15:07:00 +02002067 if (j < int_mods.count) {
2068 continue;
2069 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02002070 }
2071
Radek Krejcidce51452015-06-16 15:20:08 +02002072 /* get the imported module from the context and then free,
2073 * this check is necessary because the imported module can
2074 * be already removed
2075 */
2076 l = ctx->models.used;
2077 for (j = 0; j < l; j++) {
2078 if (ctx->models.list[j] == module->imp[i].module) {
Michal Vasko13b15832015-08-19 11:04:48 +02002079 lys_free(module->imp[i].module, free_int_mods);
Radek Krejcidce51452015-06-16 15:20:08 +02002080 break;
2081 }
2082 }
2083 }
2084 free(module->imp);
2085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002086 while (module->data) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002087 lys_node_free(module->data);
Radek Krejci21181962015-06-30 14:11:00 +02002088 }
Radek Krejci5a065542015-05-22 15:02:07 +02002089
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002090 lydict_remove(ctx, module->dsc);
2091 lydict_remove(ctx, module->ref);
2092 lydict_remove(ctx, module->org);
2093 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002094
Radek Krejcieb00f512015-07-01 16:44:58 +02002095 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002096 for (i = 0; i < module->rev_size; i++) {
2097 lydict_remove(ctx, module->rev[i].dsc);
2098 lydict_remove(ctx, module->rev[i].ref);
2099 }
2100 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002101
Radek Krejcieb00f512015-07-01 16:44:58 +02002102 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002103 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002104 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002105 }
2106 module->ident_size = 0;
2107 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002108
Radek Krejcieb00f512015-07-01 16:44:58 +02002109 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002110 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002111 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002112 }
2113 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002114
Radek Krejcieb00f512015-07-01 16:44:58 +02002115 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002116 for (i = 0; i < module->inc_size; i++) {
Michal Vasko13b15832015-08-19 11:04:48 +02002117 lys_submodule_free(module->inc[i].submodule, free_int_mods);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002118 }
2119 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002120
Radek Krejcieb00f512015-07-01 16:44:58 +02002121 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002122 for (i = 0; i < module->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02002123 lys_augment_free(ctx, module->augment[i]);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002124 }
2125 free(module->augment);
2126
Radek Krejcieb00f512015-07-01 16:44:58 +02002127 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002128 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002129 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002130 }
2131 free(module->features);
2132
Radek Krejcieb00f512015-07-01 16:44:58 +02002133 /* deviations */
2134 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002135 lys_deviation_free(ctx, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002136 }
2137 free(module->deviation);
2138
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002139 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02002140}
2141
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002142void
Michal Vasko13b15832015-08-19 11:04:48 +02002143lys_submodule_free(struct lys_submodule *submodule, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02002144{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002145 if (!submodule) {
2146 return;
2147 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002148
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002149 submodule->inc_size = 0;
2150 free(submodule->inc);
2151 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02002152
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002153 /* common part with struct ly_module */
Michal Vasko13b15832015-08-19 11:04:48 +02002154 module_free_common((struct lys_module *)submodule, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02002155
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002156 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002157
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002158 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002159}
2160
Radek Krejci76512572015-08-04 09:47:08 +02002161struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002162lys_node_dup(struct lys_module *module, const struct lys_node *node, uint8_t flags, uint8_t nacm, int recursive,
Michal Vaskof02e3742015-08-05 16:27:02 +02002163 struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002164{
Radek Krejci76512572015-08-04 09:47:08 +02002165 struct lys_node *retval = NULL, *aux, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002166 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002167 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002168
Michal Vaskoc07187d2015-08-13 15:20:57 +02002169 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002170 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002171 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002172 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002173 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002174 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002175 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002176 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002177 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002178 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002179 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002180 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002181 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002182 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002183 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002184 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002185 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002186 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002187 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002188 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002189 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002190 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002191 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002192 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002194 /* we cannot just duplicate memory since the strings are stored in
2195 * dictionary and we need to update dictionary counters.
2196 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002197
Radek Krejci1d82ef62015-08-07 14:44:40 +02002198 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002199 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002200 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002201 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002202 break;
2203
Radek Krejci76512572015-08-04 09:47:08 +02002204 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002205 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002206 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002207 break;
2208
Radek Krejci76512572015-08-04 09:47:08 +02002209 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002210 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002211 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002212 break;
2213
Radek Krejci76512572015-08-04 09:47:08 +02002214 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002215 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002216 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002217 break;
2218
Radek Krejci76512572015-08-04 09:47:08 +02002219 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002220 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002221 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002222 break;
2223
Radek Krejci76512572015-08-04 09:47:08 +02002224 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002225 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002226 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002227 break;
2228
Radek Krejci76512572015-08-04 09:47:08 +02002229 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002230 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002231 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002232 break;
2233
Radek Krejci76512572015-08-04 09:47:08 +02002234 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002235 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002236 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002237 break;
2238
Radek Krejci76512572015-08-04 09:47:08 +02002239 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002240 grp = calloc(1, sizeof *grp);
2241 retval = (struct lys_node *)grp;
2242 break;
2243
Radek Krejci76512572015-08-04 09:47:08 +02002244 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002245 rpc = calloc(1, sizeof *rpc);
2246 retval = (struct lys_node *)rpc;
2247 break;
2248
Radek Krejci76512572015-08-04 09:47:08 +02002249 case LYS_INPUT:
2250 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002251 io = calloc(1, sizeof *io);
2252 retval = (struct lys_node *)io;
2253 break;
2254
Radek Krejci76512572015-08-04 09:47:08 +02002255 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002256 ntf = calloc(1, sizeof *ntf);
2257 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002258 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002259
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002260 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002261 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002262 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002263 }
Radek Krejcib388c152015-06-04 17:03:03 +02002264
Michal Vasko253035f2015-12-17 16:58:13 +01002265 if (!retval) {
2266 LOGMEM;
2267 return NULL;
2268 }
2269
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002270 /*
2271 * duplicate generic part of the structure
2272 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002273 retval->name = lydict_insert(ctx, node->name, 0);
2274 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2275 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002276 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002277 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002278 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002279 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002280 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002281 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002282
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002283 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002284 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002286 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002287
Radek Krejci1d82ef62015-08-07 14:44:40 +02002288 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002289 retval->features = calloc(retval->features_size, sizeof *retval->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002290 if (!retval->features) {
2291 LOGMEM;
2292 goto error;
2293 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002294 for (i = 0; i < node->features_size; ++i) {
Radek Krejcicf509982015-12-15 09:22:44 +01002295 retval->features[i] = (struct lys_feature *)retval;
Michal Vasko0bd29d12015-08-19 11:45:49 +02002296 if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002297 retval->features[i] = node->features[i];
Michal Vaskod23ce592015-08-06 09:55:37 +02002298 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002299 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002300
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002301 if (recursive) {
2302 /* go recursively */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002303 LY_TREE_FOR(node->child, child) {
Michal Vasko71e1aa82015-08-12 12:17:51 +02002304 aux = lys_node_dup(module, child, retval->flags, retval->nacm, 1, unres);
Radek Krejci10c760e2015-08-14 14:45:43 +02002305 if (!aux || lys_node_addchild(retval, NULL, aux)) {
Michal Vasko49168a22015-08-17 16:35:41 +02002306 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002307 }
2308 }
2309 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002310
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002311 /*
2312 * duplicate specific part of the structure
2313 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002314 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002315 case LYS_CONTAINER:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002316 if (cont_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002317 cont->when = lys_when_dup(ctx, cont_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002318 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002319 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002320
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002321 cont->must_size = cont_orig->must_size;
2322 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002323
Radek Krejci1d82ef62015-08-07 14:44:40 +02002324 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci1d82ef62015-08-07 14:44:40 +02002325 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002326 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002327
Radek Krejci76512572015-08-04 09:47:08 +02002328 case LYS_CHOICE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002329 if (choice_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002330 choice->when = lys_when_dup(ctx, choice_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002331 }
2332
2333 if (choice_orig->dflt) {
Michal Vasko36cbaa42015-12-14 13:15:48 +01002334 rc = lys_get_sibling(choice->child, choice->module->name, 0, choice_orig->dflt->name, 0, LYS_ANYXML
Radek Krejci76512572015-08-04 09:47:08 +02002335 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
Michal Vasko1e62a092015-12-01 12:27:20 +01002336 | LYS_LIST, (const struct lys_node **)&choice->dflt);
Michal Vasko49168a22015-08-17 16:35:41 +02002337 if (rc) {
2338 if (rc == EXIT_FAILURE) {
2339 LOGINT;
2340 }
2341 goto error;
2342 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002343 } else {
Michal Vaskoc68a2a22015-08-06 09:57:24 +02002344 /* useless to check return value, we don't know whether
2345 * there really wasn't any default defined or it just hasn't
2346 * been resolved, we just hope for the best :)
2347 */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002348 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002349 }
2350 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002351
Radek Krejci76512572015-08-04 09:47:08 +02002352 case LYS_LEAF:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002353 if (lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres)) {
2354 goto error;
2355 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002356 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2357
2358 if (leaf_orig->dflt) {
2359 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002360 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002361 goto error;
2362 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002363 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002364
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002365 leaf->must_size = leaf_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002366 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002367
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002368 if (leaf_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002369 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002370 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002371 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002372
Radek Krejci76512572015-08-04 09:47:08 +02002373 case LYS_LEAFLIST:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002374 if (lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres)) {
2375 goto error;
2376 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002377 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002378
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002379 llist->min = llist_orig->min;
2380 llist->max = llist_orig->max;
2381
2382 llist->must_size = llist_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002383 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002384
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002385 if (llist_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002386 llist->when = lys_when_dup(ctx, llist_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002387 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002388 break;
2389
Radek Krejci76512572015-08-04 09:47:08 +02002390 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002391 list->min = list_orig->min;
2392 list->max = list_orig->max;
2393
2394 list->must_size = list_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002395 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002396
Radek Krejci581ce772015-11-10 17:22:40 +01002397 list->tpdf_size = list_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002398 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002399
Radek Krejci581ce772015-11-10 17:22:40 +01002400 list->keys_size = list_orig->keys_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002401 if (list->keys_size) {
2402 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01002403 if (!list->keys) {
2404 LOGMEM;
2405 goto error;
2406 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002407
2408 /* we managed to resolve it before, resolve it again manually */
2409 if (list_orig->keys[0]) {
2410 for (i = 0; i < list->keys_size; ++i) {
Michal Vasko36cbaa42015-12-14 13:15:48 +01002411 rc = lys_get_sibling(list->child, list->module->name, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
Michal Vasko1e62a092015-12-01 12:27:20 +01002412 (const struct lys_node **)&list->keys[i]);
Michal Vasko49168a22015-08-17 16:35:41 +02002413 if (rc) {
2414 if (rc == EXIT_FAILURE) {
2415 LOGINT;
2416 }
2417 goto error;
2418 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002419 }
2420 /* it was not resolved yet, add unres copy */
2421 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002422 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02002423 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002424 goto error;
Michal Vaskod23ce592015-08-06 09:55:37 +02002425 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002426 }
2427 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002428
Radek Krejci581ce772015-11-10 17:22:40 +01002429 list->unique_size = list_orig->unique_size;
2430 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002431 if (!list->unique) {
2432 LOGMEM;
2433 goto error;
2434 }
Radek Krejci581ce772015-11-10 17:22:40 +01002435 for (i = 0; i < list->unique_size; ++i) {
2436 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2437 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002438 if (!list->unique[i].expr) {
2439 LOGMEM;
2440 goto error;
2441 }
Radek Krejci581ce772015-11-10 17:22:40 +01002442 for (j = 0; j < list->unique[i].expr_size; j++) {
2443 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2444
2445 /* if it stays in unres list, duplicate it also there */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002446 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002447 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002448 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002449
2450 if (list_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002451 list->when = lys_when_dup(ctx, list_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002452 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002453 break;
2454
Radek Krejci76512572015-08-04 09:47:08 +02002455 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002456 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002457 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002458
2459 if (anyxml_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002460 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002461 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002462 break;
2463
Radek Krejci76512572015-08-04 09:47:08 +02002464 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002465 uses->grp = uses_orig->grp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002466
2467 if (uses_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002468 uses->when = lys_when_dup(ctx, uses_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002469 }
2470
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002471 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002472 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002473 uses->augment_size = uses_orig->augment_size;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02002474 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Michal Vaskof8c128d2015-08-06 15:25:28 +02002475 if (!uses->child) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002476 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002477 goto error;
2478 }
Michal Vaskof8c128d2015-08-06 15:25:28 +02002479 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002480 break;
2481
Radek Krejci76512572015-08-04 09:47:08 +02002482 case LYS_CASE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002483 if (cs_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002484 cs->when = lys_when_dup(ctx, cs_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002485 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002486 break;
2487
Radek Krejci76512572015-08-04 09:47:08 +02002488 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002489 grp->tpdf_size = grp_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002490 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002491 break;
2492
Radek Krejci76512572015-08-04 09:47:08 +02002493 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002494 rpc->tpdf_size = rpc_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002495 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002496 break;
2497
Radek Krejci76512572015-08-04 09:47:08 +02002498 case LYS_INPUT:
2499 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002500 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002501 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002502 break;
2503
Radek Krejci76512572015-08-04 09:47:08 +02002504 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002505 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002506 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcia01e5432015-06-16 10:35:25 +02002507 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002508
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002509 default:
Radek Krejci00768f42015-06-18 17:04:04 +02002510 /* LY_NODE_AUGMENT */
Michal Vaskod23ce592015-08-06 09:55:37 +02002511 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002512 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002513 }
2514
2515 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002516
2517error:
2518
2519 lys_node_free(retval);
2520 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002521}
2522
Michal Vasko13b15832015-08-19 11:04:48 +02002523void
2524lys_free(struct lys_module *module, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02002525{
Radek Krejcidce51452015-06-16 15:20:08 +02002526 struct ly_ctx *ctx;
2527 int i;
2528
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002529 if (!module) {
2530 return;
2531 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002532
Radek Krejcidce51452015-06-16 15:20:08 +02002533 /* remove schema from the context */
2534 ctx = module->ctx;
2535 if (ctx->models.used) {
2536 for (i = 0; i < ctx->models.used; i++) {
2537 if (ctx->models.list[i] == module) {
2538 /* replace the position in the list by the last module in the list */
2539 ctx->models.used--;
2540 ctx->models.list[i] = ctx->models.list[ctx->models.used];
2541 ctx->models.list[ctx->models.used] = NULL;
2542 /* we are done */
2543 break;
2544 }
2545 }
2546 }
2547
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002548 /* common part with struct ly_submodule */
Michal Vasko13b15832015-08-19 11:04:48 +02002549 module_free_common(module, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02002550
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002551 /* specific items to free */
2552 lydict_remove(module->ctx, module->ns);
2553 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02002554
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002555 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002556}
Radek Krejci7e97c352015-06-19 16:26:34 +02002557
2558/*
2559 * op: 1 - enable, 0 - disable
2560 */
2561static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002562lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002563{
2564 int all = 0;
2565 int i, j, k;
2566
2567 if (!module || !name || !strlen(name)) {
2568 return EXIT_FAILURE;
2569 }
2570
2571 if (!strcmp(name, "*")) {
2572 /* enable all */
2573 all = 1;
2574 }
2575
2576 /* module itself */
2577 for (i = 0; i < module->features_size; i++) {
2578 if (all || !strcmp(module->features[i].name, name)) {
2579 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002580 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002581 /* enable referenced features (recursion) */
2582 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002583 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002584 module->features[i].features[k]->name, op);
2585 }
2586 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002587 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002588 }
2589 if (!all) {
2590 return EXIT_SUCCESS;
2591 }
2592 }
2593 }
2594
2595 /* submodules */
2596 for (j = 0; j < module->inc_size; j++) {
2597 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2598 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2599 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002600 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002601 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002602 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002603 }
2604 if (!all) {
2605 return EXIT_SUCCESS;
2606 }
2607 }
2608 }
2609 }
2610
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002611 /* TODO submodules of submodules ... */
2612
Radek Krejci7e97c352015-06-19 16:26:34 +02002613 if (all) {
2614 return EXIT_SUCCESS;
2615 } else {
2616 return EXIT_FAILURE;
2617 }
2618}
2619
2620API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002621lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002622{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002623 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002624}
2625
2626API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002627lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002628{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002629 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002630}
2631
2632API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002633lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002634{
2635 int i, j;
2636
2637 if (!module || !feature) {
2638 return -1;
2639 }
2640
2641 /* search for the specified feature */
2642 /* module itself */
2643 for (i = 0; i < module->features_size; i++) {
2644 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002645 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002646 return 1;
2647 } else {
2648 return 0;
2649 }
2650 }
2651 }
2652
2653 /* submodules */
2654 for (j = 0; j < module->inc_size; j++) {
2655 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2656 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002657 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002658 return 1;
2659 } else {
2660 return 0;
2661 }
2662 }
2663 }
2664 }
2665
2666 /* TODO submodules of submodules ... */
2667
2668 /* feature definition not found */
2669 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002670}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002671
Radek Krejci96a10da2015-07-30 11:00:14 +02002672API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01002673lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002674{
Radek Krejci96a10da2015-07-30 11:00:14 +02002675 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002676 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002677 unsigned int count;
2678
2679 if (!module) {
2680 return NULL;
2681 }
2682
2683 count = module->features_size;
2684 for (i = 0; i < module->inc_size; i++) {
2685 count += module->inc[i].submodule->features_size;
2686 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002687 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01002688 if (!result) {
2689 LOGMEM;
2690 return NULL;
2691 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002692 if (states) {
2693 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01002694 if (!(*states)) {
2695 LOGMEM;
2696 free(result);
2697 return NULL;
2698 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002699 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002700 count = 0;
2701
2702 /* module itself */
2703 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002704 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002705 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002706 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002707 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002708 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002709 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002710 }
2711 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002712 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002713 }
2714
2715 /* submodules */
2716 for (j = 0; j < module->inc_size; j++) {
2717 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002718 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002719 if (states) {
2720 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2721 (*states)[count] = 1;
2722 } else {
2723 (*states)[count] = 0;
2724 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002725 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002726 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002727 }
2728 }
2729
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002730 /* TODO submodules of submodules ... */
2731
2732 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002733 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002734
2735 return result;
2736}
Michal Vaskobaefb032015-09-24 14:52:10 +02002737
2738API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002739lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02002740{
2741 if (!node || !node->parent) {
2742 return NULL;
2743 }
2744
2745 if (node->parent->nodetype == LYS_AUGMENT) {
2746 return ((struct lys_node_augment *)node->parent)->target;
2747 }
2748
2749 return node->parent;
2750}
Michal Vasko1b229152016-01-13 11:28:38 +01002751
2752API void
2753lys_set_private(const struct lys_node *node, void *priv)
2754{
2755 if (!node) {
2756 return;
2757 }
2758
2759 ((struct lys_node *)node)->private = priv;
2760}
Michal Vasko86252b32016-01-19 09:00:56 +01002761
2762API const struct lys_node *
2763lys_get_node(const struct lys_module *module, const char *nodeid)
2764{
2765 const struct lys_node *ret;
2766
2767 if (!module || !nodeid) {
2768 ly_errno = LY_EINVAL;
2769 return NULL;
2770 }
2771
2772 if (nodeid[0] != '/') {
2773 ly_errno = LY_EINVAL;
2774 return NULL;
2775 }
2776
2777 if (resolve_schema_nodeid(nodeid, NULL, module, LYS_AUGMENT, &ret)) {
2778 ly_errno = LY_EINVAL;
2779 return NULL;
2780 }
2781
2782 return ret;
2783}