blob: 250ff38a1d2c7792cc09fb54173641e4e3a435f7 [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
2 * @file tree.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Manipulation with libyang data structures
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020021#define _GNU_SOURCE
Radek Krejcida04f4a2015-05-21 12:54:09 +020022
Radek Krejci812b10a2015-05-28 16:48:25 +020023#include <assert.h>
Radek Krejci5a988152015-07-15 11:16:26 +020024#include <ctype.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020025#include <stdlib.h>
26#include <sys/mman.h>
27#include <sys/stat.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020028#include <string.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020029
30#include "common.h"
31#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020032#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020033#include "resolve.h"
Radek Krejci106efc02015-06-10 14:36:27 +020034#include "xml.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020035#include "tree_internal.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020036
Michal Vaskoa76ee152015-08-17 15:38:22 +020037static const struct internal_modules int_mods = {
38 .modules = {
39 {"ietf-yang-types", "2013-07-15"},
40 {"ietf-inet-types", "2013-07-15"},
41 {"ietf-yang-library", "2015-07-03"}
42 },
43 .count = LY_INTERNAL_MODULE_COUNT
44};
45
Radek Krejci48061fb2015-08-05 15:41:07 +020046API struct lys_feature *
47lys_is_disabled(struct lys_node *node, int recursive)
48{
49 int i;
50
51check:
52 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
53 /* input/output does not have if-feature, so skip them */
54
55 /* check local if-features */
56 for (i = 0; i < node->features_size; i++) {
57 if (!(node->features[i]->flags & LYS_FENABLED)) {
58 return node->features[i];
59 }
60 }
61 }
62
63 if (!recursive) {
64 return NULL;
65 }
66
67 /* go through parents */
68 if (node->nodetype == LYS_AUGMENT) {
69 /* go to parent actually means go to the target node */
70 node = ((struct lys_node_augment *)node)->target;
71 goto check;
72 } else if (node->parent) {
73 node = node->parent;
74 goto check;
75 }
76
77 return NULL;
78}
79
Radek Krejci7f40ce32015-08-12 20:38:46 +020080static struct lys_node *
81check_mand_getnext(struct lys_node *cur, struct lys_node *parent)
82{
83 struct lys_node *next;
84
85 if (!cur) {
86 next = parent->child;
87 } else {
88 next = cur->next;
89 }
90
91repeat:
Michal Vasko591e0b22015-08-13 13:53:43 +020092 while (next && (next->nodetype & (LYS_AUGMENT | LYS_GROUPING | LYS_LEAFLIST))) {
Radek Krejci7f40ce32015-08-12 20:38:46 +020093 next = cur = next->next;
94 }
95
96 while (!next) {
97 if (cur->parent == parent) {
98 /* no next element */
99 return NULL;
100 }
101 cur = cur->parent;
102 next = cur->next;
103 goto repeat;
104 }
105
106 switch (next->nodetype) {
107 case LYS_CONTAINER:
108 if (((struct lys_node_container *)next)->presence) {
109 /* mandatory elements under the non-existing presence
110 * container are not mandatory - 7.6.5, rule 1 */
111 next = next->next;
112 goto repeat;
113 }
114 /* no break */
115 case LYS_LIST:
116 case LYS_USES:
117 case LYS_CASE:
118 /* go into */
119 next = next->child;
120 goto repeat;
121 case LYS_LEAF:
122 case LYS_CHOICE:
123 case LYS_ANYXML:
124 return next;
125 default:
126 /* we should not be here */
127 return NULL;
128 }
129}
130
131static struct lys_node *
132check_mand_check(struct lys_node *node, struct lys_node *stop, struct lyd_node *data)
133{
134 struct lys_node *siter = NULL, *parent;
135 struct lyd_node *diter = NULL;
136
137 if (node->flags & LYS_MAND_TRUE) {
138 switch (node->nodetype) {
139 case LYS_LEAF:
140 case LYS_ANYXML:
141 case LYS_CHOICE:
142 if (node->parent->nodetype == LYS_CASE) {
143 /* 7.6.5, rule 2 */
144 /* 7.9.4, rule 1 */
145 if (node->parent->parent->parent == data->schema) {
146 /* the only case the node's siblings can exist is that the
147 * data node passed originaly to ly_check_mandatory()
148 * had this choice as a child
149 */
150 /* try to find the node's siblings in data */
151 LY_TREE_FOR(data->child, diter) {
152 LY_TREE_FOR(node->parent->child, siter) {
153 if (siter == diter->schema) {
154 /* some sibling exists, rule applies */
155 break;
156 }
157 }
158 if (siter) {
159 break;
160 }
161 }
162 }
163 if (!siter) {
164 /* no sibling exists */
165 return NULL;
166 }
167 } else {
168 for(parent = node->parent; parent != stop; parent = parent->parent) {
169 if (parent->nodetype != LYS_CONTAINER) {
170 /* 7.6.5, rule 1, checking presence is not needed
171 * since it is done in check_mand_getnext()
172 */
173 return NULL;
174 }
175 }
176 }
177 /* 7.6.5, rule 3 (or 2) */
178 /* 7.9.4, rule 2 */
179 return node;
180 default:
181 /* error */
182 break;
183 }
184 }
185
186 return NULL;
187}
188
189struct lys_node *
190ly_check_mandatory(struct lyd_node *data)
191{
192 struct lys_node *siter, *saux = NULL, *result, *parent = NULL;
193 struct lyd_node *diter;
194 int found;
195
196 siter = data->schema->child;
197
198repeat:
199 while (siter) {
200 switch (siter->nodetype) {
201 case LYS_CONTAINER:
202 case LYS_LEAF:
203 case LYS_ANYXML:
204 /* search for instance */
205 LY_TREE_FOR(data->child, diter) {
206 if (diter->schema == siter) {
207 break;
208 }
209 }
210 if (diter) {
211 /* result has a child defined by siter, check another siter */
212 siter = siter->next;
213 break;
214 }
215
216 /* the siter has no instance under the result, check if there is
217 * some mandatory node; first the siter itself ... */
218 result = check_mand_check(siter, siter->parent, data);
219 if (result) {
220 return result;
221 }
222 /* ... and then the subtree */
223 if (siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
224 while ((saux = check_mand_getnext(saux, siter))) {
225 result = check_mand_check(saux, siter, data);
226 if (result) {
227 return result;
228 }
229 }
230 }
231 siter = siter->next;
232 break;
233 case LYS_CHOICE:
234 if (siter->flags & LYS_MAND_TRUE) {
235 /* search for instance */
236 saux = siter;
237 parent = NULL;
238 siter = siter->child;
239 found = 0;
240repeat_choice:
241 while (siter) {
242 switch(siter->nodetype) {
243 case LYS_CONTAINER:
244 case LYS_LEAF:
245 case LYS_LEAFLIST:
246 case LYS_LIST:
247 case LYS_ANYXML:
248 LY_TREE_FOR(data->child, diter) {
249 if (diter->schema == siter) {
250 break;
251 }
252 }
253 if (diter) {
254 /* got instance, done */
255 siter = parent = NULL;
256 found = 1;
257 break;
258 }
259 siter = siter->next;
260 break;
261 case LYS_CASE:
262 case LYS_CHOICE:
263 case LYS_USES:
264 /* go into */
265 parent = siter;
266 siter = siter->child;
267 break;
268 case LYS_AUGMENT:
269 case LYS_GROUPING:
270 /* skip */
271 siter = siter->next;
272 break;
273 default:
274 /* error */
275 break;
276 }
277 }
278
279 if (parent) {
280 siter = parent->next;
281 if (parent->parent == saux) {
282 parent = NULL;
283 } else {
284 parent = parent->parent;
285 }
286 goto repeat_choice;
287 }
288
289 if (!found) {
290 return saux;
291 }
292
293 siter = saux;
294 }
295
296 /* go into */
297 parent = siter;
298 siter = siter->child;
299 break;
300 case LYS_USES:
301 case LYS_CASE:
302 /* go into */
303 parent = siter;
304 siter = siter->child;
305 break;
306 default:
307 /* can ignore, go to next */
308 siter = siter->next;
309 break;
310 }
311 }
312
313 if (parent) {
314 siter = parent->next;
315 if (parent->parent == data->schema) {
316 parent = NULL;
317 } else {
318 parent = parent->parent;
319 }
320 goto repeat;
321 }
322
323 return NULL;
324}
325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200326void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200327lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200328{
Radek Krejci76512572015-08-04 09:47:08 +0200329 struct lys_node *parent, *first;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200331 if (!node) {
332 return;
333 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200334
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200335 /* unlink from data model if necessary */
336 if (node->module) {
337 if (node->module->data == node) {
338 node->module->data = node->next;
Radek Krejci21181962015-06-30 14:11:00 +0200339 } else if (node->module->rpc == node) {
340 node->module->rpc = node->next;
341 } else if (node->module->notif == node) {
342 node->module->notif = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200343 }
344 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200345
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200346 /* store pointers to important nodes */
347 parent = node->parent;
348 if (parent && !parent->nodetype) {
349 /* handle augments - first, unlink it from the augment parent ... */
350 if (parent->child == node) {
351 parent->child = node->next;
352 }
353 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200354 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200355 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200357 /* unlink from parent */
358 if (parent) {
359 if (parent->child == node) {
360 parent->child = node->next;
361 }
362 node->parent = NULL;
363 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200364
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200365 /* unlink from siblings */
366 if (node->prev == node) {
367 /* there are no more siblings */
368 return;
369 }
370 if (node->next) {
371 node->next->prev = node->prev;
372 } else {
373 /* unlinking the last element */
374 if (parent) {
375 first = parent->child;
376 } else {
377 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200378 while (first->prev->next) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200379 first = node->prev;
380 }
381 }
382 first->prev = node->prev;
383 }
384 if (node->prev->next) {
385 node->prev->next = node->next;
386 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200387
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200388 /* clean up the unlinked element */
389 node->next = NULL;
390 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200391}
392
Radek Krejci10c760e2015-08-14 14:45:43 +0200393/*
394 * get next grouping in the root's subtree, in the
395 * first call, tha last is NULL
396 */
397static struct lys_node_grp *
398lys_get_next_grouping(struct lys_node_grp* lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200399{
Radek Krejci10c760e2015-08-14 14:45:43 +0200400 struct lys_node *last = (struct lys_node *)lastgrp;
401 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200402
Radek Krejci10c760e2015-08-14 14:45:43 +0200403 assert(root);
404
405 if (!last) {
406 last = root;
407 }
408
409 while (1) {
410 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
411 next = last->child;
412 } else {
413 next = NULL;
414 }
415 if (!next) {
416 if (last == root) {
417 /* we are done */
418 return NULL;
419 }
420
421 /* no children, go to siblings */
422 next = last->next;
423 }
424 while (!next) {
425 /* go back through parents */
426 if (last->parent == root) {
427 /* we are done */
428 return NULL;
429 }
430 last = last->parent;
431 next = last->next;
432 }
433
434 if (next->nodetype == LYS_GROUPING) {
435 return (struct lys_node_grp *)next;
436 }
437
438 last = next;
439 }
440}
441
442int
Radek Krejci07911992015-08-14 15:13:31 +0200443lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
444{
445 struct lys_node *start, *stop, *par_iter, *iter;
446 struct lys_node_grp *grp;
447 int down;
448
449 assert(node);
450
451 if (!parent) {
452 assert(module);
453 } else {
454 module = parent->module;
455 }
456
457 switch (node->nodetype) {
458 case LYS_GROUPING:
459 /* 6.2.1, rule 6 */
460 if (parent) {
461 if (parent->child) {
462 down = 1;
463 start = parent->child;
464 } else {
465 down = 0;
466 start = parent;
467 }
468 } else {
469 down = 1;
470 start = module->data;
471 }
472 /* go up */
473 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
474 if (par_iter->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES)) {
475 continue;
476 }
477
478 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
479 if (!stop) {
480 stop = par_iter;
481 } else if (iter == stop) {
482 break;
483 }
484 if (iter->nodetype != LYS_GROUPING) {
485 continue;
486 }
487
488 if (node->name == iter->name) {
489 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
490 return EXIT_FAILURE;
491 }
492 }
493 }
494 /* go down, because grouping can be defined after e.g. container in which is collision */
495 if (down) {
496 for (iter = start, stop = NULL; iter; iter = iter->prev) {
497 if (!stop) {
498 stop = start;
499 } else if (iter == stop) {
500 break;
501 }
502 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
503 continue;
504 }
505
506 grp = NULL;
507 while ((grp = lys_get_next_grouping(grp, iter))) {
508 if (node->name == grp->name) {
509 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
510 return EXIT_FAILURE;
511 }
512 }
513 }
514 }
515 break;
516 case LYS_LEAF:
517 case LYS_LEAFLIST:
518 case LYS_LIST:
519 case LYS_CONTAINER:
520 case LYS_CHOICE:
521 case LYS_ANYXML:
522 /* 6.2.1, rule 7 */
523 if (parent) {
524 iter = parent;
525 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE))) {
526 iter = iter->parent;
527 }
528 if (!iter) {
529 stop = NULL;
530 iter = module->data;
531 } else {
532 stop = iter;
533 iter = iter->child;
534 }
535 } else {
536 stop = NULL;
537 iter = module->data;
538 }
539 while (iter) {
540 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
541 iter = iter->child;
542 continue;
543 }
544
545 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
546 if (iter->module == node->module && iter->name == node->name) {
547 LOGVAL(LYE_SPEC, 0, "Duplicated child identifier \"%s\" in \"%s\".", node->name,
548 stop ? stop->name : "(sub)module");
549 return EXIT_FAILURE;
550 }
551 }
552
553 /* special case for choice - we must check the choice's name as
554 * well as the names of nodes under the choice
555 */
556 if (iter->nodetype == LYS_CHOICE) {
557 iter = iter->child;
558 continue;
559 }
560
561 /* go to siblings */
562 if (!iter->next) {
563 /* no sibling, go to parent's sibling */
564 do {
565 iter = iter->parent;
566 if (iter && iter->next) {
567 break;
568 }
569 } while (iter != stop);
570
571 if (iter == stop) {
572 break;
573 }
574 }
575 iter = iter->next;
576 }
577 break;
578 case LYS_CASE:
579 /* 6.2.1, rule 8 */
580 LY_TREE_FOR(parent->child, iter) {
581 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
582 continue;
583 }
584
585 if (iter->module == node->module && iter->name == node->name) {
586 LOGVAL(LYE_DUPID, 0, "case", node->name);
587 return EXIT_FAILURE;
588 }
589 }
590 break;
591 default:
592 /* no check needed */
593 break;
594 }
595
596 return EXIT_SUCCESS;
597}
598
599int
Radek Krejci10c760e2015-08-14 14:45:43 +0200600lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
601{
Radek Krejci07911992015-08-14 15:13:31 +0200602 struct lys_node *iter, **trg = NULL;
603 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200604
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200605 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200606
Radek Krejci10c760e2015-08-14 14:45:43 +0200607 if (parent) {
608 type = parent->nodetype;
609 module = parent->module;
610 } else {
611 assert(module);
612 type = 0;
Radek Krejcic7459c62015-08-17 10:15:12 +0200613 if (child->nodetype == LYS_NOTIF) {
614 trg = &module->notif;
615 } else if (child->nodetype == LYS_RPC) {
616 trg = &module->rpc;
617 } else {
618 trg = &module->data;
619 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200620 }
621
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200622 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200623 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200624 case LYS_CONTAINER:
625 case LYS_LIST:
626 case LYS_GROUPING:
627 case LYS_USES:
628 case LYS_INPUT:
629 case LYS_OUTPUT:
630 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200631 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200632 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
633 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200634 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200635 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
636 return EXIT_FAILURE;
637 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200638
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200639 break;
Radek Krejci76512572015-08-04 09:47:08 +0200640 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200641 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200642 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200643 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"choice\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200644 strnodetype(child->nodetype), parent->name);
645 return EXIT_FAILURE;
646 }
647 break;
Radek Krejci76512572015-08-04 09:47:08 +0200648 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200649 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200650 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200651 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"case\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200652 strnodetype(child->nodetype), parent->name);
653 return EXIT_FAILURE;
654 }
655 break;
Radek Krejci76512572015-08-04 09:47:08 +0200656 case LYS_RPC:
657 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200658 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"rpc\" %s.",
Michal Vasko38d01f72015-06-15 09:41:06 +0200659 strnodetype(child->nodetype), parent->name);
660 return EXIT_FAILURE;
661 }
662 break;
Radek Krejci76512572015-08-04 09:47:08 +0200663 case LYS_LEAF:
664 case LYS_LEAFLIST:
665 case LYS_ANYXML:
Radek Krejci10c760e2015-08-14 14:45:43 +0200666 LOGVAL(LYE_SPEC, 0, "The \"%s\" statement (%s) cannot have any data substatement.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200667 strnodetype(parent->nodetype), parent->name);
668 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200669 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200670 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200671 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
672 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200673 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200674 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
675 return EXIT_FAILURE;
676 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200677 break;
678 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200679 /* top level */
680 if (!(child->nodetype &
681 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
682 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci2c0ca272015-08-14 15:31:01 +0200683 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in (sub)module \"%s\"",
684 strnodetype(child->nodetype), module->name);
Radek Krejci10c760e2015-08-14 14:45:43 +0200685 return EXIT_FAILURE;
686 }
687
688 break;;
689 }
690
691 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200692 if (lys_check_id(child, parent, module)) {
693 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200694 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200695
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200696 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200697 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200698 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200699
Radek Krejci10c760e2015-08-14 14:45:43 +0200700 if (!parent) {
701 if (*trg) {
702 (*trg)->prev->next = child;
703 child->prev = (*trg)->prev;
704 (*trg)->prev = child;
705 } else {
706 (*trg) = child;
707 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200708 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +0200709 if (!parent->child) {
710 /* the only/first child of the parent */
711 parent->child = child;
712 child->parent = parent;
713 iter = child;
714 } else {
715 /* add a new child at the end of parent's child list */
716 iter = parent->child->prev;
717 iter->next = child;
718 child->prev = iter;
719 }
720 while (iter->next) {
721 iter = iter->next;
722 iter->parent = parent;
723 }
724 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200725 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200726
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200727 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200728}
729
Radek Krejcib8048692015-08-05 13:36:34 +0200730API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +0200731lys_parse(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200732{
Michal Vaskof02e3742015-08-05 16:27:02 +0200733 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200734 struct lys_module *mod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200735
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200736 if (!ctx || !data) {
737 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
738 return NULL;
739 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200740
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200741 unres = calloc(1, sizeof *unres);
742
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200743 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200744 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200745 mod = yin_read_module(ctx, data, 1, unres);
746 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200747 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200748 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +0200749 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200750 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200751 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200752
Radek Krejci0b5805d2015-08-13 09:38:02 +0200753 if (mod && unres->count && resolve_unres(mod, unres)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200754 lys_free(mod);
755 mod = NULL;
756 }
757 free(unres->item);
758 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +0200759 free(unres->str_snode);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200760#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200761 free(unres->line);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200762#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200763 free(unres);
764
765 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200766}
767
Radek Krejcib8048692015-08-05 13:36:34 +0200768struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +0200769lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +0200770{
Michal Vaskof02e3742015-08-05 16:27:02 +0200771 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200772 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200773
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200774 assert(module);
775 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200776
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200777 unres = calloc(1, sizeof *unres);
778
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200779 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200780 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200781 submod = yin_read_submodule(module, data, implement, unres);
782 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200783 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200784 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +0200785 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200786 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200787 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200788
Radek Krejci0b5805d2015-08-13 09:38:02 +0200789 if (submod && unres->count && resolve_unres((struct lys_module *)submod, unres)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200790 lys_submodule_free(submod);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200791 submod = NULL;
792 }
793 free(unres->item);
794 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +0200795 free(unres->str_snode);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200796#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200797 free(unres->line);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200798#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200799 free(unres);
800
801 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +0200802}
803
Radek Krejcib8048692015-08-05 13:36:34 +0200804API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +0200805lys_read(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +0200806{
Radek Krejcib8048692015-08-05 13:36:34 +0200807 struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +0200808 struct stat sb;
809 char *addr;
810
811 if (!ctx || fd < 0) {
812 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
813 return NULL;
814 }
815
816 /*
817 * TODO
818 * This is just a temporary solution to make working automatic search for
819 * imported modules. This doesn't work e.g. for streams (stdin)
820 */
821 fstat(fd, &sb);
822 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
823 module = lys_parse(ctx, addr, format);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200824 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200825
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200826 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200827}
828
Radek Krejcib8048692015-08-05 13:36:34 +0200829struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +0200830lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +0200831{
Radek Krejcib8048692015-08-05 13:36:34 +0200832 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200833 struct stat sb;
834 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +0200835
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200836 assert(module);
837 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +0200838
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200839 /*
840 * TODO
841 * This is just a temporary solution to make working automatic search for
842 * imported modules. This doesn't work e.g. for streams (stdin)
843 */
844 fstat(fd, &sb);
845 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
846 /* TODO addr error check */
Radek Krejci1d82ef62015-08-07 14:44:40 +0200847 submodule = lys_submodule_parse(module, addr, format, implement);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200848 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +0200849
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200850 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +0200851
852}
853
Radek Krejci1d82ef62015-08-07 14:44:40 +0200854static struct lys_restr *
855lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200856{
Radek Krejci1574a8d2015-08-03 14:16:52 +0200857 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200858 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200859
Radek Krejci3733a802015-06-19 13:43:21 +0200860 if (!size) {
861 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200862 }
Radek Krejci3733a802015-06-19 13:43:21 +0200863
864 result = calloc(size, sizeof *result);
865 for (i = 0; i < size; i++) {
866 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
867 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
868 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
869 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
870 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
871 }
872
873 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200874}
875
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200876void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200877lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +0200878{
879 assert(ctx);
880 if (!restr) {
881 return;
882 }
883
884 lydict_remove(ctx, restr->expr);
885 lydict_remove(ctx, restr->dsc);
886 lydict_remove(ctx, restr->ref);
887 lydict_remove(ctx, restr->eapptag);
888 lydict_remove(ctx, restr->emsg);
889}
890
Radek Krejci1d82ef62015-08-07 14:44:40 +0200891static void
892lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Michal Vaskof02e3742015-08-05 16:27:02 +0200893 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +0200894{
895 int i;
896
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200897 new->prefix = lydict_insert(mod->ctx, old->prefix, 0);
Radek Krejci3733a802015-06-19 13:43:21 +0200898 new->base = old->base;
899 new->der = old->der;
900
Radek Krejci1d82ef62015-08-07 14:44:40 +0200901 i = unres_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200902 if (i != -1) {
903 /* HACK for unres */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200904 new->der = (struct lys_tpdf *)parent;
Radek Krejci1d82ef62015-08-07 14:44:40 +0200905 unres_add_str(mod, unres, new, UNRES_TYPE_DER, unres->str_snode[i], 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200906 return;
907 }
908
Radek Krejci3733a802015-06-19 13:43:21 +0200909 switch (new->base) {
910 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +0200911 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200912 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +0200913 }
Radek Krejci3733a802015-06-19 13:43:21 +0200914 break;
915
916 case LY_TYPE_BITS:
917 new->info.bits.count = old->info.bits.count;
918 if (new->info.bits.count) {
919 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
920 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200921 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
922 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
923 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Radek Krejci3733a802015-06-19 13:43:21 +0200924 new->info.bits.bit[i].status = old->info.bits.bit[i].status;
925 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
926 }
927 }
928 break;
929
Radek Krejcif9401c32015-06-26 16:47:36 +0200930 case LY_TYPE_DEC64:
931 new->info.dec64.dig = old->info.dec64.dig;
932 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200933 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +0200934 }
935 break;
936
Radek Krejci3733a802015-06-19 13:43:21 +0200937 case LY_TYPE_ENUM:
938 new->info.enums.count = old->info.enums.count;
939 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200940 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Radek Krejci3733a802015-06-19 13:43:21 +0200941 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200942 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
943 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
944 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
945 new->info.enums.enm[i].status = old->info.enums.enm[i].status;
946 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +0200947 }
948 }
949 break;
950
Radek Krejci4a7b5ee2015-06-19 14:56:43 +0200951 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200952 if (old->info.ident.ref) {
953 new->info.ident.ref = old->info.ident.ref;
954 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200955 i = unres_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200956 assert(i != -1);
Radek Krejci1d82ef62015-08-07 14:44:40 +0200957 unres_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i], 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200958 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +0200959 break;
960
Radek Krejciaf351422015-06-19 14:49:38 +0200961 case LY_TYPE_INST:
962 new->info.inst.req = old->info.inst.req;
963 break;
964
Radek Krejcif2860132015-06-20 12:37:20 +0200965 case LY_TYPE_INT8:
966 case LY_TYPE_INT16:
967 case LY_TYPE_INT32:
968 case LY_TYPE_INT64:
969 case LY_TYPE_UINT8:
970 case LY_TYPE_UINT16:
971 case LY_TYPE_UINT32:
972 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +0200973 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200974 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +0200975 }
Radek Krejcif2860132015-06-20 12:37:20 +0200976 break;
977
Radek Krejcidc4c1412015-06-19 15:39:54 +0200978 case LY_TYPE_LEAFREF:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200979 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Radek Krejci1d82ef62015-08-07 14:44:40 +0200980 unres_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200981 break;
982
Radek Krejci3733a802015-06-19 13:43:21 +0200983 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +0200984 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200985 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200986 }
Radek Krejci1d82ef62015-08-07 14:44:40 +0200987 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 +0200988 break;
989
Radek Krejcie4c366b2015-07-02 10:11:31 +0200990 case LY_TYPE_UNION:
991 new->info.uni.count = old->info.uni.count;
992 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200993 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200994 for (i = 0; i < new->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200995 lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200996 }
997 }
998 break;
999
Radek Krejci3733a802015-06-19 13:43:21 +02001000 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001001 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001002 break;
1003 }
1004}
1005
1006void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001007lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001008{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001009 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001010
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001011 assert(ctx);
1012 if (!type) {
1013 return;
1014 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001015
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001016 lydict_remove(ctx, type->prefix);
Radek Krejci5a065542015-05-22 15:02:07 +02001017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001018 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001019 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001020 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001021 free(type->info.binary.length);
1022 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001023 case LY_TYPE_BITS:
1024 for (i = 0; i < type->info.bits.count; i++) {
1025 lydict_remove(ctx, type->info.bits.bit[i].name);
1026 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1027 lydict_remove(ctx, type->info.bits.bit[i].ref);
1028 }
1029 free(type->info.bits.bit);
1030 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001031
1032 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001033 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001034 free(type->info.dec64.range);
1035 break;
1036
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001037 case LY_TYPE_ENUM:
1038 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001039 lydict_remove(ctx, type->info.enums.enm[i].name);
1040 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1041 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001042 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001043 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001044 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001045
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001046 case LY_TYPE_INT8:
1047 case LY_TYPE_INT16:
1048 case LY_TYPE_INT32:
1049 case LY_TYPE_INT64:
1050 case LY_TYPE_UINT8:
1051 case LY_TYPE_UINT16:
1052 case LY_TYPE_UINT32:
1053 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001054 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001055 free(type->info.num.range);
1056 break;
1057
Radek Krejcidc4c1412015-06-19 15:39:54 +02001058 case LY_TYPE_LEAFREF:
1059 lydict_remove(ctx, type->info.lref.path);
1060 break;
1061
Radek Krejci3733a802015-06-19 13:43:21 +02001062 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001063 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001064 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001065 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001066 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001067 }
1068 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001069 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001070
Radek Krejcie4c366b2015-07-02 10:11:31 +02001071 case LY_TYPE_UNION:
1072 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001073 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001074 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001075 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001076 break;
1077
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001078 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001079 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001080 break;
1081 }
Radek Krejci5a065542015-05-22 15:02:07 +02001082}
1083
Radek Krejci1d82ef62015-08-07 14:44:40 +02001084static struct lys_tpdf *
1085lys_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 +02001086{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001087 struct lys_tpdf *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001088 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001089
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001090 if (!size) {
1091 return NULL;
1092 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001093
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001094 result = calloc(size, sizeof *result);
1095 for (i = 0; i < size; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001096 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1097 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1098 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001099 result[i].flags = old[i].flags;
1100 result[i].module = old[i].module;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001101
Radek Krejci1d82ef62015-08-07 14:44:40 +02001102 lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001103
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001104 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1105 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001106 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001107
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001108 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001109}
1110
Radek Krejci1d82ef62015-08-07 14:44:40 +02001111static void
1112lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001113{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001114 assert(ctx);
1115 if (!tpdf) {
1116 return;
1117 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001118
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001119 lydict_remove(ctx, tpdf->name);
1120 lydict_remove(ctx, tpdf->dsc);
1121 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001122
Radek Krejci1d82ef62015-08-07 14:44:40 +02001123 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001124
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001125 lydict_remove(ctx, tpdf->units);
1126 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001127}
1128
Radek Krejci1d82ef62015-08-07 14:44:40 +02001129static struct lys_when *
1130lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001131{
Radek Krejci76512572015-08-04 09:47:08 +02001132 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001133
1134 if (!old) {
1135 return NULL;
1136 }
1137
1138 new = calloc(1, sizeof *new);
1139 new->cond = lydict_insert(ctx, old->cond, 0);
1140 new->dsc = lydict_insert(ctx, old->dsc, 0);
1141 new->ref = lydict_insert(ctx, old->ref, 0);
1142
1143 return new;
1144}
1145
Radek Krejci1d82ef62015-08-07 14:44:40 +02001146static void
1147lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001148{
1149 if (!w) {
1150 return;
1151 }
1152
1153 lydict_remove(ctx, w->cond);
1154 lydict_remove(ctx, w->dsc);
1155 lydict_remove(ctx, w->ref);
1156
1157 free(w);
1158}
1159
Radek Krejcib7f5e412015-08-13 10:15:51 +02001160static void
1161lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment aug)
1162{
1163 struct lys_node *child, *sub;
1164
1165 lydict_remove(ctx, aug.target_name);
1166 lydict_remove(ctx, aug.dsc);
1167 lydict_remove(ctx, aug.ref);
1168
1169 free(aug.features);
1170
1171 lys_when_free(ctx, aug.when);
1172
1173 LY_TREE_FOR_SAFE(aug.child, child, sub) {
1174 lys_node_free(sub);
1175 }
1176}
1177
Radek Krejci76512572015-08-04 09:47:08 +02001178static struct lys_node_augment *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001179lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size,
Michal Vasko41de7352015-08-06 09:53:34 +02001180 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001181{
Radek Krejci76512572015-08-04 09:47:08 +02001182 struct lys_node_augment *new = NULL;
Michal Vasko41de7352015-08-06 09:53:34 +02001183 struct lys_node *snode;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001184 int i = -1;
Radek Krejci106efc02015-06-10 14:36:27 +02001185
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001186 if (!size) {
1187 return NULL;
1188 }
Radek Krejci106efc02015-06-10 14:36:27 +02001189
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001190 new = calloc(size, sizeof *new);
1191 for (i = 0; i < size; i++) {
1192 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1193 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1194 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1195 new[i].flags = old[i].flags;
Michal Vasko591e0b22015-08-13 13:53:43 +02001196 new[i].nodetype = old[i].nodetype;
1197 /* .target = NULL */
Radek Krejci106efc02015-06-10 14:36:27 +02001198
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001199 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001200
Michal Vasko41de7352015-08-06 09:53:34 +02001201 /* copy the augment nodes */
1202 assert(old[i].child);
1203 LY_TREE_FOR(old[i].child, snode) {
Radek Krejci10c760e2015-08-14 14:45:43 +02001204 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 +02001205 for ( ; i >= 0; i--) {
1206 lys_augment_free(module->ctx, new[i]);
1207 }
1208 free(new);
1209 return NULL;
1210 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001211 }
1212 }
Radek Krejci106efc02015-06-10 14:36:27 +02001213
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001214 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001215}
1216
Radek Krejci76512572015-08-04 09:47:08 +02001217static struct lys_refine *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001218lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size, struct lys_node_uses *uses,
Michal Vaskof02e3742015-08-05 16:27:02 +02001219 struct unres_schema *unres)
Michal Vasko1982cad2015-06-08 15:49:30 +02001220{
Radek Krejci76512572015-08-04 09:47:08 +02001221 struct lys_refine *result;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001222 int i, j;
Michal Vasko1982cad2015-06-08 15:49:30 +02001223
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001224 if (!size) {
1225 return NULL;
1226 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001227
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001228 result = calloc(size, sizeof *result);
1229 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001230 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001231 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1232 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001233 result[i].flags = old[i].flags;
1234 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001235
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001236 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001237 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001238 for (j = 0; j < result[i].must_size; ++j) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001239 unres_add_node(mod, unres, &result[i].must[j], UNRES_MUST, (struct lys_node *)uses, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001240 }
1241
Radek Krejci76512572015-08-04 09:47:08 +02001242 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001243 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001244 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001245 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001246 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001247 result[i].mod.list = old[i].mod.list;
1248 }
1249 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001250
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001251 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001252}
1253
Radek Krejci1d82ef62015-08-07 14:44:40 +02001254static void
1255lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001256{
Radek Krejcia52656e2015-08-05 13:41:50 +02001257 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001258
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001259 assert(ctx);
1260 if (!ident) {
1261 return;
1262 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001263
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001264 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001265 * if caller free only a single data model which is used (its identity is
1266 * reference from identity in another module), this silly freeing can lead
1267 * to segmentation fault. But without noting if the module is used by some
1268 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001269 *
1270 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001271 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001272 */
1273 while (ident->der) {
1274 der = ident->der;
1275 ident->der = der->next;
1276 free(der);
1277 }
Radek Krejci6793db02015-05-22 17:49:54 +02001278
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001279 lydict_remove(ctx, ident->name);
1280 lydict_remove(ctx, ident->dsc);
1281 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001282
1283}
1284
Radek Krejci1d82ef62015-08-07 14:44:40 +02001285static void
1286lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001287{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001288 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001289
Radek Krejcid12f57b2015-08-06 10:43:39 +02001290 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001291 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001292 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001293 }
1294 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001295}
1296
Radek Krejci1d82ef62015-08-07 14:44:40 +02001297static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001298lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1299{
1300 int i;
1301
1302 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1303 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001304 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001305 }
1306 free(io->tpdf);
1307}
1308
Radek Krejci1d82ef62015-08-07 14:44:40 +02001309static void
1310lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001311{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001312 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001313
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001314 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001315 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001316 }
1317 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001318
Radek Krejci1d82ef62015-08-07 14:44:40 +02001319 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001320}
1321
Radek Krejci1d82ef62015-08-07 14:44:40 +02001322static void
1323lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001324{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001325 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001326
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001327 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001328 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001329 }
1330 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001331
Radek Krejci1d82ef62015-08-07 14:44:40 +02001332 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001333
Radek Krejci1d82ef62015-08-07 14:44:40 +02001334 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001335 lydict_remove(ctx, leaf->units);
1336 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001337}
1338
Radek Krejci1d82ef62015-08-07 14:44:40 +02001339static void
1340lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001341{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001342 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001343
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001344 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001345 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001346 }
1347 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001348
Radek Krejci1d82ef62015-08-07 14:44:40 +02001349 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001350
Radek Krejci1d82ef62015-08-07 14:44:40 +02001351 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001352 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001353}
1354
Radek Krejci1d82ef62015-08-07 14:44:40 +02001355static void
1356lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001357{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001358 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001359
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001360 /* handle only specific parts for LY_NODE_LIST */
1361 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001362 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001363 }
1364 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001365
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001366 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001367 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001368 }
1369 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001370
Radek Krejci1d82ef62015-08-07 14:44:40 +02001371 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001372
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001373 for (i = 0; i < list->unique_size; i++) {
1374 free(list->unique[i].leafs);
1375 }
1376 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001377
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001378 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001379}
1380
Radek Krejci1d82ef62015-08-07 14:44:40 +02001381static void
1382lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001383{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001384 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001385
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001386 /* handle only specific parts for LY_NODE_CONTAINER */
1387 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001388
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001389 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001390 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001391 }
1392 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001393
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001394 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001395 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001396 }
1397 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001398
Radek Krejci1d82ef62015-08-07 14:44:40 +02001399 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001400}
1401
Radek Krejci1d82ef62015-08-07 14:44:40 +02001402static void
1403lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001404{
1405 lydict_remove(ctx, f->name);
1406 lydict_remove(ctx, f->dsc);
1407 lydict_remove(ctx, f->ref);
1408 free(f->features);
1409}
1410
Radek Krejci1d82ef62015-08-07 14:44:40 +02001411static void
1412lys_deviation_free(struct ly_ctx *ctx, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001413{
1414 int i, j;
1415
1416 lydict_remove(ctx, dev->target_name);
1417 lydict_remove(ctx, dev->dsc);
1418 lydict_remove(ctx, dev->ref);
1419
1420 for (i = 0; i < dev->deviate_size; i++) {
1421 lydict_remove(ctx, dev->deviate[i].dflt);
1422 lydict_remove(ctx, dev->deviate[i].units);
1423
1424 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1425 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001426 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001427 }
1428 free(dev->deviate[i].must);
1429
1430 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1431 free(dev->deviate[j].unique[j].leafs);
1432 }
1433 free(dev->deviate[i].unique);
1434 }
1435 }
1436 free(dev->deviate);
1437}
1438
Radek Krejci1d82ef62015-08-07 14:44:40 +02001439static void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001440lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +02001441{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001442 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001443
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001444 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001445 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001446 lydict_remove(ctx, uses->refine[i].dsc);
1447 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001448
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001449 for (j = 0; j < uses->refine[j].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001450 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001451 }
1452 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001453
Radek Krejci76512572015-08-04 09:47:08 +02001454 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001455 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001456 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001457 lydict_remove(ctx, uses->refine[i].mod.presence);
1458 }
1459 }
1460 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001461
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001462 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001463 lys_augment_free(ctx, uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001464 }
1465 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001466
Radek Krejci1d82ef62015-08-07 14:44:40 +02001467 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001468}
1469
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001470void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001471lys_node_free(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001472{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001473 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001474 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001475
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001476 if (!node) {
1477 return;
1478 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001479
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001480 assert(node->module);
1481 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001482
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001483 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001484
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001485 /* common part */
1486 LY_TREE_FOR_SAFE(node->child, next, sub) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001487 lys_node_free(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001488 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001489
Radek Krejcid12f57b2015-08-06 10:43:39 +02001490 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1491 free(node->features);
1492 lydict_remove(ctx, node->name);
1493 lydict_remove(ctx, node->dsc);
1494 lydict_remove(ctx, node->ref);
1495 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001496
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001497 /* specific part */
1498 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001499 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001500 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001501 break;
Radek Krejci76512572015-08-04 09:47:08 +02001502 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001503 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001504 break;
Radek Krejci76512572015-08-04 09:47:08 +02001505 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001506 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001507 break;
Radek Krejci76512572015-08-04 09:47:08 +02001508 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001509 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001510 break;
Radek Krejci76512572015-08-04 09:47:08 +02001511 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001512 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001513 break;
Radek Krejci76512572015-08-04 09:47:08 +02001514 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001515 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001516 break;
Radek Krejci76512572015-08-04 09:47:08 +02001517 case LYS_USES:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001518 lys_uses_free(ctx, (struct lys_node_uses *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001519 break;
Radek Krejci76512572015-08-04 09:47:08 +02001520 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001521 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001522 break;
Radek Krejci76512572015-08-04 09:47:08 +02001523 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001524 /* do nothing */
1525 break;
Radek Krejci76512572015-08-04 09:47:08 +02001526 case LYS_GROUPING:
1527 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001528 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001529 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001530 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001531
1532 case LYS_INPUT:
1533 case LYS_OUTPUT:
1534 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1535 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001536 case LYS_UNKNOWN:
1537 LOGINT;
1538 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001539 }
Radek Krejci5a065542015-05-22 15:02:07 +02001540
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001541 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001542 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001543 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001544}
1545
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001546static void
Radek Krejcib8048692015-08-05 13:36:34 +02001547module_free_common(struct lys_module *module)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001548{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001549 struct ly_ctx *ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001550 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001551 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001552
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001553 assert(module->ctx);
1554 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001555
Radek Krejcidce51452015-06-16 15:20:08 +02001556 /* as first step, free the imported modules */
1557 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa76ee152015-08-17 15:38:22 +02001558 /* do not free internal modules */
1559 for (j = 0; j < int_mods.count; ++j) {
1560 if (!strcmp(int_mods.modules[j].name, module->imp[i].module->name)
1561 && module->imp[i].module->rev
1562 && !strcmp(int_mods.modules[j].revision, module->imp[i].module->rev[0].date)) {
1563 break;
1564 }
1565 }
1566 if (j < int_mods.count) {
1567 continue;
1568 }
1569
Radek Krejcidce51452015-06-16 15:20:08 +02001570 /* get the imported module from the context and then free,
1571 * this check is necessary because the imported module can
1572 * be already removed
1573 */
1574 l = ctx->models.used;
1575 for (j = 0; j < l; j++) {
1576 if (ctx->models.list[j] == module->imp[i].module) {
Radek Krejci912da452015-07-29 14:10:06 +02001577 lys_free(module->imp[i].module);
Radek Krejcidce51452015-06-16 15:20:08 +02001578 break;
1579 }
1580 }
1581 }
1582 free(module->imp);
1583
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001584 while (module->data) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001585 lys_node_free(module->data);
Radek Krejci21181962015-06-30 14:11:00 +02001586 }
1587 while (module->rpc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001588 lys_node_free(module->rpc);
Radek Krejci21181962015-06-30 14:11:00 +02001589 }
1590 while (module->notif) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001591 lys_node_free(module->notif);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001592 }
Radek Krejci5a065542015-05-22 15:02:07 +02001593
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001594 lydict_remove(ctx, module->dsc);
1595 lydict_remove(ctx, module->ref);
1596 lydict_remove(ctx, module->org);
1597 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001598
Radek Krejcieb00f512015-07-01 16:44:58 +02001599 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001600 for (i = 0; i < module->rev_size; i++) {
1601 lydict_remove(ctx, module->rev[i].dsc);
1602 lydict_remove(ctx, module->rev[i].ref);
1603 }
1604 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001605
Radek Krejcieb00f512015-07-01 16:44:58 +02001606 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001607 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001608 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001609 }
1610 module->ident_size = 0;
1611 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001612
Radek Krejcieb00f512015-07-01 16:44:58 +02001613 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001614 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001615 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001616 }
1617 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001618
Radek Krejcieb00f512015-07-01 16:44:58 +02001619 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001620 for (i = 0; i < module->inc_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001621 lys_submodule_free(module->inc[i].submodule);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001622 }
1623 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001624
Radek Krejcieb00f512015-07-01 16:44:58 +02001625 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02001626 for (i = 0; i < module->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001627 lys_augment_free(ctx, module->augment[i]);
Radek Krejcif5be10f2015-06-16 13:29:36 +02001628 }
1629 free(module->augment);
1630
Radek Krejcieb00f512015-07-01 16:44:58 +02001631 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001632 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001633 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001634 }
1635 free(module->features);
1636
Radek Krejcieb00f512015-07-01 16:44:58 +02001637 /* deviations */
1638 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001639 lys_deviation_free(ctx, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001640 }
1641 free(module->deviation);
1642
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001643 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02001644}
1645
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001646void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001647lys_submodule_free(struct lys_submodule *submodule)
Radek Krejciefaeba32015-05-27 14:30:57 +02001648{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001649 if (!submodule) {
1650 return;
1651 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001652
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001653 submodule->inc_size = 0;
1654 free(submodule->inc);
1655 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02001656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001657 /* common part with struct ly_module */
Radek Krejcib8048692015-08-05 13:36:34 +02001658 module_free_common((struct lys_module *)submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001659
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001660 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02001661
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001662 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001663}
1664
Radek Krejcib8048692015-08-05 13:36:34 +02001665static struct lys_node_leaf *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001666lys_uniq_find(struct lys_node_list *list, struct lys_node_leaf *orig_leaf)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001667{
Radek Krejci1d82ef62015-08-07 14:44:40 +02001668 struct lys_node *node, *node2, *ret = NULL, *parent1, *parent2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001669 int depth = 1, i;
1670
1671 /* find the correct direct descendant of list in orig_leaf */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001672 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001673 while (1) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001674 if (!node->parent) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001675 return NULL;
1676 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001677 if (!strcmp(node->parent->name, list->name)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001678 break;
1679 }
1680
Radek Krejci1d82ef62015-08-07 14:44:40 +02001681 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001682 ++depth;
1683 }
1684
1685 /* make sure the nodes are equal */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001686 parent1 = node->parent->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001687 parent2 = list->parent;
1688 while (1) {
1689 if ((parent1 && !parent2) || (!parent1 && parent2)) {
1690 return NULL;
1691 }
1692
1693 if (parent1 == parent2) {
1694 break;
1695 }
1696
1697 parent1 = parent1->parent;
1698 parent2 = parent2->parent;
1699 }
1700
1701 /* find the descendant in the list */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001702 LY_TREE_FOR(list->child, node2) {
1703 if (!strcmp(node2->name, node->name)) {
1704 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001705 break;
1706 }
1707 }
1708
1709 if (!ret) {
1710 return NULL;
1711 }
1712
1713 /* continue traversing both trees, the nodes are always truly equal */
1714 while (1) {
1715 --depth;
1716 if (!depth) {
Radek Krejci76512572015-08-04 09:47:08 +02001717 if (ret->nodetype != LYS_LEAF) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001718 return NULL;
1719 }
Radek Krejcib8048692015-08-05 13:36:34 +02001720 return (struct lys_node_leaf *)ret;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001721 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001722 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001723 for (i = 0; i < depth-1; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001724 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001725 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001726 LY_TREE_FOR(ret->child, node2) {
1727 if (!strcmp(node2->name, node->name)) {
1728 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001729 break;
1730 }
1731 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001732 if (!node2) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001733 return NULL;
1734 }
1735 }
1736}
1737
Radek Krejci76512572015-08-04 09:47:08 +02001738struct lys_node *
Michal Vasko71e1aa82015-08-12 12:17:51 +02001739lys_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 +02001740 struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001741{
Radek Krejci76512572015-08-04 09:47:08 +02001742 struct lys_node *retval = NULL, *aux, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001743 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001744 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001745
Michal Vaskoc07187d2015-08-13 15:20:57 +02001746 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001747 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001748 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001749 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001750 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001751 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001752 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001753 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001754 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001755 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001756 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001757 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001758 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001759 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001760 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001761 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001762 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001763 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001764 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001765 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001766 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001767 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001768 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001769 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001770
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001771 /* we cannot just duplicate memory since the strings are stored in
1772 * dictionary and we need to update dictionary counters.
1773 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001774
Radek Krejci1d82ef62015-08-07 14:44:40 +02001775 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001776 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001777 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02001778 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001779 break;
1780
Radek Krejci76512572015-08-04 09:47:08 +02001781 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001782 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02001783 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001784 break;
1785
Radek Krejci76512572015-08-04 09:47:08 +02001786 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001787 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02001788 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001789 break;
1790
Radek Krejci76512572015-08-04 09:47:08 +02001791 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001792 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02001793 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001794 break;
1795
Radek Krejci76512572015-08-04 09:47:08 +02001796 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001797 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02001798 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001799 break;
1800
Radek Krejci76512572015-08-04 09:47:08 +02001801 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001802 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02001803 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001804 break;
1805
Radek Krejci76512572015-08-04 09:47:08 +02001806 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001807 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02001808 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001809 break;
1810
Radek Krejci76512572015-08-04 09:47:08 +02001811 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001812 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02001813 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001814 break;
1815
Radek Krejci76512572015-08-04 09:47:08 +02001816 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001817 grp = calloc(1, sizeof *grp);
1818 retval = (struct lys_node *)grp;
1819 break;
1820
Radek Krejci76512572015-08-04 09:47:08 +02001821 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001822 rpc = calloc(1, sizeof *rpc);
1823 retval = (struct lys_node *)rpc;
1824 break;
1825
Radek Krejci76512572015-08-04 09:47:08 +02001826 case LYS_INPUT:
1827 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001828 io = calloc(1, sizeof *io);
1829 retval = (struct lys_node *)io;
1830 break;
1831
Radek Krejci76512572015-08-04 09:47:08 +02001832 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001833 ntf = calloc(1, sizeof *ntf);
1834 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02001835 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001836
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001837 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02001838 LOGINT;
1839 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001840 }
Radek Krejcib388c152015-06-04 17:03:03 +02001841
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001842 /*
1843 * duplicate generic part of the structure
1844 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001845 retval->name = lydict_insert(ctx, node->name, 0);
1846 retval->dsc = lydict_insert(ctx, node->dsc, 0);
1847 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02001848 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001849 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001850 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001851 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001852 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001853 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001854
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001855 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001856 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001857
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001858 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001859
Radek Krejci1d82ef62015-08-07 14:44:40 +02001860 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001861 retval->features = calloc(retval->features_size, sizeof *retval->features);
Radek Krejci1d82ef62015-08-07 14:44:40 +02001862 for (i = 0; i < node->features_size; ++i) {
1863 if (unres_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
1864 retval->features[i] = node->features[i];
Michal Vaskod23ce592015-08-06 09:55:37 +02001865 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001866 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001867
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001868 if (recursive) {
1869 /* go recursively */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001870 LY_TREE_FOR(node->child, child) {
Michal Vasko71e1aa82015-08-12 12:17:51 +02001871 aux = lys_node_dup(module, child, retval->flags, retval->nacm, 1, unres);
Radek Krejci10c760e2015-08-14 14:45:43 +02001872 if (!aux || lys_node_addchild(retval, NULL, aux)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02001873 LOGINT;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001874 lys_node_free(retval);
Michal Vaskod23ce592015-08-06 09:55:37 +02001875 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001876 }
1877 }
1878 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001879
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001880 /*
1881 * duplicate specific part of the structure
1882 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001883 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001884 case LYS_CONTAINER:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001885 if (cont_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001886 cont->when = lys_when_dup(ctx, cont_orig->when);
1887 unres_add_node(module, unres, cont->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001888 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001889 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001890
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001891 cont->must_size = cont_orig->must_size;
1892 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001893
Radek Krejci1d82ef62015-08-07 14:44:40 +02001894 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001895 for (i = 0; i < cont->must_size; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001896 unres_add_node(module, unres, &cont->must[i], UNRES_MUST, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001897 }
1898
Radek Krejci1d82ef62015-08-07 14:44:40 +02001899 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001900 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001901
Radek Krejci76512572015-08-04 09:47:08 +02001902 case LYS_CHOICE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001903 if (choice_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001904 choice->when = lys_when_dup(ctx, choice_orig->when);
1905 unres_add_node(module, unres, choice->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001906 }
1907
1908 if (choice_orig->dflt) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001909 rc = resolve_sibling(choice->module, choice->child, NULL, 0, choice_orig->dflt->name, 0, LYS_ANYXML
Radek Krejci76512572015-08-04 09:47:08 +02001910 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001911 | LYS_LIST, &choice->dflt);
1912 assert(!rc);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001913 } else {
Michal Vaskoc68a2a22015-08-06 09:57:24 +02001914 /* useless to check return value, we don't know whether
1915 * there really wasn't any default defined or it just hasn't
1916 * been resolved, we just hope for the best :)
1917 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001918 unres_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001919 }
1920 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001921
Radek Krejci76512572015-08-04 09:47:08 +02001922 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001923 lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001924 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
1925
1926 if (leaf_orig->dflt) {
1927 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci1d82ef62015-08-07 14:44:40 +02001928 unres_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001929 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001930
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001931 leaf->must_size = leaf_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001932 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001933 for (i = 0; i < leaf->must_size; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001934 unres_add_node(module, unres, &leaf->must[i], UNRES_MUST, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001935 }
Radek Krejci00768f42015-06-18 17:04:04 +02001936
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001937 if (leaf_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001938 leaf->when = lys_when_dup(ctx, leaf_orig->when);
1939 unres_add_node(module, unres, leaf->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001940 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001941 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001942
Radek Krejci76512572015-08-04 09:47:08 +02001943 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001944 lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001945 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001946
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001947 llist->min = llist_orig->min;
1948 llist->max = llist_orig->max;
1949
1950 llist->must_size = llist_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001951 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001952 for (i = 0; i < llist->must_size; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001953 unres_add_node(module, unres, &llist->must[i], UNRES_MUST, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001954 }
Radek Krejci00768f42015-06-18 17:04:04 +02001955
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001956 if (llist_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001957 llist->when = lys_when_dup(ctx, llist_orig->when);
1958 unres_add_node(module, unres, llist->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001959 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001960 break;
1961
Radek Krejci76512572015-08-04 09:47:08 +02001962 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001963 list->min = list_orig->min;
1964 list->max = list_orig->max;
1965
1966 list->must_size = list_orig->must_size;
1967 list->tpdf_size = list_orig->tpdf_size;
1968 list->keys_size = list_orig->keys_size;
1969 list->unique_size = list_orig->unique_size;
1970
Radek Krejci1d82ef62015-08-07 14:44:40 +02001971 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001972 for (i = 0; i < list->must_size; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001973 unres_add_node(module, unres, &list->must[i], UNRES_MUST, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001974 }
1975
Radek Krejci1d82ef62015-08-07 14:44:40 +02001976 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001977
1978 if (list->keys_size) {
1979 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001980
1981 /* we managed to resolve it before, resolve it again manually */
1982 if (list_orig->keys[0]) {
1983 for (i = 0; i < list->keys_size; ++i) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001984 rc = resolve_sibling(list->module, list->child, NULL, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
1985 (struct lys_node **)&list->keys[i]);
1986 assert(!rc);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001987 }
1988 /* it was not resolved yet, add unres copy */
1989 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001990 if (unres_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02001991 LOGINT;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001992 lys_node_free(retval);
Michal Vaskod23ce592015-08-06 09:55:37 +02001993 return NULL;
1994 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001995 }
1996 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001997
1998 list->unique = calloc(list->unique_size, sizeof *list->unique);
1999 if (list_orig->unique) {
2000 for (i = 0; i < list->unique_size; ++i) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002001 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
2002 for (j = 0; j < list->unique[i].leafs_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002003 list->unique[i].leafs[j] = lys_uniq_find(list, list_orig->unique[i].leafs[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002004 }
2005 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002006 } else {
2007 for (i = 0; i < list->unique_size; ++i) {
2008 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02002009 list->unique[i].leafs = (struct lys_node_leaf **)list;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002010 unres_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002011 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002012 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002013
2014 if (list_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002015 list->when = lys_when_dup(ctx, list_orig->when);
2016 unres_add_node(module, unres, list->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002017 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002018 break;
2019
Radek Krejci76512572015-08-04 09:47:08 +02002020 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002021 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002022 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002023 for (i = 0; i < anyxml->must_size; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002024 unres_add_node(module, unres, &anyxml->must[i], UNRES_MUST, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002025 }
2026
2027 if (anyxml_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002028 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
2029 unres_add_node(module, unres, anyxml->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002030 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002031 break;
2032
Radek Krejci76512572015-08-04 09:47:08 +02002033 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002034 uses->grp = uses_orig->grp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002035
2036 if (uses_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002037 uses->when = lys_when_dup(ctx, uses_orig->when);
2038 unres_add_node(module, unres, uses->when, UNRES_WHEN, (struct lys_node *)uses, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002039 }
2040
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002041 uses->refine_size = uses_orig->refine_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002042 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size, uses, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002043 uses->augment_size = uses_orig->augment_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002044 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 +02002045 if (!uses->child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002046 unres_add_node(module, unres, uses, UNRES_USES, NULL, 0);
Michal Vaskof8c128d2015-08-06 15:25:28 +02002047 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002048 break;
2049
Radek Krejci76512572015-08-04 09:47:08 +02002050 case LYS_CASE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002051 if (cs_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002052 cs->when = lys_when_dup(ctx, cs_orig->when);
2053 unres_add_node(module, unres, cs->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002054 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002055 break;
2056
Radek Krejci76512572015-08-04 09:47:08 +02002057 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002058 grp->tpdf_size = grp_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002059 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002060 break;
2061
Radek Krejci76512572015-08-04 09:47:08 +02002062 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002063 rpc->tpdf_size = rpc_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002064 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002065 break;
2066
Radek Krejci76512572015-08-04 09:47:08 +02002067 case LYS_INPUT:
2068 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002069 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002070 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002071 break;
2072
Radek Krejci76512572015-08-04 09:47:08 +02002073 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002074 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002075 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcia01e5432015-06-16 10:35:25 +02002076 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002077
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002078 default:
Radek Krejci00768f42015-06-18 17:04:04 +02002079 /* LY_NODE_AUGMENT */
Michal Vaskod23ce592015-08-06 09:55:37 +02002080 LOGINT;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002081 lys_node_free(retval);
Michal Vaskod23ce592015-08-06 09:55:37 +02002082 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002083 }
2084
2085 return retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002086}
2087
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002088API void
Radek Krejcib8048692015-08-05 13:36:34 +02002089lys_free(struct lys_module *module)
Radek Krejciefaeba32015-05-27 14:30:57 +02002090{
Radek Krejcidce51452015-06-16 15:20:08 +02002091 struct ly_ctx *ctx;
2092 int i;
2093
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002094 if (!module) {
2095 return;
2096 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002097
Radek Krejcidce51452015-06-16 15:20:08 +02002098 /* remove schema from the context */
2099 ctx = module->ctx;
2100 if (ctx->models.used) {
2101 for (i = 0; i < ctx->models.used; i++) {
2102 if (ctx->models.list[i] == module) {
2103 /* replace the position in the list by the last module in the list */
2104 ctx->models.used--;
2105 ctx->models.list[i] = ctx->models.list[ctx->models.used];
2106 ctx->models.list[ctx->models.used] = NULL;
2107 /* we are done */
2108 break;
2109 }
2110 }
2111 }
2112
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002113 /* common part with struct ly_submodule */
2114 module_free_common(module);
Radek Krejciefaeba32015-05-27 14:30:57 +02002115
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002116 /* specific items to free */
2117 lydict_remove(module->ctx, module->ns);
2118 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02002119
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002120 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002121}
Radek Krejci7e97c352015-06-19 16:26:34 +02002122
2123/*
2124 * op: 1 - enable, 0 - disable
2125 */
2126static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002127lys_features_change(struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002128{
2129 int all = 0;
2130 int i, j, k;
2131
2132 if (!module || !name || !strlen(name)) {
2133 return EXIT_FAILURE;
2134 }
2135
2136 if (!strcmp(name, "*")) {
2137 /* enable all */
2138 all = 1;
2139 }
2140
2141 /* module itself */
2142 for (i = 0; i < module->features_size; i++) {
2143 if (all || !strcmp(module->features[i].name, name)) {
2144 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002145 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002146 /* enable referenced features (recursion) */
2147 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002148 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002149 module->features[i].features[k]->name, op);
2150 }
2151 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002152 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002153 }
2154 if (!all) {
2155 return EXIT_SUCCESS;
2156 }
2157 }
2158 }
2159
2160 /* submodules */
2161 for (j = 0; j < module->inc_size; j++) {
2162 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2163 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2164 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002165 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002166 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002167 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002168 }
2169 if (!all) {
2170 return EXIT_SUCCESS;
2171 }
2172 }
2173 }
2174 }
2175
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002176 /* TODO submodules of submodules ... */
2177
Radek Krejci7e97c352015-06-19 16:26:34 +02002178 if (all) {
2179 return EXIT_SUCCESS;
2180 } else {
2181 return EXIT_FAILURE;
2182 }
2183}
2184
2185API int
Radek Krejcib8048692015-08-05 13:36:34 +02002186lys_features_enable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002187{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002188 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002189}
2190
2191API int
Radek Krejcib8048692015-08-05 13:36:34 +02002192lys_features_disable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002193{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002194 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002195}
2196
2197API int
Radek Krejcib8048692015-08-05 13:36:34 +02002198lys_features_state(struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002199{
2200 int i, j;
2201
2202 if (!module || !feature) {
2203 return -1;
2204 }
2205
2206 /* search for the specified feature */
2207 /* module itself */
2208 for (i = 0; i < module->features_size; i++) {
2209 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002210 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002211 return 1;
2212 } else {
2213 return 0;
2214 }
2215 }
2216 }
2217
2218 /* submodules */
2219 for (j = 0; j < module->inc_size; j++) {
2220 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2221 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002222 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002223 return 1;
2224 } else {
2225 return 0;
2226 }
2227 }
2228 }
2229 }
2230
2231 /* TODO submodules of submodules ... */
2232
2233 /* feature definition not found */
2234 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002235}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002236
Radek Krejci96a10da2015-07-30 11:00:14 +02002237API const char **
Radek Krejcib8048692015-08-05 13:36:34 +02002238lys_features_list(struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002239{
Radek Krejci96a10da2015-07-30 11:00:14 +02002240 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002241 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002242 unsigned int count;
2243
2244 if (!module) {
2245 return NULL;
2246 }
2247
2248 count = module->features_size;
2249 for (i = 0; i < module->inc_size; i++) {
2250 count += module->inc[i].submodule->features_size;
2251 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002252 result = malloc((count + 1) * sizeof *result);
2253 if (states) {
2254 *states = malloc((count + 1) * sizeof **states);
Michal Vasko2367e7c2015-07-07 11:33:44 +02002255 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002256 count = 0;
2257
2258 /* module itself */
2259 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002260 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002261 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002262 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002263 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002264 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002265 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002266 }
2267 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002268 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002269 }
2270
2271 /* submodules */
2272 for (j = 0; j < module->inc_size; j++) {
2273 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002274 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002275 if (states) {
2276 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2277 (*states)[count] = 1;
2278 } else {
2279 (*states)[count] = 0;
2280 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002281 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002282 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002283 }
2284 }
2285
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002286 /* TODO submodules of submodules ... */
2287
2288 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002289 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002290
2291 return result;
2292}
Radek Krejcib20c62d2015-07-07 17:07:14 +02002293
2294API struct lyd_node *
Radek Krejci25b9fd32015-08-10 15:06:07 +02002295lyd_parse(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
Radek Krejcib20c62d2015-07-07 17:07:14 +02002296{
2297 if (!ctx || !data) {
2298 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2299 return NULL;
2300 }
2301
2302 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02002303 case LYD_XML:
Radek Krejci25b9fd32015-08-10 15:06:07 +02002304 return xml_read_data(ctx, data, options);
Radek Krejcia9167ef2015-08-03 11:01:11 +02002305 case LYD_JSON:
Radek Krejcib20c62d2015-07-07 17:07:14 +02002306 default:
2307 /* TODO */
2308 return NULL;
2309 }
2310
2311 return NULL;
2312}
2313
Radek Krejci0e1d1a62015-07-31 11:17:01 +02002314API void
Radek Krejci912da452015-07-29 14:10:06 +02002315lyd_free(struct lyd_node *node)
Radek Krejcib20c62d2015-07-07 17:07:14 +02002316{
2317 struct lyd_node *next, *child;
2318
Radek Krejci52f791c2015-07-15 11:14:17 +02002319 if (!node) {
2320 return;
2321 }
2322
Radek Krejci76512572015-08-04 09:47:08 +02002323 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
Radek Krejcie4748472015-07-08 18:00:22 +02002324 /* free children */
2325 LY_TREE_FOR_SAFE(node->child, next, child) {
Radek Krejci912da452015-07-29 14:10:06 +02002326 lyd_free(child);
Radek Krejcie4748472015-07-08 18:00:22 +02002327 }
Radek Krejci76512572015-08-04 09:47:08 +02002328 } else if (node->schema->nodetype == LYS_ANYXML) {
Radek Krejci9566b092015-07-31 11:18:15 +02002329 lyxml_free_elem(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
Radek Krejcie4748472015-07-08 18:00:22 +02002330 } else {
2331 /* free value */
2332 switch(((struct lyd_node_leaf *)node)->value_type) {
2333 case LY_TYPE_BINARY:
2334 case LY_TYPE_STRING:
2335 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf *)node)->value.string);
2336 break;
Radek Krejci3e3affe2015-07-09 15:38:40 +02002337 case LY_TYPE_BITS:
2338 if (((struct lyd_node_leaf *)node)->value.bit) {
2339 free(((struct lyd_node_leaf *)node)->value.bit);
2340 }
2341 break;
Radek Krejcie4748472015-07-08 18:00:22 +02002342 default:
Radek Krejci7511f402015-07-10 09:56:30 +02002343 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
Radek Krejcie4748472015-07-08 18:00:22 +02002344 break;
2345 }
Radek Krejcib20c62d2015-07-07 17:07:14 +02002346 }
2347
2348 if (node->prev->next) {
2349 node->prev->next = node->next;
2350 } else if (node->parent) {
2351 /* first node */
2352 node->parent->child = node->next;
2353 }
2354 if (node->next) {
2355 node->next->prev = node->prev;
2356 }
2357
2358 free(node);
2359}
Michal Vaskof54f2f82015-07-17 13:12:05 +02002360
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002361API int
Radek Krejci9566b092015-07-31 11:18:15 +02002362lyd_is_last(struct lyd_node *node)
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002363{
2364 struct lyd_node *n;
2365
2366 if (!node->next) {
2367 return 1;
2368 }
2369
2370 for (n = node->next; n; n = n->next) {
2371 switch (n->schema->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002372 case LYS_LIST:
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002373 if (!((struct lyd_node_list *)n)->lprev) {
2374 return 0;
2375 }
2376 break;
Radek Krejci76512572015-08-04 09:47:08 +02002377 case LYS_LEAFLIST:
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002378 if (!((struct lyd_node_leaflist *)n)->lprev) {
2379 return 0;
2380 }
2381 break;
2382 default:
2383 return 0;
2384 }
2385 }
2386 return 1;
2387}