blob: 35c42151534f9812102b551e3ca4d356f0326948 [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>
28#include <sys/stat.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020029#include <string.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020030
31#include "common.h"
32#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020033#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020034#include "resolve.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020035#include "xml_internal.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020036#include "tree_internal.h"
Radek Krejcieab784a2015-08-27 09:56:53 +020037#include "validation.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020038
Michal Vaskoa76ee152015-08-17 15:38:22 +020039static const struct internal_modules int_mods = {
40 .modules = {
41 {"ietf-yang-types", "2013-07-15"},
42 {"ietf-inet-types", "2013-07-15"},
43 {"ietf-yang-library", "2015-07-03"}
44 },
45 .count = LY_INTERNAL_MODULE_COUNT
46};
47
Radek Krejci48061fb2015-08-05 15:41:07 +020048API struct lys_feature *
49lys_is_disabled(struct lys_node *node, int recursive)
50{
51 int i;
52
53check:
54 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
55 /* input/output does not have if-feature, so skip them */
56
57 /* check local if-features */
58 for (i = 0; i < node->features_size; i++) {
59 if (!(node->features[i]->flags & LYS_FENABLED)) {
60 return node->features[i];
61 }
62 }
63 }
64
65 if (!recursive) {
66 return NULL;
67 }
68
69 /* go through parents */
70 if (node->nodetype == LYS_AUGMENT) {
71 /* go to parent actually means go to the target node */
72 node = ((struct lys_node_augment *)node)->target;
Radek Krejci48061fb2015-08-05 15:41:07 +020073 } else if (node->parent) {
74 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020075 } else {
76 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020077 }
78
Radek Krejci074bf852015-08-19 14:22:16 +020079 if (recursive == 2) {
80 /* continue only if the node cannot have a data instance */
81 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
82 return NULL;
83 }
84 }
85 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020086}
87
Michal Vasko1dca6882015-10-22 14:29:42 +020088int
Michal Vasko165dc4a2015-10-23 09:44:27 +020089lys_get_sibling(struct lys_module *mod, struct lys_node *siblings, const char *mod_name, int mod_name_len,
90 const char *name, int nam_len, LYS_NODE type, struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +020091{
92 struct lys_node *node, *old_siblings = NULL;
93 struct lys_module *prefix_mod, *cur_mod;
94 int in_submod;
Michal Vasko1dca6882015-10-22 14:29:42 +020095
96 assert(siblings && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +020097 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +020098
99 /* find the beginning */
100 while (siblings->prev->next) {
101 siblings = siblings->prev;
102 }
103
104 /* fill the name length in case the caller is so indifferent */
105 if (!nam_len) {
106 nam_len = strlen(name);
107 }
108
109 /* we start with the module itself, submodules come later */
110 in_submod = 0;
111
112 /* set prefix_mod correctly */
113 if (mod_name) {
Michal Vaskob6729c62015-10-21 12:09:47 +0200114 prefix_mod = lys_get_import_module(siblings->module, NULL, 0, mod_name, mod_name_len);
Michal Vasko1dca6882015-10-22 14:29:42 +0200115 if (!prefix_mod) {
116 return -1;
117 }
118 cur_mod = prefix_mod;
119 /* it is not our module */
120 if (cur_mod != mod) {
121 old_siblings = siblings;
122 siblings = cur_mod->data;
123 }
124 } else {
125 if (mod) {
126 prefix_mod = mod;
127 } else {
128 prefix_mod = siblings->module;
129 }
130 if (prefix_mod->type) {
131 prefix_mod = ((struct lys_submodule *)prefix_mod)->belongsto;
132 }
133 cur_mod = prefix_mod;
134 }
135
136 while (1) {
137 /* try to find the node */
138 node = NULL;
139 while ((node = lys_getnext(node, siblings->parent, cur_mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
140 if (!type || (node->nodetype & type)) {
141 /* module check */
142 if (!node->module->type) {
143 if (cur_mod != node->module) {
144 continue;
145 }
146 } else {
147 /* both are submodules */
148 if (cur_mod->type) {
149 if (cur_mod != node->module) {
150 continue;
151 }
152 } else {
153 if (cur_mod != ((struct lys_submodule *)node->module)->belongsto) {
154 continue;
155 }
156 }
157 }
158
159 /* direct name check */
160 if ((node->name == name) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
161 if (ret) {
162 *ret = node;
163 }
164 return EXIT_SUCCESS;
165 }
166 }
167 }
168
169 /* The original siblings may be valid,
170 * it's a special case when we're looking
171 * for a node from an augment.
172 */
Michal Vasko165dc4a2015-10-23 09:44:27 +0200173 if ((type & LYS_AUGMENT) && old_siblings) {
Michal Vasko1dca6882015-10-22 14:29:42 +0200174 siblings = old_siblings;
175 old_siblings = NULL;
176 continue;
177 }
178
179 /* we're not top-level, search ended */
180 if (siblings->parent) {
181 break;
182 }
183
184 /* let's try the submodules */
185 if (in_submod == prefix_mod->inc_size) {
186 break;
187 }
188 cur_mod = (struct lys_module *)prefix_mod->inc[in_submod].submodule;
189 siblings = cur_mod->data;
190 ++in_submod;
191 }
192
193 return EXIT_FAILURE;
194}
195
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200196int
197lys_get_data_sibling(struct lys_module *mod, struct lys_node *siblings, const char *name, LYS_NODE type,
198 struct lys_node **ret)
199{
200 struct lys_node *node;
201 struct lys_module *cur_mod;
202 int in_submod;
203
204 assert(siblings && name);
205 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
206
207 /* find the beginning */
208 while (siblings->prev->next) {
209 siblings = siblings->prev;
210 }
211
212 /* we start with the module itself, submodules come later */
213 in_submod = 0;
214
215 if (!mod) {
216 mod = siblings->module;
217 }
218 cur_mod = mod;
219
220 while (1) {
221 /* try to find the node */
222 node = NULL;
223 while ((node = lys_getnext(node, siblings->parent, cur_mod, 0))) {
224 if (!type || (node->nodetype & type)) {
225 /* module check */
226 if (!node->module->type) {
227 if (cur_mod != node->module) {
228 continue;
229 }
230 } else {
231 /* both are submodules */
232 if (cur_mod->type) {
233 if (cur_mod != node->module) {
234 continue;
235 }
236 } else {
237 if (cur_mod != ((struct lys_submodule *)node->module)->belongsto) {
238 continue;
239 }
240 }
241 }
242
243 /* direct name check */
244 if ((node->name == name) || !strcmp(node->name, name)) {
245 if (ret) {
246 *ret = node;
247 }
248 return EXIT_SUCCESS;
249 }
250 }
251 }
252
253 /* we're not top-level, search ended */
254 if (siblings->parent) {
255 break;
256 }
257
258 /* let's try the submodules */
259 if (in_submod == mod->inc_size) {
260 break;
261 }
262 cur_mod = (struct lys_module *)mod->inc[in_submod].submodule;
263 siblings = cur_mod->data;
264 ++in_submod;
265 }
266
267 return EXIT_FAILURE;
268}
269
Michal Vasko1dca6882015-10-22 14:29:42 +0200270API struct lys_node *
Radek Krejci8bc87f62015-09-02 16:19:05 +0200271lys_getnext(struct lys_node *last, struct lys_node *parent, struct lys_module *module, int options)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200272{
273 struct lys_node *next;
274
Radek Krejci8bc87f62015-09-02 16:19:05 +0200275 if (!last) {
276 /* first call */
277
278 /* get know where to start */
279 if (parent) {
280 /* schema subtree */
281 next = last = parent->child;
282 } else {
283 /* top level data */
284 assert(module);
285 next = last = module->data;
286 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200287 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200288 /* continue after the last returned value */
289 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200290 }
291
292repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200293 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200294 if (options & LYS_GETNEXT_WITHGROUPING) {
295 return next;
296 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200297 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200298 }
299
300 while (!next) {
Michal Vasko7c386e72015-10-07 15:13:33 +0200301 if (lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200302 /* no next element */
303 return NULL;
304 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200305 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200306 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200307 goto repeat;
308 }
309
310 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200311 case LYS_INPUT:
312 case LYS_OUTPUT:
313 if (options & LYS_GETNEXT_WITHINOUT) {
314 return next;
315 } else {
316 next = next->child;
317 goto repeat;
318 }
319 break;
320
Michal Vaskoa5835e92015-10-20 15:07:39 +0200321 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200322 if (options & LYS_GETNEXT_WITHCASE) {
323 return next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200324 } else {
325 next = next->child;
326 goto repeat;
Michal Vasko1dca6882015-10-22 14:29:42 +0200327 }
Michal Vaskob6eedf02015-10-22 16:07:03 +0200328 break;
329
Michal Vasko1dca6882015-10-22 14:29:42 +0200330 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200331 /* go into */
332 next = next->child;
333 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200334
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200335 case LYS_RPC:
336 case LYS_NOTIF:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200337 case LYS_CONTAINER:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200338 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200339 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200340 case LYS_LIST:
341 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200342 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200343
344 case LYS_CHOICE:
345 if (options & LYS_GETNEXT_WITHCHOICE) {
346 return next;
347 } else {
348 /* go into */
349 next = next->child;
350 goto repeat;
351 }
352 break;
353
Radek Krejci7f40ce32015-08-12 20:38:46 +0200354 default:
355 /* we should not be here */
356 return NULL;
357 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200358
359
360}
361
362static struct lys_node *
363check_mand_getnext(struct lys_node *last, struct lys_node *parent)
364{
365 struct lys_node *next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200366 next = lys_getnext(last, parent, NULL, LYS_GETNEXT_WITHCHOICE);
367
Radek Krejci4b6c2112015-10-06 12:48:34 +0200368repeat:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200369 if (next && next->nodetype == LYS_CONTAINER) {
370 if (((struct lys_node_container *)next)->presence) {
371 /* mandatory elements under the non-existing presence
372 * container are not mandatory - 7.6.5, rule 1 */
373 next = next->next;
374 } else {
375 /* go into */
376 next = next->child;
377 }
378 goto repeat;
379 }
380
381 return next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200382}
383
384static struct lys_node *
385check_mand_check(struct lys_node *node, struct lys_node *stop, struct lyd_node *data)
386{
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200387 struct lys_node *siter = NULL, *parent = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200388 struct lyd_node *diter = NULL;
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200389 struct lyd_set *set = NULL;
390 unsigned int i;
Radek Krejci14a11a62015-08-17 17:27:38 +0200391 uint32_t minmax;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200392
393 if (node->flags & LYS_MAND_TRUE) {
394 switch (node->nodetype) {
395 case LYS_LEAF:
396 case LYS_ANYXML:
397 case LYS_CHOICE:
398 if (node->parent->nodetype == LYS_CASE) {
399 /* 7.6.5, rule 2 */
400 /* 7.9.4, rule 1 */
401 if (node->parent->parent->parent == data->schema) {
402 /* the only case the node's siblings can exist is that the
403 * data node passed originaly to ly_check_mandatory()
404 * had this choice as a child
405 */
406 /* try to find the node's siblings in data */
407 LY_TREE_FOR(data->child, diter) {
408 LY_TREE_FOR(node->parent->child, siter) {
409 if (siter == diter->schema) {
410 /* some sibling exists, rule applies */
411 break;
412 }
413 }
414 if (siter) {
415 break;
416 }
417 }
418 }
419 if (!siter) {
420 /* no sibling exists */
421 return NULL;
422 }
423 } else {
424 for(parent = node->parent; parent != stop; parent = parent->parent) {
425 if (parent->nodetype != LYS_CONTAINER) {
426 /* 7.6.5, rule 1, checking presence is not needed
427 * since it is done in check_mand_getnext()
428 */
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200429 lyd_set_free(set);
Radek Krejci7f40ce32015-08-12 20:38:46 +0200430 return NULL;
431 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200432 /* add the parent to the list for searching in data tree */
433 if (!set) {
434 set = lyd_set_new();
435 }
436 lyd_set_add(set, (struct lyd_node *)parent);
Radek Krejci7f40ce32015-08-12 20:38:46 +0200437 }
438 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200439
440 /* search for instance */
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200441 if (set) {
442 for (i = 0; i < set->number; i++) {
443 LY_TREE_FOR(data->child, diter) {
444 if (diter->schema == (struct lys_node *)(set->set[i])) {
445 break;
446 }
447 }
448 if (!diter) {
449 /* instance not found */
450 node = (struct lys_node *)(set->set[i]);
451 lyd_set_free(set);
452 return node;
453 }
454 data = diter;
455 }
456 lyd_set_free(set);
457 }
458
Radek Krejci14a11a62015-08-17 17:27:38 +0200459 LY_TREE_FOR(data->child, diter) {
460 if (diter->schema == node) {
461 return NULL;
462 }
463 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200464
Radek Krejci14a11a62015-08-17 17:27:38 +0200465 /* instance not found */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200466 /* 7.6.5, rule 3 (or 2) */
467 /* 7.9.4, rule 2 */
468 return node;
469 default:
470 /* error */
471 break;
472 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200473 } else if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
474 /* search for number of instances */
475 minmax = 0;
476 LY_TREE_FOR(data->child, diter) {
477 if (diter->schema == node) {
478 minmax++;
479 }
480 }
481
482 /* check the specified constraints */
483 if (node->nodetype == LYS_LIST) {
484 if (((struct lys_node_list *)node)->min && minmax < ((struct lys_node_list *)node)->min) {
485 return node;
486 }
487
488 if (((struct lys_node_list *)node)->max && minmax > ((struct lys_node_list *)node)->max) {
489 return node;
490 }
491 } else if (node->nodetype == LYS_LEAFLIST) {
492 if (((struct lys_node_leaflist *)node)->min && minmax < ((struct lys_node_leaflist *)node)->min) {
493 return node;
494 }
495
496 if (((struct lys_node_leaflist *)node)->max && minmax > ((struct lys_node_leaflist *)node)->max) {
497 return node;
498 }
499 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200500 }
501
502 return NULL;
503}
504
505struct lys_node *
506ly_check_mandatory(struct lyd_node *data)
507{
Radek Krejci14a11a62015-08-17 17:27:38 +0200508 struct lys_node *siter, *saux, *saux2, *result, *parent = NULL, *parent2;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200509 struct lyd_node *diter;
510 int found;
511
512 siter = data->schema->child;
513
514repeat:
515 while (siter) {
Radek Krejci074bf852015-08-19 14:22:16 +0200516 if (lys_is_disabled(siter, 2)) {
517 siter = siter->next;
518 continue;
519 }
520
Radek Krejci7f40ce32015-08-12 20:38:46 +0200521 switch (siter->nodetype) {
522 case LYS_CONTAINER:
523 case LYS_LEAF:
524 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200525 case LYS_LIST:
526 case LYS_LEAFLIST:
527 /* check if there is some mandatory node; first test the siter itself ... */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200528 result = check_mand_check(siter, siter->parent, data);
529 if (result) {
530 return result;
531 }
532 /* ... and then the subtree */
Radek Krejci14a11a62015-08-17 17:27:38 +0200533 if (parent && siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
534 saux = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200535 while ((saux = check_mand_getnext(saux, siter))) {
536 result = check_mand_check(saux, siter, data);
537 if (result) {
538 return result;
539 }
540 }
541 }
542 siter = siter->next;
543 break;
544 case LYS_CHOICE:
Radek Krejci14a11a62015-08-17 17:27:38 +0200545 /* search for instance */
546 saux = siter;
547 siter = siter->child;
548 found = 0;
549 parent2 = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200550repeat_choice:
Radek Krejci074bf852015-08-19 14:22:16 +0200551 while (siter) {
552 if (lys_is_disabled(siter, 2)) {
553 siter = siter->next;
554 continue;
555 }
556
Radek Krejci14a11a62015-08-17 17:27:38 +0200557 switch (siter->nodetype) {
558 case LYS_CONTAINER:
559 case LYS_LEAF:
560 case LYS_LEAFLIST:
561 case LYS_LIST:
562 case LYS_ANYXML:
563 LY_TREE_FOR(data->child, diter) {
564 if (diter->schema == siter) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200565 break;
566 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200567 }
568 if (diter) {
569 /* got instance */
570 /* check presence of mandatory siblings */
Radek Krejci65d0a652015-08-27 13:09:42 +0200571 if (parent2 && parent2->nodetype == LYS_CASE) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200572 saux2 = NULL;
Radek Krejci37bda002015-08-27 11:23:56 +0200573 while ((saux2 = check_mand_getnext(saux2, parent2))) {
574 result = check_mand_check(saux2, parent2, data);
Radek Krejci14a11a62015-08-17 17:27:38 +0200575 if (result) {
576 return result;
577 }
578 }
579 }
580 siter = parent2 = NULL;
581 found = 1;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200582 break;
583 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200584 siter = siter->next;
585 break;
586 case LYS_CASE:
587 case LYS_CHOICE:
588 case LYS_USES:
589 /* go into */
Radek Krejci37bda002015-08-27 11:23:56 +0200590 if (!parent2) {
591 parent2 = siter;
592 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200593 siter = siter->child;
594 break;
595 case LYS_AUGMENT:
596 case LYS_GROUPING:
597 /* skip */
598 siter = siter->next;
599 break;
600 default:
601 /* error */
602 break;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200603 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200604 }
605
Radek Krejci14a11a62015-08-17 17:27:38 +0200606 if (parent2) {
607 siter = parent2->next;
608 if (parent2->parent == saux) {
609 parent2 = NULL;
610 } else {
611 parent2 = parent2->parent;
612 }
613 goto repeat_choice;
614 }
615
Radek Krejci074bf852015-08-19 14:22:16 +0200616 if (!found && (saux->flags & LYS_MAND_TRUE)) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200617 return saux;
618 }
619
620 /* go to next */
621 siter = saux->next;
622
Radek Krejci7f40ce32015-08-12 20:38:46 +0200623 break;
624 case LYS_USES:
625 case LYS_CASE:
626 /* go into */
627 parent = siter;
628 siter = siter->child;
629 break;
630 default:
631 /* can ignore, go to next */
632 siter = siter->next;
633 break;
634 }
635 }
636
637 if (parent) {
638 siter = parent->next;
639 if (parent->parent == data->schema) {
640 parent = NULL;
641 } else {
642 parent = parent->parent;
643 }
644 goto repeat;
645 }
646
647 return NULL;
648}
649
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200650void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200651lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200652{
Radek Krejci76512572015-08-04 09:47:08 +0200653 struct lys_node *parent, *first;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200654
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200655 if (!node) {
656 return;
657 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200658
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200659 /* unlink from data model if necessary */
660 if (node->module) {
661 if (node->module->data == node) {
662 node->module->data = node->next;
663 }
664 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200665
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200666 /* store pointers to important nodes */
667 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200668 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200669 /* handle augments - first, unlink it from the augment parent ... */
670 if (parent->child == node) {
671 parent->child = node->next;
672 }
673 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200674 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200675 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200676
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200677 /* unlink from parent */
678 if (parent) {
679 if (parent->child == node) {
680 parent->child = node->next;
681 }
682 node->parent = NULL;
683 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200684
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200685 /* unlink from siblings */
686 if (node->prev == node) {
687 /* there are no more siblings */
688 return;
689 }
690 if (node->next) {
691 node->next->prev = node->prev;
692 } else {
693 /* unlinking the last element */
694 if (parent) {
695 first = parent->child;
696 } else {
697 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200698 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200699 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200700 }
701 }
702 first->prev = node->prev;
703 }
704 if (node->prev->next) {
705 node->prev->next = node->next;
706 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200707
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200708 /* clean up the unlinked element */
709 node->next = NULL;
710 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200711}
712
Michal Vasko563ef092015-09-04 13:17:23 +0200713struct lys_node_grp *
714lys_find_grouping_up(const char *name, struct lys_node *start, int in_submodules)
715{
716 struct lys_node *par_iter, *iter, *stop;
717 int i;
718
719 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200720 /* top-level augment, look into module (uses augment is handled correctly below) */
721 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
722 par_iter = par_iter->parent->module->data;
723 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200724 break;
725 }
726 }
727
Michal Vasko6f929da2015-10-02 16:23:25 +0200728 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200729 continue;
730 }
731
732 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
733 if (!stop) {
734 stop = par_iter;
735 } else if (iter == stop) {
736 break;
737 }
738 if (iter->nodetype != LYS_GROUPING) {
739 continue;
740 }
741
Radek Krejcif8426a72015-10-31 23:14:03 +0100742 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200743 return (struct lys_node_grp *)iter;
744 }
745 }
746 }
747
748 if (in_submodules) {
749 for (i = 0; i < start->module->inc_size; ++i) {
750 for (iter = start->module->inc[i].submodule->data; iter; iter = iter->next) {
751 if (iter->nodetype != LYS_GROUPING) {
752 continue;
753 }
754
Radek Krejcif8426a72015-10-31 23:14:03 +0100755 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200756 return (struct lys_node_grp *)iter;
757 }
758 }
759 }
760 }
761
762 return NULL;
763}
764
Radek Krejci10c760e2015-08-14 14:45:43 +0200765/*
766 * get next grouping in the root's subtree, in the
767 * first call, tha last is NULL
768 */
769static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200770lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200771{
Radek Krejci10c760e2015-08-14 14:45:43 +0200772 struct lys_node *last = (struct lys_node *)lastgrp;
773 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200774
Radek Krejci10c760e2015-08-14 14:45:43 +0200775 assert(root);
776
777 if (!last) {
778 last = root;
779 }
780
781 while (1) {
782 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
783 next = last->child;
784 } else {
785 next = NULL;
786 }
787 if (!next) {
788 if (last == root) {
789 /* we are done */
790 return NULL;
791 }
792
793 /* no children, go to siblings */
794 next = last->next;
795 }
796 while (!next) {
797 /* go back through parents */
798 if (last->parent == root) {
799 /* we are done */
800 return NULL;
801 }
802 last = last->parent;
803 next = last->next;
804 }
805
806 if (next->nodetype == LYS_GROUPING) {
807 return (struct lys_node_grp *)next;
808 }
809
810 last = next;
811 }
812}
813
Michal Vasko0d343d12015-08-24 14:57:36 +0200814/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200815int
Radek Krejci07911992015-08-14 15:13:31 +0200816lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
817{
Michal Vasko563ef092015-09-04 13:17:23 +0200818 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200819 struct lys_node_grp *grp;
820 int down;
821
822 assert(node);
823
824 if (!parent) {
825 assert(module);
826 } else {
827 module = parent->module;
828 }
829
830 switch (node->nodetype) {
831 case LYS_GROUPING:
832 /* 6.2.1, rule 6 */
833 if (parent) {
834 if (parent->child) {
835 down = 1;
836 start = parent->child;
837 } else {
838 down = 0;
839 start = parent;
840 }
841 } else {
842 down = 1;
843 start = module->data;
844 }
845 /* go up */
Michal Vasko563ef092015-09-04 13:17:23 +0200846 if (lys_find_grouping_up(node->name, start, 0)) {
847 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
848 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200849 }
850 /* go down, because grouping can be defined after e.g. container in which is collision */
851 if (down) {
852 for (iter = start, stop = NULL; iter; iter = iter->prev) {
853 if (!stop) {
854 stop = start;
855 } else if (iter == stop) {
856 break;
857 }
858 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
859 continue;
860 }
861
862 grp = NULL;
863 while ((grp = lys_get_next_grouping(grp, iter))) {
864 if (node->name == grp->name) {
865 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
866 return EXIT_FAILURE;
867 }
868 }
869 }
870 }
871 break;
872 case LYS_LEAF:
873 case LYS_LEAFLIST:
874 case LYS_LIST:
875 case LYS_CONTAINER:
876 case LYS_CHOICE:
877 case LYS_ANYXML:
878 /* 6.2.1, rule 7 */
879 if (parent) {
880 iter = parent;
881 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE))) {
882 iter = iter->parent;
883 }
884 if (!iter) {
885 stop = NULL;
886 iter = module->data;
887 } else {
888 stop = iter;
889 iter = iter->child;
890 }
891 } else {
892 stop = NULL;
893 iter = module->data;
894 }
895 while (iter) {
896 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
897 iter = iter->child;
898 continue;
899 }
900
901 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
902 if (iter->module == node->module && iter->name == node->name) {
903 LOGVAL(LYE_SPEC, 0, "Duplicated child identifier \"%s\" in \"%s\".", node->name,
904 stop ? stop->name : "(sub)module");
905 return EXIT_FAILURE;
906 }
907 }
908
909 /* special case for choice - we must check the choice's name as
910 * well as the names of nodes under the choice
911 */
912 if (iter->nodetype == LYS_CHOICE) {
913 iter = iter->child;
914 continue;
915 }
916
917 /* go to siblings */
918 if (!iter->next) {
919 /* no sibling, go to parent's sibling */
920 do {
921 iter = iter->parent;
922 if (iter && iter->next) {
923 break;
924 }
925 } while (iter != stop);
926
927 if (iter == stop) {
928 break;
929 }
930 }
931 iter = iter->next;
932 }
933 break;
934 case LYS_CASE:
935 /* 6.2.1, rule 8 */
936 LY_TREE_FOR(parent->child, iter) {
937 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
938 continue;
939 }
940
941 if (iter->module == node->module && iter->name == node->name) {
942 LOGVAL(LYE_DUPID, 0, "case", node->name);
943 return EXIT_FAILURE;
944 }
945 }
946 break;
947 default:
948 /* no check needed */
949 break;
950 }
951
952 return EXIT_SUCCESS;
953}
954
Michal Vasko0d343d12015-08-24 14:57:36 +0200955/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200956int
Radek Krejci10c760e2015-08-14 14:45:43 +0200957lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
958{
Radek Krejci92720552015-10-05 15:28:27 +0200959 struct lys_node *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200960 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200961
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200962 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200963
Radek Krejci10c760e2015-08-14 14:45:43 +0200964 if (parent) {
965 type = parent->nodetype;
966 module = parent->module;
967 } else {
968 assert(module);
969 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200970 }
971
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200972 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200973 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200974 case LYS_CONTAINER:
975 case LYS_LIST:
976 case LYS_GROUPING:
977 case LYS_USES:
978 case LYS_INPUT:
979 case LYS_OUTPUT:
980 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200981 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200982 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
983 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200984 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200985 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
986 return EXIT_FAILURE;
987 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200988
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200989 break;
Radek Krejci76512572015-08-04 09:47:08 +0200990 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200991 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200992 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200993 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"choice\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200994 strnodetype(child->nodetype), parent->name);
995 return EXIT_FAILURE;
996 }
997 break;
Radek Krejci76512572015-08-04 09:47:08 +0200998 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200999 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +02001000 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001001 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"case\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001002 strnodetype(child->nodetype), parent->name);
1003 return EXIT_FAILURE;
1004 }
1005 break;
Radek Krejci76512572015-08-04 09:47:08 +02001006 case LYS_RPC:
1007 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001008 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"rpc\" %s.",
Michal Vasko38d01f72015-06-15 09:41:06 +02001009 strnodetype(child->nodetype), parent->name);
1010 return EXIT_FAILURE;
1011 }
1012 break;
Radek Krejci76512572015-08-04 09:47:08 +02001013 case LYS_LEAF:
1014 case LYS_LEAFLIST:
1015 case LYS_ANYXML:
Radek Krejci10c760e2015-08-14 14:45:43 +02001016 LOGVAL(LYE_SPEC, 0, "The \"%s\" statement (%s) cannot have any data substatement.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001017 strnodetype(parent->nodetype), parent->name);
1018 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +02001019 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001020 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +02001021 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
1022 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001023 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001024 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
1025 return EXIT_FAILURE;
1026 }
Michal Vasko591e0b22015-08-13 13:53:43 +02001027 break;
1028 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +02001029 /* top level */
1030 if (!(child->nodetype &
1031 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
1032 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci2c0ca272015-08-14 15:31:01 +02001033 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in (sub)module \"%s\"",
1034 strnodetype(child->nodetype), module->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02001035 return EXIT_FAILURE;
1036 }
1037
1038 break;;
1039 }
1040
1041 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +02001042 if (lys_check_id(child, parent, module)) {
1043 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001044 }
Radek Krejcib7155b52015-06-10 17:03:01 +02001045
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001046 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001047 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001048 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001049
Radek Krejci10c760e2015-08-14 14:45:43 +02001050 if (!parent) {
Radek Krejci92720552015-10-05 15:28:27 +02001051 if (module->data) {
1052 module->data->prev->next = child;
1053 child->prev = module->data->prev;
1054 module->data->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +02001055 } else {
Radek Krejci92720552015-10-05 15:28:27 +02001056 module->data = child;
Radek Krejci10c760e2015-08-14 14:45:43 +02001057 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001058 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +02001059 if (!parent->child) {
1060 /* the only/first child of the parent */
1061 parent->child = child;
1062 child->parent = parent;
1063 iter = child;
1064 } else {
1065 /* add a new child at the end of parent's child list */
1066 iter = parent->child->prev;
1067 iter->next = child;
1068 child->prev = iter;
1069 }
1070 while (iter->next) {
1071 iter = iter->next;
1072 iter->parent = parent;
1073 }
1074 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001075 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001076
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001077 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001078}
1079
Radek Krejcib8048692015-08-05 13:36:34 +02001080API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +02001081lys_parse(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001082{
Michal Vaskof02e3742015-08-05 16:27:02 +02001083 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +02001084 struct lys_module *mod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001086 if (!ctx || !data) {
1087 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1088 return NULL;
1089 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001090
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001091 unres = calloc(1, sizeof *unres);
1092
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001093 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001094 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001095 mod = yin_read_module(ctx, data, 1, unres);
1096 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001097 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001098 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001099 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001100 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001101 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001102
Michal Vasko0bd29d12015-08-19 11:45:49 +02001103 if (mod && unres->count && resolve_unres_schema(mod, unres)) {
Michal Vasko13b15832015-08-19 11:04:48 +02001104 lys_free(mod, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001105 mod = NULL;
1106 }
1107 free(unres->item);
1108 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +02001109 free(unres->str_snode);
Michal Vaskoc07187d2015-08-13 15:20:57 +02001110#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001111 free(unres->line);
Michal Vaskoc07187d2015-08-13 15:20:57 +02001112#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001113 free(unres);
1114
1115 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001116}
1117
Radek Krejcib8048692015-08-05 13:36:34 +02001118struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001119lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02001120{
Michal Vaskof02e3742015-08-05 16:27:02 +02001121 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +02001122 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001123
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001124 assert(module);
1125 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001126
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001127 unres = calloc(1, sizeof *unres);
1128
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001129 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001130 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001131 submod = yin_read_submodule(module, data, implement, unres);
1132 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001133 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001134 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001135 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001136 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001137 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001138
Michal Vasko0bd29d12015-08-19 11:45:49 +02001139 if (submod && unres->count && resolve_unres_schema((struct lys_module *)submod, unres)) {
Michal Vasko13b15832015-08-19 11:04:48 +02001140 lys_submodule_free(submod, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001141 submod = NULL;
1142 }
1143 free(unres->item);
1144 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +02001145 free(unres->str_snode);
Michal Vaskoc07187d2015-08-13 15:20:57 +02001146#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001147 free(unres->line);
Michal Vaskoc07187d2015-08-13 15:20:57 +02001148#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001149 free(unres);
1150
1151 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001152}
1153
Radek Krejcib8048692015-08-05 13:36:34 +02001154API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +02001155lys_read(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001156{
Radek Krejcib8048692015-08-05 13:36:34 +02001157 struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +02001158 struct stat sb;
1159 char *addr;
1160
1161 if (!ctx || fd < 0) {
1162 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1163 return NULL;
1164 }
1165
1166 /*
1167 * TODO
1168 * This is just a temporary solution to make working automatic search for
1169 * imported modules. This doesn't work e.g. for streams (stdin)
1170 */
1171 fstat(fd, &sb);
1172 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001173 if (addr == MAP_FAILED) {
1174 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
1175 return NULL;
1176 }
Radek Krejci63a91a92015-07-29 13:31:04 +02001177 module = lys_parse(ctx, addr, format);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001178 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001180 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001181}
1182
Radek Krejcib8048692015-08-05 13:36:34 +02001183struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001184lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02001185{
Radek Krejcib8048692015-08-05 13:36:34 +02001186 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001187 struct stat sb;
1188 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001189
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001190 assert(module);
1191 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001192
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001193 /*
1194 * TODO
1195 * This is just a temporary solution to make working automatic search for
1196 * imported modules. This doesn't work e.g. for streams (stdin)
1197 */
1198 fstat(fd, &sb);
1199 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001200 if (addr == MAP_FAILED) {
1201 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
1202 return NULL;
1203 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001204 submodule = lys_submodule_parse(module, addr, format, implement);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001205 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +02001206
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001207 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02001208
1209}
1210
Radek Krejci1d82ef62015-08-07 14:44:40 +02001211static struct lys_restr *
1212lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001213{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001214 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001215 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001216
Radek Krejci3733a802015-06-19 13:43:21 +02001217 if (!size) {
1218 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001219 }
Radek Krejci3733a802015-06-19 13:43:21 +02001220
1221 result = calloc(size, sizeof *result);
1222 for (i = 0; i < size; i++) {
1223 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1224 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1225 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1226 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1227 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1228 }
1229
1230 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001231}
1232
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001233void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001234lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001235{
1236 assert(ctx);
1237 if (!restr) {
1238 return;
1239 }
1240
1241 lydict_remove(ctx, restr->expr);
1242 lydict_remove(ctx, restr->dsc);
1243 lydict_remove(ctx, restr->ref);
1244 lydict_remove(ctx, restr->eapptag);
1245 lydict_remove(ctx, restr->emsg);
1246}
1247
Michal Vaskob84f88a2015-09-24 13:16:10 +02001248static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001249lys_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 +02001250 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001251{
1252 int i;
1253
Michal Vasko1dca6882015-10-22 14:29:42 +02001254 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001255 new->base = old->base;
1256 new->der = old->der;
1257
Michal Vasko0bd29d12015-08-19 11:45:49 +02001258 i = unres_schema_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001259 if (i != -1) {
1260 /* HACK for unres */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001261 new->der = (struct lys_tpdf *)parent;
Michal Vaskob84f88a2015-09-24 13:16:10 +02001262 /* all these unres additions can fail even though they did not before */
Michal Vasko0bd29d12015-08-19 11:45:49 +02001263 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_DER, unres->str_snode[i], 0) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001264 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001265 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001266 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001267 }
1268
Radek Krejci3733a802015-06-19 13:43:21 +02001269 switch (new->base) {
1270 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +02001271 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001272 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001273 }
Radek Krejci3733a802015-06-19 13:43:21 +02001274 break;
1275
1276 case LY_TYPE_BITS:
1277 new->info.bits.count = old->info.bits.count;
1278 if (new->info.bits.count) {
1279 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1280 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001281 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1282 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1283 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001284 new->info.bits.bit[i].status = old->info.bits.bit[i].status;
1285 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1286 }
1287 }
1288 break;
1289
Radek Krejcif9401c32015-06-26 16:47:36 +02001290 case LY_TYPE_DEC64:
1291 new->info.dec64.dig = old->info.dec64.dig;
1292 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001293 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +02001294 }
1295 break;
1296
Radek Krejci3733a802015-06-19 13:43:21 +02001297 case LY_TYPE_ENUM:
1298 new->info.enums.count = old->info.enums.count;
1299 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001300 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Radek Krejci3733a802015-06-19 13:43:21 +02001301 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001302 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1303 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1304 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1305 new->info.enums.enm[i].status = old->info.enums.enm[i].status;
1306 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +02001307 }
1308 }
1309 break;
1310
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001311 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001312 if (old->info.ident.ref) {
1313 new->info.ident.ref = old->info.ident.ref;
1314 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001315 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001316 assert(i != -1);
Michal Vasko0bd29d12015-08-19 11:45:49 +02001317 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i], 0) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001318 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001319 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001320 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001321 break;
1322
Radek Krejciaf351422015-06-19 14:49:38 +02001323 case LY_TYPE_INST:
1324 new->info.inst.req = old->info.inst.req;
1325 break;
1326
Radek Krejcif2860132015-06-20 12:37:20 +02001327 case LY_TYPE_INT8:
1328 case LY_TYPE_INT16:
1329 case LY_TYPE_INT32:
1330 case LY_TYPE_INT64:
1331 case LY_TYPE_UINT8:
1332 case LY_TYPE_UINT16:
1333 case LY_TYPE_UINT32:
1334 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +02001335 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001336 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001337 }
Radek Krejcif2860132015-06-20 12:37:20 +02001338 break;
1339
Radek Krejcidc4c1412015-06-19 15:39:54 +02001340 case LY_TYPE_LEAFREF:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001341 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02001342 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001343 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001344 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001345 break;
1346
Radek Krejci3733a802015-06-19 13:43:21 +02001347 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +02001348 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001349 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001350 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001351 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 +02001352 break;
1353
Radek Krejcie4c366b2015-07-02 10:11:31 +02001354 case LY_TYPE_UNION:
1355 new->info.uni.count = old->info.uni.count;
1356 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001357 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001358 for (i = 0; i < new->info.uni.count; i++) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001359 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres)) {
1360 return -1;
1361 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001362 }
1363 }
1364 break;
1365
Radek Krejci3733a802015-06-19 13:43:21 +02001366 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001367 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001368 break;
1369 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001370
1371 return EXIT_SUCCESS;
Radek Krejci3733a802015-06-19 13:43:21 +02001372}
1373
1374void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001375lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001376{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001377 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001378
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001379 assert(ctx);
1380 if (!type) {
1381 return;
1382 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001383
Michal Vasko1dca6882015-10-22 14:29:42 +02001384 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001385
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001386 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001387 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001388 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001389 free(type->info.binary.length);
1390 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001391 case LY_TYPE_BITS:
1392 for (i = 0; i < type->info.bits.count; i++) {
1393 lydict_remove(ctx, type->info.bits.bit[i].name);
1394 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1395 lydict_remove(ctx, type->info.bits.bit[i].ref);
1396 }
1397 free(type->info.bits.bit);
1398 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001399
1400 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001401 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001402 free(type->info.dec64.range);
1403 break;
1404
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001405 case LY_TYPE_ENUM:
1406 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001407 lydict_remove(ctx, type->info.enums.enm[i].name);
1408 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1409 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001410 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001411 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001412 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001413
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001414 case LY_TYPE_INT8:
1415 case LY_TYPE_INT16:
1416 case LY_TYPE_INT32:
1417 case LY_TYPE_INT64:
1418 case LY_TYPE_UINT8:
1419 case LY_TYPE_UINT16:
1420 case LY_TYPE_UINT32:
1421 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001422 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001423 free(type->info.num.range);
1424 break;
1425
Radek Krejcidc4c1412015-06-19 15:39:54 +02001426 case LY_TYPE_LEAFREF:
1427 lydict_remove(ctx, type->info.lref.path);
1428 break;
1429
Radek Krejci3733a802015-06-19 13:43:21 +02001430 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001431 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001432 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001433 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001434 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001435 }
1436 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001437 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001438
Radek Krejcie4c366b2015-07-02 10:11:31 +02001439 case LY_TYPE_UNION:
1440 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001441 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001442 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001443 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001444 break;
1445
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001446 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001447 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001448 break;
1449 }
Radek Krejci5a065542015-05-22 15:02:07 +02001450}
1451
Radek Krejci1d82ef62015-08-07 14:44:40 +02001452static void
1453lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001454{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001455 assert(ctx);
1456 if (!tpdf) {
1457 return;
1458 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001459
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001460 lydict_remove(ctx, tpdf->name);
1461 lydict_remove(ctx, tpdf->dsc);
1462 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001463
Radek Krejci1d82ef62015-08-07 14:44:40 +02001464 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001465
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001466 lydict_remove(ctx, tpdf->units);
1467 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001468}
1469
Michal Vaskob84f88a2015-09-24 13:16:10 +02001470static struct lys_tpdf *
1471lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1472{
1473 struct lys_tpdf *result;
1474 int i, j;
1475
1476 if (!size) {
1477 return NULL;
1478 }
1479
1480 result = calloc(size, sizeof *result);
1481 for (i = 0; i < size; i++) {
1482 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1483 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1484 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1485 result[i].flags = old[i].flags;
1486 result[i].module = old[i].module;
1487
1488 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres)) {
1489 for (j = 0; j <= i; ++j) {
1490 lys_tpdf_free(mod->ctx, &result[j]);
1491 }
1492 free(result);
1493 return NULL;
1494 }
1495
1496 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1497 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1498 }
1499
1500 return result;
1501}
1502
Radek Krejci1d82ef62015-08-07 14:44:40 +02001503static struct lys_when *
1504lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001505{
Radek Krejci76512572015-08-04 09:47:08 +02001506 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001507
1508 if (!old) {
1509 return NULL;
1510 }
1511
1512 new = calloc(1, sizeof *new);
1513 new->cond = lydict_insert(ctx, old->cond, 0);
1514 new->dsc = lydict_insert(ctx, old->dsc, 0);
1515 new->ref = lydict_insert(ctx, old->ref, 0);
1516
1517 return new;
1518}
1519
Michal Vasko0308dd62015-10-07 09:14:40 +02001520void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001521lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001522{
1523 if (!w) {
1524 return;
1525 }
1526
1527 lydict_remove(ctx, w->cond);
1528 lydict_remove(ctx, w->dsc);
1529 lydict_remove(ctx, w->ref);
1530
1531 free(w);
1532}
1533
Radek Krejcib7f5e412015-08-13 10:15:51 +02001534static void
1535lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment aug)
1536{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001537 struct lys_node *next, *sub;
1538
1539 /* children from a resolved uses */
1540 LY_TREE_FOR_SAFE(aug.child, next, sub) {
1541 lys_node_free(sub);
1542 }
1543
Radek Krejcib7f5e412015-08-13 10:15:51 +02001544 lydict_remove(ctx, aug.target_name);
1545 lydict_remove(ctx, aug.dsc);
1546 lydict_remove(ctx, aug.ref);
1547
1548 free(aug.features);
1549
1550 lys_when_free(ctx, aug.when);
1551
Michal Vasko7d356a52015-08-19 15:06:31 +02001552 /* Do not free the children, they were appended somewhere and their
1553 * new parent will take care of them.
1554 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001555}
1556
Radek Krejci76512572015-08-04 09:47:08 +02001557static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001558lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001559{
Radek Krejci76512572015-08-04 09:47:08 +02001560 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001561 struct lys_node *old_child, *new_child;
1562 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001563
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001564 if (!size) {
1565 return NULL;
1566 }
Radek Krejci106efc02015-06-10 14:36:27 +02001567
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001568 new = calloc(size, sizeof *new);
1569 for (i = 0; i < size; i++) {
1570 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1571 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1572 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1573 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001574 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001575 new[i].nodetype = old[i].nodetype;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001576 /* this must succeed, it was already resolved once */
1577 if (resolve_schema_nodeid(new[i].target_name, parent->child, new[i].module, LYS_AUGMENT, &new[i].target)) {
1578 LOGINT;
1579 free(new);
1580 return NULL;
1581 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001582 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001583
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001584 /* Correct the augment nodes.
1585 * This function can only be called from lys_node_dup() with uses
1586 * being the node duplicated, so we must have a case of grouping
1587 * with a uses with augments. The augmented nodes have already been
1588 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001589 * (it was set to their actual data parent, not an augment), and
1590 * the new augment does not have child pointer to its augment nodes,
1591 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001592 */
1593 LY_TREE_FOR(new[i].target->child, new_child) {
1594 if (new_child->name == old[i].child->name) {
1595 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001596 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001597 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001598 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001599 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001600 LY_TREE_FOR(old[i].child, old_child) {
1601 /* all augment nodes were connected as siblings, there can be no more after this */
1602 if (old_child->parent != (struct lys_node *)&old[i]) {
1603 break;
1604 }
1605
1606 assert(old_child->name == new_child->name);
1607
1608 new_child->parent = (struct lys_node *)&new[i];
1609 new_child = new_child->next;
1610 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001611 }
Radek Krejci106efc02015-06-10 14:36:27 +02001612
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001613 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001614}
1615
Radek Krejci76512572015-08-04 09:47:08 +02001616static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001617lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001618{
Radek Krejci76512572015-08-04 09:47:08 +02001619 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001620 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001621
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001622 if (!size) {
1623 return NULL;
1624 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001625
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001626 result = calloc(size, sizeof *result);
1627 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001628 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001629 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1630 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001631 result[i].flags = old[i].flags;
1632 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001633
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001634 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001635 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001636
Radek Krejci76512572015-08-04 09:47:08 +02001637 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001638 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001639 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001640 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001641 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001642 result[i].mod.list = old[i].mod.list;
1643 }
1644 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001645
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001646 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001647}
1648
Radek Krejci1d82ef62015-08-07 14:44:40 +02001649static void
1650lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001651{
Radek Krejcia52656e2015-08-05 13:41:50 +02001652 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001653
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001654 assert(ctx);
1655 if (!ident) {
1656 return;
1657 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001658
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001659 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001660 * if caller free only a single data model which is used (its identity is
1661 * reference from identity in another module), this silly freeing can lead
1662 * to segmentation fault. But without noting if the module is used by some
1663 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001664 *
1665 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001666 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001667 */
1668 while (ident->der) {
1669 der = ident->der;
1670 ident->der = der->next;
1671 free(der);
1672 }
Radek Krejci6793db02015-05-22 17:49:54 +02001673
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001674 lydict_remove(ctx, ident->name);
1675 lydict_remove(ctx, ident->dsc);
1676 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001677
1678}
1679
Radek Krejci1d82ef62015-08-07 14:44:40 +02001680static void
1681lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001682{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001683 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001684
Radek Krejcid12f57b2015-08-06 10:43:39 +02001685 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001686 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001687 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001688 }
1689 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001690}
1691
Radek Krejci1d82ef62015-08-07 14:44:40 +02001692static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001693lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1694{
1695 int i;
1696
1697 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1698 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001699 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001700 }
1701 free(io->tpdf);
1702}
1703
Radek Krejci1d82ef62015-08-07 14:44:40 +02001704static void
1705lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001706{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001707 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001708
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001709 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001710 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001711 }
1712 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001713
Radek Krejci1d82ef62015-08-07 14:44:40 +02001714 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001715}
1716
Radek Krejci1d82ef62015-08-07 14:44:40 +02001717static void
1718lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001719{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001720 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001721
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001722 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001723 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001724 }
1725 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001726
Radek Krejci1d82ef62015-08-07 14:44:40 +02001727 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001728
Radek Krejci1d82ef62015-08-07 14:44:40 +02001729 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001730 lydict_remove(ctx, leaf->units);
1731 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001732}
1733
Radek Krejci1d82ef62015-08-07 14:44:40 +02001734static void
1735lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001736{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001737 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001738
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001739 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001740 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001741 }
1742 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001743
Radek Krejci1d82ef62015-08-07 14:44:40 +02001744 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001745
Radek Krejci1d82ef62015-08-07 14:44:40 +02001746 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001747 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001748}
1749
Radek Krejci1d82ef62015-08-07 14:44:40 +02001750static void
1751lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001752{
Radek Krejci581ce772015-11-10 17:22:40 +01001753 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001754
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001755 /* handle only specific parts for LY_NODE_LIST */
1756 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001757 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001758 }
1759 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001760
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001761 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001762 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001763 }
1764 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001765
Radek Krejci1d82ef62015-08-07 14:44:40 +02001766 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001767
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001768 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001769 for (j = 0; j > list->unique[i].expr_size; j++) {
1770 lydict_remove(ctx, list->unique[i].expr[j]);
1771 }
1772 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001773 }
1774 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001775
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001776 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001777}
1778
Radek Krejci1d82ef62015-08-07 14:44:40 +02001779static void
1780lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001781{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001782 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001783
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001784 /* handle only specific parts for LY_NODE_CONTAINER */
1785 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001786
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001787 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001788 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001789 }
1790 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001791
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001792 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001793 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001794 }
1795 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001796
Radek Krejci1d82ef62015-08-07 14:44:40 +02001797 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001798}
1799
Radek Krejci1d82ef62015-08-07 14:44:40 +02001800static void
1801lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001802{
1803 lydict_remove(ctx, f->name);
1804 lydict_remove(ctx, f->dsc);
1805 lydict_remove(ctx, f->ref);
1806 free(f->features);
1807}
1808
Radek Krejci1d82ef62015-08-07 14:44:40 +02001809static void
1810lys_deviation_free(struct ly_ctx *ctx, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001811{
Radek Krejci581ce772015-11-10 17:22:40 +01001812 int i, j, k;
Radek Krejcieb00f512015-07-01 16:44:58 +02001813
1814 lydict_remove(ctx, dev->target_name);
1815 lydict_remove(ctx, dev->dsc);
1816 lydict_remove(ctx, dev->ref);
1817
1818 for (i = 0; i < dev->deviate_size; i++) {
1819 lydict_remove(ctx, dev->deviate[i].dflt);
1820 lydict_remove(ctx, dev->deviate[i].units);
1821
1822 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1823 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001824 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001825 }
1826 free(dev->deviate[i].must);
1827
1828 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001829 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1830 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1831 }
1832 free(dev->deviate[j].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001833 }
1834 free(dev->deviate[i].unique);
1835 }
1836 }
1837 free(dev->deviate);
1838}
1839
Radek Krejci1d82ef62015-08-07 14:44:40 +02001840static void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001841lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +02001842{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001843 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001844
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001845 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001846 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001847 lydict_remove(ctx, uses->refine[i].dsc);
1848 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001849
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001850 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001851 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001852 }
1853 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001854
Radek Krejci76512572015-08-04 09:47:08 +02001855 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001856 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001857 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001858 lydict_remove(ctx, uses->refine[i].mod.presence);
1859 }
1860 }
1861 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001862
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001863 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001864 lys_augment_free(ctx, uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001865 }
1866 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001867
Radek Krejci1d82ef62015-08-07 14:44:40 +02001868 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001869}
1870
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001871void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001872lys_node_free(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001873{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001874 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001875 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001876
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001877 if (!node) {
1878 return;
1879 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001880
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001881 assert(node->module);
1882 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001883
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001884 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001885
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001886 /* common part */
1887 LY_TREE_FOR_SAFE(node->child, next, sub) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001888 lys_node_free(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001889 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001890
Radek Krejcid12f57b2015-08-06 10:43:39 +02001891 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1892 free(node->features);
1893 lydict_remove(ctx, node->name);
1894 lydict_remove(ctx, node->dsc);
1895 lydict_remove(ctx, node->ref);
1896 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001897
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001898 /* specific part */
1899 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001900 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001901 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001902 break;
Radek Krejci76512572015-08-04 09:47:08 +02001903 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001904 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001905 break;
Radek Krejci76512572015-08-04 09:47:08 +02001906 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001907 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001908 break;
Radek Krejci76512572015-08-04 09:47:08 +02001909 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001910 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001911 break;
Radek Krejci76512572015-08-04 09:47:08 +02001912 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001913 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001914 break;
Radek Krejci76512572015-08-04 09:47:08 +02001915 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001916 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001917 break;
Radek Krejci76512572015-08-04 09:47:08 +02001918 case LYS_USES:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001919 lys_uses_free(ctx, (struct lys_node_uses *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001920 break;
Radek Krejci76512572015-08-04 09:47:08 +02001921 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001922 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001923 break;
Radek Krejci76512572015-08-04 09:47:08 +02001924 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001925 /* do nothing */
1926 break;
Radek Krejci76512572015-08-04 09:47:08 +02001927 case LYS_GROUPING:
1928 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001929 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001930 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001931 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001932
1933 case LYS_INPUT:
1934 case LYS_OUTPUT:
1935 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1936 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001937 case LYS_UNKNOWN:
1938 LOGINT;
1939 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001940 }
Radek Krejci5a065542015-05-22 15:02:07 +02001941
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001942 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001943 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001944 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001945}
1946
Michal Vasko8ce24d72015-10-21 11:27:26 +02001947struct lys_module *
Michal Vaskob6729c62015-10-21 12:09:47 +02001948lys_get_import_module(struct lys_module *module, const char *prefix, int pref_len, const char *name, int name_len)
Michal Vasko8ce24d72015-10-21 11:27:26 +02001949{
Michal Vaskob6729c62015-10-21 12:09:47 +02001950 int i, match;
1951
1952 assert(prefix || name);
1953 if (prefix && !pref_len) {
1954 pref_len = strlen(prefix);
1955 }
1956 if (name && !name_len) {
1957 name_len = strlen(name);
1958 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02001959
Michal Vaskod8da86b2015-10-21 13:35:37 +02001960 if ((!prefix || (!strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
1961 && (!name || (!strncmp(module->name, name, name_len) && !module->name[name_len]))) {
1962 return module;
1963 }
1964
Michal Vasko8ce24d72015-10-21 11:27:26 +02001965 for (i = 0; i < module->imp_size; ++i) {
Michal Vaskob6729c62015-10-21 12:09:47 +02001966 match = 0;
1967 if (!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len])) {
1968 match = 1;
1969 }
1970 if (match && (!name
1971 || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02001972 return module->imp[i].module;
1973 }
1974 }
1975
1976 return NULL;
1977}
1978
Michal Vasko13b15832015-08-19 11:04:48 +02001979/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001980static void
Michal Vasko13b15832015-08-19 11:04:48 +02001981module_free_common(struct lys_module *module, int free_int_mods)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001982{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001983 struct ly_ctx *ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001984 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001985 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001986
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001987 assert(module->ctx);
1988 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001989
Radek Krejcidce51452015-06-16 15:20:08 +02001990 /* as first step, free the imported modules */
1991 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa76ee152015-08-17 15:38:22 +02001992 /* do not free internal modules */
Michal Vasko18bd09b2015-08-19 15:07:00 +02001993 if (!free_int_mods) {
1994 for (j = 0; j < int_mods.count; ++j) {
Michal Vaskod83c03a2015-08-21 09:09:24 +02001995 if (module->imp[i].module && !strcmp(int_mods.modules[j].name, module->imp[i].module->name)
Michal Vasko18bd09b2015-08-19 15:07:00 +02001996 && module->imp[i].module->rev
1997 && !strcmp(int_mods.modules[j].revision, module->imp[i].module->rev[0].date)) {
1998 break;
1999 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02002000 }
Michal Vasko18bd09b2015-08-19 15:07:00 +02002001 if (j < int_mods.count) {
2002 continue;
2003 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02002004 }
2005
Radek Krejcidce51452015-06-16 15:20:08 +02002006 /* get the imported module from the context and then free,
2007 * this check is necessary because the imported module can
2008 * be already removed
2009 */
2010 l = ctx->models.used;
2011 for (j = 0; j < l; j++) {
2012 if (ctx->models.list[j] == module->imp[i].module) {
Michal Vasko13b15832015-08-19 11:04:48 +02002013 lys_free(module->imp[i].module, free_int_mods);
Radek Krejcidce51452015-06-16 15:20:08 +02002014 break;
2015 }
2016 }
2017 }
2018 free(module->imp);
2019
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002020 while (module->data) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002021 lys_node_free(module->data);
Radek Krejci21181962015-06-30 14:11:00 +02002022 }
Radek Krejci5a065542015-05-22 15:02:07 +02002023
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002024 lydict_remove(ctx, module->dsc);
2025 lydict_remove(ctx, module->ref);
2026 lydict_remove(ctx, module->org);
2027 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002028
Radek Krejcieb00f512015-07-01 16:44:58 +02002029 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002030 for (i = 0; i < module->rev_size; i++) {
2031 lydict_remove(ctx, module->rev[i].dsc);
2032 lydict_remove(ctx, module->rev[i].ref);
2033 }
2034 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002035
Radek Krejcieb00f512015-07-01 16:44:58 +02002036 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002037 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002038 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002039 }
2040 module->ident_size = 0;
2041 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002042
Radek Krejcieb00f512015-07-01 16:44:58 +02002043 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002044 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002045 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002046 }
2047 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002048
Radek Krejcieb00f512015-07-01 16:44:58 +02002049 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002050 for (i = 0; i < module->inc_size; i++) {
Michal Vasko13b15832015-08-19 11:04:48 +02002051 lys_submodule_free(module->inc[i].submodule, free_int_mods);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002052 }
2053 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002054
Radek Krejcieb00f512015-07-01 16:44:58 +02002055 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002056 for (i = 0; i < module->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02002057 lys_augment_free(ctx, module->augment[i]);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002058 }
2059 free(module->augment);
2060
Radek Krejcieb00f512015-07-01 16:44:58 +02002061 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002062 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002063 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002064 }
2065 free(module->features);
2066
Radek Krejcieb00f512015-07-01 16:44:58 +02002067 /* deviations */
2068 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002069 lys_deviation_free(ctx, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002070 }
2071 free(module->deviation);
2072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002073 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02002074}
2075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002076void
Michal Vasko13b15832015-08-19 11:04:48 +02002077lys_submodule_free(struct lys_submodule *submodule, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02002078{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002079 if (!submodule) {
2080 return;
2081 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002082
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002083 submodule->inc_size = 0;
2084 free(submodule->inc);
2085 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02002086
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002087 /* common part with struct ly_module */
Michal Vasko13b15832015-08-19 11:04:48 +02002088 module_free_common((struct lys_module *)submodule, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02002089
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002090 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002091
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002092 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002093}
2094
Radek Krejci76512572015-08-04 09:47:08 +02002095struct lys_node *
Michal Vasko71e1aa82015-08-12 12:17:51 +02002096lys_node_dup(struct lys_module *module, struct lys_node *node, uint8_t flags, uint8_t nacm, int recursive,
Michal Vaskof02e3742015-08-05 16:27:02 +02002097 struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002098{
Radek Krejci76512572015-08-04 09:47:08 +02002099 struct lys_node *retval = NULL, *aux, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002100 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002101 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002102
Michal Vaskoc07187d2015-08-13 15:20:57 +02002103 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002104 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002105 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002106 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002107 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002108 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002109 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002110 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002111 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002112 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002113 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002114 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002115 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002116 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002117 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002118 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002119 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002120 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002121 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002122 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002123 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002124 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002125 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002126 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002127
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002128 /* we cannot just duplicate memory since the strings are stored in
2129 * dictionary and we need to update dictionary counters.
2130 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002131
Radek Krejci1d82ef62015-08-07 14:44:40 +02002132 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002133 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002134 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002135 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002136 break;
2137
Radek Krejci76512572015-08-04 09:47:08 +02002138 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002139 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002140 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002141 break;
2142
Radek Krejci76512572015-08-04 09:47:08 +02002143 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002144 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002145 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002146 break;
2147
Radek Krejci76512572015-08-04 09:47:08 +02002148 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002149 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002150 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002151 break;
2152
Radek Krejci76512572015-08-04 09:47:08 +02002153 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002154 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002155 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002156 break;
2157
Radek Krejci76512572015-08-04 09:47:08 +02002158 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002159 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002160 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002161 break;
2162
Radek Krejci76512572015-08-04 09:47:08 +02002163 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002164 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002165 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002166 break;
2167
Radek Krejci76512572015-08-04 09:47:08 +02002168 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002169 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002170 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002171 break;
2172
Radek Krejci76512572015-08-04 09:47:08 +02002173 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002174 grp = calloc(1, sizeof *grp);
2175 retval = (struct lys_node *)grp;
2176 break;
2177
Radek Krejci76512572015-08-04 09:47:08 +02002178 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002179 rpc = calloc(1, sizeof *rpc);
2180 retval = (struct lys_node *)rpc;
2181 break;
2182
Radek Krejci76512572015-08-04 09:47:08 +02002183 case LYS_INPUT:
2184 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002185 io = calloc(1, sizeof *io);
2186 retval = (struct lys_node *)io;
2187 break;
2188
Radek Krejci76512572015-08-04 09:47:08 +02002189 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002190 ntf = calloc(1, sizeof *ntf);
2191 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002192 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002194 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002195 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002196 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002197 }
Radek Krejcib388c152015-06-04 17:03:03 +02002198
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002199 /*
2200 * duplicate generic part of the structure
2201 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002202 retval->name = lydict_insert(ctx, node->name, 0);
2203 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2204 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002205 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002206 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002207 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002208 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002209 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002210 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002211
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002212 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002213 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002214
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002215 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002216
Radek Krejci1d82ef62015-08-07 14:44:40 +02002217 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002218 retval->features = calloc(retval->features_size, sizeof *retval->features);
Radek Krejci1d82ef62015-08-07 14:44:40 +02002219 for (i = 0; i < node->features_size; ++i) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002220 if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002221 retval->features[i] = node->features[i];
Michal Vaskod23ce592015-08-06 09:55:37 +02002222 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002223 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002224
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002225 if (recursive) {
2226 /* go recursively */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002227 LY_TREE_FOR(node->child, child) {
Michal Vasko71e1aa82015-08-12 12:17:51 +02002228 aux = lys_node_dup(module, child, retval->flags, retval->nacm, 1, unres);
Radek Krejci10c760e2015-08-14 14:45:43 +02002229 if (!aux || lys_node_addchild(retval, NULL, aux)) {
Michal Vasko49168a22015-08-17 16:35:41 +02002230 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002231 }
2232 }
2233 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002234
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002235 /*
2236 * duplicate specific part of the structure
2237 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002238 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002239 case LYS_CONTAINER:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002240 if (cont_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002241 cont->when = lys_when_dup(ctx, cont_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002242 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002243 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002244
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002245 cont->must_size = cont_orig->must_size;
2246 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002247
Radek Krejci1d82ef62015-08-07 14:44:40 +02002248 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci1d82ef62015-08-07 14:44:40 +02002249 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002250 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002251
Radek Krejci76512572015-08-04 09:47:08 +02002252 case LYS_CHOICE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002253 if (choice_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002254 choice->when = lys_when_dup(ctx, choice_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002255 }
2256
2257 if (choice_orig->dflt) {
Michal Vasko165dc4a2015-10-23 09:44:27 +02002258 rc = lys_get_sibling(choice->module, choice->child, NULL, 0, choice_orig->dflt->name, 0, LYS_ANYXML
Radek Krejci76512572015-08-04 09:47:08 +02002259 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002260 | LYS_LIST, &choice->dflt);
Michal Vasko49168a22015-08-17 16:35:41 +02002261 if (rc) {
2262 if (rc == EXIT_FAILURE) {
2263 LOGINT;
2264 }
2265 goto error;
2266 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002267 } else {
Michal Vaskoc68a2a22015-08-06 09:57:24 +02002268 /* useless to check return value, we don't know whether
2269 * there really wasn't any default defined or it just hasn't
2270 * been resolved, we just hope for the best :)
2271 */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002272 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002273 }
2274 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002275
Radek Krejci76512572015-08-04 09:47:08 +02002276 case LYS_LEAF:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002277 if (lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres)) {
2278 goto error;
2279 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002280 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2281
2282 if (leaf_orig->dflt) {
2283 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002284 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002285 goto error;
2286 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002287 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002288
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002289 leaf->must_size = leaf_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002290 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002291
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002292 if (leaf_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002293 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002294 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002295 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002296
Radek Krejci76512572015-08-04 09:47:08 +02002297 case LYS_LEAFLIST:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002298 if (lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres)) {
2299 goto error;
2300 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002301 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002302
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002303 llist->min = llist_orig->min;
2304 llist->max = llist_orig->max;
2305
2306 llist->must_size = llist_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002307 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002308
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002309 if (llist_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002310 llist->when = lys_when_dup(ctx, llist_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002311 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002312 break;
2313
Radek Krejci76512572015-08-04 09:47:08 +02002314 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002315 list->min = list_orig->min;
2316 list->max = list_orig->max;
2317
2318 list->must_size = list_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002319 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002320
Radek Krejci581ce772015-11-10 17:22:40 +01002321 list->tpdf_size = list_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002322 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002323
Radek Krejci581ce772015-11-10 17:22:40 +01002324 list->keys_size = list_orig->keys_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002325 if (list->keys_size) {
2326 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002327
2328 /* we managed to resolve it before, resolve it again manually */
2329 if (list_orig->keys[0]) {
2330 for (i = 0; i < list->keys_size; ++i) {
Michal Vasko165dc4a2015-10-23 09:44:27 +02002331 rc = lys_get_sibling(list->module, list->child, NULL, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2332 (struct lys_node **)&list->keys[i]);
Michal Vasko49168a22015-08-17 16:35:41 +02002333 if (rc) {
2334 if (rc == EXIT_FAILURE) {
2335 LOGINT;
2336 }
2337 goto error;
2338 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002339 }
2340 /* it was not resolved yet, add unres copy */
2341 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002342 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02002343 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002344 goto error;
Michal Vaskod23ce592015-08-06 09:55:37 +02002345 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002346 }
2347 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002348
Radek Krejci581ce772015-11-10 17:22:40 +01002349 list->unique_size = list_orig->unique_size;
2350 list->unique = malloc(list->unique_size * sizeof *list->unique);
2351 for (i = 0; i < list->unique_size; ++i) {
2352 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2353 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
2354 for (j = 0; j < list->unique[i].expr_size; j++) {
2355 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2356
2357 /* if it stays in unres list, duplicate it also there */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002358 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002359 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002360 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002361
2362 if (list_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002363 list->when = lys_when_dup(ctx, list_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002364 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002365 break;
2366
Radek Krejci76512572015-08-04 09:47:08 +02002367 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002368 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002369 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002370
2371 if (anyxml_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002372 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002373 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002374 break;
2375
Radek Krejci76512572015-08-04 09:47:08 +02002376 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002377 uses->grp = uses_orig->grp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002378
2379 if (uses_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002380 uses->when = lys_when_dup(ctx, uses_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002381 }
2382
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002383 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002384 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002385 uses->augment_size = uses_orig->augment_size;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02002386 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Michal Vaskof8c128d2015-08-06 15:25:28 +02002387 if (!uses->child) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002388 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002389 goto error;
2390 }
Michal Vaskof8c128d2015-08-06 15:25:28 +02002391 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002392 break;
2393
Radek Krejci76512572015-08-04 09:47:08 +02002394 case LYS_CASE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002395 if (cs_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002396 cs->when = lys_when_dup(ctx, cs_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002397 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002398 break;
2399
Radek Krejci76512572015-08-04 09:47:08 +02002400 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002401 grp->tpdf_size = grp_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002402 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002403 break;
2404
Radek Krejci76512572015-08-04 09:47:08 +02002405 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002406 rpc->tpdf_size = rpc_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002407 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002408 break;
2409
Radek Krejci76512572015-08-04 09:47:08 +02002410 case LYS_INPUT:
2411 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002412 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002413 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002414 break;
2415
Radek Krejci76512572015-08-04 09:47:08 +02002416 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002417 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002418 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcia01e5432015-06-16 10:35:25 +02002419 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002420
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002421 default:
Radek Krejci00768f42015-06-18 17:04:04 +02002422 /* LY_NODE_AUGMENT */
Michal Vaskod23ce592015-08-06 09:55:37 +02002423 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002424 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002425 }
2426
2427 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002428
2429error:
2430
2431 lys_node_free(retval);
2432 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002433}
2434
Michal Vasko13b15832015-08-19 11:04:48 +02002435void
2436lys_free(struct lys_module *module, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02002437{
Radek Krejcidce51452015-06-16 15:20:08 +02002438 struct ly_ctx *ctx;
2439 int i;
2440
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002441 if (!module) {
2442 return;
2443 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002444
Radek Krejcidce51452015-06-16 15:20:08 +02002445 /* remove schema from the context */
2446 ctx = module->ctx;
2447 if (ctx->models.used) {
2448 for (i = 0; i < ctx->models.used; i++) {
2449 if (ctx->models.list[i] == module) {
2450 /* replace the position in the list by the last module in the list */
2451 ctx->models.used--;
2452 ctx->models.list[i] = ctx->models.list[ctx->models.used];
2453 ctx->models.list[ctx->models.used] = NULL;
2454 /* we are done */
2455 break;
2456 }
2457 }
2458 }
2459
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002460 /* common part with struct ly_submodule */
Michal Vasko13b15832015-08-19 11:04:48 +02002461 module_free_common(module, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02002462
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002463 /* specific items to free */
2464 lydict_remove(module->ctx, module->ns);
2465 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02002466
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002467 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002468}
Radek Krejci7e97c352015-06-19 16:26:34 +02002469
2470/*
2471 * op: 1 - enable, 0 - disable
2472 */
2473static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002474lys_features_change(struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002475{
2476 int all = 0;
2477 int i, j, k;
2478
2479 if (!module || !name || !strlen(name)) {
2480 return EXIT_FAILURE;
2481 }
2482
2483 if (!strcmp(name, "*")) {
2484 /* enable all */
2485 all = 1;
2486 }
2487
2488 /* module itself */
2489 for (i = 0; i < module->features_size; i++) {
2490 if (all || !strcmp(module->features[i].name, name)) {
2491 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002492 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002493 /* enable referenced features (recursion) */
2494 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002495 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002496 module->features[i].features[k]->name, op);
2497 }
2498 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002499 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002500 }
2501 if (!all) {
2502 return EXIT_SUCCESS;
2503 }
2504 }
2505 }
2506
2507 /* submodules */
2508 for (j = 0; j < module->inc_size; j++) {
2509 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2510 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2511 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002512 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002513 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002514 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002515 }
2516 if (!all) {
2517 return EXIT_SUCCESS;
2518 }
2519 }
2520 }
2521 }
2522
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002523 /* TODO submodules of submodules ... */
2524
Radek Krejci7e97c352015-06-19 16:26:34 +02002525 if (all) {
2526 return EXIT_SUCCESS;
2527 } else {
2528 return EXIT_FAILURE;
2529 }
2530}
2531
2532API int
Radek Krejcib8048692015-08-05 13:36:34 +02002533lys_features_enable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002534{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002535 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002536}
2537
2538API int
Radek Krejcib8048692015-08-05 13:36:34 +02002539lys_features_disable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002540{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002541 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002542}
2543
2544API int
Radek Krejcib8048692015-08-05 13:36:34 +02002545lys_features_state(struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002546{
2547 int i, j;
2548
2549 if (!module || !feature) {
2550 return -1;
2551 }
2552
2553 /* search for the specified feature */
2554 /* module itself */
2555 for (i = 0; i < module->features_size; i++) {
2556 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002557 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002558 return 1;
2559 } else {
2560 return 0;
2561 }
2562 }
2563 }
2564
2565 /* submodules */
2566 for (j = 0; j < module->inc_size; j++) {
2567 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2568 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002569 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002570 return 1;
2571 } else {
2572 return 0;
2573 }
2574 }
2575 }
2576 }
2577
2578 /* TODO submodules of submodules ... */
2579
2580 /* feature definition not found */
2581 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002582}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002583
Radek Krejci96a10da2015-07-30 11:00:14 +02002584API const char **
Radek Krejcib8048692015-08-05 13:36:34 +02002585lys_features_list(struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002586{
Radek Krejci96a10da2015-07-30 11:00:14 +02002587 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002588 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002589 unsigned int count;
2590
2591 if (!module) {
2592 return NULL;
2593 }
2594
2595 count = module->features_size;
2596 for (i = 0; i < module->inc_size; i++) {
2597 count += module->inc[i].submodule->features_size;
2598 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002599 result = malloc((count + 1) * sizeof *result);
2600 if (states) {
2601 *states = malloc((count + 1) * sizeof **states);
Michal Vasko2367e7c2015-07-07 11:33:44 +02002602 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002603 count = 0;
2604
2605 /* module itself */
2606 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002607 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002608 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002609 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002610 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002611 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002612 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002613 }
2614 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002615 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002616 }
2617
2618 /* submodules */
2619 for (j = 0; j < module->inc_size; j++) {
2620 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002621 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002622 if (states) {
2623 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2624 (*states)[count] = 1;
2625 } else {
2626 (*states)[count] = 0;
2627 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002628 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002629 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002630 }
2631 }
2632
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002633 /* TODO submodules of submodules ... */
2634
2635 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002636 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002637
2638 return result;
2639}
Michal Vaskobaefb032015-09-24 14:52:10 +02002640
2641API struct lys_node *
2642lys_parent(struct lys_node *node)
2643{
2644 if (!node || !node->parent) {
2645 return NULL;
2646 }
2647
2648 if (node->parent->nodetype == LYS_AUGMENT) {
2649 return ((struct lys_node_augment *)node->parent)->target;
2650 }
2651
2652 return node->parent;
2653}