blob: f4cdd7a9b3eecdfff3e85bd01e6bf35e29eae65f [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
2 * @file tree.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Manipulation with libyang data structures
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020021#define _GNU_SOURCE
Radek Krejcida04f4a2015-05-21 12:54:09 +020022
Radek Krejci812b10a2015-05-28 16:48:25 +020023#include <assert.h>
Radek Krejci5a988152015-07-15 11:16:26 +020024#include <ctype.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020025#include <stdlib.h>
26#include <sys/mman.h>
27#include <sys/stat.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020028#include <string.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020029
30#include "common.h"
31#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020032#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020033#include "resolve.h"
Radek Krejci106efc02015-06-10 14:36:27 +020034#include "xml.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020035#include "tree_internal.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020036
Michal Vaskoa76ee152015-08-17 15:38:22 +020037static const struct internal_modules int_mods = {
38 .modules = {
39 {"ietf-yang-types", "2013-07-15"},
40 {"ietf-inet-types", "2013-07-15"},
41 {"ietf-yang-library", "2015-07-03"}
42 },
43 .count = LY_INTERNAL_MODULE_COUNT
44};
45
Radek Krejci48061fb2015-08-05 15:41:07 +020046API struct lys_feature *
47lys_is_disabled(struct lys_node *node, int recursive)
48{
49 int i;
50
51check:
52 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
53 /* input/output does not have if-feature, so skip them */
54
55 /* check local if-features */
56 for (i = 0; i < node->features_size; i++) {
57 if (!(node->features[i]->flags & LYS_FENABLED)) {
58 return node->features[i];
59 }
60 }
61 }
62
63 if (!recursive) {
64 return NULL;
65 }
66
67 /* go through parents */
68 if (node->nodetype == LYS_AUGMENT) {
69 /* go to parent actually means go to the target node */
70 node = ((struct lys_node_augment *)node)->target;
71 goto check;
72 } else if (node->parent) {
73 node = node->parent;
74 goto check;
75 }
76
77 return NULL;
78}
79
Radek Krejci7f40ce32015-08-12 20:38:46 +020080static struct lys_node *
81check_mand_getnext(struct lys_node *cur, struct lys_node *parent)
82{
83 struct lys_node *next;
84
85 if (!cur) {
86 next = parent->child;
87 } else {
88 next = cur->next;
89 }
90
91repeat:
Michal Vasko591e0b22015-08-13 13:53:43 +020092 while (next && (next->nodetype & (LYS_AUGMENT | LYS_GROUPING | LYS_LEAFLIST))) {
Radek Krejci7f40ce32015-08-12 20:38:46 +020093 next = cur = next->next;
94 }
95
96 while (!next) {
97 if (cur->parent == parent) {
98 /* no next element */
99 return NULL;
100 }
101 cur = cur->parent;
102 next = cur->next;
103 goto repeat;
104 }
105
106 switch (next->nodetype) {
107 case LYS_CONTAINER:
108 if (((struct lys_node_container *)next)->presence) {
109 /* mandatory elements under the non-existing presence
110 * container are not mandatory - 7.6.5, rule 1 */
111 next = next->next;
112 goto repeat;
113 }
114 /* no break */
115 case LYS_LIST:
116 case LYS_USES:
117 case LYS_CASE:
118 /* go into */
119 next = next->child;
120 goto repeat;
121 case LYS_LEAF:
122 case LYS_CHOICE:
123 case LYS_ANYXML:
124 return next;
125 default:
126 /* we should not be here */
127 return NULL;
128 }
129}
130
131static struct lys_node *
132check_mand_check(struct lys_node *node, struct lys_node *stop, struct lyd_node *data)
133{
134 struct lys_node *siter = NULL, *parent;
135 struct lyd_node *diter = NULL;
136
137 if (node->flags & LYS_MAND_TRUE) {
138 switch (node->nodetype) {
139 case LYS_LEAF:
140 case LYS_ANYXML:
141 case LYS_CHOICE:
142 if (node->parent->nodetype == LYS_CASE) {
143 /* 7.6.5, rule 2 */
144 /* 7.9.4, rule 1 */
145 if (node->parent->parent->parent == data->schema) {
146 /* the only case the node's siblings can exist is that the
147 * data node passed originaly to ly_check_mandatory()
148 * had this choice as a child
149 */
150 /* try to find the node's siblings in data */
151 LY_TREE_FOR(data->child, diter) {
152 LY_TREE_FOR(node->parent->child, siter) {
153 if (siter == diter->schema) {
154 /* some sibling exists, rule applies */
155 break;
156 }
157 }
158 if (siter) {
159 break;
160 }
161 }
162 }
163 if (!siter) {
164 /* no sibling exists */
165 return NULL;
166 }
167 } else {
168 for(parent = node->parent; parent != stop; parent = parent->parent) {
169 if (parent->nodetype != LYS_CONTAINER) {
170 /* 7.6.5, rule 1, checking presence is not needed
171 * since it is done in check_mand_getnext()
172 */
173 return NULL;
174 }
175 }
176 }
177 /* 7.6.5, rule 3 (or 2) */
178 /* 7.9.4, rule 2 */
179 return node;
180 default:
181 /* error */
182 break;
183 }
184 }
185
186 return NULL;
187}
188
189struct lys_node *
190ly_check_mandatory(struct lyd_node *data)
191{
192 struct lys_node *siter, *saux = NULL, *result, *parent = NULL;
193 struct lyd_node *diter;
194 int found;
195
196 siter = data->schema->child;
197
198repeat:
199 while (siter) {
200 switch (siter->nodetype) {
201 case LYS_CONTAINER:
202 case LYS_LEAF:
203 case LYS_ANYXML:
204 /* search for instance */
205 LY_TREE_FOR(data->child, diter) {
206 if (diter->schema == siter) {
207 break;
208 }
209 }
210 if (diter) {
211 /* result has a child defined by siter, check another siter */
212 siter = siter->next;
213 break;
214 }
215
216 /* the siter has no instance under the result, check if there is
217 * some mandatory node; first the siter itself ... */
218 result = check_mand_check(siter, siter->parent, data);
219 if (result) {
220 return result;
221 }
222 /* ... and then the subtree */
223 if (siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
224 while ((saux = check_mand_getnext(saux, siter))) {
225 result = check_mand_check(saux, siter, data);
226 if (result) {
227 return result;
228 }
229 }
230 }
231 siter = siter->next;
232 break;
233 case LYS_CHOICE:
234 if (siter->flags & LYS_MAND_TRUE) {
235 /* search for instance */
236 saux = siter;
237 parent = NULL;
238 siter = siter->child;
239 found = 0;
240repeat_choice:
241 while (siter) {
242 switch(siter->nodetype) {
243 case LYS_CONTAINER:
244 case LYS_LEAF:
245 case LYS_LEAFLIST:
246 case LYS_LIST:
247 case LYS_ANYXML:
248 LY_TREE_FOR(data->child, diter) {
249 if (diter->schema == siter) {
250 break;
251 }
252 }
253 if (diter) {
254 /* got instance, done */
255 siter = parent = NULL;
256 found = 1;
257 break;
258 }
259 siter = siter->next;
260 break;
261 case LYS_CASE:
262 case LYS_CHOICE:
263 case LYS_USES:
264 /* go into */
265 parent = siter;
266 siter = siter->child;
267 break;
268 case LYS_AUGMENT:
269 case LYS_GROUPING:
270 /* skip */
271 siter = siter->next;
272 break;
273 default:
274 /* error */
275 break;
276 }
277 }
278
279 if (parent) {
280 siter = parent->next;
281 if (parent->parent == saux) {
282 parent = NULL;
283 } else {
284 parent = parent->parent;
285 }
286 goto repeat_choice;
287 }
288
289 if (!found) {
290 return saux;
291 }
292
293 siter = saux;
294 }
295
296 /* go into */
297 parent = siter;
298 siter = siter->child;
299 break;
300 case LYS_USES:
301 case LYS_CASE:
302 /* go into */
303 parent = siter;
304 siter = siter->child;
305 break;
306 default:
307 /* can ignore, go to next */
308 siter = siter->next;
309 break;
310 }
311 }
312
313 if (parent) {
314 siter = parent->next;
315 if (parent->parent == data->schema) {
316 parent = NULL;
317 } else {
318 parent = parent->parent;
319 }
320 goto repeat;
321 }
322
323 return NULL;
324}
325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200326void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200327lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200328{
Radek Krejci76512572015-08-04 09:47:08 +0200329 struct lys_node *parent, *first;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200331 if (!node) {
332 return;
333 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200334
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200335 /* unlink from data model if necessary */
336 if (node->module) {
337 if (node->module->data == node) {
338 node->module->data = node->next;
Radek Krejci21181962015-06-30 14:11:00 +0200339 } else if (node->module->rpc == node) {
340 node->module->rpc = node->next;
341 } else if (node->module->notif == node) {
342 node->module->notif = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200343 }
344 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200345
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200346 /* store pointers to important nodes */
347 parent = node->parent;
348 if (parent && !parent->nodetype) {
349 /* handle augments - first, unlink it from the augment parent ... */
350 if (parent->child == node) {
351 parent->child = node->next;
352 }
353 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200354 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200355 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200357 /* unlink from parent */
358 if (parent) {
359 if (parent->child == node) {
360 parent->child = node->next;
361 }
362 node->parent = NULL;
363 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200364
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200365 /* unlink from siblings */
366 if (node->prev == node) {
367 /* there are no more siblings */
368 return;
369 }
370 if (node->next) {
371 node->next->prev = node->prev;
372 } else {
373 /* unlinking the last element */
374 if (parent) {
375 first = parent->child;
376 } else {
377 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200378 while (first->prev->next) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200379 first = node->prev;
380 }
381 }
382 first->prev = node->prev;
383 }
384 if (node->prev->next) {
385 node->prev->next = node->next;
386 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200387
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200388 /* clean up the unlinked element */
389 node->next = NULL;
390 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200391}
392
Radek Krejci10c760e2015-08-14 14:45:43 +0200393/*
394 * get next grouping in the root's subtree, in the
395 * first call, tha last is NULL
396 */
397static struct lys_node_grp *
398lys_get_next_grouping(struct lys_node_grp* lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200399{
Radek Krejci10c760e2015-08-14 14:45:43 +0200400 struct lys_node *last = (struct lys_node *)lastgrp;
401 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200402
Radek Krejci10c760e2015-08-14 14:45:43 +0200403 assert(root);
404
405 if (!last) {
406 last = root;
407 }
408
409 while (1) {
410 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
411 next = last->child;
412 } else {
413 next = NULL;
414 }
415 if (!next) {
416 if (last == root) {
417 /* we are done */
418 return NULL;
419 }
420
421 /* no children, go to siblings */
422 next = last->next;
423 }
424 while (!next) {
425 /* go back through parents */
426 if (last->parent == root) {
427 /* we are done */
428 return NULL;
429 }
430 last = last->parent;
431 next = last->next;
432 }
433
434 if (next->nodetype == LYS_GROUPING) {
435 return (struct lys_node_grp *)next;
436 }
437
438 last = next;
439 }
440}
441
442int
Radek Krejci07911992015-08-14 15:13:31 +0200443lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
444{
445 struct lys_node *start, *stop, *par_iter, *iter;
446 struct lys_node_grp *grp;
447 int down;
448
449 assert(node);
450
451 if (!parent) {
452 assert(module);
453 } else {
454 module = parent->module;
455 }
456
457 switch (node->nodetype) {
458 case LYS_GROUPING:
459 /* 6.2.1, rule 6 */
460 if (parent) {
461 if (parent->child) {
462 down = 1;
463 start = parent->child;
464 } else {
465 down = 0;
466 start = parent;
467 }
468 } else {
469 down = 1;
470 start = module->data;
471 }
472 /* go up */
473 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
474 if (par_iter->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES)) {
475 continue;
476 }
477
478 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
479 if (!stop) {
480 stop = par_iter;
481 } else if (iter == stop) {
482 break;
483 }
484 if (iter->nodetype != LYS_GROUPING) {
485 continue;
486 }
487
488 if (node->name == iter->name) {
489 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
490 return EXIT_FAILURE;
491 }
492 }
493 }
494 /* go down, because grouping can be defined after e.g. container in which is collision */
495 if (down) {
496 for (iter = start, stop = NULL; iter; iter = iter->prev) {
497 if (!stop) {
498 stop = start;
499 } else if (iter == stop) {
500 break;
501 }
502 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
503 continue;
504 }
505
506 grp = NULL;
507 while ((grp = lys_get_next_grouping(grp, iter))) {
508 if (node->name == grp->name) {
509 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
510 return EXIT_FAILURE;
511 }
512 }
513 }
514 }
515 break;
516 case LYS_LEAF:
517 case LYS_LEAFLIST:
518 case LYS_LIST:
519 case LYS_CONTAINER:
520 case LYS_CHOICE:
521 case LYS_ANYXML:
522 /* 6.2.1, rule 7 */
523 if (parent) {
524 iter = parent;
525 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE))) {
526 iter = iter->parent;
527 }
528 if (!iter) {
529 stop = NULL;
530 iter = module->data;
531 } else {
532 stop = iter;
533 iter = iter->child;
534 }
535 } else {
536 stop = NULL;
537 iter = module->data;
538 }
539 while (iter) {
540 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
541 iter = iter->child;
542 continue;
543 }
544
545 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
546 if (iter->module == node->module && iter->name == node->name) {
547 LOGVAL(LYE_SPEC, 0, "Duplicated child identifier \"%s\" in \"%s\".", node->name,
548 stop ? stop->name : "(sub)module");
549 return EXIT_FAILURE;
550 }
551 }
552
553 /* special case for choice - we must check the choice's name as
554 * well as the names of nodes under the choice
555 */
556 if (iter->nodetype == LYS_CHOICE) {
557 iter = iter->child;
558 continue;
559 }
560
561 /* go to siblings */
562 if (!iter->next) {
563 /* no sibling, go to parent's sibling */
564 do {
565 iter = iter->parent;
566 if (iter && iter->next) {
567 break;
568 }
569 } while (iter != stop);
570
571 if (iter == stop) {
572 break;
573 }
574 }
575 iter = iter->next;
576 }
577 break;
578 case LYS_CASE:
579 /* 6.2.1, rule 8 */
580 LY_TREE_FOR(parent->child, iter) {
581 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
582 continue;
583 }
584
585 if (iter->module == node->module && iter->name == node->name) {
586 LOGVAL(LYE_DUPID, 0, "case", node->name);
587 return EXIT_FAILURE;
588 }
589 }
590 break;
591 default:
592 /* no check needed */
593 break;
594 }
595
596 return EXIT_SUCCESS;
597}
598
599int
Radek Krejci10c760e2015-08-14 14:45:43 +0200600lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
601{
Radek Krejci07911992015-08-14 15:13:31 +0200602 struct lys_node *iter, **trg = NULL;
603 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200604
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200605 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200606
Radek Krejci10c760e2015-08-14 14:45:43 +0200607 if (parent) {
608 type = parent->nodetype;
609 module = parent->module;
610 } else {
611 assert(module);
612 type = 0;
Radek Krejcic7459c62015-08-17 10:15:12 +0200613 if (child->nodetype == LYS_NOTIF) {
614 trg = &module->notif;
615 } else if (child->nodetype == LYS_RPC) {
616 trg = &module->rpc;
617 } else {
618 trg = &module->data;
619 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200620 }
621
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200622 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200623 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200624 case LYS_CONTAINER:
625 case LYS_LIST:
626 case LYS_GROUPING:
627 case LYS_USES:
628 case LYS_INPUT:
629 case LYS_OUTPUT:
630 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200631 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200632 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
633 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200634 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200635 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
636 return EXIT_FAILURE;
637 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200638
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200639 break;
Radek Krejci76512572015-08-04 09:47:08 +0200640 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200641 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200642 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200643 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"choice\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200644 strnodetype(child->nodetype), parent->name);
645 return EXIT_FAILURE;
646 }
647 break;
Radek Krejci76512572015-08-04 09:47:08 +0200648 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200649 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200650 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200651 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"case\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200652 strnodetype(child->nodetype), parent->name);
653 return EXIT_FAILURE;
654 }
655 break;
Radek Krejci76512572015-08-04 09:47:08 +0200656 case LYS_RPC:
657 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200658 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"rpc\" %s.",
Michal Vasko38d01f72015-06-15 09:41:06 +0200659 strnodetype(child->nodetype), parent->name);
660 return EXIT_FAILURE;
661 }
662 break;
Radek Krejci76512572015-08-04 09:47:08 +0200663 case LYS_LEAF:
664 case LYS_LEAFLIST:
665 case LYS_ANYXML:
Radek Krejci10c760e2015-08-14 14:45:43 +0200666 LOGVAL(LYE_SPEC, 0, "The \"%s\" statement (%s) cannot have any data substatement.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200667 strnodetype(parent->nodetype), parent->name);
668 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200669 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200670 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200671 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
672 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200673 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200674 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
675 return EXIT_FAILURE;
676 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200677 break;
678 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200679 /* top level */
680 if (!(child->nodetype &
681 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
682 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci2c0ca272015-08-14 15:31:01 +0200683 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in (sub)module \"%s\"",
684 strnodetype(child->nodetype), module->name);
Radek Krejci10c760e2015-08-14 14:45:43 +0200685 return EXIT_FAILURE;
686 }
687
688 break;;
689 }
690
691 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200692 if (lys_check_id(child, parent, module)) {
693 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200694 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200695
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200696 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200697 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200698 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200699
Radek Krejci10c760e2015-08-14 14:45:43 +0200700 if (!parent) {
701 if (*trg) {
702 (*trg)->prev->next = child;
703 child->prev = (*trg)->prev;
704 (*trg)->prev = child;
705 } else {
706 (*trg) = child;
707 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200708 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +0200709 if (!parent->child) {
710 /* the only/first child of the parent */
711 parent->child = child;
712 child->parent = parent;
713 iter = child;
714 } else {
715 /* add a new child at the end of parent's child list */
716 iter = parent->child->prev;
717 iter->next = child;
718 child->prev = iter;
719 }
720 while (iter->next) {
721 iter = iter->next;
722 iter->parent = parent;
723 }
724 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200725 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200726
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200727 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200728}
729
Radek Krejcib8048692015-08-05 13:36:34 +0200730API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +0200731lys_parse(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200732{
Michal Vaskof02e3742015-08-05 16:27:02 +0200733 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200734 struct lys_module *mod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200735
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200736 if (!ctx || !data) {
737 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
738 return NULL;
739 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200740
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200741 unres = calloc(1, sizeof *unres);
742
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200743 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200744 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200745 mod = yin_read_module(ctx, data, 1, unres);
746 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200747 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200748 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +0200749 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200750 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200751 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200752
Radek Krejci0b5805d2015-08-13 09:38:02 +0200753 if (mod && unres->count && resolve_unres(mod, unres)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200754 lys_free(mod);
755 mod = NULL;
756 }
757 free(unres->item);
758 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +0200759 free(unres->str_snode);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200760#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200761 free(unres->line);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200762#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200763 free(unres);
764
765 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200766}
767
Radek Krejcib8048692015-08-05 13:36:34 +0200768struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +0200769lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +0200770{
Michal Vaskof02e3742015-08-05 16:27:02 +0200771 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200772 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200773
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200774 assert(module);
775 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200776
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200777 unres = calloc(1, sizeof *unres);
778
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200779 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200780 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200781 submod = yin_read_submodule(module, data, implement, unres);
782 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200783 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200784 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +0200785 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200786 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200787 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200788
Radek Krejci0b5805d2015-08-13 09:38:02 +0200789 if (submod && unres->count && resolve_unres((struct lys_module *)submod, unres)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200790 lys_submodule_free(submod);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200791 submod = NULL;
792 }
793 free(unres->item);
794 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +0200795 free(unres->str_snode);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200796#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200797 free(unres->line);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200798#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200799 free(unres);
800
801 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +0200802}
803
Radek Krejcib8048692015-08-05 13:36:34 +0200804API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +0200805lys_read(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +0200806{
Radek Krejcib8048692015-08-05 13:36:34 +0200807 struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +0200808 struct stat sb;
809 char *addr;
810
811 if (!ctx || fd < 0) {
812 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
813 return NULL;
814 }
815
816 /*
817 * TODO
818 * This is just a temporary solution to make working automatic search for
819 * imported modules. This doesn't work e.g. for streams (stdin)
820 */
821 fstat(fd, &sb);
822 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
823 module = lys_parse(ctx, addr, format);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200824 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200825
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200826 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200827}
828
Radek Krejcib8048692015-08-05 13:36:34 +0200829struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +0200830lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +0200831{
Radek Krejcib8048692015-08-05 13:36:34 +0200832 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200833 struct stat sb;
834 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +0200835
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200836 assert(module);
837 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +0200838
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200839 /*
840 * TODO
841 * This is just a temporary solution to make working automatic search for
842 * imported modules. This doesn't work e.g. for streams (stdin)
843 */
844 fstat(fd, &sb);
845 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
846 /* TODO addr error check */
Radek Krejci1d82ef62015-08-07 14:44:40 +0200847 submodule = lys_submodule_parse(module, addr, format, implement);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200848 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +0200849
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200850 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +0200851
852}
853
Radek Krejci1d82ef62015-08-07 14:44:40 +0200854static struct lys_restr *
855lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200856{
Radek Krejci1574a8d2015-08-03 14:16:52 +0200857 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200858 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200859
Radek Krejci3733a802015-06-19 13:43:21 +0200860 if (!size) {
861 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200862 }
Radek Krejci3733a802015-06-19 13:43:21 +0200863
864 result = calloc(size, sizeof *result);
865 for (i = 0; i < size; i++) {
866 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
867 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
868 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
869 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
870 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
871 }
872
873 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200874}
875
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200876void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200877lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +0200878{
879 assert(ctx);
880 if (!restr) {
881 return;
882 }
883
884 lydict_remove(ctx, restr->expr);
885 lydict_remove(ctx, restr->dsc);
886 lydict_remove(ctx, restr->ref);
887 lydict_remove(ctx, restr->eapptag);
888 lydict_remove(ctx, restr->emsg);
889}
890
Radek Krejci1d82ef62015-08-07 14:44:40 +0200891static void
892lys_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 +0200893 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +0200894{
895 int i;
896
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200897 new->prefix = lydict_insert(mod->ctx, old->prefix, 0);
Radek Krejci3733a802015-06-19 13:43:21 +0200898 new->base = old->base;
899 new->der = old->der;
900
Radek Krejci1d82ef62015-08-07 14:44:40 +0200901 i = unres_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200902 if (i != -1) {
903 /* HACK for unres */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200904 new->der = (struct lys_tpdf *)parent;
Michal Vasko49168a22015-08-17 16:35:41 +0200905 if (unres_add_str(mod, unres, new, UNRES_TYPE_DER, unres->str_snode[i], 0) == -1) {
906 LOGINT;
907 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200908 return;
909 }
910
Radek Krejci3733a802015-06-19 13:43:21 +0200911 switch (new->base) {
912 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +0200913 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200914 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +0200915 }
Radek Krejci3733a802015-06-19 13:43:21 +0200916 break;
917
918 case LY_TYPE_BITS:
919 new->info.bits.count = old->info.bits.count;
920 if (new->info.bits.count) {
921 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
922 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200923 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
924 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
925 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Radek Krejci3733a802015-06-19 13:43:21 +0200926 new->info.bits.bit[i].status = old->info.bits.bit[i].status;
927 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
928 }
929 }
930 break;
931
Radek Krejcif9401c32015-06-26 16:47:36 +0200932 case LY_TYPE_DEC64:
933 new->info.dec64.dig = old->info.dec64.dig;
934 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200935 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +0200936 }
937 break;
938
Radek Krejci3733a802015-06-19 13:43:21 +0200939 case LY_TYPE_ENUM:
940 new->info.enums.count = old->info.enums.count;
941 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200942 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Radek Krejci3733a802015-06-19 13:43:21 +0200943 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200944 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
945 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
946 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
947 new->info.enums.enm[i].status = old->info.enums.enm[i].status;
948 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +0200949 }
950 }
951 break;
952
Radek Krejci4a7b5ee2015-06-19 14:56:43 +0200953 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200954 if (old->info.ident.ref) {
955 new->info.ident.ref = old->info.ident.ref;
956 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200957 i = unres_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200958 assert(i != -1);
Michal Vasko49168a22015-08-17 16:35:41 +0200959 if (unres_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i], 0) == -1) {
960 LOGINT;
961 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200962 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +0200963 break;
964
Radek Krejciaf351422015-06-19 14:49:38 +0200965 case LY_TYPE_INST:
966 new->info.inst.req = old->info.inst.req;
967 break;
968
Radek Krejcif2860132015-06-20 12:37:20 +0200969 case LY_TYPE_INT8:
970 case LY_TYPE_INT16:
971 case LY_TYPE_INT32:
972 case LY_TYPE_INT64:
973 case LY_TYPE_UINT8:
974 case LY_TYPE_UINT16:
975 case LY_TYPE_UINT32:
976 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +0200977 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200978 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +0200979 }
Radek Krejcif2860132015-06-20 12:37:20 +0200980 break;
981
Radek Krejcidc4c1412015-06-19 15:39:54 +0200982 case LY_TYPE_LEAFREF:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200983 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko49168a22015-08-17 16:35:41 +0200984 if (unres_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0) == -1) {
985 LOGINT;
986 }
Radek Krejcidc4c1412015-06-19 15:39:54 +0200987 break;
988
Radek Krejci3733a802015-06-19 13:43:21 +0200989 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +0200990 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200991 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200992 }
Radek Krejci1d82ef62015-08-07 14:44:40 +0200993 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 +0200994 break;
995
Radek Krejcie4c366b2015-07-02 10:11:31 +0200996 case LY_TYPE_UNION:
997 new->info.uni.count = old->info.uni.count;
998 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200999 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001000 for (i = 0; i < new->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001001 lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001002 }
1003 }
1004 break;
1005
Radek Krejci3733a802015-06-19 13:43:21 +02001006 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001007 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001008 break;
1009 }
1010}
1011
1012void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001013lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001014{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001015 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001016
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001017 assert(ctx);
1018 if (!type) {
1019 return;
1020 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001021
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001022 lydict_remove(ctx, type->prefix);
Radek Krejci5a065542015-05-22 15:02:07 +02001023
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001024 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001025 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001026 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001027 free(type->info.binary.length);
1028 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001029 case LY_TYPE_BITS:
1030 for (i = 0; i < type->info.bits.count; i++) {
1031 lydict_remove(ctx, type->info.bits.bit[i].name);
1032 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1033 lydict_remove(ctx, type->info.bits.bit[i].ref);
1034 }
1035 free(type->info.bits.bit);
1036 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001037
1038 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001039 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001040 free(type->info.dec64.range);
1041 break;
1042
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001043 case LY_TYPE_ENUM:
1044 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001045 lydict_remove(ctx, type->info.enums.enm[i].name);
1046 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1047 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001048 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001049 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001050 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001051
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001052 case LY_TYPE_INT8:
1053 case LY_TYPE_INT16:
1054 case LY_TYPE_INT32:
1055 case LY_TYPE_INT64:
1056 case LY_TYPE_UINT8:
1057 case LY_TYPE_UINT16:
1058 case LY_TYPE_UINT32:
1059 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001060 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001061 free(type->info.num.range);
1062 break;
1063
Radek Krejcidc4c1412015-06-19 15:39:54 +02001064 case LY_TYPE_LEAFREF:
1065 lydict_remove(ctx, type->info.lref.path);
1066 break;
1067
Radek Krejci3733a802015-06-19 13:43:21 +02001068 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001069 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001070 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001071 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001072 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001073 }
1074 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001075 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001076
Radek Krejcie4c366b2015-07-02 10:11:31 +02001077 case LY_TYPE_UNION:
1078 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001079 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001080 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001081 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001082 break;
1083
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001084 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001085 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001086 break;
1087 }
Radek Krejci5a065542015-05-22 15:02:07 +02001088}
1089
Radek Krejci1d82ef62015-08-07 14:44:40 +02001090static struct lys_tpdf *
1091lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001092{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001093 struct lys_tpdf *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001094 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001095
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001096 if (!size) {
1097 return NULL;
1098 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001099
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001100 result = calloc(size, sizeof *result);
1101 for (i = 0; i < size; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001102 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1103 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1104 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001105 result[i].flags = old[i].flags;
1106 result[i].module = old[i].module;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001107
Radek Krejci1d82ef62015-08-07 14:44:40 +02001108 lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001109
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001110 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1111 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001112 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001113
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001114 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001115}
1116
Radek Krejci1d82ef62015-08-07 14:44:40 +02001117static void
1118lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001119{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001120 assert(ctx);
1121 if (!tpdf) {
1122 return;
1123 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001124
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001125 lydict_remove(ctx, tpdf->name);
1126 lydict_remove(ctx, tpdf->dsc);
1127 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001128
Radek Krejci1d82ef62015-08-07 14:44:40 +02001129 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001130
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001131 lydict_remove(ctx, tpdf->units);
1132 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001133}
1134
Radek Krejci1d82ef62015-08-07 14:44:40 +02001135static struct lys_when *
1136lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001137{
Radek Krejci76512572015-08-04 09:47:08 +02001138 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001139
1140 if (!old) {
1141 return NULL;
1142 }
1143
1144 new = calloc(1, sizeof *new);
1145 new->cond = lydict_insert(ctx, old->cond, 0);
1146 new->dsc = lydict_insert(ctx, old->dsc, 0);
1147 new->ref = lydict_insert(ctx, old->ref, 0);
1148
1149 return new;
1150}
1151
Radek Krejci1d82ef62015-08-07 14:44:40 +02001152static void
1153lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001154{
1155 if (!w) {
1156 return;
1157 }
1158
1159 lydict_remove(ctx, w->cond);
1160 lydict_remove(ctx, w->dsc);
1161 lydict_remove(ctx, w->ref);
1162
1163 free(w);
1164}
1165
Radek Krejcib7f5e412015-08-13 10:15:51 +02001166static void
1167lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment aug)
1168{
1169 struct lys_node *child, *sub;
1170
1171 lydict_remove(ctx, aug.target_name);
1172 lydict_remove(ctx, aug.dsc);
1173 lydict_remove(ctx, aug.ref);
1174
1175 free(aug.features);
1176
1177 lys_when_free(ctx, aug.when);
1178
1179 LY_TREE_FOR_SAFE(aug.child, child, sub) {
1180 lys_node_free(sub);
1181 }
1182}
1183
Radek Krejci76512572015-08-04 09:47:08 +02001184static struct lys_node_augment *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001185lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size,
Michal Vasko41de7352015-08-06 09:53:34 +02001186 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001187{
Radek Krejci76512572015-08-04 09:47:08 +02001188 struct lys_node_augment *new = NULL;
Michal Vasko41de7352015-08-06 09:53:34 +02001189 struct lys_node *snode;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001190 int i = -1;
Radek Krejci106efc02015-06-10 14:36:27 +02001191
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001192 if (!size) {
1193 return NULL;
1194 }
Radek Krejci106efc02015-06-10 14:36:27 +02001195
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001196 new = calloc(size, sizeof *new);
1197 for (i = 0; i < size; i++) {
1198 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1199 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1200 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1201 new[i].flags = old[i].flags;
Michal Vasko591e0b22015-08-13 13:53:43 +02001202 new[i].nodetype = old[i].nodetype;
1203 /* .target = NULL */
Radek Krejci106efc02015-06-10 14:36:27 +02001204
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001205 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001206
Michal Vasko41de7352015-08-06 09:53:34 +02001207 /* copy the augment nodes */
1208 assert(old[i].child);
1209 LY_TREE_FOR(old[i].child, snode) {
Radek Krejci10c760e2015-08-14 14:45:43 +02001210 if (lys_node_addchild((struct lys_node *)&new[i], NULL, lys_node_dup(module, snode, snode->flags, snode->nacm, 1, unres))) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001211 for ( ; i >= 0; i--) {
1212 lys_augment_free(module->ctx, new[i]);
1213 }
1214 free(new);
1215 return NULL;
1216 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001217 }
1218 }
Radek Krejci106efc02015-06-10 14:36:27 +02001219
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001220 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001221}
1222
Radek Krejci76512572015-08-04 09:47:08 +02001223static struct lys_refine *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001224lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size, struct lys_node_uses *uses,
Michal Vaskof02e3742015-08-05 16:27:02 +02001225 struct unres_schema *unres)
Michal Vasko1982cad2015-06-08 15:49:30 +02001226{
Radek Krejci76512572015-08-04 09:47:08 +02001227 struct lys_refine *result;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001228 int i, j;
Michal Vasko1982cad2015-06-08 15:49:30 +02001229
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001230 if (!size) {
1231 return NULL;
1232 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001233
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001234 result = calloc(size, sizeof *result);
1235 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001236 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001237 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1238 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001239 result[i].flags = old[i].flags;
1240 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001241
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001242 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001243 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001244 for (j = 0; j < result[i].must_size; ++j) {
Michal Vasko49168a22015-08-17 16:35:41 +02001245 if (unres_add_node(mod, unres, &result[i].must[j], UNRES_MUST, (struct lys_node *)uses, 0) == -1) {
1246 free(result);
1247 return NULL;
1248 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001249 }
1250
Radek Krejci76512572015-08-04 09:47:08 +02001251 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001252 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001253 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001254 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001255 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001256 result[i].mod.list = old[i].mod.list;
1257 }
1258 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001259
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001260 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001261}
1262
Radek Krejci1d82ef62015-08-07 14:44:40 +02001263static void
1264lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001265{
Radek Krejcia52656e2015-08-05 13:41:50 +02001266 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001267
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001268 assert(ctx);
1269 if (!ident) {
1270 return;
1271 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001272
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001273 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001274 * if caller free only a single data model which is used (its identity is
1275 * reference from identity in another module), this silly freeing can lead
1276 * to segmentation fault. But without noting if the module is used by some
1277 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001278 *
1279 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001280 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001281 */
1282 while (ident->der) {
1283 der = ident->der;
1284 ident->der = der->next;
1285 free(der);
1286 }
Radek Krejci6793db02015-05-22 17:49:54 +02001287
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001288 lydict_remove(ctx, ident->name);
1289 lydict_remove(ctx, ident->dsc);
1290 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001291
1292}
1293
Radek Krejci1d82ef62015-08-07 14:44:40 +02001294static void
1295lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001296{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001297 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001298
Radek Krejcid12f57b2015-08-06 10:43:39 +02001299 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001300 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001301 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001302 }
1303 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001304}
1305
Radek Krejci1d82ef62015-08-07 14:44:40 +02001306static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001307lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1308{
1309 int i;
1310
1311 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1312 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001313 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001314 }
1315 free(io->tpdf);
1316}
1317
Radek Krejci1d82ef62015-08-07 14:44:40 +02001318static void
1319lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001320{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001321 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001322
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001323 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001324 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001325 }
1326 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001327
Radek Krejci1d82ef62015-08-07 14:44:40 +02001328 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001329}
1330
Radek Krejci1d82ef62015-08-07 14:44:40 +02001331static void
1332lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001333{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001334 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001335
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001336 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001337 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001338 }
1339 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001340
Radek Krejci1d82ef62015-08-07 14:44:40 +02001341 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001342
Radek Krejci1d82ef62015-08-07 14:44:40 +02001343 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001344 lydict_remove(ctx, leaf->units);
1345 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001346}
1347
Radek Krejci1d82ef62015-08-07 14:44:40 +02001348static void
1349lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001350{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001351 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001352
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001353 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001354 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001355 }
1356 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001357
Radek Krejci1d82ef62015-08-07 14:44:40 +02001358 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001359
Radek Krejci1d82ef62015-08-07 14:44:40 +02001360 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001361 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001362}
1363
Radek Krejci1d82ef62015-08-07 14:44:40 +02001364static void
1365lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001366{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001367 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001368
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001369 /* handle only specific parts for LY_NODE_LIST */
1370 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001371 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001372 }
1373 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001374
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001375 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001376 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001377 }
1378 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001379
Radek Krejci1d82ef62015-08-07 14:44:40 +02001380 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001381
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001382 for (i = 0; i < list->unique_size; i++) {
1383 free(list->unique[i].leafs);
1384 }
1385 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001386
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001387 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001388}
1389
Radek Krejci1d82ef62015-08-07 14:44:40 +02001390static void
1391lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001392{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001393 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001395 /* handle only specific parts for LY_NODE_CONTAINER */
1396 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001397
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001398 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001399 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001400 }
1401 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001402
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001403 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001404 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001405 }
1406 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001407
Radek Krejci1d82ef62015-08-07 14:44:40 +02001408 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001409}
1410
Radek Krejci1d82ef62015-08-07 14:44:40 +02001411static void
1412lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001413{
1414 lydict_remove(ctx, f->name);
1415 lydict_remove(ctx, f->dsc);
1416 lydict_remove(ctx, f->ref);
1417 free(f->features);
1418}
1419
Radek Krejci1d82ef62015-08-07 14:44:40 +02001420static void
1421lys_deviation_free(struct ly_ctx *ctx, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001422{
1423 int i, j;
1424
1425 lydict_remove(ctx, dev->target_name);
1426 lydict_remove(ctx, dev->dsc);
1427 lydict_remove(ctx, dev->ref);
1428
1429 for (i = 0; i < dev->deviate_size; i++) {
1430 lydict_remove(ctx, dev->deviate[i].dflt);
1431 lydict_remove(ctx, dev->deviate[i].units);
1432
1433 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1434 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001435 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001436 }
1437 free(dev->deviate[i].must);
1438
1439 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1440 free(dev->deviate[j].unique[j].leafs);
1441 }
1442 free(dev->deviate[i].unique);
1443 }
1444 }
1445 free(dev->deviate);
1446}
1447
Radek Krejci1d82ef62015-08-07 14:44:40 +02001448static void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001449lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +02001450{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001451 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001452
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001453 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001454 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001455 lydict_remove(ctx, uses->refine[i].dsc);
1456 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001457
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001458 for (j = 0; j < uses->refine[j].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001459 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001460 }
1461 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001462
Radek Krejci76512572015-08-04 09:47:08 +02001463 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001464 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001465 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001466 lydict_remove(ctx, uses->refine[i].mod.presence);
1467 }
1468 }
1469 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001470
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001471 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001472 lys_augment_free(ctx, uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001473 }
1474 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001475
Radek Krejci1d82ef62015-08-07 14:44:40 +02001476 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001477}
1478
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001479void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001480lys_node_free(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001481{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001482 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001483 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001484
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001485 if (!node) {
1486 return;
1487 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001488
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001489 assert(node->module);
1490 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001491
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001492 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001493
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001494 /* common part */
1495 LY_TREE_FOR_SAFE(node->child, next, sub) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001496 lys_node_free(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001497 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001498
Radek Krejcid12f57b2015-08-06 10:43:39 +02001499 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1500 free(node->features);
1501 lydict_remove(ctx, node->name);
1502 lydict_remove(ctx, node->dsc);
1503 lydict_remove(ctx, node->ref);
1504 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001505
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001506 /* specific part */
1507 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001508 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001509 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001510 break;
Radek Krejci76512572015-08-04 09:47:08 +02001511 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001512 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001513 break;
Radek Krejci76512572015-08-04 09:47:08 +02001514 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001515 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001516 break;
Radek Krejci76512572015-08-04 09:47:08 +02001517 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001518 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001519 break;
Radek Krejci76512572015-08-04 09:47:08 +02001520 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001521 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001522 break;
Radek Krejci76512572015-08-04 09:47:08 +02001523 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001524 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001525 break;
Radek Krejci76512572015-08-04 09:47:08 +02001526 case LYS_USES:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001527 lys_uses_free(ctx, (struct lys_node_uses *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001528 break;
Radek Krejci76512572015-08-04 09:47:08 +02001529 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001530 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001531 break;
Radek Krejci76512572015-08-04 09:47:08 +02001532 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001533 /* do nothing */
1534 break;
Radek Krejci76512572015-08-04 09:47:08 +02001535 case LYS_GROUPING:
1536 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001537 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001538 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001539 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001540
1541 case LYS_INPUT:
1542 case LYS_OUTPUT:
1543 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1544 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001545 case LYS_UNKNOWN:
1546 LOGINT;
1547 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001548 }
Radek Krejci5a065542015-05-22 15:02:07 +02001549
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001550 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001551 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001552 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001553}
1554
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001555static void
Radek Krejcib8048692015-08-05 13:36:34 +02001556module_free_common(struct lys_module *module)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001557{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001558 struct ly_ctx *ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001559 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001560 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001561
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001562 assert(module->ctx);
1563 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001564
Radek Krejcidce51452015-06-16 15:20:08 +02001565 /* as first step, free the imported modules */
1566 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa76ee152015-08-17 15:38:22 +02001567 /* do not free internal modules */
1568 for (j = 0; j < int_mods.count; ++j) {
1569 if (!strcmp(int_mods.modules[j].name, module->imp[i].module->name)
1570 && module->imp[i].module->rev
1571 && !strcmp(int_mods.modules[j].revision, module->imp[i].module->rev[0].date)) {
1572 break;
1573 }
1574 }
1575 if (j < int_mods.count) {
1576 continue;
1577 }
1578
Radek Krejcidce51452015-06-16 15:20:08 +02001579 /* get the imported module from the context and then free,
1580 * this check is necessary because the imported module can
1581 * be already removed
1582 */
1583 l = ctx->models.used;
1584 for (j = 0; j < l; j++) {
1585 if (ctx->models.list[j] == module->imp[i].module) {
Radek Krejci912da452015-07-29 14:10:06 +02001586 lys_free(module->imp[i].module);
Radek Krejcidce51452015-06-16 15:20:08 +02001587 break;
1588 }
1589 }
1590 }
1591 free(module->imp);
1592
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001593 while (module->data) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001594 lys_node_free(module->data);
Radek Krejci21181962015-06-30 14:11:00 +02001595 }
1596 while (module->rpc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001597 lys_node_free(module->rpc);
Radek Krejci21181962015-06-30 14:11:00 +02001598 }
1599 while (module->notif) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001600 lys_node_free(module->notif);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001601 }
Radek Krejci5a065542015-05-22 15:02:07 +02001602
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001603 lydict_remove(ctx, module->dsc);
1604 lydict_remove(ctx, module->ref);
1605 lydict_remove(ctx, module->org);
1606 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001607
Radek Krejcieb00f512015-07-01 16:44:58 +02001608 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001609 for (i = 0; i < module->rev_size; i++) {
1610 lydict_remove(ctx, module->rev[i].dsc);
1611 lydict_remove(ctx, module->rev[i].ref);
1612 }
1613 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001614
Radek Krejcieb00f512015-07-01 16:44:58 +02001615 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001616 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001617 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001618 }
1619 module->ident_size = 0;
1620 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001621
Radek Krejcieb00f512015-07-01 16:44:58 +02001622 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001623 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001624 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001625 }
1626 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001627
Radek Krejcieb00f512015-07-01 16:44:58 +02001628 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001629 for (i = 0; i < module->inc_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001630 lys_submodule_free(module->inc[i].submodule);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001631 }
1632 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001633
Radek Krejcieb00f512015-07-01 16:44:58 +02001634 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02001635 for (i = 0; i < module->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001636 lys_augment_free(ctx, module->augment[i]);
Radek Krejcif5be10f2015-06-16 13:29:36 +02001637 }
1638 free(module->augment);
1639
Radek Krejcieb00f512015-07-01 16:44:58 +02001640 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001641 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001642 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001643 }
1644 free(module->features);
1645
Radek Krejcieb00f512015-07-01 16:44:58 +02001646 /* deviations */
1647 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001648 lys_deviation_free(ctx, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001649 }
1650 free(module->deviation);
1651
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001652 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02001653}
1654
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001655void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001656lys_submodule_free(struct lys_submodule *submodule)
Radek Krejciefaeba32015-05-27 14:30:57 +02001657{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001658 if (!submodule) {
1659 return;
1660 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001661
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001662 submodule->inc_size = 0;
1663 free(submodule->inc);
1664 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02001665
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001666 /* common part with struct ly_module */
Radek Krejcib8048692015-08-05 13:36:34 +02001667 module_free_common((struct lys_module *)submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001668
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001669 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02001670
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001671 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001672}
1673
Radek Krejcib8048692015-08-05 13:36:34 +02001674static struct lys_node_leaf *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001675lys_uniq_find(struct lys_node_list *list, struct lys_node_leaf *orig_leaf)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001676{
Radek Krejci1d82ef62015-08-07 14:44:40 +02001677 struct lys_node *node, *node2, *ret = NULL, *parent1, *parent2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001678 int depth = 1, i;
1679
1680 /* find the correct direct descendant of list in orig_leaf */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001681 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001682 while (1) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001683 if (!node->parent) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001684 return NULL;
1685 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001686 if (!strcmp(node->parent->name, list->name)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001687 break;
1688 }
1689
Radek Krejci1d82ef62015-08-07 14:44:40 +02001690 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001691 ++depth;
1692 }
1693
1694 /* make sure the nodes are equal */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001695 parent1 = node->parent->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001696 parent2 = list->parent;
1697 while (1) {
1698 if ((parent1 && !parent2) || (!parent1 && parent2)) {
1699 return NULL;
1700 }
1701
1702 if (parent1 == parent2) {
1703 break;
1704 }
1705
1706 parent1 = parent1->parent;
1707 parent2 = parent2->parent;
1708 }
1709
1710 /* find the descendant in the list */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001711 LY_TREE_FOR(list->child, node2) {
1712 if (!strcmp(node2->name, node->name)) {
1713 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001714 break;
1715 }
1716 }
1717
1718 if (!ret) {
1719 return NULL;
1720 }
1721
1722 /* continue traversing both trees, the nodes are always truly equal */
1723 while (1) {
1724 --depth;
1725 if (!depth) {
Radek Krejci76512572015-08-04 09:47:08 +02001726 if (ret->nodetype != LYS_LEAF) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001727 return NULL;
1728 }
Radek Krejcib8048692015-08-05 13:36:34 +02001729 return (struct lys_node_leaf *)ret;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001730 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001731 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001732 for (i = 0; i < depth-1; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001733 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001734 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001735 LY_TREE_FOR(ret->child, node2) {
1736 if (!strcmp(node2->name, node->name)) {
1737 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001738 break;
1739 }
1740 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001741 if (!node2) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001742 return NULL;
1743 }
1744 }
1745}
1746
Radek Krejci76512572015-08-04 09:47:08 +02001747struct lys_node *
Michal Vasko71e1aa82015-08-12 12:17:51 +02001748lys_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 +02001749 struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001750{
Radek Krejci76512572015-08-04 09:47:08 +02001751 struct lys_node *retval = NULL, *aux, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001752 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001753 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001754
Michal Vaskoc07187d2015-08-13 15:20:57 +02001755 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001756 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001757 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001758 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001759 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001760 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001761 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001762 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001763 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001764 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001765 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001766 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001767 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001768 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001769 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001770 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001771 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001772 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001773 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001774 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001775 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001776 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001777 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001778 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001779
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001780 /* we cannot just duplicate memory since the strings are stored in
1781 * dictionary and we need to update dictionary counters.
1782 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001783
Radek Krejci1d82ef62015-08-07 14:44:40 +02001784 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001785 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001786 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02001787 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001788 break;
1789
Radek Krejci76512572015-08-04 09:47:08 +02001790 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001791 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02001792 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001793 break;
1794
Radek Krejci76512572015-08-04 09:47:08 +02001795 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001796 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02001797 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001798 break;
1799
Radek Krejci76512572015-08-04 09:47:08 +02001800 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001801 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02001802 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001803 break;
1804
Radek Krejci76512572015-08-04 09:47:08 +02001805 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001806 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02001807 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001808 break;
1809
Radek Krejci76512572015-08-04 09:47:08 +02001810 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001811 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02001812 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001813 break;
1814
Radek Krejci76512572015-08-04 09:47:08 +02001815 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001816 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02001817 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001818 break;
1819
Radek Krejci76512572015-08-04 09:47:08 +02001820 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001821 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02001822 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001823 break;
1824
Radek Krejci76512572015-08-04 09:47:08 +02001825 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001826 grp = calloc(1, sizeof *grp);
1827 retval = (struct lys_node *)grp;
1828 break;
1829
Radek Krejci76512572015-08-04 09:47:08 +02001830 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001831 rpc = calloc(1, sizeof *rpc);
1832 retval = (struct lys_node *)rpc;
1833 break;
1834
Radek Krejci76512572015-08-04 09:47:08 +02001835 case LYS_INPUT:
1836 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001837 io = calloc(1, sizeof *io);
1838 retval = (struct lys_node *)io;
1839 break;
1840
Radek Krejci76512572015-08-04 09:47:08 +02001841 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001842 ntf = calloc(1, sizeof *ntf);
1843 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02001844 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001845
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001846 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02001847 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02001848 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001849 }
Radek Krejcib388c152015-06-04 17:03:03 +02001850
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001851 /*
1852 * duplicate generic part of the structure
1853 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001854 retval->name = lydict_insert(ctx, node->name, 0);
1855 retval->dsc = lydict_insert(ctx, node->dsc, 0);
1856 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02001857 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001858 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001859 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001860 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001861 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001862 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001863
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001864 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001865 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001866
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001867 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001868
Radek Krejci1d82ef62015-08-07 14:44:40 +02001869 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001870 retval->features = calloc(retval->features_size, sizeof *retval->features);
Radek Krejci1d82ef62015-08-07 14:44:40 +02001871 for (i = 0; i < node->features_size; ++i) {
1872 if (unres_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
1873 retval->features[i] = node->features[i];
Michal Vaskod23ce592015-08-06 09:55:37 +02001874 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001875 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001876
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001877 if (recursive) {
1878 /* go recursively */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001879 LY_TREE_FOR(node->child, child) {
Michal Vasko71e1aa82015-08-12 12:17:51 +02001880 aux = lys_node_dup(module, child, retval->flags, retval->nacm, 1, unres);
Radek Krejci10c760e2015-08-14 14:45:43 +02001881 if (!aux || lys_node_addchild(retval, NULL, aux)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02001882 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02001883 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001884 }
1885 }
1886 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001887
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001888 /*
1889 * duplicate specific part of the structure
1890 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001891 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001892 case LYS_CONTAINER:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001893 if (cont_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001894 cont->when = lys_when_dup(ctx, cont_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02001895 if (unres_add_node(module, unres, cont->when, UNRES_WHEN, retval, 0) == -1) {
1896 goto error;
1897 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001898 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001899 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001900
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001901 cont->must_size = cont_orig->must_size;
1902 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001903
Radek Krejci1d82ef62015-08-07 14:44:40 +02001904 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001905 for (i = 0; i < cont->must_size; ++i) {
Michal Vasko49168a22015-08-17 16:35:41 +02001906 if (unres_add_node(module, unres, &cont->must[i], UNRES_MUST, retval, 0) == -1) {
1907 goto error;
1908 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001909 }
1910
Radek Krejci1d82ef62015-08-07 14:44:40 +02001911 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001912 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001913
Radek Krejci76512572015-08-04 09:47:08 +02001914 case LYS_CHOICE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001915 if (choice_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001916 choice->when = lys_when_dup(ctx, choice_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02001917 if (unres_add_node(module, unres, choice->when, UNRES_WHEN, retval, 0) == -1) {
1918 goto error;
1919 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001920 }
1921
1922 if (choice_orig->dflt) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001923 rc = resolve_sibling(choice->module, choice->child, NULL, 0, choice_orig->dflt->name, 0, LYS_ANYXML
Radek Krejci76512572015-08-04 09:47:08 +02001924 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001925 | LYS_LIST, &choice->dflt);
Michal Vasko49168a22015-08-17 16:35:41 +02001926 if (rc) {
1927 if (rc == EXIT_FAILURE) {
1928 LOGINT;
1929 }
1930 goto error;
1931 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001932 } else {
Michal Vaskoc68a2a22015-08-06 09:57:24 +02001933 /* useless to check return value, we don't know whether
1934 * there really wasn't any default defined or it just hasn't
1935 * been resolved, we just hope for the best :)
1936 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001937 unres_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001938 }
1939 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001940
Radek Krejci76512572015-08-04 09:47:08 +02001941 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001942 lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001943 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
1944
1945 if (leaf_orig->dflt) {
1946 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02001947 if (unres_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0) == -1) {
1948 goto error;
1949 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001950 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001951
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001952 leaf->must_size = leaf_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001953 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001954 for (i = 0; i < leaf->must_size; ++i) {
Michal Vasko49168a22015-08-17 16:35:41 +02001955 if (unres_add_node(module, unres, &leaf->must[i], UNRES_MUST, retval, 0) == -1) {
1956 goto error;
1957 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001958 }
Radek Krejci00768f42015-06-18 17:04:04 +02001959
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001960 if (leaf_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001961 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02001962 if (unres_add_node(module, unres, leaf->when, UNRES_WHEN, retval, 0) == -1) {
1963 goto error;
1964 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001965 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001966 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001967
Radek Krejci76512572015-08-04 09:47:08 +02001968 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001969 lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001970 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001971
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001972 llist->min = llist_orig->min;
1973 llist->max = llist_orig->max;
1974
1975 llist->must_size = llist_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001976 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001977 for (i = 0; i < llist->must_size; ++i) {
Michal Vasko49168a22015-08-17 16:35:41 +02001978 if (unres_add_node(module, unres, &llist->must[i], UNRES_MUST, retval, 0) == -1) {
1979 goto error;
1980 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001981 }
Radek Krejci00768f42015-06-18 17:04:04 +02001982
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001983 if (llist_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001984 llist->when = lys_when_dup(ctx, llist_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02001985 if (unres_add_node(module, unres, llist->when, UNRES_WHEN, retval, 0) == -1) {
1986 goto error;
1987 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001988 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001989 break;
1990
Radek Krejci76512572015-08-04 09:47:08 +02001991 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001992 list->min = list_orig->min;
1993 list->max = list_orig->max;
1994
1995 list->must_size = list_orig->must_size;
1996 list->tpdf_size = list_orig->tpdf_size;
1997 list->keys_size = list_orig->keys_size;
1998 list->unique_size = list_orig->unique_size;
1999
Radek Krejci1d82ef62015-08-07 14:44:40 +02002000 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002001 for (i = 0; i < list->must_size; ++i) {
Michal Vasko49168a22015-08-17 16:35:41 +02002002 if (unres_add_node(module, unres, &list->must[i], UNRES_MUST, retval, 0) == -1) {
2003 goto error;
2004 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002005 }
2006
Radek Krejci1d82ef62015-08-07 14:44:40 +02002007 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002008
2009 if (list->keys_size) {
2010 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002011
2012 /* we managed to resolve it before, resolve it again manually */
2013 if (list_orig->keys[0]) {
2014 for (i = 0; i < list->keys_size; ++i) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002015 rc = resolve_sibling(list->module, list->child, NULL, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2016 (struct lys_node **)&list->keys[i]);
Michal Vasko49168a22015-08-17 16:35:41 +02002017 if (rc) {
2018 if (rc == EXIT_FAILURE) {
2019 LOGINT;
2020 }
2021 goto error;
2022 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002023 }
2024 /* it was not resolved yet, add unres copy */
2025 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002026 if (unres_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02002027 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002028 goto error;
Michal Vaskod23ce592015-08-06 09:55:37 +02002029 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002030 }
2031 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002032
2033 list->unique = calloc(list->unique_size, sizeof *list->unique);
2034 if (list_orig->unique) {
2035 for (i = 0; i < list->unique_size; ++i) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002036 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
2037 for (j = 0; j < list->unique[i].leafs_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002038 list->unique[i].leafs[j] = lys_uniq_find(list, list_orig->unique[i].leafs[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002039 }
2040 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002041 } else {
2042 for (i = 0; i < list->unique_size; ++i) {
2043 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02002044 list->unique[i].leafs = (struct lys_node_leaf **)list;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002045 unres_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002046 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002047 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002048
2049 if (list_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002050 list->when = lys_when_dup(ctx, list_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02002051 if (unres_add_node(module, unres, list->when, UNRES_WHEN, retval, 0) == -1) {
2052 goto error;
2053 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002054 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002055 break;
2056
Radek Krejci76512572015-08-04 09:47:08 +02002057 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002058 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002059 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002060 for (i = 0; i < anyxml->must_size; ++i) {
Michal Vasko49168a22015-08-17 16:35:41 +02002061 if (unres_add_node(module, unres, &anyxml->must[i], UNRES_MUST, retval, 0) == -1) {
2062 goto error;
2063 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002064 }
2065
2066 if (anyxml_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002067 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02002068 if (unres_add_node(module, unres, anyxml->when, UNRES_WHEN, retval, 0) == -1) {
2069 goto error;
2070 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002071 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002072 break;
2073
Radek Krejci76512572015-08-04 09:47:08 +02002074 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002075 uses->grp = uses_orig->grp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002076
2077 if (uses_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002078 uses->when = lys_when_dup(ctx, uses_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02002079 if (unres_add_node(module, unres, uses->when, UNRES_WHEN, (struct lys_node *)uses, 0) == -1) {
2080 goto error;
2081 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002082 }
2083
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002084 uses->refine_size = uses_orig->refine_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002085 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size, uses, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002086 uses->augment_size = uses_orig->augment_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002087 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size, unres);
Michal Vaskof8c128d2015-08-06 15:25:28 +02002088 if (!uses->child) {
Michal Vasko49168a22015-08-17 16:35:41 +02002089 if (unres_add_node(module, unres, uses, UNRES_USES, NULL, 0) == -1) {
2090 goto error;
2091 }
Michal Vaskof8c128d2015-08-06 15:25:28 +02002092 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002093 break;
2094
Radek Krejci76512572015-08-04 09:47:08 +02002095 case LYS_CASE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002096 if (cs_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002097 cs->when = lys_when_dup(ctx, cs_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02002098 if (unres_add_node(module, unres, cs->when, UNRES_WHEN, retval, 0) == -1) {
2099 goto error;
2100 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002101 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002102 break;
2103
Radek Krejci76512572015-08-04 09:47:08 +02002104 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002105 grp->tpdf_size = grp_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002106 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002107 break;
2108
Radek Krejci76512572015-08-04 09:47:08 +02002109 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002110 rpc->tpdf_size = rpc_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002111 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002112 break;
2113
Radek Krejci76512572015-08-04 09:47:08 +02002114 case LYS_INPUT:
2115 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002116 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002117 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002118 break;
2119
Radek Krejci76512572015-08-04 09:47:08 +02002120 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002121 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002122 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcia01e5432015-06-16 10:35:25 +02002123 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002124
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002125 default:
Radek Krejci00768f42015-06-18 17:04:04 +02002126 /* LY_NODE_AUGMENT */
Michal Vaskod23ce592015-08-06 09:55:37 +02002127 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002128 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002129 }
2130
2131 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002132
2133error:
2134
2135 lys_node_free(retval);
2136 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002137}
2138
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002139API void
Radek Krejcib8048692015-08-05 13:36:34 +02002140lys_free(struct lys_module *module)
Radek Krejciefaeba32015-05-27 14:30:57 +02002141{
Radek Krejcidce51452015-06-16 15:20:08 +02002142 struct ly_ctx *ctx;
2143 int i;
2144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002145 if (!module) {
2146 return;
2147 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002148
Radek Krejcidce51452015-06-16 15:20:08 +02002149 /* remove schema from the context */
2150 ctx = module->ctx;
2151 if (ctx->models.used) {
2152 for (i = 0; i < ctx->models.used; i++) {
2153 if (ctx->models.list[i] == module) {
2154 /* replace the position in the list by the last module in the list */
2155 ctx->models.used--;
2156 ctx->models.list[i] = ctx->models.list[ctx->models.used];
2157 ctx->models.list[ctx->models.used] = NULL;
2158 /* we are done */
2159 break;
2160 }
2161 }
2162 }
2163
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002164 /* common part with struct ly_submodule */
2165 module_free_common(module);
Radek Krejciefaeba32015-05-27 14:30:57 +02002166
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002167 /* specific items to free */
2168 lydict_remove(module->ctx, module->ns);
2169 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02002170
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002171 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002172}
Radek Krejci7e97c352015-06-19 16:26:34 +02002173
2174/*
2175 * op: 1 - enable, 0 - disable
2176 */
2177static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002178lys_features_change(struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002179{
2180 int all = 0;
2181 int i, j, k;
2182
2183 if (!module || !name || !strlen(name)) {
2184 return EXIT_FAILURE;
2185 }
2186
2187 if (!strcmp(name, "*")) {
2188 /* enable all */
2189 all = 1;
2190 }
2191
2192 /* module itself */
2193 for (i = 0; i < module->features_size; i++) {
2194 if (all || !strcmp(module->features[i].name, name)) {
2195 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002196 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002197 /* enable referenced features (recursion) */
2198 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002199 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002200 module->features[i].features[k]->name, op);
2201 }
2202 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002203 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002204 }
2205 if (!all) {
2206 return EXIT_SUCCESS;
2207 }
2208 }
2209 }
2210
2211 /* submodules */
2212 for (j = 0; j < module->inc_size; j++) {
2213 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2214 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2215 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002216 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002217 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002218 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002219 }
2220 if (!all) {
2221 return EXIT_SUCCESS;
2222 }
2223 }
2224 }
2225 }
2226
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002227 /* TODO submodules of submodules ... */
2228
Radek Krejci7e97c352015-06-19 16:26:34 +02002229 if (all) {
2230 return EXIT_SUCCESS;
2231 } else {
2232 return EXIT_FAILURE;
2233 }
2234}
2235
2236API int
Radek Krejcib8048692015-08-05 13:36:34 +02002237lys_features_enable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002238{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002239 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002240}
2241
2242API int
Radek Krejcib8048692015-08-05 13:36:34 +02002243lys_features_disable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002244{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002245 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002246}
2247
2248API int
Radek Krejcib8048692015-08-05 13:36:34 +02002249lys_features_state(struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002250{
2251 int i, j;
2252
2253 if (!module || !feature) {
2254 return -1;
2255 }
2256
2257 /* search for the specified feature */
2258 /* module itself */
2259 for (i = 0; i < module->features_size; i++) {
2260 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002261 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002262 return 1;
2263 } else {
2264 return 0;
2265 }
2266 }
2267 }
2268
2269 /* submodules */
2270 for (j = 0; j < module->inc_size; j++) {
2271 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2272 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002273 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002274 return 1;
2275 } else {
2276 return 0;
2277 }
2278 }
2279 }
2280 }
2281
2282 /* TODO submodules of submodules ... */
2283
2284 /* feature definition not found */
2285 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002286}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002287
Radek Krejci96a10da2015-07-30 11:00:14 +02002288API const char **
Radek Krejcib8048692015-08-05 13:36:34 +02002289lys_features_list(struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002290{
Radek Krejci96a10da2015-07-30 11:00:14 +02002291 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002292 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002293 unsigned int count;
2294
2295 if (!module) {
2296 return NULL;
2297 }
2298
2299 count = module->features_size;
2300 for (i = 0; i < module->inc_size; i++) {
2301 count += module->inc[i].submodule->features_size;
2302 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002303 result = malloc((count + 1) * sizeof *result);
2304 if (states) {
2305 *states = malloc((count + 1) * sizeof **states);
Michal Vasko2367e7c2015-07-07 11:33:44 +02002306 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002307 count = 0;
2308
2309 /* module itself */
2310 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002311 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002312 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002313 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002314 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002315 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002316 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002317 }
2318 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002319 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002320 }
2321
2322 /* submodules */
2323 for (j = 0; j < module->inc_size; j++) {
2324 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002325 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002326 if (states) {
2327 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2328 (*states)[count] = 1;
2329 } else {
2330 (*states)[count] = 0;
2331 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002332 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002333 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002334 }
2335 }
2336
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002337 /* TODO submodules of submodules ... */
2338
2339 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002340 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002341
2342 return result;
2343}
Radek Krejcib20c62d2015-07-07 17:07:14 +02002344
2345API struct lyd_node *
Radek Krejci25b9fd32015-08-10 15:06:07 +02002346lyd_parse(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
Radek Krejcib20c62d2015-07-07 17:07:14 +02002347{
2348 if (!ctx || !data) {
2349 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2350 return NULL;
2351 }
2352
2353 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02002354 case LYD_XML:
Radek Krejci25b9fd32015-08-10 15:06:07 +02002355 return xml_read_data(ctx, data, options);
Radek Krejcia9167ef2015-08-03 11:01:11 +02002356 case LYD_JSON:
Radek Krejcib20c62d2015-07-07 17:07:14 +02002357 default:
2358 /* TODO */
2359 return NULL;
2360 }
2361
2362 return NULL;
2363}
2364
Radek Krejci0e1d1a62015-07-31 11:17:01 +02002365API void
Radek Krejci912da452015-07-29 14:10:06 +02002366lyd_free(struct lyd_node *node)
Radek Krejcib20c62d2015-07-07 17:07:14 +02002367{
2368 struct lyd_node *next, *child;
2369
Radek Krejci52f791c2015-07-15 11:14:17 +02002370 if (!node) {
2371 return;
2372 }
2373
Radek Krejci76512572015-08-04 09:47:08 +02002374 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
Radek Krejcie4748472015-07-08 18:00:22 +02002375 /* free children */
2376 LY_TREE_FOR_SAFE(node->child, next, child) {
Radek Krejci912da452015-07-29 14:10:06 +02002377 lyd_free(child);
Radek Krejcie4748472015-07-08 18:00:22 +02002378 }
Radek Krejci76512572015-08-04 09:47:08 +02002379 } else if (node->schema->nodetype == LYS_ANYXML) {
Radek Krejci9566b092015-07-31 11:18:15 +02002380 lyxml_free_elem(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
Radek Krejcie4748472015-07-08 18:00:22 +02002381 } else {
2382 /* free value */
2383 switch(((struct lyd_node_leaf *)node)->value_type) {
2384 case LY_TYPE_BINARY:
2385 case LY_TYPE_STRING:
2386 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf *)node)->value.string);
2387 break;
Radek Krejci3e3affe2015-07-09 15:38:40 +02002388 case LY_TYPE_BITS:
2389 if (((struct lyd_node_leaf *)node)->value.bit) {
2390 free(((struct lyd_node_leaf *)node)->value.bit);
2391 }
2392 break;
Radek Krejcie4748472015-07-08 18:00:22 +02002393 default:
Radek Krejci7511f402015-07-10 09:56:30 +02002394 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
Radek Krejcie4748472015-07-08 18:00:22 +02002395 break;
2396 }
Radek Krejcib20c62d2015-07-07 17:07:14 +02002397 }
2398
2399 if (node->prev->next) {
2400 node->prev->next = node->next;
2401 } else if (node->parent) {
2402 /* first node */
2403 node->parent->child = node->next;
2404 }
2405 if (node->next) {
2406 node->next->prev = node->prev;
2407 }
2408
2409 free(node);
2410}
Michal Vaskof54f2f82015-07-17 13:12:05 +02002411
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002412API int
Radek Krejci9566b092015-07-31 11:18:15 +02002413lyd_is_last(struct lyd_node *node)
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002414{
2415 struct lyd_node *n;
2416
2417 if (!node->next) {
2418 return 1;
2419 }
2420
2421 for (n = node->next; n; n = n->next) {
2422 switch (n->schema->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002423 case LYS_LIST:
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002424 if (!((struct lyd_node_list *)n)->lprev) {
2425 return 0;
2426 }
2427 break;
Radek Krejci76512572015-08-04 09:47:08 +02002428 case LYS_LEAFLIST:
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002429 if (!((struct lyd_node_leaflist *)n)->lprev) {
2430 return 0;
2431 }
2432 break;
2433 default:
2434 return 0;
2435 }
2436 }
2437 return 1;
2438}