blob: 2ff9122e6e7e0eaf3092ef495976ab220eeeafdc [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 Vasko13b15832015-08-19 11:04:48 +0200754 lys_free(mod, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200755 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)) {
Michal Vasko13b15832015-08-19 11:04:48 +0200790 lys_submodule_free(submod, 0);
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{
Radek Krejcib7f5e412015-08-13 10:15:51 +02001169 lydict_remove(ctx, aug.target_name);
1170 lydict_remove(ctx, aug.dsc);
1171 lydict_remove(ctx, aug.ref);
1172
1173 free(aug.features);
1174
1175 lys_when_free(ctx, aug.when);
1176
Michal Vasko84f52f12015-08-19 15:06:31 +02001177 /* Do not free the children, they were appended somewhere and their
1178 * new parent will take care of them.
1179 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001180}
1181
Radek Krejci76512572015-08-04 09:47:08 +02001182static struct lys_node_augment *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001183lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size,
Michal Vasko41de7352015-08-06 09:53:34 +02001184 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001185{
Radek Krejci76512572015-08-04 09:47:08 +02001186 struct lys_node_augment *new = NULL;
Michal Vasko41de7352015-08-06 09:53:34 +02001187 struct lys_node *snode;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001188 int i = -1;
Radek Krejci106efc02015-06-10 14:36:27 +02001189
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001190 if (!size) {
1191 return NULL;
1192 }
Radek Krejci106efc02015-06-10 14:36:27 +02001193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001194 new = calloc(size, sizeof *new);
1195 for (i = 0; i < size; i++) {
1196 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1197 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1198 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1199 new[i].flags = old[i].flags;
Michal Vasko591e0b22015-08-13 13:53:43 +02001200 new[i].nodetype = old[i].nodetype;
1201 /* .target = NULL */
Radek Krejci106efc02015-06-10 14:36:27 +02001202
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001203 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001204
Michal Vasko41de7352015-08-06 09:53:34 +02001205 /* copy the augment nodes */
1206 assert(old[i].child);
1207 LY_TREE_FOR(old[i].child, snode) {
Radek Krejci10c760e2015-08-14 14:45:43 +02001208 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 +02001209 for ( ; i >= 0; i--) {
1210 lys_augment_free(module->ctx, new[i]);
1211 }
1212 free(new);
1213 return NULL;
1214 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001215 }
1216 }
Radek Krejci106efc02015-06-10 14:36:27 +02001217
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001218 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001219}
1220
Radek Krejci76512572015-08-04 09:47:08 +02001221static struct lys_refine *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001222lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size, struct lys_node_uses *uses,
Michal Vaskof02e3742015-08-05 16:27:02 +02001223 struct unres_schema *unres)
Michal Vasko1982cad2015-06-08 15:49:30 +02001224{
Radek Krejci76512572015-08-04 09:47:08 +02001225 struct lys_refine *result;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001226 int i, j;
Michal Vasko1982cad2015-06-08 15:49:30 +02001227
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001228 if (!size) {
1229 return NULL;
1230 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001231
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001232 result = calloc(size, sizeof *result);
1233 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001234 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001235 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1236 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001237 result[i].flags = old[i].flags;
1238 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001239
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001240 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001241 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001242 for (j = 0; j < result[i].must_size; ++j) {
Michal Vasko49168a22015-08-17 16:35:41 +02001243 if (unres_add_node(mod, unres, &result[i].must[j], UNRES_MUST, (struct lys_node *)uses, 0) == -1) {
1244 free(result);
1245 return NULL;
1246 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001247 }
1248
Radek Krejci76512572015-08-04 09:47:08 +02001249 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001250 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001251 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001252 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001253 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001254 result[i].mod.list = old[i].mod.list;
1255 }
1256 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001257
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001258 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001259}
1260
Radek Krejci1d82ef62015-08-07 14:44:40 +02001261static void
1262lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001263{
Radek Krejcia52656e2015-08-05 13:41:50 +02001264 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001265
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001266 assert(ctx);
1267 if (!ident) {
1268 return;
1269 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001270
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001271 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001272 * if caller free only a single data model which is used (its identity is
1273 * reference from identity in another module), this silly freeing can lead
1274 * to segmentation fault. But without noting if the module is used by some
1275 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001276 *
1277 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001278 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001279 */
1280 while (ident->der) {
1281 der = ident->der;
1282 ident->der = der->next;
1283 free(der);
1284 }
Radek Krejci6793db02015-05-22 17:49:54 +02001285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001286 lydict_remove(ctx, ident->name);
1287 lydict_remove(ctx, ident->dsc);
1288 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001289
1290}
1291
Radek Krejci1d82ef62015-08-07 14:44:40 +02001292static void
1293lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001294{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001295 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001296
Radek Krejcid12f57b2015-08-06 10:43:39 +02001297 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001298 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001299 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001300 }
1301 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001302}
1303
Radek Krejci1d82ef62015-08-07 14:44:40 +02001304static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001305lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1306{
1307 int i;
1308
1309 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1310 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001311 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001312 }
1313 free(io->tpdf);
1314}
1315
Radek Krejci1d82ef62015-08-07 14:44:40 +02001316static void
1317lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001318{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001319 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001320
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001321 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001322 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001323 }
1324 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001325
Radek Krejci1d82ef62015-08-07 14:44:40 +02001326 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001327}
1328
Radek Krejci1d82ef62015-08-07 14:44:40 +02001329static void
1330lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001331{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001332 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001333
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001334 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001335 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001336 }
1337 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001338
Radek Krejci1d82ef62015-08-07 14:44:40 +02001339 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001340
Radek Krejci1d82ef62015-08-07 14:44:40 +02001341 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001342 lydict_remove(ctx, leaf->units);
1343 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001344}
1345
Radek Krejci1d82ef62015-08-07 14:44:40 +02001346static void
1347lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001348{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001349 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001350
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001351 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001352 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001353 }
1354 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001355
Radek Krejci1d82ef62015-08-07 14:44:40 +02001356 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001357
Radek Krejci1d82ef62015-08-07 14:44:40 +02001358 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001359 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001360}
1361
Radek Krejci1d82ef62015-08-07 14:44:40 +02001362static void
1363lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001364{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001365 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001366
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001367 /* handle only specific parts for LY_NODE_LIST */
1368 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001369 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001370 }
1371 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001372
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001373 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001374 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001375 }
1376 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001377
Radek Krejci1d82ef62015-08-07 14:44:40 +02001378 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001380 for (i = 0; i < list->unique_size; i++) {
1381 free(list->unique[i].leafs);
1382 }
1383 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001384
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001385 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001386}
1387
Radek Krejci1d82ef62015-08-07 14:44:40 +02001388static void
1389lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001390{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001391 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001392
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001393 /* handle only specific parts for LY_NODE_CONTAINER */
1394 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001395
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001396 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001397 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001398 }
1399 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001401 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001402 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001403 }
1404 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001405
Radek Krejci1d82ef62015-08-07 14:44:40 +02001406 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001407}
1408
Radek Krejci1d82ef62015-08-07 14:44:40 +02001409static void
1410lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001411{
1412 lydict_remove(ctx, f->name);
1413 lydict_remove(ctx, f->dsc);
1414 lydict_remove(ctx, f->ref);
1415 free(f->features);
1416}
1417
Radek Krejci1d82ef62015-08-07 14:44:40 +02001418static void
1419lys_deviation_free(struct ly_ctx *ctx, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001420{
1421 int i, j;
1422
1423 lydict_remove(ctx, dev->target_name);
1424 lydict_remove(ctx, dev->dsc);
1425 lydict_remove(ctx, dev->ref);
1426
1427 for (i = 0; i < dev->deviate_size; i++) {
1428 lydict_remove(ctx, dev->deviate[i].dflt);
1429 lydict_remove(ctx, dev->deviate[i].units);
1430
1431 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1432 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001433 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001434 }
1435 free(dev->deviate[i].must);
1436
1437 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1438 free(dev->deviate[j].unique[j].leafs);
1439 }
1440 free(dev->deviate[i].unique);
1441 }
1442 }
1443 free(dev->deviate);
1444}
1445
Radek Krejci1d82ef62015-08-07 14:44:40 +02001446static void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001447lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +02001448{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001449 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001450
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001451 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001452 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001453 lydict_remove(ctx, uses->refine[i].dsc);
1454 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001455
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001456 for (j = 0; j < uses->refine[j].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001457 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001458 }
1459 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001460
Radek Krejci76512572015-08-04 09:47:08 +02001461 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001462 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001463 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001464 lydict_remove(ctx, uses->refine[i].mod.presence);
1465 }
1466 }
1467 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001468
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001469 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001470 lys_augment_free(ctx, uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001471 }
1472 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001473
Radek Krejci1d82ef62015-08-07 14:44:40 +02001474 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001475}
1476
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001477void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001478lys_node_free(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001479{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001480 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001481 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001482
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001483 if (!node) {
1484 return;
1485 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001486
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001487 assert(node->module);
1488 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001489
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001490 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001491
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001492 /* common part */
1493 LY_TREE_FOR_SAFE(node->child, next, sub) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001494 lys_node_free(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001495 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001496
Radek Krejcid12f57b2015-08-06 10:43:39 +02001497 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1498 free(node->features);
1499 lydict_remove(ctx, node->name);
1500 lydict_remove(ctx, node->dsc);
1501 lydict_remove(ctx, node->ref);
1502 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001503
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001504 /* specific part */
1505 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001506 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001507 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001508 break;
Radek Krejci76512572015-08-04 09:47:08 +02001509 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001510 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001511 break;
Radek Krejci76512572015-08-04 09:47:08 +02001512 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001513 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001514 break;
Radek Krejci76512572015-08-04 09:47:08 +02001515 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001516 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001517 break;
Radek Krejci76512572015-08-04 09:47:08 +02001518 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001519 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001520 break;
Radek Krejci76512572015-08-04 09:47:08 +02001521 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001522 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001523 break;
Radek Krejci76512572015-08-04 09:47:08 +02001524 case LYS_USES:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001525 lys_uses_free(ctx, (struct lys_node_uses *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001526 break;
Radek Krejci76512572015-08-04 09:47:08 +02001527 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001528 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001529 break;
Radek Krejci76512572015-08-04 09:47:08 +02001530 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001531 /* do nothing */
1532 break;
Radek Krejci76512572015-08-04 09:47:08 +02001533 case LYS_GROUPING:
1534 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001535 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001536 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001537 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001538
1539 case LYS_INPUT:
1540 case LYS_OUTPUT:
1541 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1542 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001543 case LYS_UNKNOWN:
1544 LOGINT;
1545 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001546 }
Radek Krejci5a065542015-05-22 15:02:07 +02001547
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001548 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001549 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001550 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001551}
1552
Michal Vasko13b15832015-08-19 11:04:48 +02001553/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001554static void
Michal Vasko13b15832015-08-19 11:04:48 +02001555module_free_common(struct lys_module *module, int free_int_mods)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001556{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001557 struct ly_ctx *ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001558 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001559 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001560
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001561 assert(module->ctx);
1562 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001563
Radek Krejcidce51452015-06-16 15:20:08 +02001564 /* as first step, free the imported modules */
1565 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa76ee152015-08-17 15:38:22 +02001566 /* do not free internal modules */
Michal Vaskoddde94f2015-08-19 15:07:00 +02001567 if (!free_int_mods) {
1568 for (j = 0; j < int_mods.count; ++j) {
Michal Vaskod83c03a2015-08-21 09:09:24 +02001569 if (module->imp[i].module && !strcmp(int_mods.modules[j].name, module->imp[i].module->name)
Michal Vaskoddde94f2015-08-19 15:07:00 +02001570 && module->imp[i].module->rev
1571 && !strcmp(int_mods.modules[j].revision, module->imp[i].module->rev[0].date)) {
1572 break;
1573 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02001574 }
Michal Vaskoddde94f2015-08-19 15:07:00 +02001575 if (j < int_mods.count) {
1576 continue;
1577 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02001578 }
1579
Radek Krejcidce51452015-06-16 15:20:08 +02001580 /* get the imported module from the context and then free,
1581 * this check is necessary because the imported module can
1582 * be already removed
1583 */
1584 l = ctx->models.used;
1585 for (j = 0; j < l; j++) {
1586 if (ctx->models.list[j] == module->imp[i].module) {
Michal Vasko13b15832015-08-19 11:04:48 +02001587 lys_free(module->imp[i].module, free_int_mods);
Radek Krejcidce51452015-06-16 15:20:08 +02001588 break;
1589 }
1590 }
1591 }
1592 free(module->imp);
1593
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001594 while (module->data) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001595 lys_node_free(module->data);
Radek Krejci21181962015-06-30 14:11:00 +02001596 }
1597 while (module->rpc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001598 lys_node_free(module->rpc);
Radek Krejci21181962015-06-30 14:11:00 +02001599 }
1600 while (module->notif) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001601 lys_node_free(module->notif);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001602 }
Radek Krejci5a065542015-05-22 15:02:07 +02001603
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001604 lydict_remove(ctx, module->dsc);
1605 lydict_remove(ctx, module->ref);
1606 lydict_remove(ctx, module->org);
1607 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001608
Radek Krejcieb00f512015-07-01 16:44:58 +02001609 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001610 for (i = 0; i < module->rev_size; i++) {
1611 lydict_remove(ctx, module->rev[i].dsc);
1612 lydict_remove(ctx, module->rev[i].ref);
1613 }
1614 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001615
Radek Krejcieb00f512015-07-01 16:44:58 +02001616 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001617 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001618 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001619 }
1620 module->ident_size = 0;
1621 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001622
Radek Krejcieb00f512015-07-01 16:44:58 +02001623 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001624 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001625 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001626 }
1627 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001628
Radek Krejcieb00f512015-07-01 16:44:58 +02001629 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001630 for (i = 0; i < module->inc_size; i++) {
Michal Vasko13b15832015-08-19 11:04:48 +02001631 lys_submodule_free(module->inc[i].submodule, free_int_mods);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001632 }
1633 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001634
Radek Krejcieb00f512015-07-01 16:44:58 +02001635 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02001636 for (i = 0; i < module->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001637 lys_augment_free(ctx, module->augment[i]);
Radek Krejcif5be10f2015-06-16 13:29:36 +02001638 }
1639 free(module->augment);
1640
Radek Krejcieb00f512015-07-01 16:44:58 +02001641 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001642 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001643 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001644 }
1645 free(module->features);
1646
Radek Krejcieb00f512015-07-01 16:44:58 +02001647 /* deviations */
1648 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001649 lys_deviation_free(ctx, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001650 }
1651 free(module->deviation);
1652
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001653 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02001654}
1655
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001656void
Michal Vasko13b15832015-08-19 11:04:48 +02001657lys_submodule_free(struct lys_submodule *submodule, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02001658{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001659 if (!submodule) {
1660 return;
1661 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001662
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001663 submodule->inc_size = 0;
1664 free(submodule->inc);
1665 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02001666
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001667 /* common part with struct ly_module */
Michal Vasko13b15832015-08-19 11:04:48 +02001668 module_free_common((struct lys_module *)submodule, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02001669
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001670 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02001671
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001672 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001673}
1674
Radek Krejcib8048692015-08-05 13:36:34 +02001675static struct lys_node_leaf *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001676lys_uniq_find(struct lys_node_list *list, struct lys_node_leaf *orig_leaf)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001677{
Radek Krejci1d82ef62015-08-07 14:44:40 +02001678 struct lys_node *node, *node2, *ret = NULL, *parent1, *parent2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001679 int depth = 1, i;
1680
1681 /* find the correct direct descendant of list in orig_leaf */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001682 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001683 while (1) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001684 if (!node->parent) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001685 return NULL;
1686 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001687 if (!strcmp(node->parent->name, list->name)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001688 break;
1689 }
1690
Radek Krejci1d82ef62015-08-07 14:44:40 +02001691 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001692 ++depth;
1693 }
1694
1695 /* make sure the nodes are equal */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001696 parent1 = node->parent->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001697 parent2 = list->parent;
1698 while (1) {
1699 if ((parent1 && !parent2) || (!parent1 && parent2)) {
1700 return NULL;
1701 }
1702
1703 if (parent1 == parent2) {
1704 break;
1705 }
1706
1707 parent1 = parent1->parent;
1708 parent2 = parent2->parent;
1709 }
1710
1711 /* find the descendant in the list */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001712 LY_TREE_FOR(list->child, node2) {
1713 if (!strcmp(node2->name, node->name)) {
1714 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001715 break;
1716 }
1717 }
1718
1719 if (!ret) {
1720 return NULL;
1721 }
1722
1723 /* continue traversing both trees, the nodes are always truly equal */
1724 while (1) {
1725 --depth;
1726 if (!depth) {
Radek Krejci76512572015-08-04 09:47:08 +02001727 if (ret->nodetype != LYS_LEAF) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001728 return NULL;
1729 }
Radek Krejcib8048692015-08-05 13:36:34 +02001730 return (struct lys_node_leaf *)ret;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001731 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001732 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001733 for (i = 0; i < depth-1; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001734 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001735 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001736 LY_TREE_FOR(ret->child, node2) {
1737 if (!strcmp(node2->name, node->name)) {
1738 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001739 break;
1740 }
1741 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001742 if (!node2) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001743 return NULL;
1744 }
1745 }
1746}
1747
Radek Krejci76512572015-08-04 09:47:08 +02001748struct lys_node *
Michal Vasko71e1aa82015-08-12 12:17:51 +02001749lys_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 +02001750 struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001751{
Radek Krejci76512572015-08-04 09:47:08 +02001752 struct lys_node *retval = NULL, *aux, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001753 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001754 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001755
Michal Vaskoc07187d2015-08-13 15:20:57 +02001756 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001757 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001758 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001759 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001760 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001761 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001762 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001763 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001764 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001765 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001766 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001767 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001768 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001769 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001770 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001771 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001772 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001773 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001774 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001775 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001776 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001777 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001778 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001779 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001780
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001781 /* we cannot just duplicate memory since the strings are stored in
1782 * dictionary and we need to update dictionary counters.
1783 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001784
Radek Krejci1d82ef62015-08-07 14:44:40 +02001785 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001786 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001787 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02001788 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001789 break;
1790
Radek Krejci76512572015-08-04 09:47:08 +02001791 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001792 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02001793 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001794 break;
1795
Radek Krejci76512572015-08-04 09:47:08 +02001796 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001797 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02001798 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001799 break;
1800
Radek Krejci76512572015-08-04 09:47:08 +02001801 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001802 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02001803 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001804 break;
1805
Radek Krejci76512572015-08-04 09:47:08 +02001806 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001807 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02001808 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001809 break;
1810
Radek Krejci76512572015-08-04 09:47:08 +02001811 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001812 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02001813 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001814 break;
1815
Radek Krejci76512572015-08-04 09:47:08 +02001816 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001817 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02001818 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001819 break;
1820
Radek Krejci76512572015-08-04 09:47:08 +02001821 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001822 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02001823 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001824 break;
1825
Radek Krejci76512572015-08-04 09:47:08 +02001826 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001827 grp = calloc(1, sizeof *grp);
1828 retval = (struct lys_node *)grp;
1829 break;
1830
Radek Krejci76512572015-08-04 09:47:08 +02001831 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001832 rpc = calloc(1, sizeof *rpc);
1833 retval = (struct lys_node *)rpc;
1834 break;
1835
Radek Krejci76512572015-08-04 09:47:08 +02001836 case LYS_INPUT:
1837 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001838 io = calloc(1, sizeof *io);
1839 retval = (struct lys_node *)io;
1840 break;
1841
Radek Krejci76512572015-08-04 09:47:08 +02001842 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001843 ntf = calloc(1, sizeof *ntf);
1844 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02001845 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001846
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001847 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02001848 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02001849 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001850 }
Radek Krejcib388c152015-06-04 17:03:03 +02001851
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001852 /*
1853 * duplicate generic part of the structure
1854 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001855 retval->name = lydict_insert(ctx, node->name, 0);
1856 retval->dsc = lydict_insert(ctx, node->dsc, 0);
1857 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02001858 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001859 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001860 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001861 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001862 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001863 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001864
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001865 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001866 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001867
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001868 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001869
Radek Krejci1d82ef62015-08-07 14:44:40 +02001870 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001871 retval->features = calloc(retval->features_size, sizeof *retval->features);
Radek Krejci1d82ef62015-08-07 14:44:40 +02001872 for (i = 0; i < node->features_size; ++i) {
1873 if (unres_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
1874 retval->features[i] = node->features[i];
Michal Vaskod23ce592015-08-06 09:55:37 +02001875 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001876 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001878 if (recursive) {
1879 /* go recursively */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001880 LY_TREE_FOR(node->child, child) {
Michal Vasko71e1aa82015-08-12 12:17:51 +02001881 aux = lys_node_dup(module, child, retval->flags, retval->nacm, 1, unres);
Radek Krejci10c760e2015-08-14 14:45:43 +02001882 if (!aux || lys_node_addchild(retval, NULL, aux)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02001883 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02001884 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001885 }
1886 }
1887 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001888
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001889 /*
1890 * duplicate specific part of the structure
1891 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001892 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001893 case LYS_CONTAINER:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001894 if (cont_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001895 cont->when = lys_when_dup(ctx, cont_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02001896 if (unres_add_node(module, unres, cont->when, UNRES_WHEN, retval, 0) == -1) {
1897 goto error;
1898 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001899 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001900 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001901
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001902 cont->must_size = cont_orig->must_size;
1903 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001904
Radek Krejci1d82ef62015-08-07 14:44:40 +02001905 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001906 for (i = 0; i < cont->must_size; ++i) {
Michal Vasko49168a22015-08-17 16:35:41 +02001907 if (unres_add_node(module, unres, &cont->must[i], UNRES_MUST, retval, 0) == -1) {
1908 goto error;
1909 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001910 }
1911
Radek Krejci1d82ef62015-08-07 14:44:40 +02001912 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001913 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001914
Radek Krejci76512572015-08-04 09:47:08 +02001915 case LYS_CHOICE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001916 if (choice_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001917 choice->when = lys_when_dup(ctx, choice_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02001918 if (unres_add_node(module, unres, choice->when, UNRES_WHEN, retval, 0) == -1) {
1919 goto error;
1920 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001921 }
1922
1923 if (choice_orig->dflt) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001924 rc = resolve_sibling(choice->module, choice->child, NULL, 0, choice_orig->dflt->name, 0, LYS_ANYXML
Radek Krejci76512572015-08-04 09:47:08 +02001925 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001926 | LYS_LIST, &choice->dflt);
Michal Vasko49168a22015-08-17 16:35:41 +02001927 if (rc) {
1928 if (rc == EXIT_FAILURE) {
1929 LOGINT;
1930 }
1931 goto error;
1932 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001933 } else {
Michal Vaskoc68a2a22015-08-06 09:57:24 +02001934 /* useless to check return value, we don't know whether
1935 * there really wasn't any default defined or it just hasn't
1936 * been resolved, we just hope for the best :)
1937 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001938 unres_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001939 }
1940 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001941
Radek Krejci76512572015-08-04 09:47:08 +02001942 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001943 lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001944 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
1945
1946 if (leaf_orig->dflt) {
1947 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02001948 if (unres_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0) == -1) {
1949 goto error;
1950 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001951 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001952
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001953 leaf->must_size = leaf_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001954 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001955 for (i = 0; i < leaf->must_size; ++i) {
Michal Vasko49168a22015-08-17 16:35:41 +02001956 if (unres_add_node(module, unres, &leaf->must[i], UNRES_MUST, retval, 0) == -1) {
1957 goto error;
1958 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001959 }
Radek Krejci00768f42015-06-18 17:04:04 +02001960
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001961 if (leaf_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001962 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02001963 if (unres_add_node(module, unres, leaf->when, UNRES_WHEN, retval, 0) == -1) {
1964 goto error;
1965 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001966 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001967 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001968
Radek Krejci76512572015-08-04 09:47:08 +02001969 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001970 lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001971 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001972
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001973 llist->min = llist_orig->min;
1974 llist->max = llist_orig->max;
1975
1976 llist->must_size = llist_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001977 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001978 for (i = 0; i < llist->must_size; ++i) {
Michal Vasko49168a22015-08-17 16:35:41 +02001979 if (unres_add_node(module, unres, &llist->must[i], UNRES_MUST, retval, 0) == -1) {
1980 goto error;
1981 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001982 }
Radek Krejci00768f42015-06-18 17:04:04 +02001983
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001984 if (llist_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001985 llist->when = lys_when_dup(ctx, llist_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02001986 if (unres_add_node(module, unres, llist->when, UNRES_WHEN, retval, 0) == -1) {
1987 goto error;
1988 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001989 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001990 break;
1991
Radek Krejci76512572015-08-04 09:47:08 +02001992 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001993 list->min = list_orig->min;
1994 list->max = list_orig->max;
1995
1996 list->must_size = list_orig->must_size;
1997 list->tpdf_size = list_orig->tpdf_size;
1998 list->keys_size = list_orig->keys_size;
1999 list->unique_size = list_orig->unique_size;
2000
Radek Krejci1d82ef62015-08-07 14:44:40 +02002001 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002002 for (i = 0; i < list->must_size; ++i) {
Michal Vasko49168a22015-08-17 16:35:41 +02002003 if (unres_add_node(module, unres, &list->must[i], UNRES_MUST, retval, 0) == -1) {
2004 goto error;
2005 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002006 }
2007
Radek Krejci1d82ef62015-08-07 14:44:40 +02002008 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002009
2010 if (list->keys_size) {
2011 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002012
2013 /* we managed to resolve it before, resolve it again manually */
2014 if (list_orig->keys[0]) {
2015 for (i = 0; i < list->keys_size; ++i) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002016 rc = resolve_sibling(list->module, list->child, NULL, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2017 (struct lys_node **)&list->keys[i]);
Michal Vasko49168a22015-08-17 16:35:41 +02002018 if (rc) {
2019 if (rc == EXIT_FAILURE) {
2020 LOGINT;
2021 }
2022 goto error;
2023 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002024 }
2025 /* it was not resolved yet, add unres copy */
2026 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002027 if (unres_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02002028 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002029 goto error;
Michal Vaskod23ce592015-08-06 09:55:37 +02002030 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002031 }
2032 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002033
2034 list->unique = calloc(list->unique_size, sizeof *list->unique);
2035 if (list_orig->unique) {
2036 for (i = 0; i < list->unique_size; ++i) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002037 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
2038 for (j = 0; j < list->unique[i].leafs_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002039 list->unique[i].leafs[j] = lys_uniq_find(list, list_orig->unique[i].leafs[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002040 }
2041 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002042 } else {
2043 for (i = 0; i < list->unique_size; ++i) {
2044 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02002045 list->unique[i].leafs = (struct lys_node_leaf **)list;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002046 unres_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002047 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002048 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002049
2050 if (list_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002051 list->when = lys_when_dup(ctx, list_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02002052 if (unres_add_node(module, unres, list->when, UNRES_WHEN, retval, 0) == -1) {
2053 goto error;
2054 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002055 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002056 break;
2057
Radek Krejci76512572015-08-04 09:47:08 +02002058 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002059 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002060 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002061 for (i = 0; i < anyxml->must_size; ++i) {
Michal Vasko49168a22015-08-17 16:35:41 +02002062 if (unres_add_node(module, unres, &anyxml->must[i], UNRES_MUST, retval, 0) == -1) {
2063 goto error;
2064 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002065 }
2066
2067 if (anyxml_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002068 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02002069 if (unres_add_node(module, unres, anyxml->when, UNRES_WHEN, retval, 0) == -1) {
2070 goto error;
2071 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002072 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002073 break;
2074
Radek Krejci76512572015-08-04 09:47:08 +02002075 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002076 uses->grp = uses_orig->grp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002077
2078 if (uses_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002079 uses->when = lys_when_dup(ctx, uses_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02002080 if (unres_add_node(module, unres, uses->when, UNRES_WHEN, (struct lys_node *)uses, 0) == -1) {
2081 goto error;
2082 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002083 }
2084
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002085 uses->refine_size = uses_orig->refine_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002086 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size, uses, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002087 uses->augment_size = uses_orig->augment_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002088 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 +02002089 if (!uses->child) {
Michal Vasko49168a22015-08-17 16:35:41 +02002090 if (unres_add_node(module, unres, uses, UNRES_USES, NULL, 0) == -1) {
2091 goto error;
2092 }
Michal Vaskof8c128d2015-08-06 15:25:28 +02002093 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002094 break;
2095
Radek Krejci76512572015-08-04 09:47:08 +02002096 case LYS_CASE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002097 if (cs_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002098 cs->when = lys_when_dup(ctx, cs_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02002099 if (unres_add_node(module, unres, cs->when, UNRES_WHEN, retval, 0) == -1) {
2100 goto error;
2101 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002102 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002103 break;
2104
Radek Krejci76512572015-08-04 09:47:08 +02002105 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002106 grp->tpdf_size = grp_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002107 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002108 break;
2109
Radek Krejci76512572015-08-04 09:47:08 +02002110 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002111 rpc->tpdf_size = rpc_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002112 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002113 break;
2114
Radek Krejci76512572015-08-04 09:47:08 +02002115 case LYS_INPUT:
2116 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002117 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002118 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002119 break;
2120
Radek Krejci76512572015-08-04 09:47:08 +02002121 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002122 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002123 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcia01e5432015-06-16 10:35:25 +02002124 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002125
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002126 default:
Radek Krejci00768f42015-06-18 17:04:04 +02002127 /* LY_NODE_AUGMENT */
Michal Vaskod23ce592015-08-06 09:55:37 +02002128 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002129 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002130 }
2131
2132 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002133
2134error:
2135
2136 lys_node_free(retval);
2137 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002138}
2139
Michal Vasko13b15832015-08-19 11:04:48 +02002140void
2141lys_free(struct lys_module *module, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02002142{
Radek Krejcidce51452015-06-16 15:20:08 +02002143 struct ly_ctx *ctx;
2144 int i;
2145
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002146 if (!module) {
2147 return;
2148 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002149
Radek Krejcidce51452015-06-16 15:20:08 +02002150 /* remove schema from the context */
2151 ctx = module->ctx;
2152 if (ctx->models.used) {
2153 for (i = 0; i < ctx->models.used; i++) {
2154 if (ctx->models.list[i] == module) {
2155 /* replace the position in the list by the last module in the list */
2156 ctx->models.used--;
2157 ctx->models.list[i] = ctx->models.list[ctx->models.used];
2158 ctx->models.list[ctx->models.used] = NULL;
2159 /* we are done */
2160 break;
2161 }
2162 }
2163 }
2164
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002165 /* common part with struct ly_submodule */
Michal Vasko13b15832015-08-19 11:04:48 +02002166 module_free_common(module, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02002167
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002168 /* specific items to free */
2169 lydict_remove(module->ctx, module->ns);
2170 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02002171
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002172 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002173}
Radek Krejci7e97c352015-06-19 16:26:34 +02002174
2175/*
2176 * op: 1 - enable, 0 - disable
2177 */
2178static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002179lys_features_change(struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002180{
2181 int all = 0;
2182 int i, j, k;
2183
2184 if (!module || !name || !strlen(name)) {
2185 return EXIT_FAILURE;
2186 }
2187
2188 if (!strcmp(name, "*")) {
2189 /* enable all */
2190 all = 1;
2191 }
2192
2193 /* module itself */
2194 for (i = 0; i < module->features_size; i++) {
2195 if (all || !strcmp(module->features[i].name, name)) {
2196 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002197 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002198 /* enable referenced features (recursion) */
2199 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002200 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002201 module->features[i].features[k]->name, op);
2202 }
2203 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002204 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002205 }
2206 if (!all) {
2207 return EXIT_SUCCESS;
2208 }
2209 }
2210 }
2211
2212 /* submodules */
2213 for (j = 0; j < module->inc_size; j++) {
2214 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2215 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2216 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002217 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002218 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002219 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002220 }
2221 if (!all) {
2222 return EXIT_SUCCESS;
2223 }
2224 }
2225 }
2226 }
2227
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002228 /* TODO submodules of submodules ... */
2229
Radek Krejci7e97c352015-06-19 16:26:34 +02002230 if (all) {
2231 return EXIT_SUCCESS;
2232 } else {
2233 return EXIT_FAILURE;
2234 }
2235}
2236
2237API int
Radek Krejcib8048692015-08-05 13:36:34 +02002238lys_features_enable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002239{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002240 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002241}
2242
2243API int
Radek Krejcib8048692015-08-05 13:36:34 +02002244lys_features_disable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002245{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002246 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002247}
2248
2249API int
Radek Krejcib8048692015-08-05 13:36:34 +02002250lys_features_state(struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002251{
2252 int i, j;
2253
2254 if (!module || !feature) {
2255 return -1;
2256 }
2257
2258 /* search for the specified feature */
2259 /* module itself */
2260 for (i = 0; i < module->features_size; i++) {
2261 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002262 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002263 return 1;
2264 } else {
2265 return 0;
2266 }
2267 }
2268 }
2269
2270 /* submodules */
2271 for (j = 0; j < module->inc_size; j++) {
2272 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2273 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002274 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002275 return 1;
2276 } else {
2277 return 0;
2278 }
2279 }
2280 }
2281 }
2282
2283 /* TODO submodules of submodules ... */
2284
2285 /* feature definition not found */
2286 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002287}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002288
Radek Krejci96a10da2015-07-30 11:00:14 +02002289API const char **
Radek Krejcib8048692015-08-05 13:36:34 +02002290lys_features_list(struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002291{
Radek Krejci96a10da2015-07-30 11:00:14 +02002292 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002293 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002294 unsigned int count;
2295
2296 if (!module) {
2297 return NULL;
2298 }
2299
2300 count = module->features_size;
2301 for (i = 0; i < module->inc_size; i++) {
2302 count += module->inc[i].submodule->features_size;
2303 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002304 result = malloc((count + 1) * sizeof *result);
2305 if (states) {
2306 *states = malloc((count + 1) * sizeof **states);
Michal Vasko2367e7c2015-07-07 11:33:44 +02002307 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002308 count = 0;
2309
2310 /* module itself */
2311 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002312 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002313 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002314 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002315 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002316 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002317 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002318 }
2319 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002320 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002321 }
2322
2323 /* submodules */
2324 for (j = 0; j < module->inc_size; j++) {
2325 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002326 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002327 if (states) {
2328 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2329 (*states)[count] = 1;
2330 } else {
2331 (*states)[count] = 0;
2332 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002333 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002334 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002335 }
2336 }
2337
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002338 /* TODO submodules of submodules ... */
2339
2340 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002341 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002342
2343 return result;
2344}
Radek Krejcib20c62d2015-07-07 17:07:14 +02002345
2346API struct lyd_node *
Radek Krejci25b9fd32015-08-10 15:06:07 +02002347lyd_parse(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
Radek Krejcib20c62d2015-07-07 17:07:14 +02002348{
2349 if (!ctx || !data) {
2350 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2351 return NULL;
2352 }
2353
2354 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02002355 case LYD_XML:
Radek Krejci25b9fd32015-08-10 15:06:07 +02002356 return xml_read_data(ctx, data, options);
Radek Krejcia9167ef2015-08-03 11:01:11 +02002357 case LYD_JSON:
Radek Krejcib20c62d2015-07-07 17:07:14 +02002358 default:
2359 /* TODO */
2360 return NULL;
2361 }
2362
2363 return NULL;
2364}
2365
Radek Krejci0e1d1a62015-07-31 11:17:01 +02002366API void
Radek Krejci912da452015-07-29 14:10:06 +02002367lyd_free(struct lyd_node *node)
Radek Krejcib20c62d2015-07-07 17:07:14 +02002368{
2369 struct lyd_node *next, *child;
2370
Radek Krejci52f791c2015-07-15 11:14:17 +02002371 if (!node) {
2372 return;
2373 }
2374
Radek Krejci76512572015-08-04 09:47:08 +02002375 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
Radek Krejcie4748472015-07-08 18:00:22 +02002376 /* free children */
2377 LY_TREE_FOR_SAFE(node->child, next, child) {
Radek Krejci912da452015-07-29 14:10:06 +02002378 lyd_free(child);
Radek Krejcie4748472015-07-08 18:00:22 +02002379 }
Radek Krejci76512572015-08-04 09:47:08 +02002380 } else if (node->schema->nodetype == LYS_ANYXML) {
Radek Krejci9566b092015-07-31 11:18:15 +02002381 lyxml_free_elem(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
Radek Krejcie4748472015-07-08 18:00:22 +02002382 } else {
2383 /* free value */
2384 switch(((struct lyd_node_leaf *)node)->value_type) {
2385 case LY_TYPE_BINARY:
2386 case LY_TYPE_STRING:
2387 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf *)node)->value.string);
2388 break;
Radek Krejci3e3affe2015-07-09 15:38:40 +02002389 case LY_TYPE_BITS:
2390 if (((struct lyd_node_leaf *)node)->value.bit) {
2391 free(((struct lyd_node_leaf *)node)->value.bit);
2392 }
2393 break;
Radek Krejcie4748472015-07-08 18:00:22 +02002394 default:
Radek Krejci7511f402015-07-10 09:56:30 +02002395 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
Radek Krejcie4748472015-07-08 18:00:22 +02002396 break;
2397 }
Radek Krejcib20c62d2015-07-07 17:07:14 +02002398 }
2399
2400 if (node->prev->next) {
2401 node->prev->next = node->next;
2402 } else if (node->parent) {
2403 /* first node */
2404 node->parent->child = node->next;
2405 }
2406 if (node->next) {
2407 node->next->prev = node->prev;
2408 }
2409
2410 free(node);
2411}
Michal Vaskof54f2f82015-07-17 13:12:05 +02002412
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002413API int
Radek Krejci9566b092015-07-31 11:18:15 +02002414lyd_is_last(struct lyd_node *node)
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002415{
2416 struct lyd_node *n;
2417
2418 if (!node->next) {
2419 return 1;
2420 }
2421
2422 for (n = node->next; n; n = n->next) {
2423 switch (n->schema->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002424 case LYS_LIST:
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002425 if (!((struct lyd_node_list *)n)->lprev) {
2426 return 0;
2427 }
2428 break;
Radek Krejci76512572015-08-04 09:47:08 +02002429 case LYS_LEAFLIST:
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002430 if (!((struct lyd_node_leaflist *)n)->lprev) {
2431 return 0;
2432 }
2433 break;
2434 default:
2435 return 0;
2436 }
2437 }
2438 return 1;
2439}