blob: 21bdca36d6e3ce24a21cd6e7be286a6b4b703186 [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
2 * @file tree.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Manipulation with libyang data structures
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020021#define _GNU_SOURCE
Radek Krejcida04f4a2015-05-21 12:54:09 +020022
Radek Krejci812b10a2015-05-28 16:48:25 +020023#include <assert.h>
Radek Krejci5a988152015-07-15 11:16:26 +020024#include <ctype.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020025#include <stdlib.h>
26#include <sys/mman.h>
27#include <sys/stat.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020028#include <string.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020029
30#include "common.h"
31#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020032#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020033#include "resolve.h"
Radek Krejci106efc02015-06-10 14:36:27 +020034#include "xml.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020035#include "tree_internal.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020036
Michal Vaskoa76ee152015-08-17 15:38:22 +020037static const struct internal_modules int_mods = {
38 .modules = {
39 {"ietf-yang-types", "2013-07-15"},
40 {"ietf-inet-types", "2013-07-15"},
41 {"ietf-yang-library", "2015-07-03"}
42 },
43 .count = LY_INTERNAL_MODULE_COUNT
44};
45
Radek Krejci48061fb2015-08-05 15:41:07 +020046API struct lys_feature *
47lys_is_disabled(struct lys_node *node, int recursive)
48{
49 int i;
50
51check:
52 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
53 /* input/output does not have if-feature, so skip them */
54
55 /* check local if-features */
56 for (i = 0; i < node->features_size; i++) {
57 if (!(node->features[i]->flags & LYS_FENABLED)) {
58 return node->features[i];
59 }
60 }
61 }
62
63 if (!recursive) {
64 return NULL;
65 }
66
67 /* go through parents */
68 if (node->nodetype == LYS_AUGMENT) {
69 /* go to parent actually means go to the target node */
70 node = ((struct lys_node_augment *)node)->target;
Radek Krejci48061fb2015-08-05 15:41:07 +020071 } else if (node->parent) {
72 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020073 } else {
74 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020075 }
76
Radek Krejci074bf852015-08-19 14:22:16 +020077 if (recursive == 2) {
78 /* continue only if the node cannot have a data instance */
79 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
80 return NULL;
81 }
82 }
83 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020084}
85
Radek Krejci7f40ce32015-08-12 20:38:46 +020086static struct lys_node *
87check_mand_getnext(struct lys_node *cur, struct lys_node *parent)
88{
89 struct lys_node *next;
90
91 if (!cur) {
92 next = parent->child;
Radek Krejci14a11a62015-08-17 17:27:38 +020093 cur = next;
Radek Krejci7f40ce32015-08-12 20:38:46 +020094 } else {
95 next = cur->next;
96 }
97
98repeat:
Radek Krejci14a11a62015-08-17 17:27:38 +020099 while (next && (next->nodetype & (LYS_AUGMENT | LYS_GROUPING))) {
100 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200101 }
102
103 while (!next) {
104 if (cur->parent == parent) {
105 /* no next element */
106 return NULL;
107 }
108 cur = cur->parent;
109 next = cur->next;
110 goto repeat;
111 }
112
113 switch (next->nodetype) {
114 case LYS_CONTAINER:
115 if (((struct lys_node_container *)next)->presence) {
116 /* mandatory elements under the non-existing presence
117 * container are not mandatory - 7.6.5, rule 1 */
118 next = next->next;
119 goto repeat;
120 }
121 /* no break */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200122 case LYS_USES:
123 case LYS_CASE:
124 /* go into */
125 next = next->child;
126 goto repeat;
127 case LYS_LEAF:
128 case LYS_CHOICE:
129 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200130 case LYS_LIST:
131 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200132 return next;
133 default:
134 /* we should not be here */
135 return NULL;
136 }
137}
138
139static struct lys_node *
140check_mand_check(struct lys_node *node, struct lys_node *stop, struct lyd_node *data)
141{
142 struct lys_node *siter = NULL, *parent;
143 struct lyd_node *diter = NULL;
Radek Krejci14a11a62015-08-17 17:27:38 +0200144 uint32_t minmax;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200145
146 if (node->flags & LYS_MAND_TRUE) {
147 switch (node->nodetype) {
148 case LYS_LEAF:
149 case LYS_ANYXML:
150 case LYS_CHOICE:
151 if (node->parent->nodetype == LYS_CASE) {
152 /* 7.6.5, rule 2 */
153 /* 7.9.4, rule 1 */
154 if (node->parent->parent->parent == data->schema) {
155 /* the only case the node's siblings can exist is that the
156 * data node passed originaly to ly_check_mandatory()
157 * had this choice as a child
158 */
159 /* try to find the node's siblings in data */
160 LY_TREE_FOR(data->child, diter) {
161 LY_TREE_FOR(node->parent->child, siter) {
162 if (siter == diter->schema) {
163 /* some sibling exists, rule applies */
164 break;
165 }
166 }
167 if (siter) {
168 break;
169 }
170 }
171 }
172 if (!siter) {
173 /* no sibling exists */
174 return NULL;
175 }
176 } else {
177 for(parent = node->parent; parent != stop; parent = parent->parent) {
178 if (parent->nodetype != LYS_CONTAINER) {
179 /* 7.6.5, rule 1, checking presence is not needed
180 * since it is done in check_mand_getnext()
181 */
182 return NULL;
183 }
184 }
185 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200186
187 /* search for instance */
188 LY_TREE_FOR(data->child, diter) {
189 if (diter->schema == node) {
190 return NULL;
191 }
192 }
193 /* instance not found */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200194 /* 7.6.5, rule 3 (or 2) */
195 /* 7.9.4, rule 2 */
196 return node;
197 default:
198 /* error */
199 break;
200 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200201 } else if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
202 /* search for number of instances */
203 minmax = 0;
204 LY_TREE_FOR(data->child, diter) {
205 if (diter->schema == node) {
206 minmax++;
207 }
208 }
209
210 /* check the specified constraints */
211 if (node->nodetype == LYS_LIST) {
212 if (((struct lys_node_list *)node)->min && minmax < ((struct lys_node_list *)node)->min) {
213 return node;
214 }
215
216 if (((struct lys_node_list *)node)->max && minmax > ((struct lys_node_list *)node)->max) {
217 return node;
218 }
219 } else if (node->nodetype == LYS_LEAFLIST) {
220 if (((struct lys_node_leaflist *)node)->min && minmax < ((struct lys_node_leaflist *)node)->min) {
221 return node;
222 }
223
224 if (((struct lys_node_leaflist *)node)->max && minmax > ((struct lys_node_leaflist *)node)->max) {
225 return node;
226 }
227 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200228 }
229
230 return NULL;
231}
232
233struct lys_node *
234ly_check_mandatory(struct lyd_node *data)
235{
Radek Krejci14a11a62015-08-17 17:27:38 +0200236 struct lys_node *siter, *saux, *saux2, *result, *parent = NULL, *parent2;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200237 struct lyd_node *diter;
238 int found;
239
240 siter = data->schema->child;
241
242repeat:
243 while (siter) {
Radek Krejci074bf852015-08-19 14:22:16 +0200244 if (lys_is_disabled(siter, 2)) {
245 siter = siter->next;
246 continue;
247 }
248
Radek Krejci7f40ce32015-08-12 20:38:46 +0200249 switch (siter->nodetype) {
250 case LYS_CONTAINER:
251 case LYS_LEAF:
252 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200253 case LYS_LIST:
254 case LYS_LEAFLIST:
255 /* check if there is some mandatory node; first test the siter itself ... */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200256 result = check_mand_check(siter, siter->parent, data);
257 if (result) {
258 return result;
259 }
260 /* ... and then the subtree */
Radek Krejci14a11a62015-08-17 17:27:38 +0200261 if (parent && siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
262 saux = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200263 while ((saux = check_mand_getnext(saux, siter))) {
264 result = check_mand_check(saux, siter, data);
265 if (result) {
266 return result;
267 }
268 }
269 }
270 siter = siter->next;
271 break;
272 case LYS_CHOICE:
Radek Krejci14a11a62015-08-17 17:27:38 +0200273 /* search for instance */
274 saux = siter;
275 siter = siter->child;
276 found = 0;
277 parent2 = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200278repeat_choice:
Radek Krejci074bf852015-08-19 14:22:16 +0200279 while (siter) {
280 if (lys_is_disabled(siter, 2)) {
281 siter = siter->next;
282 continue;
283 }
284
Radek Krejci14a11a62015-08-17 17:27:38 +0200285 switch (siter->nodetype) {
286 case LYS_CONTAINER:
287 case LYS_LEAF:
288 case LYS_LEAFLIST:
289 case LYS_LIST:
290 case LYS_ANYXML:
291 LY_TREE_FOR(data->child, diter) {
292 if (diter->schema == siter) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200293 break;
294 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200295 }
296 if (diter) {
297 /* got instance */
298 /* check presence of mandatory siblings */
299 if (siter->parent->nodetype == LYS_CASE) {
300 saux2 = NULL;
301 while ((saux2 = check_mand_getnext(saux2, siter->parent))) {
302 result = check_mand_check(saux2, siter->parent, data);
303 if (result) {
304 return result;
305 }
306 }
307 }
308 siter = parent2 = NULL;
309 found = 1;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200310 break;
311 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200312 siter = siter->next;
313 break;
314 case LYS_CASE:
315 case LYS_CHOICE:
316 case LYS_USES:
317 /* go into */
318 parent2 = siter;
319 siter = siter->child;
320 break;
321 case LYS_AUGMENT:
322 case LYS_GROUPING:
323 /* skip */
324 siter = siter->next;
325 break;
326 default:
327 /* error */
328 break;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200329 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200330 }
331
Radek Krejci14a11a62015-08-17 17:27:38 +0200332 if (parent2) {
333 siter = parent2->next;
334 if (parent2->parent == saux) {
335 parent2 = NULL;
336 } else {
337 parent2 = parent2->parent;
338 }
339 goto repeat_choice;
340 }
341
Radek Krejci074bf852015-08-19 14:22:16 +0200342 if (!found && (saux->flags & LYS_MAND_TRUE)) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200343 return saux;
344 }
345
346 /* go to next */
347 siter = saux->next;
348
Radek Krejci7f40ce32015-08-12 20:38:46 +0200349 break;
350 case LYS_USES:
351 case LYS_CASE:
352 /* go into */
353 parent = siter;
354 siter = siter->child;
355 break;
356 default:
357 /* can ignore, go to next */
358 siter = siter->next;
359 break;
360 }
361 }
362
363 if (parent) {
364 siter = parent->next;
365 if (parent->parent == data->schema) {
366 parent = NULL;
367 } else {
368 parent = parent->parent;
369 }
370 goto repeat;
371 }
372
373 return NULL;
374}
375
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200376void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200377lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200378{
Radek Krejci76512572015-08-04 09:47:08 +0200379 struct lys_node *parent, *first;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200380
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200381 if (!node) {
382 return;
383 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200384
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200385 /* unlink from data model if necessary */
386 if (node->module) {
387 if (node->module->data == node) {
388 node->module->data = node->next;
Radek Krejci21181962015-06-30 14:11:00 +0200389 } else if (node->module->rpc == node) {
390 node->module->rpc = node->next;
391 } else if (node->module->notif == node) {
392 node->module->notif = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200393 }
394 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200395
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200396 /* store pointers to important nodes */
397 parent = node->parent;
398 if (parent && !parent->nodetype) {
399 /* handle augments - first, unlink it from the augment parent ... */
400 if (parent->child == node) {
401 parent->child = node->next;
402 }
403 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200404 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200405 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200406
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200407 /* unlink from parent */
408 if (parent) {
409 if (parent->child == node) {
410 parent->child = node->next;
411 }
412 node->parent = NULL;
413 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200414
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200415 /* unlink from siblings */
416 if (node->prev == node) {
417 /* there are no more siblings */
418 return;
419 }
420 if (node->next) {
421 node->next->prev = node->prev;
422 } else {
423 /* unlinking the last element */
424 if (parent) {
425 first = parent->child;
426 } else {
427 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200428 while (first->prev->next) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200429 first = node->prev;
430 }
431 }
432 first->prev = node->prev;
433 }
434 if (node->prev->next) {
435 node->prev->next = node->next;
436 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200437
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200438 /* clean up the unlinked element */
439 node->next = NULL;
440 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200441}
442
Radek Krejci10c760e2015-08-14 14:45:43 +0200443/*
444 * get next grouping in the root's subtree, in the
445 * first call, tha last is NULL
446 */
447static struct lys_node_grp *
448lys_get_next_grouping(struct lys_node_grp* lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200449{
Radek Krejci10c760e2015-08-14 14:45:43 +0200450 struct lys_node *last = (struct lys_node *)lastgrp;
451 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200452
Radek Krejci10c760e2015-08-14 14:45:43 +0200453 assert(root);
454
455 if (!last) {
456 last = root;
457 }
458
459 while (1) {
460 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
461 next = last->child;
462 } else {
463 next = NULL;
464 }
465 if (!next) {
466 if (last == root) {
467 /* we are done */
468 return NULL;
469 }
470
471 /* no children, go to siblings */
472 next = last->next;
473 }
474 while (!next) {
475 /* go back through parents */
476 if (last->parent == root) {
477 /* we are done */
478 return NULL;
479 }
480 last = last->parent;
481 next = last->next;
482 }
483
484 if (next->nodetype == LYS_GROUPING) {
485 return (struct lys_node_grp *)next;
486 }
487
488 last = next;
489 }
490}
491
492int
Radek Krejci07911992015-08-14 15:13:31 +0200493lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
494{
495 struct lys_node *start, *stop, *par_iter, *iter;
496 struct lys_node_grp *grp;
497 int down;
498
499 assert(node);
500
501 if (!parent) {
502 assert(module);
503 } else {
504 module = parent->module;
505 }
506
507 switch (node->nodetype) {
508 case LYS_GROUPING:
509 /* 6.2.1, rule 6 */
510 if (parent) {
511 if (parent->child) {
512 down = 1;
513 start = parent->child;
514 } else {
515 down = 0;
516 start = parent;
517 }
518 } else {
519 down = 1;
520 start = module->data;
521 }
522 /* go up */
523 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
524 if (par_iter->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES)) {
525 continue;
526 }
527
528 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
529 if (!stop) {
530 stop = par_iter;
531 } else if (iter == stop) {
532 break;
533 }
534 if (iter->nodetype != LYS_GROUPING) {
535 continue;
536 }
537
538 if (node->name == iter->name) {
539 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
540 return EXIT_FAILURE;
541 }
542 }
543 }
544 /* go down, because grouping can be defined after e.g. container in which is collision */
545 if (down) {
546 for (iter = start, stop = NULL; iter; iter = iter->prev) {
547 if (!stop) {
548 stop = start;
549 } else if (iter == stop) {
550 break;
551 }
552 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
553 continue;
554 }
555
556 grp = NULL;
557 while ((grp = lys_get_next_grouping(grp, iter))) {
558 if (node->name == grp->name) {
559 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
560 return EXIT_FAILURE;
561 }
562 }
563 }
564 }
565 break;
566 case LYS_LEAF:
567 case LYS_LEAFLIST:
568 case LYS_LIST:
569 case LYS_CONTAINER:
570 case LYS_CHOICE:
571 case LYS_ANYXML:
572 /* 6.2.1, rule 7 */
573 if (parent) {
574 iter = parent;
575 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE))) {
576 iter = iter->parent;
577 }
578 if (!iter) {
579 stop = NULL;
580 iter = module->data;
581 } else {
582 stop = iter;
583 iter = iter->child;
584 }
585 } else {
586 stop = NULL;
587 iter = module->data;
588 }
589 while (iter) {
590 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
591 iter = iter->child;
592 continue;
593 }
594
595 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
596 if (iter->module == node->module && iter->name == node->name) {
597 LOGVAL(LYE_SPEC, 0, "Duplicated child identifier \"%s\" in \"%s\".", node->name,
598 stop ? stop->name : "(sub)module");
599 return EXIT_FAILURE;
600 }
601 }
602
603 /* special case for choice - we must check the choice's name as
604 * well as the names of nodes under the choice
605 */
606 if (iter->nodetype == LYS_CHOICE) {
607 iter = iter->child;
608 continue;
609 }
610
611 /* go to siblings */
612 if (!iter->next) {
613 /* no sibling, go to parent's sibling */
614 do {
615 iter = iter->parent;
616 if (iter && iter->next) {
617 break;
618 }
619 } while (iter != stop);
620
621 if (iter == stop) {
622 break;
623 }
624 }
625 iter = iter->next;
626 }
627 break;
628 case LYS_CASE:
629 /* 6.2.1, rule 8 */
630 LY_TREE_FOR(parent->child, iter) {
631 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
632 continue;
633 }
634
635 if (iter->module == node->module && iter->name == node->name) {
636 LOGVAL(LYE_DUPID, 0, "case", node->name);
637 return EXIT_FAILURE;
638 }
639 }
640 break;
641 default:
642 /* no check needed */
643 break;
644 }
645
646 return EXIT_SUCCESS;
647}
648
649int
Radek Krejci10c760e2015-08-14 14:45:43 +0200650lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
651{
Radek Krejci07911992015-08-14 15:13:31 +0200652 struct lys_node *iter, **trg = NULL;
653 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200654
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200655 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200656
Radek Krejci10c760e2015-08-14 14:45:43 +0200657 if (parent) {
658 type = parent->nodetype;
659 module = parent->module;
660 } else {
661 assert(module);
662 type = 0;
Radek Krejcic7459c62015-08-17 10:15:12 +0200663 if (child->nodetype == LYS_NOTIF) {
664 trg = &module->notif;
665 } else if (child->nodetype == LYS_RPC) {
666 trg = &module->rpc;
667 } else {
668 trg = &module->data;
669 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200670 }
671
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200672 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200673 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200674 case LYS_CONTAINER:
675 case LYS_LIST:
676 case LYS_GROUPING:
677 case LYS_USES:
678 case LYS_INPUT:
679 case LYS_OUTPUT:
680 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200681 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200682 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
683 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200684 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200685 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
686 return EXIT_FAILURE;
687 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200688
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200689 break;
Radek Krejci76512572015-08-04 09:47:08 +0200690 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200691 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200692 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200693 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"choice\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200694 strnodetype(child->nodetype), parent->name);
695 return EXIT_FAILURE;
696 }
697 break;
Radek Krejci76512572015-08-04 09:47:08 +0200698 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200699 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200700 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200701 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"case\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200702 strnodetype(child->nodetype), parent->name);
703 return EXIT_FAILURE;
704 }
705 break;
Radek Krejci76512572015-08-04 09:47:08 +0200706 case LYS_RPC:
707 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200708 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"rpc\" %s.",
Michal Vasko38d01f72015-06-15 09:41:06 +0200709 strnodetype(child->nodetype), parent->name);
710 return EXIT_FAILURE;
711 }
712 break;
Radek Krejci76512572015-08-04 09:47:08 +0200713 case LYS_LEAF:
714 case LYS_LEAFLIST:
715 case LYS_ANYXML:
Radek Krejci10c760e2015-08-14 14:45:43 +0200716 LOGVAL(LYE_SPEC, 0, "The \"%s\" statement (%s) cannot have any data substatement.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200717 strnodetype(parent->nodetype), parent->name);
718 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200719 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200720 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200721 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
722 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200723 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200724 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
725 return EXIT_FAILURE;
726 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200727 break;
728 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200729 /* top level */
730 if (!(child->nodetype &
731 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
732 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci2c0ca272015-08-14 15:31:01 +0200733 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in (sub)module \"%s\"",
734 strnodetype(child->nodetype), module->name);
Radek Krejci10c760e2015-08-14 14:45:43 +0200735 return EXIT_FAILURE;
736 }
737
738 break;;
739 }
740
741 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200742 if (lys_check_id(child, parent, module)) {
743 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200744 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200746 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200747 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200748 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200749
Radek Krejci10c760e2015-08-14 14:45:43 +0200750 if (!parent) {
751 if (*trg) {
752 (*trg)->prev->next = child;
753 child->prev = (*trg)->prev;
754 (*trg)->prev = child;
755 } else {
756 (*trg) = child;
757 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200758 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +0200759 if (!parent->child) {
760 /* the only/first child of the parent */
761 parent->child = child;
762 child->parent = parent;
763 iter = child;
764 } else {
765 /* add a new child at the end of parent's child list */
766 iter = parent->child->prev;
767 iter->next = child;
768 child->prev = iter;
769 }
770 while (iter->next) {
771 iter = iter->next;
772 iter->parent = parent;
773 }
774 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200775 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200776
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200777 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200778}
779
Radek Krejcib8048692015-08-05 13:36:34 +0200780API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +0200781lys_parse(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200782{
Michal Vaskof02e3742015-08-05 16:27:02 +0200783 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200784 struct lys_module *mod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200785
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200786 if (!ctx || !data) {
787 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
788 return NULL;
789 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200790
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200791 unres = calloc(1, sizeof *unres);
792
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200793 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200794 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200795 mod = yin_read_module(ctx, data, 1, unres);
796 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200797 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200798 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +0200799 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200800 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200801 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200802
Radek Krejci0b5805d2015-08-13 09:38:02 +0200803 if (mod && unres->count && resolve_unres(mod, unres)) {
Michal Vasko13b15832015-08-19 11:04:48 +0200804 lys_free(mod, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200805 mod = NULL;
806 }
807 free(unres->item);
808 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +0200809 free(unres->str_snode);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200810#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200811 free(unres->line);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200812#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200813 free(unres);
814
815 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200816}
817
Radek Krejcib8048692015-08-05 13:36:34 +0200818struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +0200819lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +0200820{
Michal Vaskof02e3742015-08-05 16:27:02 +0200821 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200822 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200823
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200824 assert(module);
825 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200826
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200827 unres = calloc(1, sizeof *unres);
828
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200829 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200830 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200831 submod = yin_read_submodule(module, data, implement, unres);
832 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200833 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200834 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +0200835 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200836 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200837 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200838
Radek Krejci0b5805d2015-08-13 09:38:02 +0200839 if (submod && unres->count && resolve_unres((struct lys_module *)submod, unres)) {
Michal Vasko13b15832015-08-19 11:04:48 +0200840 lys_submodule_free(submod, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200841 submod = NULL;
842 }
843 free(unres->item);
844 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +0200845 free(unres->str_snode);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200846#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200847 free(unres->line);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200848#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200849 free(unres);
850
851 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +0200852}
853
Radek Krejcib8048692015-08-05 13:36:34 +0200854API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +0200855lys_read(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +0200856{
Radek Krejcib8048692015-08-05 13:36:34 +0200857 struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +0200858 struct stat sb;
859 char *addr;
860
861 if (!ctx || fd < 0) {
862 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
863 return NULL;
864 }
865
866 /*
867 * TODO
868 * This is just a temporary solution to make working automatic search for
869 * imported modules. This doesn't work e.g. for streams (stdin)
870 */
871 fstat(fd, &sb);
872 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
873 module = lys_parse(ctx, addr, format);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200874 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200875
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200876 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200877}
878
Radek Krejcib8048692015-08-05 13:36:34 +0200879struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +0200880lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +0200881{
Radek Krejcib8048692015-08-05 13:36:34 +0200882 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200883 struct stat sb;
884 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +0200885
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200886 assert(module);
887 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +0200888
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200889 /*
890 * TODO
891 * This is just a temporary solution to make working automatic search for
892 * imported modules. This doesn't work e.g. for streams (stdin)
893 */
894 fstat(fd, &sb);
895 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
896 /* TODO addr error check */
Radek Krejci1d82ef62015-08-07 14:44:40 +0200897 submodule = lys_submodule_parse(module, addr, format, implement);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200898 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +0200899
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200900 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +0200901
902}
903
Radek Krejci1d82ef62015-08-07 14:44:40 +0200904static struct lys_restr *
905lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200906{
Radek Krejci1574a8d2015-08-03 14:16:52 +0200907 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200908 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200909
Radek Krejci3733a802015-06-19 13:43:21 +0200910 if (!size) {
911 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200912 }
Radek Krejci3733a802015-06-19 13:43:21 +0200913
914 result = calloc(size, sizeof *result);
915 for (i = 0; i < size; i++) {
916 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
917 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
918 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
919 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
920 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
921 }
922
923 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200924}
925
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200926void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200927lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +0200928{
929 assert(ctx);
930 if (!restr) {
931 return;
932 }
933
934 lydict_remove(ctx, restr->expr);
935 lydict_remove(ctx, restr->dsc);
936 lydict_remove(ctx, restr->ref);
937 lydict_remove(ctx, restr->eapptag);
938 lydict_remove(ctx, restr->emsg);
939}
940
Radek Krejci1d82ef62015-08-07 14:44:40 +0200941static void
942lys_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 +0200943 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +0200944{
945 int i;
946
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200947 new->prefix = lydict_insert(mod->ctx, old->prefix, 0);
Radek Krejci3733a802015-06-19 13:43:21 +0200948 new->base = old->base;
949 new->der = old->der;
950
Radek Krejci1d82ef62015-08-07 14:44:40 +0200951 i = unres_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200952 if (i != -1) {
953 /* HACK for unres */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200954 new->der = (struct lys_tpdf *)parent;
Michal Vasko49168a22015-08-17 16:35:41 +0200955 if (unres_add_str(mod, unres, new, UNRES_TYPE_DER, unres->str_snode[i], 0) == -1) {
956 LOGINT;
957 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200958 return;
959 }
960
Radek Krejci3733a802015-06-19 13:43:21 +0200961 switch (new->base) {
962 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +0200963 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200964 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +0200965 }
Radek Krejci3733a802015-06-19 13:43:21 +0200966 break;
967
968 case LY_TYPE_BITS:
969 new->info.bits.count = old->info.bits.count;
970 if (new->info.bits.count) {
971 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
972 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200973 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
974 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
975 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Radek Krejci3733a802015-06-19 13:43:21 +0200976 new->info.bits.bit[i].status = old->info.bits.bit[i].status;
977 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
978 }
979 }
980 break;
981
Radek Krejcif9401c32015-06-26 16:47:36 +0200982 case LY_TYPE_DEC64:
983 new->info.dec64.dig = old->info.dec64.dig;
984 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200985 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +0200986 }
987 break;
988
Radek Krejci3733a802015-06-19 13:43:21 +0200989 case LY_TYPE_ENUM:
990 new->info.enums.count = old->info.enums.count;
991 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200992 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Radek Krejci3733a802015-06-19 13:43:21 +0200993 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200994 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
995 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
996 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
997 new->info.enums.enm[i].status = old->info.enums.enm[i].status;
998 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +0200999 }
1000 }
1001 break;
1002
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001003 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001004 if (old->info.ident.ref) {
1005 new->info.ident.ref = old->info.ident.ref;
1006 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001007 i = unres_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001008 assert(i != -1);
Michal Vasko49168a22015-08-17 16:35:41 +02001009 if (unres_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i], 0) == -1) {
1010 LOGINT;
1011 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001012 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001013 break;
1014
Radek Krejciaf351422015-06-19 14:49:38 +02001015 case LY_TYPE_INST:
1016 new->info.inst.req = old->info.inst.req;
1017 break;
1018
Radek Krejcif2860132015-06-20 12:37:20 +02001019 case LY_TYPE_INT8:
1020 case LY_TYPE_INT16:
1021 case LY_TYPE_INT32:
1022 case LY_TYPE_INT64:
1023 case LY_TYPE_UINT8:
1024 case LY_TYPE_UINT16:
1025 case LY_TYPE_UINT32:
1026 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +02001027 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001028 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001029 }
Radek Krejcif2860132015-06-20 12:37:20 +02001030 break;
1031
Radek Krejcidc4c1412015-06-19 15:39:54 +02001032 case LY_TYPE_LEAFREF:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001033 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02001034 if (unres_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0) == -1) {
1035 LOGINT;
1036 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001037 break;
1038
Radek Krejci3733a802015-06-19 13:43:21 +02001039 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +02001040 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001041 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001042 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001043 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 +02001044 break;
1045
Radek Krejcie4c366b2015-07-02 10:11:31 +02001046 case LY_TYPE_UNION:
1047 new->info.uni.count = old->info.uni.count;
1048 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001049 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001050 for (i = 0; i < new->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001051 lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001052 }
1053 }
1054 break;
1055
Radek Krejci3733a802015-06-19 13:43:21 +02001056 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001057 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001058 break;
1059 }
1060}
1061
1062void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001063lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001064{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001065 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001066
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001067 assert(ctx);
1068 if (!type) {
1069 return;
1070 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001071
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001072 lydict_remove(ctx, type->prefix);
Radek Krejci5a065542015-05-22 15:02:07 +02001073
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001074 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001075 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001076 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001077 free(type->info.binary.length);
1078 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001079 case LY_TYPE_BITS:
1080 for (i = 0; i < type->info.bits.count; i++) {
1081 lydict_remove(ctx, type->info.bits.bit[i].name);
1082 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1083 lydict_remove(ctx, type->info.bits.bit[i].ref);
1084 }
1085 free(type->info.bits.bit);
1086 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001087
1088 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001089 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001090 free(type->info.dec64.range);
1091 break;
1092
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001093 case LY_TYPE_ENUM:
1094 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001095 lydict_remove(ctx, type->info.enums.enm[i].name);
1096 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1097 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001098 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001099 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001100 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001101
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001102 case LY_TYPE_INT8:
1103 case LY_TYPE_INT16:
1104 case LY_TYPE_INT32:
1105 case LY_TYPE_INT64:
1106 case LY_TYPE_UINT8:
1107 case LY_TYPE_UINT16:
1108 case LY_TYPE_UINT32:
1109 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001110 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001111 free(type->info.num.range);
1112 break;
1113
Radek Krejcidc4c1412015-06-19 15:39:54 +02001114 case LY_TYPE_LEAFREF:
1115 lydict_remove(ctx, type->info.lref.path);
1116 break;
1117
Radek Krejci3733a802015-06-19 13:43:21 +02001118 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001119 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001120 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001121 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001122 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001123 }
1124 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001125 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001126
Radek Krejcie4c366b2015-07-02 10:11:31 +02001127 case LY_TYPE_UNION:
1128 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001129 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001130 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001131 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001132 break;
1133
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001134 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001135 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001136 break;
1137 }
Radek Krejci5a065542015-05-22 15:02:07 +02001138}
1139
Radek Krejci1d82ef62015-08-07 14:44:40 +02001140static struct lys_tpdf *
1141lys_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 +02001142{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001143 struct lys_tpdf *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001144 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001145
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001146 if (!size) {
1147 return NULL;
1148 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001150 result = calloc(size, sizeof *result);
1151 for (i = 0; i < size; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001152 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1153 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1154 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001155 result[i].flags = old[i].flags;
1156 result[i].module = old[i].module;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001157
Radek Krejci1d82ef62015-08-07 14:44:40 +02001158 lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001159
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001160 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1161 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001162 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001163
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001164 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001165}
1166
Radek Krejci1d82ef62015-08-07 14:44:40 +02001167static void
1168lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001169{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001170 assert(ctx);
1171 if (!tpdf) {
1172 return;
1173 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001174
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001175 lydict_remove(ctx, tpdf->name);
1176 lydict_remove(ctx, tpdf->dsc);
1177 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001178
Radek Krejci1d82ef62015-08-07 14:44:40 +02001179 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001180
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001181 lydict_remove(ctx, tpdf->units);
1182 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001183}
1184
Radek Krejci1d82ef62015-08-07 14:44:40 +02001185static struct lys_when *
1186lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001187{
Radek Krejci76512572015-08-04 09:47:08 +02001188 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001189
1190 if (!old) {
1191 return NULL;
1192 }
1193
1194 new = calloc(1, sizeof *new);
1195 new->cond = lydict_insert(ctx, old->cond, 0);
1196 new->dsc = lydict_insert(ctx, old->dsc, 0);
1197 new->ref = lydict_insert(ctx, old->ref, 0);
1198
1199 return new;
1200}
1201
Radek Krejci1d82ef62015-08-07 14:44:40 +02001202static void
1203lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001204{
1205 if (!w) {
1206 return;
1207 }
1208
1209 lydict_remove(ctx, w->cond);
1210 lydict_remove(ctx, w->dsc);
1211 lydict_remove(ctx, w->ref);
1212
1213 free(w);
1214}
1215
Radek Krejcib7f5e412015-08-13 10:15:51 +02001216static void
1217lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment aug)
1218{
Radek Krejcib7f5e412015-08-13 10:15:51 +02001219 lydict_remove(ctx, aug.target_name);
1220 lydict_remove(ctx, aug.dsc);
1221 lydict_remove(ctx, aug.ref);
1222
1223 free(aug.features);
1224
1225 lys_when_free(ctx, aug.when);
1226
Michal Vasko84f52f12015-08-19 15:06:31 +02001227 /* Do not free the children, they were appended somewhere and their
1228 * new parent will take care of them.
1229 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001230}
1231
Radek Krejci76512572015-08-04 09:47:08 +02001232static struct lys_node_augment *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001233lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size,
Michal Vasko41de7352015-08-06 09:53:34 +02001234 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001235{
Radek Krejci76512572015-08-04 09:47:08 +02001236 struct lys_node_augment *new = NULL;
Michal Vasko41de7352015-08-06 09:53:34 +02001237 struct lys_node *snode;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001238 int i = -1;
Radek Krejci106efc02015-06-10 14:36:27 +02001239
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001240 if (!size) {
1241 return NULL;
1242 }
Radek Krejci106efc02015-06-10 14:36:27 +02001243
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001244 new = calloc(size, sizeof *new);
1245 for (i = 0; i < size; i++) {
1246 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1247 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1248 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1249 new[i].flags = old[i].flags;
Michal Vasko591e0b22015-08-13 13:53:43 +02001250 new[i].nodetype = old[i].nodetype;
1251 /* .target = NULL */
Radek Krejci106efc02015-06-10 14:36:27 +02001252
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001253 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001254
Michal Vasko41de7352015-08-06 09:53:34 +02001255 /* copy the augment nodes */
1256 assert(old[i].child);
1257 LY_TREE_FOR(old[i].child, snode) {
Radek Krejci10c760e2015-08-14 14:45:43 +02001258 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 +02001259 for ( ; i >= 0; i--) {
1260 lys_augment_free(module->ctx, new[i]);
1261 }
1262 free(new);
1263 return NULL;
1264 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001265 }
1266 }
Radek Krejci106efc02015-06-10 14:36:27 +02001267
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001268 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001269}
1270
Radek Krejci76512572015-08-04 09:47:08 +02001271static struct lys_refine *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001272lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size, struct lys_node_uses *uses,
Michal Vaskof02e3742015-08-05 16:27:02 +02001273 struct unres_schema *unres)
Michal Vasko1982cad2015-06-08 15:49:30 +02001274{
Radek Krejci76512572015-08-04 09:47:08 +02001275 struct lys_refine *result;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001276 int i, j;
Michal Vasko1982cad2015-06-08 15:49:30 +02001277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001278 if (!size) {
1279 return NULL;
1280 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001281
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001282 result = calloc(size, sizeof *result);
1283 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001284 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001285 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1286 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001287 result[i].flags = old[i].flags;
1288 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001289
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001290 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001291 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001292 for (j = 0; j < result[i].must_size; ++j) {
Michal Vasko49168a22015-08-17 16:35:41 +02001293 if (unres_add_node(mod, unres, &result[i].must[j], UNRES_MUST, (struct lys_node *)uses, 0) == -1) {
1294 free(result);
1295 return NULL;
1296 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001297 }
1298
Radek Krejci76512572015-08-04 09:47:08 +02001299 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001300 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001301 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001302 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001303 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001304 result[i].mod.list = old[i].mod.list;
1305 }
1306 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001307
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001308 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001309}
1310
Radek Krejci1d82ef62015-08-07 14:44:40 +02001311static void
1312lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001313{
Radek Krejcia52656e2015-08-05 13:41:50 +02001314 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001315
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001316 assert(ctx);
1317 if (!ident) {
1318 return;
1319 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001320
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001321 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001322 * if caller free only a single data model which is used (its identity is
1323 * reference from identity in another module), this silly freeing can lead
1324 * to segmentation fault. But without noting if the module is used by some
1325 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001326 *
1327 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001328 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001329 */
1330 while (ident->der) {
1331 der = ident->der;
1332 ident->der = der->next;
1333 free(der);
1334 }
Radek Krejci6793db02015-05-22 17:49:54 +02001335
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001336 lydict_remove(ctx, ident->name);
1337 lydict_remove(ctx, ident->dsc);
1338 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001339
1340}
1341
Radek Krejci1d82ef62015-08-07 14:44:40 +02001342static void
1343lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001344{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001345 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001346
Radek Krejcid12f57b2015-08-06 10:43:39 +02001347 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001348 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001349 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001350 }
1351 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001352}
1353
Radek Krejci1d82ef62015-08-07 14:44:40 +02001354static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001355lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1356{
1357 int i;
1358
1359 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1360 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001361 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001362 }
1363 free(io->tpdf);
1364}
1365
Radek Krejci1d82ef62015-08-07 14:44:40 +02001366static void
1367lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001368{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001369 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001370
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001371 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001372 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001373 }
1374 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001375
Radek Krejci1d82ef62015-08-07 14:44:40 +02001376 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001377}
1378
Radek Krejci1d82ef62015-08-07 14:44:40 +02001379static void
1380lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001381{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001382 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001383
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001384 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001385 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001386 }
1387 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001388
Radek Krejci1d82ef62015-08-07 14:44:40 +02001389 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001390
Radek Krejci1d82ef62015-08-07 14:44:40 +02001391 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001392 lydict_remove(ctx, leaf->units);
1393 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001394}
1395
Radek Krejci1d82ef62015-08-07 14:44:40 +02001396static void
1397lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001398{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001399 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001401 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001402 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001403 }
1404 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001405
Radek Krejci1d82ef62015-08-07 14:44:40 +02001406 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001407
Radek Krejci1d82ef62015-08-07 14:44:40 +02001408 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001409 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001410}
1411
Radek Krejci1d82ef62015-08-07 14:44:40 +02001412static void
1413lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001414{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001415 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001416
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001417 /* handle only specific parts for LY_NODE_LIST */
1418 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001419 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001420 }
1421 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001422
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001423 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001424 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001425 }
1426 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001427
Radek Krejci1d82ef62015-08-07 14:44:40 +02001428 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001429
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001430 for (i = 0; i < list->unique_size; i++) {
1431 free(list->unique[i].leafs);
1432 }
1433 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001434
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001435 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001436}
1437
Radek Krejci1d82ef62015-08-07 14:44:40 +02001438static void
1439lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001440{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001441 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001442
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001443 /* handle only specific parts for LY_NODE_CONTAINER */
1444 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001445
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001446 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001447 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001448 }
1449 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001450
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001451 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001452 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001453 }
1454 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001455
Radek Krejci1d82ef62015-08-07 14:44:40 +02001456 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001457}
1458
Radek Krejci1d82ef62015-08-07 14:44:40 +02001459static void
1460lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001461{
1462 lydict_remove(ctx, f->name);
1463 lydict_remove(ctx, f->dsc);
1464 lydict_remove(ctx, f->ref);
1465 free(f->features);
1466}
1467
Radek Krejci1d82ef62015-08-07 14:44:40 +02001468static void
1469lys_deviation_free(struct ly_ctx *ctx, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001470{
1471 int i, j;
1472
1473 lydict_remove(ctx, dev->target_name);
1474 lydict_remove(ctx, dev->dsc);
1475 lydict_remove(ctx, dev->ref);
1476
1477 for (i = 0; i < dev->deviate_size; i++) {
1478 lydict_remove(ctx, dev->deviate[i].dflt);
1479 lydict_remove(ctx, dev->deviate[i].units);
1480
1481 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1482 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001483 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001484 }
1485 free(dev->deviate[i].must);
1486
1487 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1488 free(dev->deviate[j].unique[j].leafs);
1489 }
1490 free(dev->deviate[i].unique);
1491 }
1492 }
1493 free(dev->deviate);
1494}
1495
Radek Krejci1d82ef62015-08-07 14:44:40 +02001496static void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001497lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +02001498{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001499 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001500
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001501 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001502 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001503 lydict_remove(ctx, uses->refine[i].dsc);
1504 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001505
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001506 for (j = 0; j < uses->refine[j].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001507 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001508 }
1509 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001510
Radek Krejci76512572015-08-04 09:47:08 +02001511 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001512 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001513 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001514 lydict_remove(ctx, uses->refine[i].mod.presence);
1515 }
1516 }
1517 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001518
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001519 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001520 lys_augment_free(ctx, uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001521 }
1522 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001523
Radek Krejci1d82ef62015-08-07 14:44:40 +02001524 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001525}
1526
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001527void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001528lys_node_free(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001529{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001530 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001531 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001532
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001533 if (!node) {
1534 return;
1535 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001537 assert(node->module);
1538 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001539
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001540 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001541
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001542 /* common part */
1543 LY_TREE_FOR_SAFE(node->child, next, sub) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001544 lys_node_free(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001545 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001546
Radek Krejcid12f57b2015-08-06 10:43:39 +02001547 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1548 free(node->features);
1549 lydict_remove(ctx, node->name);
1550 lydict_remove(ctx, node->dsc);
1551 lydict_remove(ctx, node->ref);
1552 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001553
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001554 /* specific part */
1555 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001556 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001557 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001558 break;
Radek Krejci76512572015-08-04 09:47:08 +02001559 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001560 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001561 break;
Radek Krejci76512572015-08-04 09:47:08 +02001562 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001563 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001564 break;
Radek Krejci76512572015-08-04 09:47:08 +02001565 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001566 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001567 break;
Radek Krejci76512572015-08-04 09:47:08 +02001568 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001569 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001570 break;
Radek Krejci76512572015-08-04 09:47:08 +02001571 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001572 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001573 break;
Radek Krejci76512572015-08-04 09:47:08 +02001574 case LYS_USES:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001575 lys_uses_free(ctx, (struct lys_node_uses *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001576 break;
Radek Krejci76512572015-08-04 09:47:08 +02001577 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001578 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001579 break;
Radek Krejci76512572015-08-04 09:47:08 +02001580 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001581 /* do nothing */
1582 break;
Radek Krejci76512572015-08-04 09:47:08 +02001583 case LYS_GROUPING:
1584 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001585 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001586 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001587 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001588
1589 case LYS_INPUT:
1590 case LYS_OUTPUT:
1591 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1592 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001593 case LYS_UNKNOWN:
1594 LOGINT;
1595 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001596 }
Radek Krejci5a065542015-05-22 15:02:07 +02001597
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001598 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001599 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001600 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001601}
1602
Michal Vasko13b15832015-08-19 11:04:48 +02001603/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001604static void
Michal Vasko13b15832015-08-19 11:04:48 +02001605module_free_common(struct lys_module *module, int free_int_mods)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001606{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001607 struct ly_ctx *ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001608 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001609 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001610
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001611 assert(module->ctx);
1612 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001613
Radek Krejcidce51452015-06-16 15:20:08 +02001614 /* as first step, free the imported modules */
1615 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa76ee152015-08-17 15:38:22 +02001616 /* do not free internal modules */
Michal Vaskoddde94f2015-08-19 15:07:00 +02001617 if (!free_int_mods) {
1618 for (j = 0; j < int_mods.count; ++j) {
1619 if (!strcmp(int_mods.modules[j].name, module->imp[i].module->name)
1620 && module->imp[i].module->rev
1621 && !strcmp(int_mods.modules[j].revision, module->imp[i].module->rev[0].date)) {
1622 break;
1623 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02001624 }
Michal Vaskoddde94f2015-08-19 15:07:00 +02001625 if (j < int_mods.count) {
1626 continue;
1627 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02001628 }
1629
Radek Krejcidce51452015-06-16 15:20:08 +02001630 /* get the imported module from the context and then free,
1631 * this check is necessary because the imported module can
1632 * be already removed
1633 */
1634 l = ctx->models.used;
1635 for (j = 0; j < l; j++) {
1636 if (ctx->models.list[j] == module->imp[i].module) {
Michal Vasko13b15832015-08-19 11:04:48 +02001637 lys_free(module->imp[i].module, free_int_mods);
Radek Krejcidce51452015-06-16 15:20:08 +02001638 break;
1639 }
1640 }
1641 }
1642 free(module->imp);
1643
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001644 while (module->data) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001645 lys_node_free(module->data);
Radek Krejci21181962015-06-30 14:11:00 +02001646 }
1647 while (module->rpc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001648 lys_node_free(module->rpc);
Radek Krejci21181962015-06-30 14:11:00 +02001649 }
1650 while (module->notif) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001651 lys_node_free(module->notif);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001652 }
Radek Krejci5a065542015-05-22 15:02:07 +02001653
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001654 lydict_remove(ctx, module->dsc);
1655 lydict_remove(ctx, module->ref);
1656 lydict_remove(ctx, module->org);
1657 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001658
Radek Krejcieb00f512015-07-01 16:44:58 +02001659 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001660 for (i = 0; i < module->rev_size; i++) {
1661 lydict_remove(ctx, module->rev[i].dsc);
1662 lydict_remove(ctx, module->rev[i].ref);
1663 }
1664 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001665
Radek Krejcieb00f512015-07-01 16:44:58 +02001666 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001667 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001668 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001669 }
1670 module->ident_size = 0;
1671 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001672
Radek Krejcieb00f512015-07-01 16:44:58 +02001673 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001674 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001675 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001676 }
1677 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001678
Radek Krejcieb00f512015-07-01 16:44:58 +02001679 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001680 for (i = 0; i < module->inc_size; i++) {
Michal Vasko13b15832015-08-19 11:04:48 +02001681 lys_submodule_free(module->inc[i].submodule, free_int_mods);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001682 }
1683 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001684
Radek Krejcieb00f512015-07-01 16:44:58 +02001685 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02001686 for (i = 0; i < module->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001687 lys_augment_free(ctx, module->augment[i]);
Radek Krejcif5be10f2015-06-16 13:29:36 +02001688 }
1689 free(module->augment);
1690
Radek Krejcieb00f512015-07-01 16:44:58 +02001691 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001692 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001693 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001694 }
1695 free(module->features);
1696
Radek Krejcieb00f512015-07-01 16:44:58 +02001697 /* deviations */
1698 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001699 lys_deviation_free(ctx, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001700 }
1701 free(module->deviation);
1702
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001703 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02001704}
1705
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001706void
Michal Vasko13b15832015-08-19 11:04:48 +02001707lys_submodule_free(struct lys_submodule *submodule, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02001708{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001709 if (!submodule) {
1710 return;
1711 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001712
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001713 submodule->inc_size = 0;
1714 free(submodule->inc);
1715 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02001716
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001717 /* common part with struct ly_module */
Michal Vasko13b15832015-08-19 11:04:48 +02001718 module_free_common((struct lys_module *)submodule, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02001719
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001720 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02001721
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001722 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001723}
1724
Radek Krejcib8048692015-08-05 13:36:34 +02001725static struct lys_node_leaf *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001726lys_uniq_find(struct lys_node_list *list, struct lys_node_leaf *orig_leaf)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001727{
Radek Krejci1d82ef62015-08-07 14:44:40 +02001728 struct lys_node *node, *node2, *ret = NULL, *parent1, *parent2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001729 int depth = 1, i;
1730
1731 /* find the correct direct descendant of list in orig_leaf */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001732 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001733 while (1) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001734 if (!node->parent) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001735 return NULL;
1736 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001737 if (!strcmp(node->parent->name, list->name)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001738 break;
1739 }
1740
Radek Krejci1d82ef62015-08-07 14:44:40 +02001741 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001742 ++depth;
1743 }
1744
1745 /* make sure the nodes are equal */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001746 parent1 = node->parent->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001747 parent2 = list->parent;
1748 while (1) {
1749 if ((parent1 && !parent2) || (!parent1 && parent2)) {
1750 return NULL;
1751 }
1752
1753 if (parent1 == parent2) {
1754 break;
1755 }
1756
1757 parent1 = parent1->parent;
1758 parent2 = parent2->parent;
1759 }
1760
1761 /* find the descendant in the list */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001762 LY_TREE_FOR(list->child, node2) {
1763 if (!strcmp(node2->name, node->name)) {
1764 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001765 break;
1766 }
1767 }
1768
1769 if (!ret) {
1770 return NULL;
1771 }
1772
1773 /* continue traversing both trees, the nodes are always truly equal */
1774 while (1) {
1775 --depth;
1776 if (!depth) {
Radek Krejci76512572015-08-04 09:47:08 +02001777 if (ret->nodetype != LYS_LEAF) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001778 return NULL;
1779 }
Radek Krejcib8048692015-08-05 13:36:34 +02001780 return (struct lys_node_leaf *)ret;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001781 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001782 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001783 for (i = 0; i < depth-1; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001784 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001785 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001786 LY_TREE_FOR(ret->child, node2) {
1787 if (!strcmp(node2->name, node->name)) {
1788 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001789 break;
1790 }
1791 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001792 if (!node2) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001793 return NULL;
1794 }
1795 }
1796}
1797
Radek Krejci76512572015-08-04 09:47:08 +02001798struct lys_node *
Michal Vasko71e1aa82015-08-12 12:17:51 +02001799lys_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 +02001800 struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001801{
Radek Krejci76512572015-08-04 09:47:08 +02001802 struct lys_node *retval = NULL, *aux, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001803 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001804 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001805
Michal Vaskoc07187d2015-08-13 15:20:57 +02001806 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001807 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001808 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001809 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001810 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001811 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001812 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001813 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001814 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001815 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001816 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001817 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001818 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001819 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001820 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001821 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001822 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001823 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001824 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001825 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001826 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001827 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001828 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001829 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001830
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001831 /* we cannot just duplicate memory since the strings are stored in
1832 * dictionary and we need to update dictionary counters.
1833 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001834
Radek Krejci1d82ef62015-08-07 14:44:40 +02001835 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001836 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001837 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02001838 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001839 break;
1840
Radek Krejci76512572015-08-04 09:47:08 +02001841 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001842 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02001843 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001844 break;
1845
Radek Krejci76512572015-08-04 09:47:08 +02001846 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001847 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02001848 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001849 break;
1850
Radek Krejci76512572015-08-04 09:47:08 +02001851 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001852 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02001853 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001854 break;
1855
Radek Krejci76512572015-08-04 09:47:08 +02001856 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001857 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02001858 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001859 break;
1860
Radek Krejci76512572015-08-04 09:47:08 +02001861 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001862 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02001863 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001864 break;
1865
Radek Krejci76512572015-08-04 09:47:08 +02001866 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001867 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02001868 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001869 break;
1870
Radek Krejci76512572015-08-04 09:47:08 +02001871 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001872 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02001873 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001874 break;
1875
Radek Krejci76512572015-08-04 09:47:08 +02001876 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001877 grp = calloc(1, sizeof *grp);
1878 retval = (struct lys_node *)grp;
1879 break;
1880
Radek Krejci76512572015-08-04 09:47:08 +02001881 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001882 rpc = calloc(1, sizeof *rpc);
1883 retval = (struct lys_node *)rpc;
1884 break;
1885
Radek Krejci76512572015-08-04 09:47:08 +02001886 case LYS_INPUT:
1887 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001888 io = calloc(1, sizeof *io);
1889 retval = (struct lys_node *)io;
1890 break;
1891
Radek Krejci76512572015-08-04 09:47:08 +02001892 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001893 ntf = calloc(1, sizeof *ntf);
1894 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02001895 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001896
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001897 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02001898 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02001899 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001900 }
Radek Krejcib388c152015-06-04 17:03:03 +02001901
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001902 /*
1903 * duplicate generic part of the structure
1904 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001905 retval->name = lydict_insert(ctx, node->name, 0);
1906 retval->dsc = lydict_insert(ctx, node->dsc, 0);
1907 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02001908 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001909 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001910 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001911 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001912 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001913 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001914
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001915 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001916 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001917
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001918 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001919
Radek Krejci1d82ef62015-08-07 14:44:40 +02001920 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001921 retval->features = calloc(retval->features_size, sizeof *retval->features);
Radek Krejci1d82ef62015-08-07 14:44:40 +02001922 for (i = 0; i < node->features_size; ++i) {
1923 if (unres_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
1924 retval->features[i] = node->features[i];
Michal Vaskod23ce592015-08-06 09:55:37 +02001925 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001926 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001927
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001928 if (recursive) {
1929 /* go recursively */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001930 LY_TREE_FOR(node->child, child) {
Michal Vasko71e1aa82015-08-12 12:17:51 +02001931 aux = lys_node_dup(module, child, retval->flags, retval->nacm, 1, unres);
Radek Krejci10c760e2015-08-14 14:45:43 +02001932 if (!aux || lys_node_addchild(retval, NULL, aux)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02001933 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02001934 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001935 }
1936 }
1937 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001938
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001939 /*
1940 * duplicate specific part of the structure
1941 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001942 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001943 case LYS_CONTAINER:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001944 if (cont_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001945 cont->when = lys_when_dup(ctx, cont_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02001946 if (unres_add_node(module, unres, cont->when, UNRES_WHEN, retval, 0) == -1) {
1947 goto error;
1948 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001949 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001950 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001951
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001952 cont->must_size = cont_orig->must_size;
1953 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001954
Radek Krejci1d82ef62015-08-07 14:44:40 +02001955 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001956 for (i = 0; i < cont->must_size; ++i) {
Michal Vasko49168a22015-08-17 16:35:41 +02001957 if (unres_add_node(module, unres, &cont->must[i], UNRES_MUST, retval, 0) == -1) {
1958 goto error;
1959 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001960 }
1961
Radek Krejci1d82ef62015-08-07 14:44:40 +02001962 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001963 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001964
Radek Krejci76512572015-08-04 09:47:08 +02001965 case LYS_CHOICE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001966 if (choice_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001967 choice->when = lys_when_dup(ctx, choice_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02001968 if (unres_add_node(module, unres, choice->when, UNRES_WHEN, retval, 0) == -1) {
1969 goto error;
1970 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001971 }
1972
1973 if (choice_orig->dflt) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001974 rc = resolve_sibling(choice->module, choice->child, NULL, 0, choice_orig->dflt->name, 0, LYS_ANYXML
Radek Krejci76512572015-08-04 09:47:08 +02001975 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001976 | LYS_LIST, &choice->dflt);
Michal Vasko49168a22015-08-17 16:35:41 +02001977 if (rc) {
1978 if (rc == EXIT_FAILURE) {
1979 LOGINT;
1980 }
1981 goto error;
1982 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001983 } else {
Michal Vaskoc68a2a22015-08-06 09:57:24 +02001984 /* useless to check return value, we don't know whether
1985 * there really wasn't any default defined or it just hasn't
1986 * been resolved, we just hope for the best :)
1987 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001988 unres_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001989 }
1990 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001991
Radek Krejci76512572015-08-04 09:47:08 +02001992 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001993 lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001994 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
1995
1996 if (leaf_orig->dflt) {
1997 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02001998 if (unres_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0) == -1) {
1999 goto error;
2000 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002001 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002002
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002003 leaf->must_size = leaf_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002004 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002005 for (i = 0; i < leaf->must_size; ++i) {
Michal Vasko49168a22015-08-17 16:35:41 +02002006 if (unres_add_node(module, unres, &leaf->must[i], UNRES_MUST, retval, 0) == -1) {
2007 goto error;
2008 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002009 }
Radek Krejci00768f42015-06-18 17:04:04 +02002010
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002011 if (leaf_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002012 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02002013 if (unres_add_node(module, unres, leaf->when, UNRES_WHEN, retval, 0) == -1) {
2014 goto error;
2015 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002016 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002017 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002018
Radek Krejci76512572015-08-04 09:47:08 +02002019 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002020 lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002021 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002022
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002023 llist->min = llist_orig->min;
2024 llist->max = llist_orig->max;
2025
2026 llist->must_size = llist_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002027 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002028 for (i = 0; i < llist->must_size; ++i) {
Michal Vasko49168a22015-08-17 16:35:41 +02002029 if (unres_add_node(module, unres, &llist->must[i], UNRES_MUST, retval, 0) == -1) {
2030 goto error;
2031 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002032 }
Radek Krejci00768f42015-06-18 17:04:04 +02002033
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002034 if (llist_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002035 llist->when = lys_when_dup(ctx, llist_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02002036 if (unres_add_node(module, unres, llist->when, UNRES_WHEN, retval, 0) == -1) {
2037 goto error;
2038 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002039 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002040 break;
2041
Radek Krejci76512572015-08-04 09:47:08 +02002042 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002043 list->min = list_orig->min;
2044 list->max = list_orig->max;
2045
2046 list->must_size = list_orig->must_size;
2047 list->tpdf_size = list_orig->tpdf_size;
2048 list->keys_size = list_orig->keys_size;
2049 list->unique_size = list_orig->unique_size;
2050
Radek Krejci1d82ef62015-08-07 14:44:40 +02002051 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002052 for (i = 0; i < list->must_size; ++i) {
Michal Vasko49168a22015-08-17 16:35:41 +02002053 if (unres_add_node(module, unres, &list->must[i], UNRES_MUST, retval, 0) == -1) {
2054 goto error;
2055 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002056 }
2057
Radek Krejci1d82ef62015-08-07 14:44:40 +02002058 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002059
2060 if (list->keys_size) {
2061 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002062
2063 /* we managed to resolve it before, resolve it again manually */
2064 if (list_orig->keys[0]) {
2065 for (i = 0; i < list->keys_size; ++i) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002066 rc = resolve_sibling(list->module, list->child, NULL, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2067 (struct lys_node **)&list->keys[i]);
Michal Vasko49168a22015-08-17 16:35:41 +02002068 if (rc) {
2069 if (rc == EXIT_FAILURE) {
2070 LOGINT;
2071 }
2072 goto error;
2073 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002074 }
2075 /* it was not resolved yet, add unres copy */
2076 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002077 if (unres_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02002078 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002079 goto error;
Michal Vaskod23ce592015-08-06 09:55:37 +02002080 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002081 }
2082 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002083
2084 list->unique = calloc(list->unique_size, sizeof *list->unique);
2085 if (list_orig->unique) {
2086 for (i = 0; i < list->unique_size; ++i) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002087 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
2088 for (j = 0; j < list->unique[i].leafs_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002089 list->unique[i].leafs[j] = lys_uniq_find(list, list_orig->unique[i].leafs[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002090 }
2091 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002092 } else {
2093 for (i = 0; i < list->unique_size; ++i) {
2094 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02002095 list->unique[i].leafs = (struct lys_node_leaf **)list;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002096 unres_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002097 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002098 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002099
2100 if (list_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002101 list->when = lys_when_dup(ctx, list_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02002102 if (unres_add_node(module, unres, list->when, UNRES_WHEN, retval, 0) == -1) {
2103 goto error;
2104 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002105 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002106 break;
2107
Radek Krejci76512572015-08-04 09:47:08 +02002108 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002109 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002110 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002111 for (i = 0; i < anyxml->must_size; ++i) {
Michal Vasko49168a22015-08-17 16:35:41 +02002112 if (unres_add_node(module, unres, &anyxml->must[i], UNRES_MUST, retval, 0) == -1) {
2113 goto error;
2114 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002115 }
2116
2117 if (anyxml_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002118 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02002119 if (unres_add_node(module, unres, anyxml->when, UNRES_WHEN, retval, 0) == -1) {
2120 goto error;
2121 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002122 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002123 break;
2124
Radek Krejci76512572015-08-04 09:47:08 +02002125 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002126 uses->grp = uses_orig->grp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002127
2128 if (uses_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002129 uses->when = lys_when_dup(ctx, uses_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02002130 if (unres_add_node(module, unres, uses->when, UNRES_WHEN, (struct lys_node *)uses, 0) == -1) {
2131 goto error;
2132 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002133 }
2134
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002135 uses->refine_size = uses_orig->refine_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002136 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size, uses, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002137 uses->augment_size = uses_orig->augment_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002138 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 +02002139 if (!uses->child) {
Michal Vasko49168a22015-08-17 16:35:41 +02002140 if (unres_add_node(module, unres, uses, UNRES_USES, NULL, 0) == -1) {
2141 goto error;
2142 }
Michal Vaskof8c128d2015-08-06 15:25:28 +02002143 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002144 break;
2145
Radek Krejci76512572015-08-04 09:47:08 +02002146 case LYS_CASE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002147 if (cs_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002148 cs->when = lys_when_dup(ctx, cs_orig->when);
Michal Vasko49168a22015-08-17 16:35:41 +02002149 if (unres_add_node(module, unres, cs->when, UNRES_WHEN, retval, 0) == -1) {
2150 goto error;
2151 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002152 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002153 break;
2154
Radek Krejci76512572015-08-04 09:47:08 +02002155 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002156 grp->tpdf_size = grp_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002157 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002158 break;
2159
Radek Krejci76512572015-08-04 09:47:08 +02002160 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002161 rpc->tpdf_size = rpc_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002162 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002163 break;
2164
Radek Krejci76512572015-08-04 09:47:08 +02002165 case LYS_INPUT:
2166 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002167 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002168 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002169 break;
2170
Radek Krejci76512572015-08-04 09:47:08 +02002171 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002172 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002173 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcia01e5432015-06-16 10:35:25 +02002174 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002175
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002176 default:
Radek Krejci00768f42015-06-18 17:04:04 +02002177 /* LY_NODE_AUGMENT */
Michal Vaskod23ce592015-08-06 09:55:37 +02002178 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002179 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002180 }
2181
2182 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002183
2184error:
2185
2186 lys_node_free(retval);
2187 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002188}
2189
Michal Vasko13b15832015-08-19 11:04:48 +02002190void
2191lys_free(struct lys_module *module, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02002192{
Radek Krejcidce51452015-06-16 15:20:08 +02002193 struct ly_ctx *ctx;
2194 int i;
2195
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002196 if (!module) {
2197 return;
2198 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002199
Radek Krejcidce51452015-06-16 15:20:08 +02002200 /* remove schema from the context */
2201 ctx = module->ctx;
2202 if (ctx->models.used) {
2203 for (i = 0; i < ctx->models.used; i++) {
2204 if (ctx->models.list[i] == module) {
2205 /* replace the position in the list by the last module in the list */
2206 ctx->models.used--;
2207 ctx->models.list[i] = ctx->models.list[ctx->models.used];
2208 ctx->models.list[ctx->models.used] = NULL;
2209 /* we are done */
2210 break;
2211 }
2212 }
2213 }
2214
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002215 /* common part with struct ly_submodule */
Michal Vasko13b15832015-08-19 11:04:48 +02002216 module_free_common(module, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02002217
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002218 /* specific items to free */
2219 lydict_remove(module->ctx, module->ns);
2220 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02002221
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002222 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002223}
Radek Krejci7e97c352015-06-19 16:26:34 +02002224
2225/*
2226 * op: 1 - enable, 0 - disable
2227 */
2228static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002229lys_features_change(struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002230{
2231 int all = 0;
2232 int i, j, k;
2233
2234 if (!module || !name || !strlen(name)) {
2235 return EXIT_FAILURE;
2236 }
2237
2238 if (!strcmp(name, "*")) {
2239 /* enable all */
2240 all = 1;
2241 }
2242
2243 /* module itself */
2244 for (i = 0; i < module->features_size; i++) {
2245 if (all || !strcmp(module->features[i].name, name)) {
2246 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002247 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002248 /* enable referenced features (recursion) */
2249 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002250 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002251 module->features[i].features[k]->name, op);
2252 }
2253 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002254 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002255 }
2256 if (!all) {
2257 return EXIT_SUCCESS;
2258 }
2259 }
2260 }
2261
2262 /* submodules */
2263 for (j = 0; j < module->inc_size; j++) {
2264 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2265 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2266 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002267 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002268 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002269 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002270 }
2271 if (!all) {
2272 return EXIT_SUCCESS;
2273 }
2274 }
2275 }
2276 }
2277
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002278 /* TODO submodules of submodules ... */
2279
Radek Krejci7e97c352015-06-19 16:26:34 +02002280 if (all) {
2281 return EXIT_SUCCESS;
2282 } else {
2283 return EXIT_FAILURE;
2284 }
2285}
2286
2287API int
Radek Krejcib8048692015-08-05 13:36:34 +02002288lys_features_enable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002289{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002290 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002291}
2292
2293API int
Radek Krejcib8048692015-08-05 13:36:34 +02002294lys_features_disable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002295{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002296 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002297}
2298
2299API int
Radek Krejcib8048692015-08-05 13:36:34 +02002300lys_features_state(struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002301{
2302 int i, j;
2303
2304 if (!module || !feature) {
2305 return -1;
2306 }
2307
2308 /* search for the specified feature */
2309 /* module itself */
2310 for (i = 0; i < module->features_size; i++) {
2311 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002312 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002313 return 1;
2314 } else {
2315 return 0;
2316 }
2317 }
2318 }
2319
2320 /* submodules */
2321 for (j = 0; j < module->inc_size; j++) {
2322 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2323 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002324 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002325 return 1;
2326 } else {
2327 return 0;
2328 }
2329 }
2330 }
2331 }
2332
2333 /* TODO submodules of submodules ... */
2334
2335 /* feature definition not found */
2336 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002337}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002338
Radek Krejci96a10da2015-07-30 11:00:14 +02002339API const char **
Radek Krejcib8048692015-08-05 13:36:34 +02002340lys_features_list(struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002341{
Radek Krejci96a10da2015-07-30 11:00:14 +02002342 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002343 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002344 unsigned int count;
2345
2346 if (!module) {
2347 return NULL;
2348 }
2349
2350 count = module->features_size;
2351 for (i = 0; i < module->inc_size; i++) {
2352 count += module->inc[i].submodule->features_size;
2353 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002354 result = malloc((count + 1) * sizeof *result);
2355 if (states) {
2356 *states = malloc((count + 1) * sizeof **states);
Michal Vasko2367e7c2015-07-07 11:33:44 +02002357 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002358 count = 0;
2359
2360 /* module itself */
2361 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002362 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002363 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002364 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002365 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002366 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002367 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002368 }
2369 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002370 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002371 }
2372
2373 /* submodules */
2374 for (j = 0; j < module->inc_size; j++) {
2375 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002376 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002377 if (states) {
2378 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2379 (*states)[count] = 1;
2380 } else {
2381 (*states)[count] = 0;
2382 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002383 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002384 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002385 }
2386 }
2387
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002388 /* TODO submodules of submodules ... */
2389
2390 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002391 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002392
2393 return result;
2394}
Radek Krejcib20c62d2015-07-07 17:07:14 +02002395
2396API struct lyd_node *
Radek Krejci25b9fd32015-08-10 15:06:07 +02002397lyd_parse(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
Radek Krejcib20c62d2015-07-07 17:07:14 +02002398{
2399 if (!ctx || !data) {
2400 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2401 return NULL;
2402 }
2403
2404 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02002405 case LYD_XML:
Radek Krejci25b9fd32015-08-10 15:06:07 +02002406 return xml_read_data(ctx, data, options);
Radek Krejcia9167ef2015-08-03 11:01:11 +02002407 case LYD_JSON:
Radek Krejcib20c62d2015-07-07 17:07:14 +02002408 default:
2409 /* TODO */
2410 return NULL;
2411 }
2412
2413 return NULL;
2414}
2415
Radek Krejci47cda9e2015-08-19 11:52:54 +02002416API int
2417lyd_insert(struct lyd_node *parent, struct lyd_node *node, int options)
2418{
2419 struct lys_node *sparent;
2420 struct lyd_node *iter;
2421
2422 if (!node || !parent) {
2423 ly_errno = LY_EINVAL;
2424 return EXIT_FAILURE;
2425 }
2426
2427 if (node->parent || node->prev->next) {
2428 lyd_unlink(node);
2429 }
2430
2431 /* check placing the node to the appropriate place according to the schema */
2432 sparent = node->schema->parent;
2433 while (!(sparent->nodetype & (LYS_CONTAINER | LYS_LIST))) {
2434 sparent = sparent->parent;
2435 }
2436 if (sparent != parent->schema) {
2437 ly_errno = LY_EINVAL;
2438 return EXIT_FAILURE;
2439 }
2440
2441 /* TODO all other checks for new node in the data tree (uniqueness, ...) */
2442
2443 if (!parent->child) {
2444 /* add as the only child of the parent */
2445 parent->child = node;
2446 } else {
2447 /* add as the last child of the parent */
2448 parent->child->prev->next = node;
2449 node->prev = parent->child->prev;
2450 for (iter = node; iter->next; iter = iter->next);
2451 parent->child->prev = iter;
2452 }
2453 LY_TREE_FOR(node, iter) {
2454 iter->parent = parent;
2455 }
2456
2457 return EXIT_SUCCESS;
2458}
2459
2460API int
2461lyd_unlink(struct lyd_node *node)
2462{
2463 struct lyd_node *iter;
2464
2465 if (!node) {
2466 ly_errno = LY_EINVAL;
2467 return EXIT_FAILURE;
2468 }
2469
2470 /* unlink from the lists list */
2471 if (node->schema->nodetype == LYS_LIST) {
2472 if (((struct lyd_node_list *)node)->lprev) {
2473 ((struct lyd_node_list *)node)->lprev->lnext = ((struct lyd_node_list *)node)->lnext;
2474 }
2475 if (((struct lyd_node_list *)node)->lnext) {
2476 ((struct lyd_node_list *)node)->lnext->lprev = ((struct lyd_node_list *)node)->lprev;
2477 }
2478 } else if (node->schema->nodetype == LYS_LEAFLIST) {
2479 if (((struct lyd_node_leaflist *)node)->lprev) {
2480 ((struct lyd_node_leaflist *)node)->lprev->lnext = ((struct lyd_node_leaflist *)node)->lnext;
2481 }
2482 if (((struct lyd_node_leaflist *)node)->lnext) {
2483 ((struct lyd_node_leaflist *)node)->lnext->lprev = ((struct lyd_node_leaflist *)node)->lprev;
2484 }
2485 }
2486
2487 /* unlink from siblings */
2488 if (node->prev->next) {
2489 node->prev->next = node->next;
2490 }
2491 if (node->next) {
2492 node->next->prev = node->prev;
2493 } else {
2494 /* unlinking the last node */
2495 iter = node->prev;
2496 while (iter->prev != node) {
2497 iter = iter->prev;
2498 }
2499 /* update the "last" pointer from the first node */
2500 iter->prev = node->prev;
2501 }
Radek Krejci47cda9e2015-08-19 11:52:54 +02002502
2503 /* unlink from parent */
2504 if (node->parent) {
2505 if (node->parent->child == node) {
2506 /* the node is the first child */
2507 node->parent->child = node->next;
2508 }
2509 node->parent = NULL;
2510 }
2511
Radek Krejci58f6e672015-08-19 16:59:53 +02002512 node->next = NULL;
2513 node->prev = node;
2514
Radek Krejci47cda9e2015-08-19 11:52:54 +02002515 return EXIT_SUCCESS;
2516}
2517
Radek Krejci0e1d1a62015-07-31 11:17:01 +02002518API void
Radek Krejci912da452015-07-29 14:10:06 +02002519lyd_free(struct lyd_node *node)
Radek Krejcib20c62d2015-07-07 17:07:14 +02002520{
2521 struct lyd_node *next, *child;
2522
Radek Krejci52f791c2015-07-15 11:14:17 +02002523 if (!node) {
2524 return;
2525 }
2526
Radek Krejci76512572015-08-04 09:47:08 +02002527 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
Radek Krejcie4748472015-07-08 18:00:22 +02002528 /* free children */
2529 LY_TREE_FOR_SAFE(node->child, next, child) {
Radek Krejci912da452015-07-29 14:10:06 +02002530 lyd_free(child);
Radek Krejcie4748472015-07-08 18:00:22 +02002531 }
Radek Krejci76512572015-08-04 09:47:08 +02002532 } else if (node->schema->nodetype == LYS_ANYXML) {
Radek Krejci9566b092015-07-31 11:18:15 +02002533 lyxml_free_elem(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
Radek Krejcie4748472015-07-08 18:00:22 +02002534 } else {
2535 /* free value */
2536 switch(((struct lyd_node_leaf *)node)->value_type) {
2537 case LY_TYPE_BINARY:
2538 case LY_TYPE_STRING:
2539 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf *)node)->value.string);
2540 break;
Radek Krejci3e3affe2015-07-09 15:38:40 +02002541 case LY_TYPE_BITS:
2542 if (((struct lyd_node_leaf *)node)->value.bit) {
2543 free(((struct lyd_node_leaf *)node)->value.bit);
2544 }
2545 break;
Radek Krejcie4748472015-07-08 18:00:22 +02002546 default:
Radek Krejci7511f402015-07-10 09:56:30 +02002547 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
Radek Krejcie4748472015-07-08 18:00:22 +02002548 break;
2549 }
Radek Krejcib20c62d2015-07-07 17:07:14 +02002550 }
2551
Radek Krejcib3d6d552015-08-19 11:56:13 +02002552 lyd_unlink(node);
2553 free(node);
2554}
2555
2556int
2557lyd_filter_compare(struct lyd_node *first, struct lyd_node *second)
2558{
2559 struct lyd_node *diter1, *diter2;
2560 int match, c1, c2;
2561
2562 assert(first);
2563 assert(second);
2564
2565 if (first->schema != second->schema) {
2566 return 1;
Radek Krejcib20c62d2015-07-07 17:07:14 +02002567 }
2568
Radek Krejcib3d6d552015-08-19 11:56:13 +02002569
2570 switch (first->schema->nodetype) {
2571 case LYS_LIST:
2572 /* check if all the content match nodes are the same */
2573 c1 = 0;
2574 LY_TREE_FOR(first->child, diter1) {
2575 if (!(diter1->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2576 continue;
2577 } else if (!((struct lyd_node_leaf *)diter1)->value_str) {
2578 /* selection node */
2579 continue;
2580 }
2581
2582 match = 0;
2583 LY_TREE_FOR(second->child, diter2) {
2584 if (diter2->schema != diter1->schema) {
2585 continue;
2586 } else if (((struct lyd_node_leaf *)diter1)->value_str != ((struct lyd_node_leaf *)diter2)->value_str) {
2587 continue;
2588 }
2589 match = 1;
2590 c1++;
2591 }
2592 if (!match) {
2593 return 1;
2594 }
2595 }
2596 /* get number of content match nodes in the second to get know if there are some
2597 * that are not present in first
2598 */
2599 c2 = 0;
2600 LY_TREE_FOR(second->child, diter2) {
2601 if (!(diter2->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2602 continue;
2603 } else if (!((struct lyd_node_leaf *)diter2)->value_str) {
2604 /* selection node */
2605 continue;
2606 }
2607 c2++;
2608 }
2609 if (c1 != c2) {
2610 return 1;
2611 }
2612 break;
2613 case LYS_LEAF:
2614 case LYS_LEAFLIST:
2615 if (((struct lyd_node_leaf *)first)->value_str != ((struct lyd_node_leaf *)second)->value_str) {
2616 return 1;
2617 }
2618 break;
2619 default:
2620 /* no more tests are needed */
2621 break;
2622 }
2623 return 0;
Radek Krejcib20c62d2015-07-07 17:07:14 +02002624}
Michal Vaskof54f2f82015-07-17 13:12:05 +02002625
Radek Krejci78ce8612015-08-18 14:31:05 +02002626int
2627lyd_compare(struct lyd_node *first, struct lyd_node *second, int unique)
2628{
2629 struct lys_node_list *slist;
2630 struct lys_node *snode;
2631 struct lyd_node *diter;
2632 const char *val1, *val2;
2633 int i, j;
2634
Radek Krejcib3d6d552015-08-19 11:56:13 +02002635 assert(first);
2636 assert(second);
Radek Krejci78ce8612015-08-18 14:31:05 +02002637
2638 if (first->schema != second->schema) {
2639 return 1;
2640 }
2641
2642 switch (first->schema->nodetype) {
2643 case LYS_LEAFLIST:
2644 /* compare values */
2645 if (((struct lyd_node_leaflist *)first)->value_str == ((struct lyd_node_leaflist *)second)->value_str) {
2646 return 0;
2647 }
2648 return 1;
2649 case LYS_LIST:
2650 slist = (struct lys_node_list*)first->schema;
2651
2652 if (unique) {
2653 /* compare unique leafs */
2654 for (i = 0; i < slist->unique_size; i++) {
2655 for (j = 0; j < slist->unique[i].leafs_size; j++) {
2656 snode = (struct lys_node *)slist->unique[i].leafs[j];
2657 /* use default values if the instances of unique leafs are not present */
2658 val1 = val2 = ((struct lys_node_leaf *)snode)->dflt;
2659 LY_TREE_FOR(first->child, diter) {
2660 if (diter->schema == snode) {
2661 val1 = ((struct lyd_node_leaf *)diter)->value_str;
2662 break;
2663 }
2664 }
2665 LY_TREE_FOR(second->child, diter) {
2666 if (diter->schema == snode) {
2667 val2 = ((struct lyd_node_leaf *)diter)->value_str;
2668 break;
2669 }
2670 }
2671 if (val1 != val2) {
2672 break;
2673 }
2674 }
2675 if (j && j == slist->unique[i].leafs_size) {
2676 /* all unique leafs are the same in this set */
2677 return 0;
2678 }
2679 }
2680 }
2681
2682 /* compare keys */
2683 for (i = 0; i < slist->keys_size; i++) {
2684 snode = (struct lys_node *)slist->keys[i];
2685 val1 = val2 = NULL;
2686 LY_TREE_FOR(first->child, diter) {
2687 if (diter->schema == snode) {
2688 val1 = ((struct lyd_node_leaf *)diter)->value_str;
2689 break;
2690 }
2691 }
2692 LY_TREE_FOR(second->child, diter) {
2693 if (diter->schema == snode) {
2694 val2 = ((struct lyd_node_leaf *)diter)->value_str;
2695 break;
2696 }
2697 }
2698 if (val1 != val2) {
2699 return 1;
2700 }
2701 }
2702
2703 return 0;
2704 default:
2705 /* no additional check is needed */
2706 return 0;
2707 }
2708}
2709
Radek Krejcib3d6d552015-08-19 11:56:13 +02002710int
2711lyd_filter_merge(struct lyd_node *to, struct lyd_node *from)
2712{
2713 struct lyd_node *diter1, *diter2;
2714 unsigned int i, j;
2715 struct lyd_set *s1 = NULL, *s2 = NULL;
2716
2717 if (!to || !from || to->schema != from->schema) {
2718 ly_errno = LY_EINVAL;
2719 return EXIT_FAILURE;
2720 }
2721
2722 switch(to->schema->nodetype) {
2723 case LYS_LIST:
2724 s1 = lyd_set_new();
2725 s2 = lyd_set_new();
2726 /* get know about the selection and containment node in to and from nodes */
2727 LY_TREE_FOR(to->child, diter1) {
2728 /* is selection node */
2729 if ((diter1->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lyd_node_leaf *)diter1)->value_str) {
2730 lyd_set_add(s1, diter1);
2731 } else if ((diter1->schema->nodetype == LYS_ANYXML) && !((struct lyd_node_anyxml *)diter1)->value->child) {
2732 lyd_set_add(s1, diter1);
2733 } else if (diter1->schema->nodetype & (LYS_CONTAINER | LYS_LIST)) {
2734 /* or containment node */
2735 lyd_set_add(s1, diter1);
2736 }
2737 }
2738
2739 LY_TREE_FOR(from->child, diter2) {
2740 /* is selection node */
2741 if ((diter2->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lyd_node_leaf *)diter2)->value_str) {
2742 lyd_set_add(s2, diter2);
2743 } else if ((diter2->schema->nodetype == LYS_ANYXML) && !((struct lyd_node_anyxml *)diter2)->value->child) {
2744 lyd_set_add(s2, diter2);
2745 } else if (diter2->schema->nodetype & (LYS_CONTAINER | LYS_LIST)) {
2746 /* or containment node */
2747 lyd_set_add(s2, diter2);
2748 }
2749 }
2750
2751 if (!s1->number) {
2752 /* to already selects all content, so nothing is needed */
2753 break;;
2754 }
2755 if (!s2->number) {
2756 /* from selects all content, so make to select it too by
2757 * removing all selection and containment nodes
2758 */
2759 for (i = 0; i < s1->number; i++) {
2760 lyd_free(s1->set[i]);
2761 }
2762 break;
2763 }
2764
2765 /* target contain some selection or containment node, so merge
2766 * the selection/containment nodes from source to target
2767 */
2768 for (j = 0; j < s2->number; j++) {
2769 for (i = 0; i < s1->number; i++) {
2770 /* TODO cover non-empty containment nodes */
2771 if (!lyd_filter_compare(s1->set[i], s2->set[j])) {
2772 break;
2773 }
2774 }
2775 if (i == s1->number) {
2776 /* node in from is not present in to,
2777 * so insert it there */
2778 lyd_insert(to, s2->set[j], LYD_OPT_FILTER);
2779 }
2780 }
2781 break;
2782 default:
2783 /* TODO cover other types of data nodes */
2784 break;
2785 }
2786
2787 lyd_set_free(s1);
2788 lyd_set_free(s2);
2789
2790 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002791}
Michal Vaskof54f2f82015-07-17 13:12:05 +02002792
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002793API int
Radek Krejci9566b092015-07-31 11:18:15 +02002794lyd_is_last(struct lyd_node *node)
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002795{
2796 struct lyd_node *n;
2797
2798 if (!node->next) {
2799 return 1;
2800 }
2801
2802 for (n = node->next; n; n = n->next) {
2803 switch (n->schema->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002804 case LYS_LIST:
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002805 if (!((struct lyd_node_list *)n)->lprev) {
2806 return 0;
2807 }
2808 break;
Radek Krejci76512572015-08-04 09:47:08 +02002809 case LYS_LEAFLIST:
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002810 if (!((struct lyd_node_leaflist *)n)->lprev) {
2811 return 0;
2812 }
2813 break;
2814 default:
2815 return 0;
2816 }
2817 }
2818 return 1;
2819}
Radek Krejcife19f692015-08-19 11:46:48 +02002820
2821API struct lyd_set *
2822lyd_set_new(void)
2823{
2824 return calloc(1, sizeof(struct lyd_set));
2825}
2826
2827API void
2828lyd_set_free(struct lyd_set *set)
2829{
2830 if (!set) {
2831 return;
2832 }
2833
2834 free(set->set);
2835 free(set);
2836}
2837
2838API int
2839lyd_set_add(struct lyd_set *set, struct lyd_node *node)
2840{
2841 struct lyd_node **new;
2842
2843 if (!set) {
2844 ly_errno = LY_EINVAL;
2845 return EXIT_FAILURE;
2846 }
2847
2848 if (set->size == set->number) {
2849 new = realloc(set->set, (set->size + 8) * sizeof *(set->set));
2850 if (!new) {
2851 LOGMEM;
2852 return EXIT_FAILURE;
2853 }
2854 set->size += 8;
2855 set->set = new;
2856 }
2857
2858 set->set[set->number++] = node;
2859
2860 return EXIT_SUCCESS;
2861}