blob: 50950ff4d2a28a1761f0a45164e9559a66025a97 [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"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020032#include "parse.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020033#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020034#include "resolve.h"
Radek Krejci106efc02015-06-10 14:36:27 +020035#include "xml.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020036#include "tree_internal.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020037
Radek Krejci48061fb2015-08-05 15:41:07 +020038API struct lys_feature *
39lys_is_disabled(struct lys_node *node, int recursive)
40{
41 int i;
42
43check:
44 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
45 /* input/output does not have if-feature, so skip them */
46
47 /* check local if-features */
48 for (i = 0; i < node->features_size; i++) {
49 if (!(node->features[i]->flags & LYS_FENABLED)) {
50 return node->features[i];
51 }
52 }
53 }
54
55 if (!recursive) {
56 return NULL;
57 }
58
59 /* go through parents */
60 if (node->nodetype == LYS_AUGMENT) {
61 /* go to parent actually means go to the target node */
62 node = ((struct lys_node_augment *)node)->target;
63 goto check;
64 } else if (node->parent) {
65 node = node->parent;
66 goto check;
67 }
68
69 return NULL;
70}
71
Radek Krejci7f40ce32015-08-12 20:38:46 +020072static struct lys_node *
73check_mand_getnext(struct lys_node *cur, struct lys_node *parent)
74{
75 struct lys_node *next;
76
77 if (!cur) {
78 next = parent->child;
79 } else {
80 next = cur->next;
81 }
82
83repeat:
Michal Vasko591e0b22015-08-13 13:53:43 +020084 while (next && (next->nodetype & (LYS_AUGMENT | LYS_GROUPING | LYS_LEAFLIST))) {
Radek Krejci7f40ce32015-08-12 20:38:46 +020085 next = cur = next->next;
86 }
87
88 while (!next) {
89 if (cur->parent == parent) {
90 /* no next element */
91 return NULL;
92 }
93 cur = cur->parent;
94 next = cur->next;
95 goto repeat;
96 }
97
98 switch (next->nodetype) {
99 case LYS_CONTAINER:
100 if (((struct lys_node_container *)next)->presence) {
101 /* mandatory elements under the non-existing presence
102 * container are not mandatory - 7.6.5, rule 1 */
103 next = next->next;
104 goto repeat;
105 }
106 /* no break */
107 case LYS_LIST:
108 case LYS_USES:
109 case LYS_CASE:
110 /* go into */
111 next = next->child;
112 goto repeat;
113 case LYS_LEAF:
114 case LYS_CHOICE:
115 case LYS_ANYXML:
116 return next;
117 default:
118 /* we should not be here */
119 return NULL;
120 }
121}
122
123static struct lys_node *
124check_mand_check(struct lys_node *node, struct lys_node *stop, struct lyd_node *data)
125{
126 struct lys_node *siter = NULL, *parent;
127 struct lyd_node *diter = NULL;
128
129 if (node->flags & LYS_MAND_TRUE) {
130 switch (node->nodetype) {
131 case LYS_LEAF:
132 case LYS_ANYXML:
133 case LYS_CHOICE:
134 if (node->parent->nodetype == LYS_CASE) {
135 /* 7.6.5, rule 2 */
136 /* 7.9.4, rule 1 */
137 if (node->parent->parent->parent == data->schema) {
138 /* the only case the node's siblings can exist is that the
139 * data node passed originaly to ly_check_mandatory()
140 * had this choice as a child
141 */
142 /* try to find the node's siblings in data */
143 LY_TREE_FOR(data->child, diter) {
144 LY_TREE_FOR(node->parent->child, siter) {
145 if (siter == diter->schema) {
146 /* some sibling exists, rule applies */
147 break;
148 }
149 }
150 if (siter) {
151 break;
152 }
153 }
154 }
155 if (!siter) {
156 /* no sibling exists */
157 return NULL;
158 }
159 } else {
160 for(parent = node->parent; parent != stop; parent = parent->parent) {
161 if (parent->nodetype != LYS_CONTAINER) {
162 /* 7.6.5, rule 1, checking presence is not needed
163 * since it is done in check_mand_getnext()
164 */
165 return NULL;
166 }
167 }
168 }
169 /* 7.6.5, rule 3 (or 2) */
170 /* 7.9.4, rule 2 */
171 return node;
172 default:
173 /* error */
174 break;
175 }
176 }
177
178 return NULL;
179}
180
181struct lys_node *
182ly_check_mandatory(struct lyd_node *data)
183{
184 struct lys_node *siter, *saux = NULL, *result, *parent = NULL;
185 struct lyd_node *diter;
186 int found;
187
188 siter = data->schema->child;
189
190repeat:
191 while (siter) {
192 switch (siter->nodetype) {
193 case LYS_CONTAINER:
194 case LYS_LEAF:
195 case LYS_ANYXML:
196 /* search for instance */
197 LY_TREE_FOR(data->child, diter) {
198 if (diter->schema == siter) {
199 break;
200 }
201 }
202 if (diter) {
203 /* result has a child defined by siter, check another siter */
204 siter = siter->next;
205 break;
206 }
207
208 /* the siter has no instance under the result, check if there is
209 * some mandatory node; first the siter itself ... */
210 result = check_mand_check(siter, siter->parent, data);
211 if (result) {
212 return result;
213 }
214 /* ... and then the subtree */
215 if (siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
216 while ((saux = check_mand_getnext(saux, siter))) {
217 result = check_mand_check(saux, siter, data);
218 if (result) {
219 return result;
220 }
221 }
222 }
223 siter = siter->next;
224 break;
225 case LYS_CHOICE:
226 if (siter->flags & LYS_MAND_TRUE) {
227 /* search for instance */
228 saux = siter;
229 parent = NULL;
230 siter = siter->child;
231 found = 0;
232repeat_choice:
233 while (siter) {
234 switch(siter->nodetype) {
235 case LYS_CONTAINER:
236 case LYS_LEAF:
237 case LYS_LEAFLIST:
238 case LYS_LIST:
239 case LYS_ANYXML:
240 LY_TREE_FOR(data->child, diter) {
241 if (diter->schema == siter) {
242 break;
243 }
244 }
245 if (diter) {
246 /* got instance, done */
247 siter = parent = NULL;
248 found = 1;
249 break;
250 }
251 siter = siter->next;
252 break;
253 case LYS_CASE:
254 case LYS_CHOICE:
255 case LYS_USES:
256 /* go into */
257 parent = siter;
258 siter = siter->child;
259 break;
260 case LYS_AUGMENT:
261 case LYS_GROUPING:
262 /* skip */
263 siter = siter->next;
264 break;
265 default:
266 /* error */
267 break;
268 }
269 }
270
271 if (parent) {
272 siter = parent->next;
273 if (parent->parent == saux) {
274 parent = NULL;
275 } else {
276 parent = parent->parent;
277 }
278 goto repeat_choice;
279 }
280
281 if (!found) {
282 return saux;
283 }
284
285 siter = saux;
286 }
287
288 /* go into */
289 parent = siter;
290 siter = siter->child;
291 break;
292 case LYS_USES:
293 case LYS_CASE:
294 /* go into */
295 parent = siter;
296 siter = siter->child;
297 break;
298 default:
299 /* can ignore, go to next */
300 siter = siter->next;
301 break;
302 }
303 }
304
305 if (parent) {
306 siter = parent->next;
307 if (parent->parent == data->schema) {
308 parent = NULL;
309 } else {
310 parent = parent->parent;
311 }
312 goto repeat;
313 }
314
315 return NULL;
316}
317
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200318void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200319lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200320{
Radek Krejci76512572015-08-04 09:47:08 +0200321 struct lys_node *parent, *first;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200322
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200323 if (!node) {
324 return;
325 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200326
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200327 /* unlink from data model if necessary */
328 if (node->module) {
329 if (node->module->data == node) {
330 node->module->data = node->next;
Radek Krejci21181962015-06-30 14:11:00 +0200331 } else if (node->module->rpc == node) {
332 node->module->rpc = node->next;
333 } else if (node->module->notif == node) {
334 node->module->notif = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200335 }
336 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200337
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200338 /* store pointers to important nodes */
339 parent = node->parent;
340 if (parent && !parent->nodetype) {
341 /* handle augments - first, unlink it from the augment parent ... */
342 if (parent->child == node) {
343 parent->child = node->next;
344 }
345 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200346 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200347 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200348
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200349 /* unlink from parent */
350 if (parent) {
351 if (parent->child == node) {
352 parent->child = node->next;
353 }
354 node->parent = NULL;
355 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200357 /* unlink from siblings */
358 if (node->prev == node) {
359 /* there are no more siblings */
360 return;
361 }
362 if (node->next) {
363 node->next->prev = node->prev;
364 } else {
365 /* unlinking the last element */
366 if (parent) {
367 first = parent->child;
368 } else {
369 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200370 while (first->prev->next) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200371 first = node->prev;
372 }
373 }
374 first->prev = node->prev;
375 }
376 if (node->prev->next) {
377 node->prev->next = node->next;
378 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200380 /* clean up the unlinked element */
381 node->next = NULL;
382 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200383}
384
Radek Krejci10c760e2015-08-14 14:45:43 +0200385/*
386 * get next grouping in the root's subtree, in the
387 * first call, tha last is NULL
388 */
389static struct lys_node_grp *
390lys_get_next_grouping(struct lys_node_grp* lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200391{
Radek Krejci10c760e2015-08-14 14:45:43 +0200392 struct lys_node *last = (struct lys_node *)lastgrp;
393 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200394
Radek Krejci10c760e2015-08-14 14:45:43 +0200395 assert(root);
396
397 if (!last) {
398 last = root;
399 }
400
401 while (1) {
402 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
403 next = last->child;
404 } else {
405 next = NULL;
406 }
407 if (!next) {
408 if (last == root) {
409 /* we are done */
410 return NULL;
411 }
412
413 /* no children, go to siblings */
414 next = last->next;
415 }
416 while (!next) {
417 /* go back through parents */
418 if (last->parent == root) {
419 /* we are done */
420 return NULL;
421 }
422 last = last->parent;
423 next = last->next;
424 }
425
426 if (next->nodetype == LYS_GROUPING) {
427 return (struct lys_node_grp *)next;
428 }
429
430 last = next;
431 }
432}
433
434int
Radek Krejci07911992015-08-14 15:13:31 +0200435lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
436{
437 struct lys_node *start, *stop, *par_iter, *iter;
438 struct lys_node_grp *grp;
439 int down;
440
441 assert(node);
442
443 if (!parent) {
444 assert(module);
445 } else {
446 module = parent->module;
447 }
448
449 switch (node->nodetype) {
450 case LYS_GROUPING:
451 /* 6.2.1, rule 6 */
452 if (parent) {
453 if (parent->child) {
454 down = 1;
455 start = parent->child;
456 } else {
457 down = 0;
458 start = parent;
459 }
460 } else {
461 down = 1;
462 start = module->data;
463 }
464 /* go up */
465 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
466 if (par_iter->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES)) {
467 continue;
468 }
469
470 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
471 if (!stop) {
472 stop = par_iter;
473 } else if (iter == stop) {
474 break;
475 }
476 if (iter->nodetype != LYS_GROUPING) {
477 continue;
478 }
479
480 if (node->name == iter->name) {
481 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
482 return EXIT_FAILURE;
483 }
484 }
485 }
486 /* go down, because grouping can be defined after e.g. container in which is collision */
487 if (down) {
488 for (iter = start, stop = NULL; iter; iter = iter->prev) {
489 if (!stop) {
490 stop = start;
491 } else if (iter == stop) {
492 break;
493 }
494 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
495 continue;
496 }
497
498 grp = NULL;
499 while ((grp = lys_get_next_grouping(grp, iter))) {
500 if (node->name == grp->name) {
501 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
502 return EXIT_FAILURE;
503 }
504 }
505 }
506 }
507 break;
508 case LYS_LEAF:
509 case LYS_LEAFLIST:
510 case LYS_LIST:
511 case LYS_CONTAINER:
512 case LYS_CHOICE:
513 case LYS_ANYXML:
514 /* 6.2.1, rule 7 */
515 if (parent) {
516 iter = parent;
517 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE))) {
518 iter = iter->parent;
519 }
520 if (!iter) {
521 stop = NULL;
522 iter = module->data;
523 } else {
524 stop = iter;
525 iter = iter->child;
526 }
527 } else {
528 stop = NULL;
529 iter = module->data;
530 }
531 while (iter) {
532 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
533 iter = iter->child;
534 continue;
535 }
536
537 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
538 if (iter->module == node->module && iter->name == node->name) {
539 LOGVAL(LYE_SPEC, 0, "Duplicated child identifier \"%s\" in \"%s\".", node->name,
540 stop ? stop->name : "(sub)module");
541 return EXIT_FAILURE;
542 }
543 }
544
545 /* special case for choice - we must check the choice's name as
546 * well as the names of nodes under the choice
547 */
548 if (iter->nodetype == LYS_CHOICE) {
549 iter = iter->child;
550 continue;
551 }
552
553 /* go to siblings */
554 if (!iter->next) {
555 /* no sibling, go to parent's sibling */
556 do {
557 iter = iter->parent;
558 if (iter && iter->next) {
559 break;
560 }
561 } while (iter != stop);
562
563 if (iter == stop) {
564 break;
565 }
566 }
567 iter = iter->next;
568 }
569 break;
570 case LYS_CASE:
571 /* 6.2.1, rule 8 */
572 LY_TREE_FOR(parent->child, iter) {
573 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
574 continue;
575 }
576
577 if (iter->module == node->module && iter->name == node->name) {
578 LOGVAL(LYE_DUPID, 0, "case", node->name);
579 return EXIT_FAILURE;
580 }
581 }
582 break;
583 default:
584 /* no check needed */
585 break;
586 }
587
588 return EXIT_SUCCESS;
589}
590
591int
Radek Krejci10c760e2015-08-14 14:45:43 +0200592lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
593{
Radek Krejci07911992015-08-14 15:13:31 +0200594 struct lys_node *iter, **trg = NULL;
595 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200596
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200597 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200598
Radek Krejci10c760e2015-08-14 14:45:43 +0200599 if (parent) {
600 type = parent->nodetype;
601 module = parent->module;
602 } else {
603 assert(module);
604 type = 0;
605 trg = &module->data;
606 }
607
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200608 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200609 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200610 case LYS_CONTAINER:
611 case LYS_LIST:
612 case LYS_GROUPING:
613 case LYS_USES:
614 case LYS_INPUT:
615 case LYS_OUTPUT:
616 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200617 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200618 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
619 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200620 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200621 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
622 return EXIT_FAILURE;
623 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200624
625 if (type == LYS_NOTIF) {
626 trg = &module->notif;
627 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200628 break;
Radek Krejci76512572015-08-04 09:47:08 +0200629 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200630 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200631 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200632 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"choice\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200633 strnodetype(child->nodetype), parent->name);
634 return EXIT_FAILURE;
635 }
636 break;
Radek Krejci76512572015-08-04 09:47:08 +0200637 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200638 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200639 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200640 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"case\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200641 strnodetype(child->nodetype), parent->name);
642 return EXIT_FAILURE;
643 }
644 break;
Radek Krejci76512572015-08-04 09:47:08 +0200645 case LYS_RPC:
646 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200647 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"rpc\" %s.",
Michal Vasko38d01f72015-06-15 09:41:06 +0200648 strnodetype(child->nodetype), parent->name);
649 return EXIT_FAILURE;
650 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200651 trg = &module->rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +0200652 break;
Radek Krejci76512572015-08-04 09:47:08 +0200653 case LYS_LEAF:
654 case LYS_LEAFLIST:
655 case LYS_ANYXML:
Radek Krejci10c760e2015-08-14 14:45:43 +0200656 LOGVAL(LYE_SPEC, 0, "The \"%s\" statement (%s) cannot have any data substatement.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200657 strnodetype(parent->nodetype), parent->name);
658 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200659 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200660 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200661 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
662 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200663 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200664 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
665 return EXIT_FAILURE;
666 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200667 break;
668 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200669 /* top level */
670 if (!(child->nodetype &
671 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
672 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
673 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in (sub)module",
674 strnodetype(child->nodetype), strnodetype(parent->nodetype));
675 return EXIT_FAILURE;
676 }
677
678 break;;
679 }
680
681 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200682 if (lys_check_id(child, parent, module)) {
683 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200684 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200685
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200686 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200687 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200688 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200689
Radek Krejci10c760e2015-08-14 14:45:43 +0200690 if (!parent) {
691 if (*trg) {
692 (*trg)->prev->next = child;
693 child->prev = (*trg)->prev;
694 (*trg)->prev = child;
695 } else {
696 (*trg) = child;
697 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200698 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +0200699 if (!parent->child) {
700 /* the only/first child of the parent */
701 parent->child = child;
702 child->parent = parent;
703 iter = child;
704 } else {
705 /* add a new child at the end of parent's child list */
706 iter = parent->child->prev;
707 iter->next = child;
708 child->prev = iter;
709 }
710 while (iter->next) {
711 iter = iter->next;
712 iter->parent = parent;
713 }
714 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200715 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200716
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200717 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200718}
719
Radek Krejcib8048692015-08-05 13:36:34 +0200720API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +0200721lys_parse(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200722{
Michal Vaskof02e3742015-08-05 16:27:02 +0200723 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200724 struct lys_module *mod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200725
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200726 if (!ctx || !data) {
727 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
728 return NULL;
729 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200730
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200731 unres = calloc(1, sizeof *unres);
732
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200733 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200734 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200735 mod = yin_read_module(ctx, data, 1, unres);
736 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200737 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200738 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +0200739 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200740 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200741 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200742
Radek Krejci0b5805d2015-08-13 09:38:02 +0200743 if (mod && unres->count && resolve_unres(mod, unres)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200744 lys_free(mod);
745 mod = NULL;
746 }
747 free(unres->item);
748 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +0200749 free(unres->str_snode);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200750#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200751 free(unres->line);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200752#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200753 free(unres);
754
755 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200756}
757
Radek Krejcib8048692015-08-05 13:36:34 +0200758struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +0200759lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +0200760{
Michal Vaskof02e3742015-08-05 16:27:02 +0200761 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200762 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200763
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200764 assert(module);
765 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200766
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200767 unres = calloc(1, sizeof *unres);
768
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200769 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200770 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200771 submod = yin_read_submodule(module, data, implement, unres);
772 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200773 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200774 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +0200775 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200776 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200777 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200778
Radek Krejci0b5805d2015-08-13 09:38:02 +0200779 if (submod && unres->count && resolve_unres((struct lys_module *)submod, unres)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200780 lys_submodule_free(submod);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200781 submod = NULL;
782 }
783 free(unres->item);
784 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +0200785 free(unres->str_snode);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200786#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200787 free(unres->line);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200788#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200789 free(unres);
790
791 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +0200792}
793
Radek Krejcib8048692015-08-05 13:36:34 +0200794API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +0200795lys_read(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +0200796{
Radek Krejcib8048692015-08-05 13:36:34 +0200797 struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +0200798 struct stat sb;
799 char *addr;
800
801 if (!ctx || fd < 0) {
802 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
803 return NULL;
804 }
805
806 /*
807 * TODO
808 * This is just a temporary solution to make working automatic search for
809 * imported modules. This doesn't work e.g. for streams (stdin)
810 */
811 fstat(fd, &sb);
812 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
813 module = lys_parse(ctx, addr, format);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200814 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200815
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200816 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200817}
818
Radek Krejcib8048692015-08-05 13:36:34 +0200819struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +0200820lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +0200821{
Radek Krejcib8048692015-08-05 13:36:34 +0200822 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200823 struct stat sb;
824 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +0200825
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200826 assert(module);
827 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +0200828
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200829 /*
830 * TODO
831 * This is just a temporary solution to make working automatic search for
832 * imported modules. This doesn't work e.g. for streams (stdin)
833 */
834 fstat(fd, &sb);
835 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
836 /* TODO addr error check */
Radek Krejci1d82ef62015-08-07 14:44:40 +0200837 submodule = lys_submodule_parse(module, addr, format, implement);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200838 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +0200839
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200840 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +0200841
842}
843
Radek Krejci1d82ef62015-08-07 14:44:40 +0200844static struct lys_restr *
845lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200846{
Radek Krejci1574a8d2015-08-03 14:16:52 +0200847 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200848 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200849
Radek Krejci3733a802015-06-19 13:43:21 +0200850 if (!size) {
851 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200852 }
Radek Krejci3733a802015-06-19 13:43:21 +0200853
854 result = calloc(size, sizeof *result);
855 for (i = 0; i < size; i++) {
856 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
857 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
858 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
859 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
860 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
861 }
862
863 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200864}
865
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200866void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200867lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +0200868{
869 assert(ctx);
870 if (!restr) {
871 return;
872 }
873
874 lydict_remove(ctx, restr->expr);
875 lydict_remove(ctx, restr->dsc);
876 lydict_remove(ctx, restr->ref);
877 lydict_remove(ctx, restr->eapptag);
878 lydict_remove(ctx, restr->emsg);
879}
880
Radek Krejci1d82ef62015-08-07 14:44:40 +0200881static void
882lys_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 +0200883 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +0200884{
885 int i;
886
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200887 new->prefix = lydict_insert(mod->ctx, old->prefix, 0);
Radek Krejci3733a802015-06-19 13:43:21 +0200888 new->base = old->base;
889 new->der = old->der;
890
Radek Krejci1d82ef62015-08-07 14:44:40 +0200891 i = unres_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200892 if (i != -1) {
893 /* HACK for unres */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200894 new->der = (struct lys_tpdf *)parent;
Radek Krejci1d82ef62015-08-07 14:44:40 +0200895 unres_add_str(mod, unres, new, UNRES_TYPE_DER, unres->str_snode[i], 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200896 return;
897 }
898
Radek Krejci3733a802015-06-19 13:43:21 +0200899 switch (new->base) {
900 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +0200901 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200902 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +0200903 }
Radek Krejci3733a802015-06-19 13:43:21 +0200904 break;
905
906 case LY_TYPE_BITS:
907 new->info.bits.count = old->info.bits.count;
908 if (new->info.bits.count) {
909 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
910 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200911 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
912 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
913 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Radek Krejci3733a802015-06-19 13:43:21 +0200914 new->info.bits.bit[i].status = old->info.bits.bit[i].status;
915 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
916 }
917 }
918 break;
919
Radek Krejcif9401c32015-06-26 16:47:36 +0200920 case LY_TYPE_DEC64:
921 new->info.dec64.dig = old->info.dec64.dig;
922 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200923 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +0200924 }
925 break;
926
Radek Krejci3733a802015-06-19 13:43:21 +0200927 case LY_TYPE_ENUM:
928 new->info.enums.count = old->info.enums.count;
929 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200930 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Radek Krejci3733a802015-06-19 13:43:21 +0200931 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200932 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
933 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
934 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
935 new->info.enums.enm[i].status = old->info.enums.enm[i].status;
936 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +0200937 }
938 }
939 break;
940
Radek Krejci4a7b5ee2015-06-19 14:56:43 +0200941 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200942 if (old->info.ident.ref) {
943 new->info.ident.ref = old->info.ident.ref;
944 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200945 i = unres_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200946 assert(i != -1);
Radek Krejci1d82ef62015-08-07 14:44:40 +0200947 unres_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i], 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200948 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +0200949 break;
950
Radek Krejciaf351422015-06-19 14:49:38 +0200951 case LY_TYPE_INST:
952 new->info.inst.req = old->info.inst.req;
953 break;
954
Radek Krejcif2860132015-06-20 12:37:20 +0200955 case LY_TYPE_INT8:
956 case LY_TYPE_INT16:
957 case LY_TYPE_INT32:
958 case LY_TYPE_INT64:
959 case LY_TYPE_UINT8:
960 case LY_TYPE_UINT16:
961 case LY_TYPE_UINT32:
962 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +0200963 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200964 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +0200965 }
Radek Krejcif2860132015-06-20 12:37:20 +0200966 break;
967
Radek Krejcidc4c1412015-06-19 15:39:54 +0200968 case LY_TYPE_LEAFREF:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200969 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Radek Krejci1d82ef62015-08-07 14:44:40 +0200970 unres_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200971 break;
972
Radek Krejci3733a802015-06-19 13:43:21 +0200973 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +0200974 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200975 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200976 }
Radek Krejci1d82ef62015-08-07 14:44:40 +0200977 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 +0200978 break;
979
Radek Krejcie4c366b2015-07-02 10:11:31 +0200980 case LY_TYPE_UNION:
981 new->info.uni.count = old->info.uni.count;
982 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200983 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200984 for (i = 0; i < new->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200985 lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200986 }
987 }
988 break;
989
Radek Krejci3733a802015-06-19 13:43:21 +0200990 default:
Radek Krejcic7c85532015-07-02 10:16:54 +0200991 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +0200992 break;
993 }
994}
995
996void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200997lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +0200998{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200999 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001000
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001001 assert(ctx);
1002 if (!type) {
1003 return;
1004 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001005
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001006 lydict_remove(ctx, type->prefix);
Radek Krejci5a065542015-05-22 15:02:07 +02001007
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001008 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001009 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001010 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001011 free(type->info.binary.length);
1012 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001013 case LY_TYPE_BITS:
1014 for (i = 0; i < type->info.bits.count; i++) {
1015 lydict_remove(ctx, type->info.bits.bit[i].name);
1016 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1017 lydict_remove(ctx, type->info.bits.bit[i].ref);
1018 }
1019 free(type->info.bits.bit);
1020 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001021
1022 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001023 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001024 free(type->info.dec64.range);
1025 break;
1026
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001027 case LY_TYPE_ENUM:
1028 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001029 lydict_remove(ctx, type->info.enums.enm[i].name);
1030 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1031 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001032 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001033 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001034 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001035
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001036 case LY_TYPE_INT8:
1037 case LY_TYPE_INT16:
1038 case LY_TYPE_INT32:
1039 case LY_TYPE_INT64:
1040 case LY_TYPE_UINT8:
1041 case LY_TYPE_UINT16:
1042 case LY_TYPE_UINT32:
1043 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001044 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001045 free(type->info.num.range);
1046 break;
1047
Radek Krejcidc4c1412015-06-19 15:39:54 +02001048 case LY_TYPE_LEAFREF:
1049 lydict_remove(ctx, type->info.lref.path);
1050 break;
1051
Radek Krejci3733a802015-06-19 13:43:21 +02001052 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001053 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001054 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001055 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001056 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001057 }
1058 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001059 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001060
Radek Krejcie4c366b2015-07-02 10:11:31 +02001061 case LY_TYPE_UNION:
1062 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001063 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001064 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001065 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001066 break;
1067
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001068 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001069 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001070 break;
1071 }
Radek Krejci5a065542015-05-22 15:02:07 +02001072}
1073
Radek Krejci1d82ef62015-08-07 14:44:40 +02001074static struct lys_tpdf *
1075lys_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 +02001076{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001077 struct lys_tpdf *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001078 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001079
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001080 if (!size) {
1081 return NULL;
1082 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001083
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001084 result = calloc(size, sizeof *result);
1085 for (i = 0; i < size; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001086 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1087 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1088 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001089 result[i].flags = old[i].flags;
1090 result[i].module = old[i].module;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001091
Radek Krejci1d82ef62015-08-07 14:44:40 +02001092 lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001093
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001094 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1095 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001096 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001097
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001098 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001099}
1100
Radek Krejci1d82ef62015-08-07 14:44:40 +02001101static void
1102lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001103{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001104 assert(ctx);
1105 if (!tpdf) {
1106 return;
1107 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001108
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001109 lydict_remove(ctx, tpdf->name);
1110 lydict_remove(ctx, tpdf->dsc);
1111 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001112
Radek Krejci1d82ef62015-08-07 14:44:40 +02001113 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001114
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001115 lydict_remove(ctx, tpdf->units);
1116 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001117}
1118
Radek Krejci1d82ef62015-08-07 14:44:40 +02001119static struct lys_when *
1120lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001121{
Radek Krejci76512572015-08-04 09:47:08 +02001122 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001123
1124 if (!old) {
1125 return NULL;
1126 }
1127
1128 new = calloc(1, sizeof *new);
1129 new->cond = lydict_insert(ctx, old->cond, 0);
1130 new->dsc = lydict_insert(ctx, old->dsc, 0);
1131 new->ref = lydict_insert(ctx, old->ref, 0);
1132
1133 return new;
1134}
1135
Radek Krejci1d82ef62015-08-07 14:44:40 +02001136static void
1137lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001138{
1139 if (!w) {
1140 return;
1141 }
1142
1143 lydict_remove(ctx, w->cond);
1144 lydict_remove(ctx, w->dsc);
1145 lydict_remove(ctx, w->ref);
1146
1147 free(w);
1148}
1149
Radek Krejcib7f5e412015-08-13 10:15:51 +02001150static void
1151lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment aug)
1152{
1153 struct lys_node *child, *sub;
1154
1155 lydict_remove(ctx, aug.target_name);
1156 lydict_remove(ctx, aug.dsc);
1157 lydict_remove(ctx, aug.ref);
1158
1159 free(aug.features);
1160
1161 lys_when_free(ctx, aug.when);
1162
1163 LY_TREE_FOR_SAFE(aug.child, child, sub) {
1164 lys_node_free(sub);
1165 }
1166}
1167
Radek Krejci76512572015-08-04 09:47:08 +02001168static struct lys_node_augment *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001169lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size,
Michal Vasko41de7352015-08-06 09:53:34 +02001170 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001171{
Radek Krejci76512572015-08-04 09:47:08 +02001172 struct lys_node_augment *new = NULL;
Michal Vasko41de7352015-08-06 09:53:34 +02001173 struct lys_node *snode;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001174 int i = -1;
Radek Krejci106efc02015-06-10 14:36:27 +02001175
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001176 if (!size) {
1177 return NULL;
1178 }
Radek Krejci106efc02015-06-10 14:36:27 +02001179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001180 new = calloc(size, sizeof *new);
1181 for (i = 0; i < size; i++) {
1182 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1183 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1184 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1185 new[i].flags = old[i].flags;
Michal Vasko591e0b22015-08-13 13:53:43 +02001186 new[i].nodetype = old[i].nodetype;
1187 /* .target = NULL */
Radek Krejci106efc02015-06-10 14:36:27 +02001188
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001189 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001190
Michal Vasko41de7352015-08-06 09:53:34 +02001191 /* copy the augment nodes */
1192 assert(old[i].child);
1193 LY_TREE_FOR(old[i].child, snode) {
Radek Krejci10c760e2015-08-14 14:45:43 +02001194 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 +02001195 for ( ; i >= 0; i--) {
1196 lys_augment_free(module->ctx, new[i]);
1197 }
1198 free(new);
1199 return NULL;
1200 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001201 }
1202 }
Radek Krejci106efc02015-06-10 14:36:27 +02001203
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001204 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001205}
1206
Radek Krejci76512572015-08-04 09:47:08 +02001207static struct lys_refine *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001208lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size, struct lys_node_uses *uses,
Michal Vaskof02e3742015-08-05 16:27:02 +02001209 struct unres_schema *unres)
Michal Vasko1982cad2015-06-08 15:49:30 +02001210{
Radek Krejci76512572015-08-04 09:47:08 +02001211 struct lys_refine *result;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001212 int i, j;
Michal Vasko1982cad2015-06-08 15:49:30 +02001213
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001214 if (!size) {
1215 return NULL;
1216 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001217
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001218 result = calloc(size, sizeof *result);
1219 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001220 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001221 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1222 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001223 result[i].flags = old[i].flags;
1224 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001225
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001226 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001227 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001228 for (j = 0; j < result[i].must_size; ++j) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001229 unres_add_node(mod, unres, &result[i].must[j], UNRES_MUST, (struct lys_node *)uses, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001230 }
1231
Radek Krejci76512572015-08-04 09:47:08 +02001232 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001233 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001234 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001235 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001236 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001237 result[i].mod.list = old[i].mod.list;
1238 }
1239 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001240
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001241 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001242}
1243
Radek Krejci1d82ef62015-08-07 14:44:40 +02001244static void
1245lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001246{
Radek Krejcia52656e2015-08-05 13:41:50 +02001247 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001248
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001249 assert(ctx);
1250 if (!ident) {
1251 return;
1252 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001253
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001254 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001255 * if caller free only a single data model which is used (its identity is
1256 * reference from identity in another module), this silly freeing can lead
1257 * to segmentation fault. But without noting if the module is used by some
1258 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001259 *
1260 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001261 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001262 */
1263 while (ident->der) {
1264 der = ident->der;
1265 ident->der = der->next;
1266 free(der);
1267 }
Radek Krejci6793db02015-05-22 17:49:54 +02001268
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001269 lydict_remove(ctx, ident->name);
1270 lydict_remove(ctx, ident->dsc);
1271 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001272
1273}
1274
Radek Krejci1d82ef62015-08-07 14:44:40 +02001275static void
1276lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001277{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001278 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001279
Radek Krejcid12f57b2015-08-06 10:43:39 +02001280 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001281 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001282 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001283 }
1284 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001285}
1286
Radek Krejci1d82ef62015-08-07 14:44:40 +02001287static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001288lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1289{
1290 int i;
1291
1292 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1293 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001294 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001295 }
1296 free(io->tpdf);
1297}
1298
Radek Krejci1d82ef62015-08-07 14:44:40 +02001299static void
1300lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001301{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001302 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001303
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001304 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001305 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001306 }
1307 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001308
Radek Krejci1d82ef62015-08-07 14:44:40 +02001309 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001310}
1311
Radek Krejci1d82ef62015-08-07 14:44:40 +02001312static void
1313lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001314{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001315 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001316
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001317 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001318 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001319 }
1320 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001321
Radek Krejci1d82ef62015-08-07 14:44:40 +02001322 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001323
Radek Krejci1d82ef62015-08-07 14:44:40 +02001324 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001325 lydict_remove(ctx, leaf->units);
1326 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001327}
1328
Radek Krejci1d82ef62015-08-07 14:44:40 +02001329static void
1330lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001331{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001332 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001333
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001334 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001335 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001336 }
1337 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001338
Radek Krejci1d82ef62015-08-07 14:44:40 +02001339 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001340
Radek Krejci1d82ef62015-08-07 14:44:40 +02001341 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001342 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001343}
1344
Radek Krejci1d82ef62015-08-07 14:44:40 +02001345static void
1346lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001347{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001348 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001349
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001350 /* handle only specific parts for LY_NODE_LIST */
1351 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001352 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001353 }
1354 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001355
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001356 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001357 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001358 }
1359 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001360
Radek Krejci1d82ef62015-08-07 14:44:40 +02001361 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001362
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001363 for (i = 0; i < list->unique_size; i++) {
1364 free(list->unique[i].leafs);
1365 }
1366 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001367
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001368 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001369}
1370
Radek Krejci1d82ef62015-08-07 14:44:40 +02001371static void
1372lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001373{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001374 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001375
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001376 /* handle only specific parts for LY_NODE_CONTAINER */
1377 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001378
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001379 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001380 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001381 }
1382 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001383
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001384 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001385 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001386 }
1387 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001388
Radek Krejci1d82ef62015-08-07 14:44:40 +02001389 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001390}
1391
Radek Krejci1d82ef62015-08-07 14:44:40 +02001392static void
1393lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001394{
1395 lydict_remove(ctx, f->name);
1396 lydict_remove(ctx, f->dsc);
1397 lydict_remove(ctx, f->ref);
1398 free(f->features);
1399}
1400
Radek Krejci1d82ef62015-08-07 14:44:40 +02001401static void
1402lys_deviation_free(struct ly_ctx *ctx, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001403{
1404 int i, j;
1405
1406 lydict_remove(ctx, dev->target_name);
1407 lydict_remove(ctx, dev->dsc);
1408 lydict_remove(ctx, dev->ref);
1409
1410 for (i = 0; i < dev->deviate_size; i++) {
1411 lydict_remove(ctx, dev->deviate[i].dflt);
1412 lydict_remove(ctx, dev->deviate[i].units);
1413
1414 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1415 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001416 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001417 }
1418 free(dev->deviate[i].must);
1419
1420 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1421 free(dev->deviate[j].unique[j].leafs);
1422 }
1423 free(dev->deviate[i].unique);
1424 }
1425 }
1426 free(dev->deviate);
1427}
1428
Radek Krejci1d82ef62015-08-07 14:44:40 +02001429static void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001430lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +02001431{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001432 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001433
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001434 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001435 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001436 lydict_remove(ctx, uses->refine[i].dsc);
1437 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001438
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001439 for (j = 0; j < uses->refine[j].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001440 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001441 }
1442 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001443
Radek Krejci76512572015-08-04 09:47:08 +02001444 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001445 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001446 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001447 lydict_remove(ctx, uses->refine[i].mod.presence);
1448 }
1449 }
1450 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001451
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001452 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001453 lys_augment_free(ctx, uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001454 }
1455 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001456
Radek Krejci1d82ef62015-08-07 14:44:40 +02001457 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001458}
1459
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001460void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001461lys_node_free(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001462{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001463 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001464 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001465
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001466 if (!node) {
1467 return;
1468 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001469
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001470 assert(node->module);
1471 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001472
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001473 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001474
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001475 /* common part */
1476 LY_TREE_FOR_SAFE(node->child, next, sub) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001477 lys_node_free(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001478 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001479
Radek Krejcid12f57b2015-08-06 10:43:39 +02001480 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1481 free(node->features);
1482 lydict_remove(ctx, node->name);
1483 lydict_remove(ctx, node->dsc);
1484 lydict_remove(ctx, node->ref);
1485 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001486
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001487 /* specific part */
1488 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001489 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001490 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001491 break;
Radek Krejci76512572015-08-04 09:47:08 +02001492 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001493 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001494 break;
Radek Krejci76512572015-08-04 09:47:08 +02001495 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001496 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001497 break;
Radek Krejci76512572015-08-04 09:47:08 +02001498 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001499 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001500 break;
Radek Krejci76512572015-08-04 09:47:08 +02001501 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001502 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001503 break;
Radek Krejci76512572015-08-04 09:47:08 +02001504 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001505 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001506 break;
Radek Krejci76512572015-08-04 09:47:08 +02001507 case LYS_USES:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001508 lys_uses_free(ctx, (struct lys_node_uses *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001509 break;
Radek Krejci76512572015-08-04 09:47:08 +02001510 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001511 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001512 break;
Radek Krejci76512572015-08-04 09:47:08 +02001513 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001514 /* do nothing */
1515 break;
Radek Krejci76512572015-08-04 09:47:08 +02001516 case LYS_GROUPING:
1517 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001518 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001519 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001520 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001521
1522 case LYS_INPUT:
1523 case LYS_OUTPUT:
1524 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1525 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001526 case LYS_UNKNOWN:
1527 LOGINT;
1528 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001529 }
Radek Krejci5a065542015-05-22 15:02:07 +02001530
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001531 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001532 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001533 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001534}
1535
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001536static void
Radek Krejcib8048692015-08-05 13:36:34 +02001537module_free_common(struct lys_module *module)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001538{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001539 struct ly_ctx *ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001540 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001541 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001542
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001543 assert(module->ctx);
1544 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001545
Radek Krejcidce51452015-06-16 15:20:08 +02001546 /* as first step, free the imported modules */
1547 for (i = 0; i < module->imp_size; i++) {
1548 /* get the imported module from the context and then free,
1549 * this check is necessary because the imported module can
1550 * be already removed
1551 */
1552 l = ctx->models.used;
1553 for (j = 0; j < l; j++) {
1554 if (ctx->models.list[j] == module->imp[i].module) {
Radek Krejci912da452015-07-29 14:10:06 +02001555 lys_free(module->imp[i].module);
Radek Krejcidce51452015-06-16 15:20:08 +02001556 break;
1557 }
1558 }
1559 }
1560 free(module->imp);
1561
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001562 while (module->data) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001563 lys_node_free(module->data);
Radek Krejci21181962015-06-30 14:11:00 +02001564 }
1565 while (module->rpc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001566 lys_node_free(module->rpc);
Radek Krejci21181962015-06-30 14:11:00 +02001567 }
1568 while (module->notif) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001569 lys_node_free(module->notif);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001570 }
Radek Krejci5a065542015-05-22 15:02:07 +02001571
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001572 lydict_remove(ctx, module->dsc);
1573 lydict_remove(ctx, module->ref);
1574 lydict_remove(ctx, module->org);
1575 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001576
Radek Krejcieb00f512015-07-01 16:44:58 +02001577 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001578 for (i = 0; i < module->rev_size; i++) {
1579 lydict_remove(ctx, module->rev[i].dsc);
1580 lydict_remove(ctx, module->rev[i].ref);
1581 }
1582 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001583
Radek Krejcieb00f512015-07-01 16:44:58 +02001584 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001585 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001586 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001587 }
1588 module->ident_size = 0;
1589 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001590
Radek Krejcieb00f512015-07-01 16:44:58 +02001591 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001592 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001593 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001594 }
1595 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001596
Radek Krejcieb00f512015-07-01 16:44:58 +02001597 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001598 for (i = 0; i < module->inc_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001599 lys_submodule_free(module->inc[i].submodule);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001600 }
1601 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001602
Radek Krejcieb00f512015-07-01 16:44:58 +02001603 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02001604 for (i = 0; i < module->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001605 lys_augment_free(ctx, module->augment[i]);
Radek Krejcif5be10f2015-06-16 13:29:36 +02001606 }
1607 free(module->augment);
1608
Radek Krejcieb00f512015-07-01 16:44:58 +02001609 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001610 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001611 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001612 }
1613 free(module->features);
1614
Radek Krejcieb00f512015-07-01 16:44:58 +02001615 /* deviations */
1616 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001617 lys_deviation_free(ctx, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001618 }
1619 free(module->deviation);
1620
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001621 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02001622}
1623
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001624void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001625lys_submodule_free(struct lys_submodule *submodule)
Radek Krejciefaeba32015-05-27 14:30:57 +02001626{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001627 if (!submodule) {
1628 return;
1629 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001630
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001631 submodule->inc_size = 0;
1632 free(submodule->inc);
1633 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02001634
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001635 /* common part with struct ly_module */
Radek Krejcib8048692015-08-05 13:36:34 +02001636 module_free_common((struct lys_module *)submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001638 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02001639
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001640 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001641}
1642
Radek Krejcib8048692015-08-05 13:36:34 +02001643static struct lys_node_leaf *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001644lys_uniq_find(struct lys_node_list *list, struct lys_node_leaf *orig_leaf)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001645{
Radek Krejci1d82ef62015-08-07 14:44:40 +02001646 struct lys_node *node, *node2, *ret = NULL, *parent1, *parent2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001647 int depth = 1, i;
1648
1649 /* find the correct direct descendant of list in orig_leaf */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001650 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001651 while (1) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001652 if (!node->parent) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001653 return NULL;
1654 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001655 if (!strcmp(node->parent->name, list->name)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001656 break;
1657 }
1658
Radek Krejci1d82ef62015-08-07 14:44:40 +02001659 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001660 ++depth;
1661 }
1662
1663 /* make sure the nodes are equal */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001664 parent1 = node->parent->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001665 parent2 = list->parent;
1666 while (1) {
1667 if ((parent1 && !parent2) || (!parent1 && parent2)) {
1668 return NULL;
1669 }
1670
1671 if (parent1 == parent2) {
1672 break;
1673 }
1674
1675 parent1 = parent1->parent;
1676 parent2 = parent2->parent;
1677 }
1678
1679 /* find the descendant in the list */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001680 LY_TREE_FOR(list->child, node2) {
1681 if (!strcmp(node2->name, node->name)) {
1682 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001683 break;
1684 }
1685 }
1686
1687 if (!ret) {
1688 return NULL;
1689 }
1690
1691 /* continue traversing both trees, the nodes are always truly equal */
1692 while (1) {
1693 --depth;
1694 if (!depth) {
Radek Krejci76512572015-08-04 09:47:08 +02001695 if (ret->nodetype != LYS_LEAF) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001696 return NULL;
1697 }
Radek Krejcib8048692015-08-05 13:36:34 +02001698 return (struct lys_node_leaf *)ret;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001699 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001700 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001701 for (i = 0; i < depth-1; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001702 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001703 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001704 LY_TREE_FOR(ret->child, node2) {
1705 if (!strcmp(node2->name, node->name)) {
1706 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001707 break;
1708 }
1709 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001710 if (!node2) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001711 return NULL;
1712 }
1713 }
1714}
1715
Radek Krejci76512572015-08-04 09:47:08 +02001716struct lys_node *
Michal Vasko71e1aa82015-08-12 12:17:51 +02001717lys_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 +02001718 struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001719{
Radek Krejci76512572015-08-04 09:47:08 +02001720 struct lys_node *retval = NULL, *aux, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001721 struct ly_ctx *ctx = module->ctx;
1722 int i, j;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001723
Michal Vaskoc07187d2015-08-13 15:20:57 +02001724 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001725 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001726 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001727 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001728 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001729 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001730 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001731 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001732 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001733 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001734 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001735 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001736 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001737 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001738 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001739 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001740 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001741 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001742 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001743 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001744 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001745 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001746 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001747 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001748
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001749 /* we cannot just duplicate memory since the strings are stored in
1750 * dictionary and we need to update dictionary counters.
1751 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001752
Radek Krejci1d82ef62015-08-07 14:44:40 +02001753 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001754 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001755 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02001756 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001757 break;
1758
Radek Krejci76512572015-08-04 09:47:08 +02001759 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001760 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02001761 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001762 break;
1763
Radek Krejci76512572015-08-04 09:47:08 +02001764 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001765 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02001766 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001767 break;
1768
Radek Krejci76512572015-08-04 09:47:08 +02001769 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001770 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02001771 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001772 break;
1773
Radek Krejci76512572015-08-04 09:47:08 +02001774 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001775 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02001776 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001777 break;
1778
Radek Krejci76512572015-08-04 09:47:08 +02001779 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001780 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02001781 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001782 break;
1783
Radek Krejci76512572015-08-04 09:47:08 +02001784 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001785 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02001786 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001787 break;
1788
Radek Krejci76512572015-08-04 09:47:08 +02001789 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001790 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02001791 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001792 break;
1793
Radek Krejci76512572015-08-04 09:47:08 +02001794 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001795 grp = calloc(1, sizeof *grp);
1796 retval = (struct lys_node *)grp;
1797 break;
1798
Radek Krejci76512572015-08-04 09:47:08 +02001799 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001800 rpc = calloc(1, sizeof *rpc);
1801 retval = (struct lys_node *)rpc;
1802 break;
1803
Radek Krejci76512572015-08-04 09:47:08 +02001804 case LYS_INPUT:
1805 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001806 io = calloc(1, sizeof *io);
1807 retval = (struct lys_node *)io;
1808 break;
1809
Radek Krejci76512572015-08-04 09:47:08 +02001810 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001811 ntf = calloc(1, sizeof *ntf);
1812 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02001813 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001814
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001815 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02001816 LOGINT;
1817 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001818 }
Radek Krejcib388c152015-06-04 17:03:03 +02001819
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001820 /*
1821 * duplicate generic part of the structure
1822 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001823 retval->name = lydict_insert(ctx, node->name, 0);
1824 retval->dsc = lydict_insert(ctx, node->dsc, 0);
1825 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02001826 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001827 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001828 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001829 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001830 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001831 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001832
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001833 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001834 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001835
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001836 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001837
Radek Krejci1d82ef62015-08-07 14:44:40 +02001838 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001839 retval->features = calloc(retval->features_size, sizeof *retval->features);
Radek Krejci1d82ef62015-08-07 14:44:40 +02001840 for (i = 0; i < node->features_size; ++i) {
1841 if (unres_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
1842 retval->features[i] = node->features[i];
Michal Vaskod23ce592015-08-06 09:55:37 +02001843 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001844 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001845
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001846 if (recursive) {
1847 /* go recursively */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001848 LY_TREE_FOR(node->child, child) {
Michal Vasko71e1aa82015-08-12 12:17:51 +02001849 aux = lys_node_dup(module, child, retval->flags, retval->nacm, 1, unres);
Radek Krejci10c760e2015-08-14 14:45:43 +02001850 if (!aux || lys_node_addchild(retval, NULL, aux)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02001851 LOGINT;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001852 lys_node_free(retval);
Michal Vaskod23ce592015-08-06 09:55:37 +02001853 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001854 }
1855 }
1856 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001857
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001858 /*
1859 * duplicate specific part of the structure
1860 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001861 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001862 case LYS_CONTAINER:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001863 if (cont_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001864 cont->when = lys_when_dup(ctx, cont_orig->when);
1865 unres_add_node(module, unres, cont->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001866 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001867 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001868
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001869 cont->must_size = cont_orig->must_size;
1870 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001871
Radek Krejci1d82ef62015-08-07 14:44:40 +02001872 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001873 for (i = 0; i < cont->must_size; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001874 unres_add_node(module, unres, &cont->must[i], UNRES_MUST, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001875 }
1876
Radek Krejci1d82ef62015-08-07 14:44:40 +02001877 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001878 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001879
Radek Krejci76512572015-08-04 09:47:08 +02001880 case LYS_CHOICE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001881 if (choice_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001882 choice->when = lys_when_dup(ctx, choice_orig->when);
1883 unres_add_node(module, unres, choice->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001884 }
1885
1886 if (choice_orig->dflt) {
Michal Vasko58090902015-08-13 14:04:15 +02001887 choice->dflt = resolve_sibling(choice->module, choice->child, NULL, 0, choice_orig->dflt->name, 0, LYS_ANYXML
Radek Krejci76512572015-08-04 09:47:08 +02001888 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
1889 | LYS_LIST);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001890 assert(choice->dflt);
1891 } else {
Michal Vaskoc68a2a22015-08-06 09:57:24 +02001892 /* useless to check return value, we don't know whether
1893 * there really wasn't any default defined or it just hasn't
1894 * been resolved, we just hope for the best :)
1895 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001896 unres_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001897 }
1898 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001899
Radek Krejci76512572015-08-04 09:47:08 +02001900 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001901 lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001902 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
1903
1904 if (leaf_orig->dflt) {
1905 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci1d82ef62015-08-07 14:44:40 +02001906 unres_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001907 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001908
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001909 leaf->must_size = leaf_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001910 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001911 for (i = 0; i < leaf->must_size; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001912 unres_add_node(module, unres, &leaf->must[i], UNRES_MUST, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001913 }
Radek Krejci00768f42015-06-18 17:04:04 +02001914
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001915 if (leaf_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001916 leaf->when = lys_when_dup(ctx, leaf_orig->when);
1917 unres_add_node(module, unres, leaf->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001918 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001919 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001920
Radek Krejci76512572015-08-04 09:47:08 +02001921 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001922 lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001923 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001924
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001925 llist->min = llist_orig->min;
1926 llist->max = llist_orig->max;
1927
1928 llist->must_size = llist_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001929 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001930 for (i = 0; i < llist->must_size; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001931 unres_add_node(module, unres, &llist->must[i], UNRES_MUST, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001932 }
Radek Krejci00768f42015-06-18 17:04:04 +02001933
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001934 if (llist_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001935 llist->when = lys_when_dup(ctx, llist_orig->when);
1936 unres_add_node(module, unres, llist->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001937 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001938 break;
1939
Radek Krejci76512572015-08-04 09:47:08 +02001940 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001941 list->min = list_orig->min;
1942 list->max = list_orig->max;
1943
1944 list->must_size = list_orig->must_size;
1945 list->tpdf_size = list_orig->tpdf_size;
1946 list->keys_size = list_orig->keys_size;
1947 list->unique_size = list_orig->unique_size;
1948
Radek Krejci1d82ef62015-08-07 14:44:40 +02001949 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001950 for (i = 0; i < list->must_size; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001951 unres_add_node(module, unres, &list->must[i], UNRES_MUST, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001952 }
1953
Radek Krejci1d82ef62015-08-07 14:44:40 +02001954 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001955
1956 if (list->keys_size) {
1957 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001958
1959 /* we managed to resolve it before, resolve it again manually */
1960 if (list_orig->keys[0]) {
1961 for (i = 0; i < list->keys_size; ++i) {
Michal Vasko58090902015-08-13 14:04:15 +02001962 list->keys[i] = (struct lys_node_leaf *)resolve_sibling(list->module, list->child, NULL, 0,
Radek Krejci76512572015-08-04 09:47:08 +02001963 list_orig->keys[i]->name, 0, LYS_LEAF);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001964 assert(list->keys[i]);
1965 }
1966 /* it was not resolved yet, add unres copy */
1967 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001968 if (unres_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02001969 LOGINT;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001970 lys_node_free(retval);
Michal Vaskod23ce592015-08-06 09:55:37 +02001971 return NULL;
1972 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001973 }
1974 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001975
1976 list->unique = calloc(list->unique_size, sizeof *list->unique);
1977 if (list_orig->unique) {
1978 for (i = 0; i < list->unique_size; ++i) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001979 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
1980 for (j = 0; j < list->unique[i].leafs_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001981 list->unique[i].leafs[j] = lys_uniq_find(list, list_orig->unique[i].leafs[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001982 }
1983 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001984 } else {
1985 for (i = 0; i < list->unique_size; ++i) {
1986 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02001987 list->unique[i].leafs = (struct lys_node_leaf **)list;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001988 unres_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001989 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001990 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001991
1992 if (list_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001993 list->when = lys_when_dup(ctx, list_orig->when);
1994 unres_add_node(module, unres, list->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001995 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001996 break;
1997
Radek Krejci76512572015-08-04 09:47:08 +02001998 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001999 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002000 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002001 for (i = 0; i < anyxml->must_size; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002002 unres_add_node(module, unres, &anyxml->must[i], UNRES_MUST, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002003 }
2004
2005 if (anyxml_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002006 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
2007 unres_add_node(module, unres, anyxml->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002008 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002009 break;
2010
Radek Krejci76512572015-08-04 09:47:08 +02002011 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002012 uses->grp = uses_orig->grp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002013
2014 if (uses_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002015 uses->when = lys_when_dup(ctx, uses_orig->when);
2016 unres_add_node(module, unres, uses->when, UNRES_WHEN, (struct lys_node *)uses, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002017 }
2018
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002019 uses->refine_size = uses_orig->refine_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002020 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size, uses, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002021 uses->augment_size = uses_orig->augment_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002022 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 +02002023 if (!uses->child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002024 unres_add_node(module, unres, uses, UNRES_USES, NULL, 0);
Michal Vaskof8c128d2015-08-06 15:25:28 +02002025 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002026 break;
2027
Radek Krejci76512572015-08-04 09:47:08 +02002028 case LYS_CASE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002029 if (cs_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002030 cs->when = lys_when_dup(ctx, cs_orig->when);
2031 unres_add_node(module, unres, cs->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002032 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002033 break;
2034
Radek Krejci76512572015-08-04 09:47:08 +02002035 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002036 grp->tpdf_size = grp_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002037 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002038 break;
2039
Radek Krejci76512572015-08-04 09:47:08 +02002040 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002041 rpc->tpdf_size = rpc_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002042 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002043 break;
2044
Radek Krejci76512572015-08-04 09:47:08 +02002045 case LYS_INPUT:
2046 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002047 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002048 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002049 break;
2050
Radek Krejci76512572015-08-04 09:47:08 +02002051 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002052 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002053 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcia01e5432015-06-16 10:35:25 +02002054 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002055
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002056 default:
Radek Krejci00768f42015-06-18 17:04:04 +02002057 /* LY_NODE_AUGMENT */
Michal Vaskod23ce592015-08-06 09:55:37 +02002058 LOGINT;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002059 lys_node_free(retval);
Michal Vaskod23ce592015-08-06 09:55:37 +02002060 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002061 }
2062
2063 return retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002064}
2065
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002066API void
Radek Krejcib8048692015-08-05 13:36:34 +02002067lys_free(struct lys_module *module)
Radek Krejciefaeba32015-05-27 14:30:57 +02002068{
Radek Krejcidce51452015-06-16 15:20:08 +02002069 struct ly_ctx *ctx;
2070 int i;
2071
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002072 if (!module) {
2073 return;
2074 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002075
Radek Krejcidce51452015-06-16 15:20:08 +02002076 /* remove schema from the context */
2077 ctx = module->ctx;
2078 if (ctx->models.used) {
2079 for (i = 0; i < ctx->models.used; i++) {
2080 if (ctx->models.list[i] == module) {
2081 /* replace the position in the list by the last module in the list */
2082 ctx->models.used--;
2083 ctx->models.list[i] = ctx->models.list[ctx->models.used];
2084 ctx->models.list[ctx->models.used] = NULL;
2085 /* we are done */
2086 break;
2087 }
2088 }
2089 }
2090
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002091 /* common part with struct ly_submodule */
2092 module_free_common(module);
Radek Krejciefaeba32015-05-27 14:30:57 +02002093
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002094 /* specific items to free */
2095 lydict_remove(module->ctx, module->ns);
2096 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02002097
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002098 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002099}
Radek Krejci7e97c352015-06-19 16:26:34 +02002100
2101/*
2102 * op: 1 - enable, 0 - disable
2103 */
2104static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002105lys_features_change(struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002106{
2107 int all = 0;
2108 int i, j, k;
2109
2110 if (!module || !name || !strlen(name)) {
2111 return EXIT_FAILURE;
2112 }
2113
2114 if (!strcmp(name, "*")) {
2115 /* enable all */
2116 all = 1;
2117 }
2118
2119 /* module itself */
2120 for (i = 0; i < module->features_size; i++) {
2121 if (all || !strcmp(module->features[i].name, name)) {
2122 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002123 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002124 /* enable referenced features (recursion) */
2125 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002126 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002127 module->features[i].features[k]->name, op);
2128 }
2129 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002130 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002131 }
2132 if (!all) {
2133 return EXIT_SUCCESS;
2134 }
2135 }
2136 }
2137
2138 /* submodules */
2139 for (j = 0; j < module->inc_size; j++) {
2140 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2141 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2142 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002143 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002144 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002145 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002146 }
2147 if (!all) {
2148 return EXIT_SUCCESS;
2149 }
2150 }
2151 }
2152 }
2153
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002154 /* TODO submodules of submodules ... */
2155
Radek Krejci7e97c352015-06-19 16:26:34 +02002156 if (all) {
2157 return EXIT_SUCCESS;
2158 } else {
2159 return EXIT_FAILURE;
2160 }
2161}
2162
2163API int
Radek Krejcib8048692015-08-05 13:36:34 +02002164lys_features_enable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002165{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002166 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002167}
2168
2169API int
Radek Krejcib8048692015-08-05 13:36:34 +02002170lys_features_disable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002171{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002172 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002173}
2174
2175API int
Radek Krejcib8048692015-08-05 13:36:34 +02002176lys_features_state(struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002177{
2178 int i, j;
2179
2180 if (!module || !feature) {
2181 return -1;
2182 }
2183
2184 /* search for the specified feature */
2185 /* module itself */
2186 for (i = 0; i < module->features_size; i++) {
2187 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002188 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002189 return 1;
2190 } else {
2191 return 0;
2192 }
2193 }
2194 }
2195
2196 /* submodules */
2197 for (j = 0; j < module->inc_size; j++) {
2198 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2199 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002200 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002201 return 1;
2202 } else {
2203 return 0;
2204 }
2205 }
2206 }
2207 }
2208
2209 /* TODO submodules of submodules ... */
2210
2211 /* feature definition not found */
2212 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002213}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002214
Radek Krejci96a10da2015-07-30 11:00:14 +02002215API const char **
Radek Krejcib8048692015-08-05 13:36:34 +02002216lys_features_list(struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002217{
Radek Krejci96a10da2015-07-30 11:00:14 +02002218 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002219 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002220 unsigned int count;
2221
2222 if (!module) {
2223 return NULL;
2224 }
2225
2226 count = module->features_size;
2227 for (i = 0; i < module->inc_size; i++) {
2228 count += module->inc[i].submodule->features_size;
2229 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002230 result = malloc((count + 1) * sizeof *result);
2231 if (states) {
2232 *states = malloc((count + 1) * sizeof **states);
Michal Vasko2367e7c2015-07-07 11:33:44 +02002233 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002234 count = 0;
2235
2236 /* module itself */
2237 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002238 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002239 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002240 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002241 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002242 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002243 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002244 }
2245 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002246 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002247 }
2248
2249 /* submodules */
2250 for (j = 0; j < module->inc_size; j++) {
2251 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002252 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002253 if (states) {
2254 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2255 (*states)[count] = 1;
2256 } else {
2257 (*states)[count] = 0;
2258 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002259 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002260 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002261 }
2262 }
2263
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002264 /* TODO submodules of submodules ... */
2265
2266 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002267 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002268
2269 return result;
2270}
Radek Krejcib20c62d2015-07-07 17:07:14 +02002271
2272API struct lyd_node *
Radek Krejci25b9fd32015-08-10 15:06:07 +02002273lyd_parse(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
Radek Krejcib20c62d2015-07-07 17:07:14 +02002274{
2275 if (!ctx || !data) {
2276 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2277 return NULL;
2278 }
2279
2280 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02002281 case LYD_XML:
Radek Krejci25b9fd32015-08-10 15:06:07 +02002282 return xml_read_data(ctx, data, options);
Radek Krejcia9167ef2015-08-03 11:01:11 +02002283 case LYD_JSON:
Radek Krejcib20c62d2015-07-07 17:07:14 +02002284 default:
2285 /* TODO */
2286 return NULL;
2287 }
2288
2289 return NULL;
2290}
2291
Radek Krejci0e1d1a62015-07-31 11:17:01 +02002292API void
Radek Krejci912da452015-07-29 14:10:06 +02002293lyd_free(struct lyd_node *node)
Radek Krejcib20c62d2015-07-07 17:07:14 +02002294{
2295 struct lyd_node *next, *child;
2296
Radek Krejci52f791c2015-07-15 11:14:17 +02002297 if (!node) {
2298 return;
2299 }
2300
Radek Krejci76512572015-08-04 09:47:08 +02002301 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
Radek Krejcie4748472015-07-08 18:00:22 +02002302 /* free children */
2303 LY_TREE_FOR_SAFE(node->child, next, child) {
Radek Krejci912da452015-07-29 14:10:06 +02002304 lyd_free(child);
Radek Krejcie4748472015-07-08 18:00:22 +02002305 }
Radek Krejci76512572015-08-04 09:47:08 +02002306 } else if (node->schema->nodetype == LYS_ANYXML) {
Radek Krejci9566b092015-07-31 11:18:15 +02002307 lyxml_free_elem(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
Radek Krejcie4748472015-07-08 18:00:22 +02002308 } else {
2309 /* free value */
2310 switch(((struct lyd_node_leaf *)node)->value_type) {
2311 case LY_TYPE_BINARY:
2312 case LY_TYPE_STRING:
2313 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf *)node)->value.string);
2314 break;
Radek Krejci3e3affe2015-07-09 15:38:40 +02002315 case LY_TYPE_BITS:
2316 if (((struct lyd_node_leaf *)node)->value.bit) {
2317 free(((struct lyd_node_leaf *)node)->value.bit);
2318 }
2319 break;
Radek Krejcie4748472015-07-08 18:00:22 +02002320 default:
Radek Krejci7511f402015-07-10 09:56:30 +02002321 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
Radek Krejcie4748472015-07-08 18:00:22 +02002322 break;
2323 }
Radek Krejcib20c62d2015-07-07 17:07:14 +02002324 }
2325
2326 if (node->prev->next) {
2327 node->prev->next = node->next;
2328 } else if (node->parent) {
2329 /* first node */
2330 node->parent->child = node->next;
2331 }
2332 if (node->next) {
2333 node->next->prev = node->prev;
2334 }
2335
2336 free(node);
2337}
Michal Vaskof54f2f82015-07-17 13:12:05 +02002338
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002339API int
Radek Krejci9566b092015-07-31 11:18:15 +02002340lyd_is_last(struct lyd_node *node)
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002341{
2342 struct lyd_node *n;
2343
2344 if (!node->next) {
2345 return 1;
2346 }
2347
2348 for (n = node->next; n; n = n->next) {
2349 switch (n->schema->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002350 case LYS_LIST:
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002351 if (!((struct lyd_node_list *)n)->lprev) {
2352 return 0;
2353 }
2354 break;
Radek Krejci76512572015-08-04 09:47:08 +02002355 case LYS_LEAFLIST:
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002356 if (!((struct lyd_node_leaflist *)n)->lprev) {
2357 return 0;
2358 }
2359 break;
2360 default:
2361 return 0;
2362 }
2363 }
2364 return 1;
2365}