blob: 842fd33180eb065f71f2da2705675dc485757d0a [file] [log] [blame]
Radek Krejcic6704c82015-10-06 11:12:45 +02001
Radek Krejcida04f4a2015-05-21 12:54:09 +02002/**
Michal Vasko2d162e12015-09-24 14:33:29 +02003 * @file tree_schema.c
Radek Krejcida04f4a2015-05-21 12:54:09 +02004 * @author Radek Krejci <rkrejci@cesnet.cz>
Michal Vasko2d162e12015-09-24 14:33:29 +02005 * @brief Manipulation with libyang schema data structures
Radek Krejcida04f4a2015-05-21 12:54:09 +02006 *
7 * Copyright (c) 2015 CESNET, z.s.p.o.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * 3. Neither the name of the Company nor the names of its contributors
19 * may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
21 */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020022#define _GNU_SOURCE
Radek Krejcida04f4a2015-05-21 12:54:09 +020023
Radek Krejci812b10a2015-05-28 16:48:25 +020024#include <assert.h>
Radek Krejci5a988152015-07-15 11:16:26 +020025#include <ctype.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020026#include <stdlib.h>
27#include <sys/mman.h>
28#include <sys/stat.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020029#include <string.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020030
31#include "common.h"
32#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020033#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020034#include "resolve.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020035#include "xml_internal.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020036#include "tree_internal.h"
Radek Krejcieab784a2015-08-27 09:56:53 +020037#include "validation.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020038
Michal Vaskoa76ee152015-08-17 15:38:22 +020039static const struct internal_modules int_mods = {
40 .modules = {
41 {"ietf-yang-types", "2013-07-15"},
42 {"ietf-inet-types", "2013-07-15"},
43 {"ietf-yang-library", "2015-07-03"}
44 },
45 .count = LY_INTERNAL_MODULE_COUNT
46};
47
Radek Krejci48061fb2015-08-05 15:41:07 +020048API struct lys_feature *
49lys_is_disabled(struct lys_node *node, int recursive)
50{
51 int i;
52
53check:
54 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
55 /* input/output does not have if-feature, so skip them */
56
57 /* check local if-features */
58 for (i = 0; i < node->features_size; i++) {
59 if (!(node->features[i]->flags & LYS_FENABLED)) {
60 return node->features[i];
61 }
62 }
63 }
64
65 if (!recursive) {
66 return NULL;
67 }
68
69 /* go through parents */
70 if (node->nodetype == LYS_AUGMENT) {
71 /* go to parent actually means go to the target node */
72 node = ((struct lys_node_augment *)node)->target;
Radek Krejci48061fb2015-08-05 15:41:07 +020073 } else if (node->parent) {
74 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020075 } else {
76 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020077 }
78
Radek Krejci074bf852015-08-19 14:22:16 +020079 if (recursive == 2) {
80 /* continue only if the node cannot have a data instance */
81 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
82 return NULL;
83 }
84 }
85 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020086}
87
Michal Vaskof6dfae02015-10-20 13:47:06 +020088int
89lys_getsibling(struct lys_module *mod, struct lys_node *siblings, const char *mod_name, int mod_name_len,
90 const char *name, int nam_len, LYS_NODE type, struct lys_node **ret)
91{
92 struct lys_node *node, *old_siblings = NULL;
93 struct lys_module *prefix_mod, *cur_mod;
94 int in_submod;
Michal Vaskof6dfae02015-10-20 13:47:06 +020095
96 assert(siblings && name);
97 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING)));
98
99 /* find the beginning */
100 while (siblings->prev->next) {
101 siblings = siblings->prev;
102 }
103
104 /* fill the name length in case the caller is so indifferent */
105 if (!nam_len) {
106 nam_len = strlen(name);
107 }
108
109 /* we start with the module itself, submodules come later */
110 in_submod = 0;
111
112 /* set prefix_mod correctly */
113 if (mod_name) {
Michal Vaskob6729c62015-10-21 12:09:47 +0200114 prefix_mod = lys_get_import_module(siblings->module, NULL, 0, mod_name, mod_name_len);
Michal Vaskof6dfae02015-10-20 13:47:06 +0200115 if (!prefix_mod) {
116 return -1;
117 }
118 cur_mod = prefix_mod;
119 /* it is not our module */
120 if (cur_mod != mod) {
121 old_siblings = siblings;
122 siblings = cur_mod->data;
123 }
124 } else {
125 if (mod) {
126 prefix_mod = mod;
127 } else {
128 prefix_mod = siblings->module;
129 }
130 if (prefix_mod->type) {
131 prefix_mod = ((struct lys_submodule *)prefix_mod)->belongsto;
132 }
133 cur_mod = prefix_mod;
134 }
135
136 while (1) {
137 /* try to find the node */
138 node = NULL;
139 while ((node = lys_getnext(node, siblings->parent, cur_mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
140 if (!type || (node->nodetype & type)) {
141 /* module check */
142 if (!node->module->type) {
143 if (cur_mod != node->module) {
144 continue;
145 }
146 } else {
147 /* both are submodules */
148 if (cur_mod->type) {
149 if (cur_mod != node->module) {
150 continue;
151 }
152 } else {
153 if (cur_mod != ((struct lys_submodule *)node->module)->belongsto) {
154 continue;
155 }
156 }
157 }
158
159 /* direct name check */
160 if ((node->name == name) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
161 if (ret) {
162 *ret = node;
163 }
164 return EXIT_SUCCESS;
165 }
166 }
167 }
168
169 /* The original siblings may be valid,
170 * it's a special case when we're looking
171 * for a node from an augment.
172 */
173 if (old_siblings) {
174 siblings = old_siblings;
175 old_siblings = NULL;
176 continue;
177 }
178
179 /* we're not top-level, search ended */
180 if (siblings->parent) {
181 break;
182 }
183
184 /* let's try the submodules */
185 if (in_submod == prefix_mod->inc_size) {
186 break;
187 }
188 cur_mod = (struct lys_module *)prefix_mod->inc[in_submod].submodule;
189 siblings = cur_mod->data;
190 ++in_submod;
191 }
192
193 return EXIT_FAILURE;
194}
195
Michal Vasko75ceb2c2015-10-19 12:21:58 +0200196API struct lys_node *
Radek Krejci8bc87f62015-09-02 16:19:05 +0200197lys_getnext(struct lys_node *last, struct lys_node *parent, struct lys_module *module, int options)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200198{
199 struct lys_node *next;
200
Radek Krejci8bc87f62015-09-02 16:19:05 +0200201 if (!last) {
202 /* first call */
203
204 /* get know where to start */
205 if (parent) {
206 /* schema subtree */
207 next = last = parent->child;
208 } else {
209 /* top level data */
210 assert(module);
211 next = last = module->data;
212 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200213 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200214 /* continue after the last returned value */
215 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200216 }
217
218repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200219 while (next && (next->nodetype == LYS_GROUPING)) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200220 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200221 }
222
223 while (!next) {
Michal Vasko7c386e72015-10-07 15:13:33 +0200224 if (lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200225 /* no next element */
226 return NULL;
227 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200228 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200229 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200230 goto repeat;
231 }
232
233 switch (next->nodetype) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200234 case LYS_CASE:
Michal Vasko75ceb2c2015-10-19 12:21:58 +0200235 if (options & LYS_GETNEXT_WITHCASE) {
236 return next;
237 }
238 /* fallthrough */
239 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200240 /* go into */
241 next = next->child;
242 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200243
244 case LYS_CONTAINER:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200245 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200246 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200247 case LYS_LIST:
248 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200249 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200250
251 case LYS_CHOICE:
252 if (options & LYS_GETNEXT_WITHCHOICE) {
253 return next;
254 } else {
255 /* go into */
256 next = next->child;
257 goto repeat;
258 }
259 break;
260
Radek Krejci7f40ce32015-08-12 20:38:46 +0200261 default:
262 /* we should not be here */
263 return NULL;
264 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200265
266
267}
268
269static struct lys_node *
270check_mand_getnext(struct lys_node *last, struct lys_node *parent)
271{
272 struct lys_node *next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200273 next = lys_getnext(last, parent, NULL, LYS_GETNEXT_WITHCHOICE);
274
Radek Krejci4b6c2112015-10-06 12:48:34 +0200275repeat:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200276 if (next && next->nodetype == LYS_CONTAINER) {
277 if (((struct lys_node_container *)next)->presence) {
278 /* mandatory elements under the non-existing presence
279 * container are not mandatory - 7.6.5, rule 1 */
280 next = next->next;
281 } else {
282 /* go into */
283 next = next->child;
284 }
285 goto repeat;
286 }
287
288 return next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200289}
290
291static struct lys_node *
292check_mand_check(struct lys_node *node, struct lys_node *stop, struct lyd_node *data)
293{
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200294 struct lys_node *siter = NULL, *parent = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200295 struct lyd_node *diter = NULL;
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200296 struct lyd_set *set = NULL;
297 unsigned int i;
Radek Krejci14a11a62015-08-17 17:27:38 +0200298 uint32_t minmax;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200299
300 if (node->flags & LYS_MAND_TRUE) {
301 switch (node->nodetype) {
302 case LYS_LEAF:
303 case LYS_ANYXML:
304 case LYS_CHOICE:
305 if (node->parent->nodetype == LYS_CASE) {
306 /* 7.6.5, rule 2 */
307 /* 7.9.4, rule 1 */
308 if (node->parent->parent->parent == data->schema) {
309 /* the only case the node's siblings can exist is that the
310 * data node passed originaly to ly_check_mandatory()
311 * had this choice as a child
312 */
313 /* try to find the node's siblings in data */
314 LY_TREE_FOR(data->child, diter) {
315 LY_TREE_FOR(node->parent->child, siter) {
316 if (siter == diter->schema) {
317 /* some sibling exists, rule applies */
318 break;
319 }
320 }
321 if (siter) {
322 break;
323 }
324 }
325 }
326 if (!siter) {
327 /* no sibling exists */
328 return NULL;
329 }
330 } else {
331 for(parent = node->parent; parent != stop; parent = parent->parent) {
332 if (parent->nodetype != LYS_CONTAINER) {
333 /* 7.6.5, rule 1, checking presence is not needed
334 * since it is done in check_mand_getnext()
335 */
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200336 lyd_set_free(set);
Radek Krejci7f40ce32015-08-12 20:38:46 +0200337 return NULL;
338 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200339 /* add the parent to the list for searching in data tree */
340 if (!set) {
341 set = lyd_set_new();
342 }
343 lyd_set_add(set, (struct lyd_node *)parent);
Radek Krejci7f40ce32015-08-12 20:38:46 +0200344 }
345 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200346
347 /* search for instance */
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200348 if (set) {
349 for (i = 0; i < set->number; i++) {
350 LY_TREE_FOR(data->child, diter) {
351 if (diter->schema == (struct lys_node *)(set->set[i])) {
352 break;
353 }
354 }
355 if (!diter) {
356 /* instance not found */
357 node = (struct lys_node *)(set->set[i]);
358 lyd_set_free(set);
359 return node;
360 }
361 data = diter;
362 }
363 lyd_set_free(set);
364 }
365
Radek Krejci14a11a62015-08-17 17:27:38 +0200366 LY_TREE_FOR(data->child, diter) {
367 if (diter->schema == node) {
368 return NULL;
369 }
370 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200371
Radek Krejci14a11a62015-08-17 17:27:38 +0200372 /* instance not found */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200373 /* 7.6.5, rule 3 (or 2) */
374 /* 7.9.4, rule 2 */
375 return node;
376 default:
377 /* error */
378 break;
379 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200380 } else if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
381 /* search for number of instances */
382 minmax = 0;
383 LY_TREE_FOR(data->child, diter) {
384 if (diter->schema == node) {
385 minmax++;
386 }
387 }
388
389 /* check the specified constraints */
390 if (node->nodetype == LYS_LIST) {
391 if (((struct lys_node_list *)node)->min && minmax < ((struct lys_node_list *)node)->min) {
392 return node;
393 }
394
395 if (((struct lys_node_list *)node)->max && minmax > ((struct lys_node_list *)node)->max) {
396 return node;
397 }
398 } else if (node->nodetype == LYS_LEAFLIST) {
399 if (((struct lys_node_leaflist *)node)->min && minmax < ((struct lys_node_leaflist *)node)->min) {
400 return node;
401 }
402
403 if (((struct lys_node_leaflist *)node)->max && minmax > ((struct lys_node_leaflist *)node)->max) {
404 return node;
405 }
406 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200407 }
408
409 return NULL;
410}
411
412struct lys_node *
413ly_check_mandatory(struct lyd_node *data)
414{
Radek Krejci14a11a62015-08-17 17:27:38 +0200415 struct lys_node *siter, *saux, *saux2, *result, *parent = NULL, *parent2;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200416 struct lyd_node *diter;
417 int found;
418
419 siter = data->schema->child;
420
421repeat:
422 while (siter) {
Radek Krejci074bf852015-08-19 14:22:16 +0200423 if (lys_is_disabled(siter, 2)) {
424 siter = siter->next;
425 continue;
426 }
427
Radek Krejci7f40ce32015-08-12 20:38:46 +0200428 switch (siter->nodetype) {
429 case LYS_CONTAINER:
430 case LYS_LEAF:
431 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200432 case LYS_LIST:
433 case LYS_LEAFLIST:
434 /* check if there is some mandatory node; first test the siter itself ... */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200435 result = check_mand_check(siter, siter->parent, data);
436 if (result) {
437 return result;
438 }
439 /* ... and then the subtree */
Radek Krejci14a11a62015-08-17 17:27:38 +0200440 if (parent && siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
441 saux = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200442 while ((saux = check_mand_getnext(saux, siter))) {
443 result = check_mand_check(saux, siter, data);
444 if (result) {
445 return result;
446 }
447 }
448 }
449 siter = siter->next;
450 break;
451 case LYS_CHOICE:
Radek Krejci14a11a62015-08-17 17:27:38 +0200452 /* search for instance */
453 saux = siter;
454 siter = siter->child;
455 found = 0;
456 parent2 = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200457repeat_choice:
Radek Krejci074bf852015-08-19 14:22:16 +0200458 while (siter) {
459 if (lys_is_disabled(siter, 2)) {
460 siter = siter->next;
461 continue;
462 }
463
Radek Krejci14a11a62015-08-17 17:27:38 +0200464 switch (siter->nodetype) {
465 case LYS_CONTAINER:
466 case LYS_LEAF:
467 case LYS_LEAFLIST:
468 case LYS_LIST:
469 case LYS_ANYXML:
470 LY_TREE_FOR(data->child, diter) {
471 if (diter->schema == siter) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200472 break;
473 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200474 }
475 if (diter) {
476 /* got instance */
477 /* check presence of mandatory siblings */
Radek Krejci65d0a652015-08-27 13:09:42 +0200478 if (parent2 && parent2->nodetype == LYS_CASE) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200479 saux2 = NULL;
Radek Krejci37bda002015-08-27 11:23:56 +0200480 while ((saux2 = check_mand_getnext(saux2, parent2))) {
481 result = check_mand_check(saux2, parent2, data);
Radek Krejci14a11a62015-08-17 17:27:38 +0200482 if (result) {
483 return result;
484 }
485 }
486 }
487 siter = parent2 = NULL;
488 found = 1;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200489 break;
490 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200491 siter = siter->next;
492 break;
493 case LYS_CASE:
494 case LYS_CHOICE:
495 case LYS_USES:
496 /* go into */
Radek Krejci37bda002015-08-27 11:23:56 +0200497 if (!parent2) {
498 parent2 = siter;
499 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200500 siter = siter->child;
501 break;
502 case LYS_AUGMENT:
503 case LYS_GROUPING:
504 /* skip */
505 siter = siter->next;
506 break;
507 default:
508 /* error */
509 break;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200510 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200511 }
512
Radek Krejci14a11a62015-08-17 17:27:38 +0200513 if (parent2) {
514 siter = parent2->next;
515 if (parent2->parent == saux) {
516 parent2 = NULL;
517 } else {
518 parent2 = parent2->parent;
519 }
520 goto repeat_choice;
521 }
522
Radek Krejci074bf852015-08-19 14:22:16 +0200523 if (!found && (saux->flags & LYS_MAND_TRUE)) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200524 return saux;
525 }
526
527 /* go to next */
528 siter = saux->next;
529
Radek Krejci7f40ce32015-08-12 20:38:46 +0200530 break;
531 case LYS_USES:
532 case LYS_CASE:
533 /* go into */
534 parent = siter;
535 siter = siter->child;
536 break;
537 default:
538 /* can ignore, go to next */
539 siter = siter->next;
540 break;
541 }
542 }
543
544 if (parent) {
545 siter = parent->next;
546 if (parent->parent == data->schema) {
547 parent = NULL;
548 } else {
549 parent = parent->parent;
550 }
551 goto repeat;
552 }
553
554 return NULL;
555}
556
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200557void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200558lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200559{
Radek Krejci76512572015-08-04 09:47:08 +0200560 struct lys_node *parent, *first;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200561
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200562 if (!node) {
563 return;
564 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200565
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200566 /* unlink from data model if necessary */
567 if (node->module) {
568 if (node->module->data == node) {
569 node->module->data = node->next;
570 }
571 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200573 /* store pointers to important nodes */
574 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200575 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200576 /* handle augments - first, unlink it from the augment parent ... */
577 if (parent->child == node) {
578 parent->child = node->next;
579 }
580 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200581 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200582 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200583
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200584 /* unlink from parent */
585 if (parent) {
586 if (parent->child == node) {
587 parent->child = node->next;
588 }
589 node->parent = NULL;
590 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200591
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200592 /* unlink from siblings */
593 if (node->prev == node) {
594 /* there are no more siblings */
595 return;
596 }
597 if (node->next) {
598 node->next->prev = node->prev;
599 } else {
600 /* unlinking the last element */
601 if (parent) {
602 first = parent->child;
603 } else {
604 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200605 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200606 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200607 }
608 }
609 first->prev = node->prev;
610 }
611 if (node->prev->next) {
612 node->prev->next = node->next;
613 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200614
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200615 /* clean up the unlinked element */
616 node->next = NULL;
617 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200618}
619
Michal Vasko563ef092015-09-04 13:17:23 +0200620struct lys_node_grp *
621lys_find_grouping_up(const char *name, struct lys_node *start, int in_submodules)
622{
623 struct lys_node *par_iter, *iter, *stop;
624 int i;
625
626 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200627 /* top-level augment, look into module (uses augment is handled correctly below) */
628 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
629 par_iter = par_iter->parent->module->data;
630 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200631 break;
632 }
633 }
634
Michal Vasko6f929da2015-10-02 16:23:25 +0200635 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200636 continue;
637 }
638
639 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
640 if (!stop) {
641 stop = par_iter;
642 } else if (iter == stop) {
643 break;
644 }
645 if (iter->nodetype != LYS_GROUPING) {
646 continue;
647 }
648
649 if (name == iter->name) {
650 return (struct lys_node_grp *)iter;
651 }
652 }
653 }
654
655 if (in_submodules) {
656 for (i = 0; i < start->module->inc_size; ++i) {
657 for (iter = start->module->inc[i].submodule->data; iter; iter = iter->next) {
658 if (iter->nodetype != LYS_GROUPING) {
659 continue;
660 }
661
662 if (name == iter->name) {
663 return (struct lys_node_grp *)iter;
664 }
665 }
666 }
667 }
668
669 return NULL;
670}
671
Radek Krejci10c760e2015-08-14 14:45:43 +0200672/*
673 * get next grouping in the root's subtree, in the
674 * first call, tha last is NULL
675 */
676static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200677lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200678{
Radek Krejci10c760e2015-08-14 14:45:43 +0200679 struct lys_node *last = (struct lys_node *)lastgrp;
680 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200681
Radek Krejci10c760e2015-08-14 14:45:43 +0200682 assert(root);
683
684 if (!last) {
685 last = root;
686 }
687
688 while (1) {
689 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
690 next = last->child;
691 } else {
692 next = NULL;
693 }
694 if (!next) {
695 if (last == root) {
696 /* we are done */
697 return NULL;
698 }
699
700 /* no children, go to siblings */
701 next = last->next;
702 }
703 while (!next) {
704 /* go back through parents */
705 if (last->parent == root) {
706 /* we are done */
707 return NULL;
708 }
709 last = last->parent;
710 next = last->next;
711 }
712
713 if (next->nodetype == LYS_GROUPING) {
714 return (struct lys_node_grp *)next;
715 }
716
717 last = next;
718 }
719}
720
Michal Vasko0d343d12015-08-24 14:57:36 +0200721/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200722int
Radek Krejci07911992015-08-14 15:13:31 +0200723lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
724{
Michal Vasko563ef092015-09-04 13:17:23 +0200725 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200726 struct lys_node_grp *grp;
727 int down;
728
729 assert(node);
730
731 if (!parent) {
732 assert(module);
733 } else {
734 module = parent->module;
735 }
736
737 switch (node->nodetype) {
738 case LYS_GROUPING:
739 /* 6.2.1, rule 6 */
740 if (parent) {
741 if (parent->child) {
742 down = 1;
743 start = parent->child;
744 } else {
745 down = 0;
746 start = parent;
747 }
748 } else {
749 down = 1;
750 start = module->data;
751 }
752 /* go up */
Michal Vasko563ef092015-09-04 13:17:23 +0200753 if (lys_find_grouping_up(node->name, start, 0)) {
754 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
755 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200756 }
757 /* go down, because grouping can be defined after e.g. container in which is collision */
758 if (down) {
759 for (iter = start, stop = NULL; iter; iter = iter->prev) {
760 if (!stop) {
761 stop = start;
762 } else if (iter == stop) {
763 break;
764 }
765 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
766 continue;
767 }
768
769 grp = NULL;
770 while ((grp = lys_get_next_grouping(grp, iter))) {
771 if (node->name == grp->name) {
772 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
773 return EXIT_FAILURE;
774 }
775 }
776 }
777 }
778 break;
779 case LYS_LEAF:
780 case LYS_LEAFLIST:
781 case LYS_LIST:
782 case LYS_CONTAINER:
783 case LYS_CHOICE:
784 case LYS_ANYXML:
785 /* 6.2.1, rule 7 */
786 if (parent) {
787 iter = parent;
788 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE))) {
789 iter = iter->parent;
790 }
791 if (!iter) {
792 stop = NULL;
793 iter = module->data;
794 } else {
795 stop = iter;
796 iter = iter->child;
797 }
798 } else {
799 stop = NULL;
800 iter = module->data;
801 }
802 while (iter) {
803 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
804 iter = iter->child;
805 continue;
806 }
807
808 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
809 if (iter->module == node->module && iter->name == node->name) {
810 LOGVAL(LYE_SPEC, 0, "Duplicated child identifier \"%s\" in \"%s\".", node->name,
811 stop ? stop->name : "(sub)module");
812 return EXIT_FAILURE;
813 }
814 }
815
816 /* special case for choice - we must check the choice's name as
817 * well as the names of nodes under the choice
818 */
819 if (iter->nodetype == LYS_CHOICE) {
820 iter = iter->child;
821 continue;
822 }
823
824 /* go to siblings */
825 if (!iter->next) {
826 /* no sibling, go to parent's sibling */
827 do {
828 iter = iter->parent;
829 if (iter && iter->next) {
830 break;
831 }
832 } while (iter != stop);
833
834 if (iter == stop) {
835 break;
836 }
837 }
838 iter = iter->next;
839 }
840 break;
841 case LYS_CASE:
842 /* 6.2.1, rule 8 */
843 LY_TREE_FOR(parent->child, iter) {
844 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
845 continue;
846 }
847
848 if (iter->module == node->module && iter->name == node->name) {
849 LOGVAL(LYE_DUPID, 0, "case", node->name);
850 return EXIT_FAILURE;
851 }
852 }
853 break;
854 default:
855 /* no check needed */
856 break;
857 }
858
859 return EXIT_SUCCESS;
860}
861
Michal Vasko0d343d12015-08-24 14:57:36 +0200862/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200863int
Radek Krejci10c760e2015-08-14 14:45:43 +0200864lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
865{
Radek Krejci92720552015-10-05 15:28:27 +0200866 struct lys_node *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200867 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200868
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200869 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200870
Radek Krejci10c760e2015-08-14 14:45:43 +0200871 if (parent) {
872 type = parent->nodetype;
873 module = parent->module;
874 } else {
875 assert(module);
876 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200877 }
878
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200879 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200880 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200881 case LYS_CONTAINER:
882 case LYS_LIST:
883 case LYS_GROUPING:
884 case LYS_USES:
885 case LYS_INPUT:
886 case LYS_OUTPUT:
887 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200888 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200889 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
890 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200891 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200892 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
893 return EXIT_FAILURE;
894 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200895
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200896 break;
Radek Krejci76512572015-08-04 09:47:08 +0200897 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200898 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200899 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200900 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"choice\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200901 strnodetype(child->nodetype), parent->name);
902 return EXIT_FAILURE;
903 }
904 break;
Radek Krejci76512572015-08-04 09:47:08 +0200905 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200906 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200907 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200908 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"case\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200909 strnodetype(child->nodetype), parent->name);
910 return EXIT_FAILURE;
911 }
912 break;
Radek Krejci76512572015-08-04 09:47:08 +0200913 case LYS_RPC:
914 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200915 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"rpc\" %s.",
Michal Vasko38d01f72015-06-15 09:41:06 +0200916 strnodetype(child->nodetype), parent->name);
917 return EXIT_FAILURE;
918 }
919 break;
Radek Krejci76512572015-08-04 09:47:08 +0200920 case LYS_LEAF:
921 case LYS_LEAFLIST:
922 case LYS_ANYXML:
Radek Krejci10c760e2015-08-14 14:45:43 +0200923 LOGVAL(LYE_SPEC, 0, "The \"%s\" statement (%s) cannot have any data substatement.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200924 strnodetype(parent->nodetype), parent->name);
925 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200926 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200927 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200928 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
929 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200930 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200931 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
932 return EXIT_FAILURE;
933 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200934 break;
935 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200936 /* top level */
937 if (!(child->nodetype &
938 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
939 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci2c0ca272015-08-14 15:31:01 +0200940 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in (sub)module \"%s\"",
941 strnodetype(child->nodetype), module->name);
Radek Krejci10c760e2015-08-14 14:45:43 +0200942 return EXIT_FAILURE;
943 }
944
945 break;;
946 }
947
948 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200949 if (lys_check_id(child, parent, module)) {
950 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200951 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200952
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200953 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200954 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200955 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200956
Radek Krejci10c760e2015-08-14 14:45:43 +0200957 if (!parent) {
Radek Krejci92720552015-10-05 15:28:27 +0200958 if (module->data) {
959 module->data->prev->next = child;
960 child->prev = module->data->prev;
961 module->data->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200962 } else {
Radek Krejci92720552015-10-05 15:28:27 +0200963 module->data = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200964 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200965 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +0200966 if (!parent->child) {
967 /* the only/first child of the parent */
968 parent->child = child;
969 child->parent = parent;
970 iter = child;
971 } else {
972 /* add a new child at the end of parent's child list */
973 iter = parent->child->prev;
974 iter->next = child;
975 child->prev = iter;
976 }
977 while (iter->next) {
978 iter = iter->next;
979 iter->parent = parent;
980 }
981 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200982 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200983
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200984 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200985}
986
Radek Krejcib8048692015-08-05 13:36:34 +0200987API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +0200988lys_parse(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200989{
Michal Vaskof02e3742015-08-05 16:27:02 +0200990 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200991 struct lys_module *mod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200992
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200993 if (!ctx || !data) {
994 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
995 return NULL;
996 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200997
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200998 unres = calloc(1, sizeof *unres);
999
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001000 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001001 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001002 mod = yin_read_module(ctx, data, 1, unres);
1003 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001004 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001005 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001006 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001007 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001008 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001009
Michal Vasko0bd29d12015-08-19 11:45:49 +02001010 if (mod && unres->count && resolve_unres_schema(mod, unres)) {
Michal Vasko13b15832015-08-19 11:04:48 +02001011 lys_free(mod, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001012 mod = NULL;
1013 }
1014 free(unres->item);
1015 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +02001016 free(unres->str_snode);
Michal Vaskoc07187d2015-08-13 15:20:57 +02001017#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001018 free(unres->line);
Michal Vaskoc07187d2015-08-13 15:20:57 +02001019#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001020 free(unres);
1021
1022 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001023}
1024
Radek Krejcib8048692015-08-05 13:36:34 +02001025struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001026lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02001027{
Michal Vaskof02e3742015-08-05 16:27:02 +02001028 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +02001029 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001030
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001031 assert(module);
1032 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001033
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001034 unres = calloc(1, sizeof *unres);
1035
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001036 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001037 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001038 submod = yin_read_submodule(module, data, implement, unres);
1039 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001040 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001041 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001042 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001043 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001044 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001045
Michal Vasko0bd29d12015-08-19 11:45:49 +02001046 if (submod && unres->count && resolve_unres_schema((struct lys_module *)submod, unres)) {
Michal Vasko13b15832015-08-19 11:04:48 +02001047 lys_submodule_free(submod, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001048 submod = NULL;
1049 }
1050 free(unres->item);
1051 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +02001052 free(unres->str_snode);
Michal Vaskoc07187d2015-08-13 15:20:57 +02001053#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001054 free(unres->line);
Michal Vaskoc07187d2015-08-13 15:20:57 +02001055#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001056 free(unres);
1057
1058 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001059}
1060
Radek Krejcib8048692015-08-05 13:36:34 +02001061API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +02001062lys_read(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001063{
Radek Krejcib8048692015-08-05 13:36:34 +02001064 struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +02001065 struct stat sb;
1066 char *addr;
1067
1068 if (!ctx || fd < 0) {
1069 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1070 return NULL;
1071 }
1072
1073 /*
1074 * TODO
1075 * This is just a temporary solution to make working automatic search for
1076 * imported modules. This doesn't work e.g. for streams (stdin)
1077 */
1078 fstat(fd, &sb);
1079 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
1080 module = lys_parse(ctx, addr, format);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001081 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001082
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001083 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001084}
1085
Radek Krejcib8048692015-08-05 13:36:34 +02001086struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001087lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02001088{
Radek Krejcib8048692015-08-05 13:36:34 +02001089 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001090 struct stat sb;
1091 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001092
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001093 assert(module);
1094 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001095
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001096 /*
1097 * TODO
1098 * This is just a temporary solution to make working automatic search for
1099 * imported modules. This doesn't work e.g. for streams (stdin)
1100 */
1101 fstat(fd, &sb);
1102 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
1103 /* TODO addr error check */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001104 submodule = lys_submodule_parse(module, addr, format, implement);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001105 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +02001106
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001107 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02001108
1109}
1110
Radek Krejci1d82ef62015-08-07 14:44:40 +02001111static struct lys_restr *
1112lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001113{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001114 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001115 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001116
Radek Krejci3733a802015-06-19 13:43:21 +02001117 if (!size) {
1118 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001119 }
Radek Krejci3733a802015-06-19 13:43:21 +02001120
1121 result = calloc(size, sizeof *result);
1122 for (i = 0; i < size; i++) {
1123 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1124 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1125 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1126 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1127 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1128 }
1129
1130 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001131}
1132
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001133void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001134lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001135{
1136 assert(ctx);
1137 if (!restr) {
1138 return;
1139 }
1140
1141 lydict_remove(ctx, restr->expr);
1142 lydict_remove(ctx, restr->dsc);
1143 lydict_remove(ctx, restr->ref);
1144 lydict_remove(ctx, restr->eapptag);
1145 lydict_remove(ctx, restr->emsg);
1146}
1147
Michal Vaskob84f88a2015-09-24 13:16:10 +02001148static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001149lys_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 +02001150 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001151{
1152 int i;
1153
Michal Vasko0fb82c62015-10-20 13:41:53 +02001154 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001155 new->base = old->base;
1156 new->der = old->der;
1157
Michal Vasko0bd29d12015-08-19 11:45:49 +02001158 i = unres_schema_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001159 if (i != -1) {
1160 /* HACK for unres */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001161 new->der = (struct lys_tpdf *)parent;
Michal Vaskob84f88a2015-09-24 13:16:10 +02001162 /* all these unres additions can fail even though they did not before */
Michal Vasko0bd29d12015-08-19 11:45:49 +02001163 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_DER, unres->str_snode[i], 0) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001164 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001165 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001166 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001167 }
1168
Radek Krejci3733a802015-06-19 13:43:21 +02001169 switch (new->base) {
1170 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +02001171 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001172 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001173 }
Radek Krejci3733a802015-06-19 13:43:21 +02001174 break;
1175
1176 case LY_TYPE_BITS:
1177 new->info.bits.count = old->info.bits.count;
1178 if (new->info.bits.count) {
1179 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1180 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001181 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1182 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1183 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001184 new->info.bits.bit[i].status = old->info.bits.bit[i].status;
1185 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1186 }
1187 }
1188 break;
1189
Radek Krejcif9401c32015-06-26 16:47:36 +02001190 case LY_TYPE_DEC64:
1191 new->info.dec64.dig = old->info.dec64.dig;
1192 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001193 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +02001194 }
1195 break;
1196
Radek Krejci3733a802015-06-19 13:43:21 +02001197 case LY_TYPE_ENUM:
1198 new->info.enums.count = old->info.enums.count;
1199 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001200 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Radek Krejci3733a802015-06-19 13:43:21 +02001201 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001202 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1203 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1204 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1205 new->info.enums.enm[i].status = old->info.enums.enm[i].status;
1206 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +02001207 }
1208 }
1209 break;
1210
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001211 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001212 if (old->info.ident.ref) {
1213 new->info.ident.ref = old->info.ident.ref;
1214 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001215 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001216 assert(i != -1);
Michal Vasko0bd29d12015-08-19 11:45:49 +02001217 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i], 0) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001218 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001219 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001220 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001221 break;
1222
Radek Krejciaf351422015-06-19 14:49:38 +02001223 case LY_TYPE_INST:
1224 new->info.inst.req = old->info.inst.req;
1225 break;
1226
Radek Krejcif2860132015-06-20 12:37:20 +02001227 case LY_TYPE_INT8:
1228 case LY_TYPE_INT16:
1229 case LY_TYPE_INT32:
1230 case LY_TYPE_INT64:
1231 case LY_TYPE_UINT8:
1232 case LY_TYPE_UINT16:
1233 case LY_TYPE_UINT32:
1234 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +02001235 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001236 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001237 }
Radek Krejcif2860132015-06-20 12:37:20 +02001238 break;
1239
Radek Krejcidc4c1412015-06-19 15:39:54 +02001240 case LY_TYPE_LEAFREF:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001241 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02001242 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001243 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001244 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001245 break;
1246
Radek Krejci3733a802015-06-19 13:43:21 +02001247 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +02001248 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001249 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001250 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001251 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 +02001252 break;
1253
Radek Krejcie4c366b2015-07-02 10:11:31 +02001254 case LY_TYPE_UNION:
1255 new->info.uni.count = old->info.uni.count;
1256 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001257 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001258 for (i = 0; i < new->info.uni.count; i++) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001259 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres)) {
1260 return -1;
1261 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001262 }
1263 }
1264 break;
1265
Radek Krejci3733a802015-06-19 13:43:21 +02001266 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001267 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001268 break;
1269 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001270
1271 return EXIT_SUCCESS;
Radek Krejci3733a802015-06-19 13:43:21 +02001272}
1273
1274void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001275lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001276{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001277 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001278
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001279 assert(ctx);
1280 if (!type) {
1281 return;
1282 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001283
Michal Vasko0fb82c62015-10-20 13:41:53 +02001284 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001286 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001287 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001288 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001289 free(type->info.binary.length);
1290 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001291 case LY_TYPE_BITS:
1292 for (i = 0; i < type->info.bits.count; i++) {
1293 lydict_remove(ctx, type->info.bits.bit[i].name);
1294 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1295 lydict_remove(ctx, type->info.bits.bit[i].ref);
1296 }
1297 free(type->info.bits.bit);
1298 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001299
1300 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001301 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001302 free(type->info.dec64.range);
1303 break;
1304
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001305 case LY_TYPE_ENUM:
1306 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001307 lydict_remove(ctx, type->info.enums.enm[i].name);
1308 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1309 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001310 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001311 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001312 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001313
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001314 case LY_TYPE_INT8:
1315 case LY_TYPE_INT16:
1316 case LY_TYPE_INT32:
1317 case LY_TYPE_INT64:
1318 case LY_TYPE_UINT8:
1319 case LY_TYPE_UINT16:
1320 case LY_TYPE_UINT32:
1321 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001322 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001323 free(type->info.num.range);
1324 break;
1325
Radek Krejcidc4c1412015-06-19 15:39:54 +02001326 case LY_TYPE_LEAFREF:
1327 lydict_remove(ctx, type->info.lref.path);
1328 break;
1329
Radek Krejci3733a802015-06-19 13:43:21 +02001330 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001331 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001332 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001333 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001334 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001335 }
1336 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001337 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001338
Radek Krejcie4c366b2015-07-02 10:11:31 +02001339 case LY_TYPE_UNION:
1340 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001341 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001342 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001343 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001344 break;
1345
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001346 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001347 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001348 break;
1349 }
Radek Krejci5a065542015-05-22 15:02:07 +02001350}
1351
Radek Krejci1d82ef62015-08-07 14:44:40 +02001352static void
1353lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001354{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001355 assert(ctx);
1356 if (!tpdf) {
1357 return;
1358 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001359
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001360 lydict_remove(ctx, tpdf->name);
1361 lydict_remove(ctx, tpdf->dsc);
1362 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001363
Radek Krejci1d82ef62015-08-07 14:44:40 +02001364 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001365
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001366 lydict_remove(ctx, tpdf->units);
1367 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001368}
1369
Michal Vaskob84f88a2015-09-24 13:16:10 +02001370static struct lys_tpdf *
1371lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1372{
1373 struct lys_tpdf *result;
1374 int i, j;
1375
1376 if (!size) {
1377 return NULL;
1378 }
1379
1380 result = calloc(size, sizeof *result);
1381 for (i = 0; i < size; i++) {
1382 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1383 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1384 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1385 result[i].flags = old[i].flags;
1386 result[i].module = old[i].module;
1387
1388 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres)) {
1389 for (j = 0; j <= i; ++j) {
1390 lys_tpdf_free(mod->ctx, &result[j]);
1391 }
1392 free(result);
1393 return NULL;
1394 }
1395
1396 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1397 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1398 }
1399
1400 return result;
1401}
1402
Radek Krejci1d82ef62015-08-07 14:44:40 +02001403static struct lys_when *
1404lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001405{
Radek Krejci76512572015-08-04 09:47:08 +02001406 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001407
1408 if (!old) {
1409 return NULL;
1410 }
1411
1412 new = calloc(1, sizeof *new);
1413 new->cond = lydict_insert(ctx, old->cond, 0);
1414 new->dsc = lydict_insert(ctx, old->dsc, 0);
1415 new->ref = lydict_insert(ctx, old->ref, 0);
1416
1417 return new;
1418}
1419
Michal Vasko0308dd62015-10-07 09:14:40 +02001420void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001421lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001422{
1423 if (!w) {
1424 return;
1425 }
1426
1427 lydict_remove(ctx, w->cond);
1428 lydict_remove(ctx, w->dsc);
1429 lydict_remove(ctx, w->ref);
1430
1431 free(w);
1432}
1433
Radek Krejcib7f5e412015-08-13 10:15:51 +02001434static void
1435lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment aug)
1436{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001437 struct lys_node *next, *sub;
1438
1439 /* children from a resolved uses */
1440 LY_TREE_FOR_SAFE(aug.child, next, sub) {
1441 lys_node_free(sub);
1442 }
1443
Radek Krejcib7f5e412015-08-13 10:15:51 +02001444 lydict_remove(ctx, aug.target_name);
1445 lydict_remove(ctx, aug.dsc);
1446 lydict_remove(ctx, aug.ref);
1447
1448 free(aug.features);
1449
1450 lys_when_free(ctx, aug.when);
1451
Michal Vasko7d356a52015-08-19 15:06:31 +02001452 /* Do not free the children, they were appended somewhere and their
1453 * new parent will take care of them.
1454 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001455}
1456
Radek Krejci76512572015-08-04 09:47:08 +02001457static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001458lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001459{
Radek Krejci76512572015-08-04 09:47:08 +02001460 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001461 struct lys_node *old_child, *new_child;
1462 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001463
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001464 if (!size) {
1465 return NULL;
1466 }
Radek Krejci106efc02015-06-10 14:36:27 +02001467
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001468 new = calloc(size, sizeof *new);
1469 for (i = 0; i < size; i++) {
1470 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1471 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1472 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1473 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001474 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001475 new[i].nodetype = old[i].nodetype;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001476 /* this must succeed, it was already resolved once */
1477 if (resolve_schema_nodeid(new[i].target_name, parent->child, new[i].module, LYS_AUGMENT, &new[i].target)) {
1478 LOGINT;
1479 free(new);
1480 return NULL;
1481 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001482 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001483
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001484 /* Correct the augment nodes.
1485 * This function can only be called from lys_node_dup() with uses
1486 * being the node duplicated, so we must have a case of grouping
1487 * with a uses with augments. The augmented nodes have already been
1488 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001489 * (it was set to their actual data parent, not an augment), and
1490 * the new augment does not have child pointer to its augment nodes,
1491 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001492 */
1493 LY_TREE_FOR(new[i].target->child, new_child) {
1494 if (new_child->name == old[i].child->name) {
1495 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001496 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001497 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001498 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001499 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001500 LY_TREE_FOR(old[i].child, old_child) {
1501 /* all augment nodes were connected as siblings, there can be no more after this */
1502 if (old_child->parent != (struct lys_node *)&old[i]) {
1503 break;
1504 }
1505
1506 assert(old_child->name == new_child->name);
1507
1508 new_child->parent = (struct lys_node *)&new[i];
1509 new_child = new_child->next;
1510 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001511 }
Radek Krejci106efc02015-06-10 14:36:27 +02001512
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001513 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001514}
1515
Radek Krejci76512572015-08-04 09:47:08 +02001516static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001517lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001518{
Radek Krejci76512572015-08-04 09:47:08 +02001519 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001520 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001521
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001522 if (!size) {
1523 return NULL;
1524 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001525
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001526 result = calloc(size, sizeof *result);
1527 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001528 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001529 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1530 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001531 result[i].flags = old[i].flags;
1532 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001533
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001534 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001535 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001536
Radek Krejci76512572015-08-04 09:47:08 +02001537 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001538 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001539 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001540 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001541 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001542 result[i].mod.list = old[i].mod.list;
1543 }
1544 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001545
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001546 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001547}
1548
Radek Krejci1d82ef62015-08-07 14:44:40 +02001549static void
1550lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001551{
Radek Krejcia52656e2015-08-05 13:41:50 +02001552 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001553
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001554 assert(ctx);
1555 if (!ident) {
1556 return;
1557 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001558
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001559 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001560 * if caller free only a single data model which is used (its identity is
1561 * reference from identity in another module), this silly freeing can lead
1562 * to segmentation fault. But without noting if the module is used by some
1563 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001564 *
1565 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001566 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001567 */
1568 while (ident->der) {
1569 der = ident->der;
1570 ident->der = der->next;
1571 free(der);
1572 }
Radek Krejci6793db02015-05-22 17:49:54 +02001573
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001574 lydict_remove(ctx, ident->name);
1575 lydict_remove(ctx, ident->dsc);
1576 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001577
1578}
1579
Radek Krejci1d82ef62015-08-07 14:44:40 +02001580static void
1581lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001582{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001583 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001584
Radek Krejcid12f57b2015-08-06 10:43:39 +02001585 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001586 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001587 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001588 }
1589 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001590}
1591
Radek Krejci1d82ef62015-08-07 14:44:40 +02001592static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001593lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1594{
1595 int i;
1596
1597 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1598 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001599 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001600 }
1601 free(io->tpdf);
1602}
1603
Radek Krejci1d82ef62015-08-07 14:44:40 +02001604static void
1605lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001606{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001607 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001608
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001609 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001610 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001611 }
1612 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001613
Radek Krejci1d82ef62015-08-07 14:44:40 +02001614 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001615}
1616
Radek Krejci1d82ef62015-08-07 14:44:40 +02001617static void
1618lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001619{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001620 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001621
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001622 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001623 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001624 }
1625 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001626
Radek Krejci1d82ef62015-08-07 14:44:40 +02001627 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001628
Radek Krejci1d82ef62015-08-07 14:44:40 +02001629 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001630 lydict_remove(ctx, leaf->units);
1631 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001632}
1633
Radek Krejci1d82ef62015-08-07 14:44:40 +02001634static void
1635lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001636{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001637 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001638
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001639 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001640 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001641 }
1642 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001643
Radek Krejci1d82ef62015-08-07 14:44:40 +02001644 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001645
Radek Krejci1d82ef62015-08-07 14:44:40 +02001646 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001647 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001648}
1649
Radek Krejci1d82ef62015-08-07 14:44:40 +02001650static void
1651lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001652{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001653 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001654
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001655 /* handle only specific parts for LY_NODE_LIST */
1656 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001657 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001658 }
1659 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001660
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001661 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001662 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001663 }
1664 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001665
Radek Krejci1d82ef62015-08-07 14:44:40 +02001666 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001667
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001668 for (i = 0; i < list->unique_size; i++) {
1669 free(list->unique[i].leafs);
1670 }
1671 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001672
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001673 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001674}
1675
Radek Krejci1d82ef62015-08-07 14:44:40 +02001676static void
1677lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001678{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001679 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001680
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001681 /* handle only specific parts for LY_NODE_CONTAINER */
1682 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001683
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001684 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001685 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001686 }
1687 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001688
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001689 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001690 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001691 }
1692 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001693
Radek Krejci1d82ef62015-08-07 14:44:40 +02001694 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001695}
1696
Radek Krejci1d82ef62015-08-07 14:44:40 +02001697static void
1698lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001699{
1700 lydict_remove(ctx, f->name);
1701 lydict_remove(ctx, f->dsc);
1702 lydict_remove(ctx, f->ref);
1703 free(f->features);
1704}
1705
Radek Krejci1d82ef62015-08-07 14:44:40 +02001706static void
1707lys_deviation_free(struct ly_ctx *ctx, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001708{
1709 int i, j;
1710
1711 lydict_remove(ctx, dev->target_name);
1712 lydict_remove(ctx, dev->dsc);
1713 lydict_remove(ctx, dev->ref);
1714
1715 for (i = 0; i < dev->deviate_size; i++) {
1716 lydict_remove(ctx, dev->deviate[i].dflt);
1717 lydict_remove(ctx, dev->deviate[i].units);
1718
1719 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1720 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001721 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001722 }
1723 free(dev->deviate[i].must);
1724
1725 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1726 free(dev->deviate[j].unique[j].leafs);
1727 }
1728 free(dev->deviate[i].unique);
1729 }
1730 }
1731 free(dev->deviate);
1732}
1733
Radek Krejci1d82ef62015-08-07 14:44:40 +02001734static void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001735lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +02001736{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001737 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001738
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001739 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001740 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001741 lydict_remove(ctx, uses->refine[i].dsc);
1742 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001743
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001744 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001745 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001746 }
1747 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001748
Radek Krejci76512572015-08-04 09:47:08 +02001749 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001750 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001751 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001752 lydict_remove(ctx, uses->refine[i].mod.presence);
1753 }
1754 }
1755 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001756
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001757 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001758 lys_augment_free(ctx, uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001759 }
1760 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001761
Radek Krejci1d82ef62015-08-07 14:44:40 +02001762 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001763}
1764
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001765void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001766lys_node_free(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001767{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001768 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001769 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001770
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001771 if (!node) {
1772 return;
1773 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001774
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001775 assert(node->module);
1776 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001777
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001778 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001779
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001780 /* common part */
1781 LY_TREE_FOR_SAFE(node->child, next, sub) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001782 lys_node_free(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001783 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001784
Radek Krejcid12f57b2015-08-06 10:43:39 +02001785 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1786 free(node->features);
1787 lydict_remove(ctx, node->name);
1788 lydict_remove(ctx, node->dsc);
1789 lydict_remove(ctx, node->ref);
1790 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001791
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001792 /* specific part */
1793 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001794 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001795 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001796 break;
Radek Krejci76512572015-08-04 09:47:08 +02001797 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001798 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001799 break;
Radek Krejci76512572015-08-04 09:47:08 +02001800 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001801 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001802 break;
Radek Krejci76512572015-08-04 09:47:08 +02001803 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001804 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001805 break;
Radek Krejci76512572015-08-04 09:47:08 +02001806 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001807 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001808 break;
Radek Krejci76512572015-08-04 09:47:08 +02001809 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001810 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001811 break;
Radek Krejci76512572015-08-04 09:47:08 +02001812 case LYS_USES:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001813 lys_uses_free(ctx, (struct lys_node_uses *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001814 break;
Radek Krejci76512572015-08-04 09:47:08 +02001815 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001816 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001817 break;
Radek Krejci76512572015-08-04 09:47:08 +02001818 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001819 /* do nothing */
1820 break;
Radek Krejci76512572015-08-04 09:47:08 +02001821 case LYS_GROUPING:
1822 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001823 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001824 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001825 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001826
1827 case LYS_INPUT:
1828 case LYS_OUTPUT:
1829 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1830 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001831 case LYS_UNKNOWN:
1832 LOGINT;
1833 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001834 }
Radek Krejci5a065542015-05-22 15:02:07 +02001835
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001836 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001837 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001838 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001839}
1840
Michal Vasko8ce24d72015-10-21 11:27:26 +02001841struct lys_module *
Michal Vaskob6729c62015-10-21 12:09:47 +02001842lys_get_import_module(struct lys_module *module, const char *prefix, int pref_len, const char *name, int name_len)
Michal Vasko8ce24d72015-10-21 11:27:26 +02001843{
Michal Vaskob6729c62015-10-21 12:09:47 +02001844 int i, match;
1845
1846 assert(prefix || name);
1847 if (prefix && !pref_len) {
1848 pref_len = strlen(prefix);
1849 }
1850 if (name && !name_len) {
1851 name_len = strlen(name);
1852 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02001853
Michal Vaskod8da86b2015-10-21 13:35:37 +02001854 if ((!prefix || (!strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
1855 && (!name || (!strncmp(module->name, name, name_len) && !module->name[name_len]))) {
1856 return module;
1857 }
1858
Michal Vasko8ce24d72015-10-21 11:27:26 +02001859 for (i = 0; i < module->imp_size; ++i) {
Michal Vaskob6729c62015-10-21 12:09:47 +02001860 match = 0;
1861 if (!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len])) {
1862 match = 1;
1863 }
1864 if (match && (!name
1865 || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02001866 return module->imp[i].module;
1867 }
1868 }
1869
1870 return NULL;
1871}
1872
Michal Vasko13b15832015-08-19 11:04:48 +02001873/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001874static void
Michal Vasko13b15832015-08-19 11:04:48 +02001875module_free_common(struct lys_module *module, int free_int_mods)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001876{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001877 struct ly_ctx *ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001878 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001879 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001880
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001881 assert(module->ctx);
1882 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001883
Radek Krejcidce51452015-06-16 15:20:08 +02001884 /* as first step, free the imported modules */
1885 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa76ee152015-08-17 15:38:22 +02001886 /* do not free internal modules */
Michal Vasko18bd09b2015-08-19 15:07:00 +02001887 if (!free_int_mods) {
1888 for (j = 0; j < int_mods.count; ++j) {
Michal Vaskod83c03a2015-08-21 09:09:24 +02001889 if (module->imp[i].module && !strcmp(int_mods.modules[j].name, module->imp[i].module->name)
Michal Vasko18bd09b2015-08-19 15:07:00 +02001890 && module->imp[i].module->rev
1891 && !strcmp(int_mods.modules[j].revision, module->imp[i].module->rev[0].date)) {
1892 break;
1893 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02001894 }
Michal Vasko18bd09b2015-08-19 15:07:00 +02001895 if (j < int_mods.count) {
1896 continue;
1897 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02001898 }
1899
Radek Krejcidce51452015-06-16 15:20:08 +02001900 /* get the imported module from the context and then free,
1901 * this check is necessary because the imported module can
1902 * be already removed
1903 */
1904 l = ctx->models.used;
1905 for (j = 0; j < l; j++) {
1906 if (ctx->models.list[j] == module->imp[i].module) {
Michal Vasko13b15832015-08-19 11:04:48 +02001907 lys_free(module->imp[i].module, free_int_mods);
Radek Krejcidce51452015-06-16 15:20:08 +02001908 break;
1909 }
1910 }
1911 }
1912 free(module->imp);
1913
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001914 while (module->data) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001915 lys_node_free(module->data);
Radek Krejci21181962015-06-30 14:11:00 +02001916 }
Radek Krejci5a065542015-05-22 15:02:07 +02001917
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001918 lydict_remove(ctx, module->dsc);
1919 lydict_remove(ctx, module->ref);
1920 lydict_remove(ctx, module->org);
1921 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001922
Radek Krejcieb00f512015-07-01 16:44:58 +02001923 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001924 for (i = 0; i < module->rev_size; i++) {
1925 lydict_remove(ctx, module->rev[i].dsc);
1926 lydict_remove(ctx, module->rev[i].ref);
1927 }
1928 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001929
Radek Krejcieb00f512015-07-01 16:44:58 +02001930 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001931 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001932 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001933 }
1934 module->ident_size = 0;
1935 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001936
Radek Krejcieb00f512015-07-01 16:44:58 +02001937 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001938 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001939 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001940 }
1941 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001942
Radek Krejcieb00f512015-07-01 16:44:58 +02001943 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001944 for (i = 0; i < module->inc_size; i++) {
Michal Vasko13b15832015-08-19 11:04:48 +02001945 lys_submodule_free(module->inc[i].submodule, free_int_mods);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001946 }
1947 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001948
Radek Krejcieb00f512015-07-01 16:44:58 +02001949 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02001950 for (i = 0; i < module->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001951 lys_augment_free(ctx, module->augment[i]);
Radek Krejcif5be10f2015-06-16 13:29:36 +02001952 }
1953 free(module->augment);
1954
Radek Krejcieb00f512015-07-01 16:44:58 +02001955 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001956 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001957 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001958 }
1959 free(module->features);
1960
Radek Krejcieb00f512015-07-01 16:44:58 +02001961 /* deviations */
1962 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001963 lys_deviation_free(ctx, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001964 }
1965 free(module->deviation);
1966
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001967 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02001968}
1969
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001970void
Michal Vasko13b15832015-08-19 11:04:48 +02001971lys_submodule_free(struct lys_submodule *submodule, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02001972{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001973 if (!submodule) {
1974 return;
1975 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001976
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001977 submodule->inc_size = 0;
1978 free(submodule->inc);
1979 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02001980
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001981 /* common part with struct ly_module */
Michal Vasko13b15832015-08-19 11:04:48 +02001982 module_free_common((struct lys_module *)submodule, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02001983
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001984 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02001985
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001986 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001987}
1988
Radek Krejcib8048692015-08-05 13:36:34 +02001989static struct lys_node_leaf *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001990lys_uniq_find(struct lys_node_list *list, struct lys_node_leaf *orig_leaf)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001991{
Radek Krejci1d82ef62015-08-07 14:44:40 +02001992 struct lys_node *node, *node2, *ret = NULL, *parent1, *parent2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001993 int depth = 1, i;
1994
1995 /* find the correct direct descendant of list in orig_leaf */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001996 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001997 while (1) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001998 if (!node->parent) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001999 return NULL;
2000 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002001 if (!strcmp(node->parent->name, list->name)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002002 break;
2003 }
2004
Radek Krejci1d82ef62015-08-07 14:44:40 +02002005 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002006 ++depth;
2007 }
2008
2009 /* make sure the nodes are equal */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002010 parent1 = node->parent->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002011 parent2 = list->parent;
2012 while (1) {
2013 if ((parent1 && !parent2) || (!parent1 && parent2)) {
2014 return NULL;
2015 }
2016
2017 if (parent1 == parent2) {
2018 break;
2019 }
2020
2021 parent1 = parent1->parent;
2022 parent2 = parent2->parent;
2023 }
2024
2025 /* find the descendant in the list */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002026 LY_TREE_FOR(list->child, node2) {
2027 if (!strcmp(node2->name, node->name)) {
2028 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002029 break;
2030 }
2031 }
2032
2033 if (!ret) {
2034 return NULL;
2035 }
2036
2037 /* continue traversing both trees, the nodes are always truly equal */
2038 while (1) {
2039 --depth;
2040 if (!depth) {
Radek Krejci76512572015-08-04 09:47:08 +02002041 if (ret->nodetype != LYS_LEAF) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002042 return NULL;
2043 }
Radek Krejcib8048692015-08-05 13:36:34 +02002044 return (struct lys_node_leaf *)ret;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002045 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002046 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002047 for (i = 0; i < depth-1; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002048 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002049 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002050 LY_TREE_FOR(ret->child, node2) {
2051 if (!strcmp(node2->name, node->name)) {
2052 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002053 break;
2054 }
2055 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002056 if (!node2) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002057 return NULL;
2058 }
2059 }
2060}
2061
Radek Krejci76512572015-08-04 09:47:08 +02002062struct lys_node *
Michal Vasko71e1aa82015-08-12 12:17:51 +02002063lys_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 +02002064 struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002065{
Radek Krejci76512572015-08-04 09:47:08 +02002066 struct lys_node *retval = NULL, *aux, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002067 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002068 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002069
Michal Vaskoc07187d2015-08-13 15:20:57 +02002070 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002071 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002072 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002073 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002074 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002075 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002076 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002077 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002078 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002079 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002080 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002081 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002082 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002083 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002084 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002085 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002086 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002087 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002088 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002089 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002090 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002091 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002092 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002093 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002094
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002095 /* we cannot just duplicate memory since the strings are stored in
2096 * dictionary and we need to update dictionary counters.
2097 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002098
Radek Krejci1d82ef62015-08-07 14:44:40 +02002099 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002100 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002101 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002102 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002103 break;
2104
Radek Krejci76512572015-08-04 09:47:08 +02002105 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002106 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002107 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002108 break;
2109
Radek Krejci76512572015-08-04 09:47:08 +02002110 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002111 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002112 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002113 break;
2114
Radek Krejci76512572015-08-04 09:47:08 +02002115 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002116 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002117 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002118 break;
2119
Radek Krejci76512572015-08-04 09:47:08 +02002120 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002121 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002122 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002123 break;
2124
Radek Krejci76512572015-08-04 09:47:08 +02002125 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002126 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002127 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002128 break;
2129
Radek Krejci76512572015-08-04 09:47:08 +02002130 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002131 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002132 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002133 break;
2134
Radek Krejci76512572015-08-04 09:47:08 +02002135 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002136 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002137 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002138 break;
2139
Radek Krejci76512572015-08-04 09:47:08 +02002140 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002141 grp = calloc(1, sizeof *grp);
2142 retval = (struct lys_node *)grp;
2143 break;
2144
Radek Krejci76512572015-08-04 09:47:08 +02002145 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002146 rpc = calloc(1, sizeof *rpc);
2147 retval = (struct lys_node *)rpc;
2148 break;
2149
Radek Krejci76512572015-08-04 09:47:08 +02002150 case LYS_INPUT:
2151 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002152 io = calloc(1, sizeof *io);
2153 retval = (struct lys_node *)io;
2154 break;
2155
Radek Krejci76512572015-08-04 09:47:08 +02002156 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002157 ntf = calloc(1, sizeof *ntf);
2158 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002159 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002160
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002161 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002162 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002163 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002164 }
Radek Krejcib388c152015-06-04 17:03:03 +02002165
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002166 /*
2167 * duplicate generic part of the structure
2168 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002169 retval->name = lydict_insert(ctx, node->name, 0);
2170 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2171 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002172 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002173 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002174 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002175 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002176 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002177 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002178
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002179 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002180 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002181
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002182 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002183
Radek Krejci1d82ef62015-08-07 14:44:40 +02002184 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002185 retval->features = calloc(retval->features_size, sizeof *retval->features);
Radek Krejci1d82ef62015-08-07 14:44:40 +02002186 for (i = 0; i < node->features_size; ++i) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002187 if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002188 retval->features[i] = node->features[i];
Michal Vaskod23ce592015-08-06 09:55:37 +02002189 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002190 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002191
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002192 if (recursive) {
2193 /* go recursively */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002194 LY_TREE_FOR(node->child, child) {
Michal Vasko71e1aa82015-08-12 12:17:51 +02002195 aux = lys_node_dup(module, child, retval->flags, retval->nacm, 1, unres);
Radek Krejci10c760e2015-08-14 14:45:43 +02002196 if (!aux || lys_node_addchild(retval, NULL, aux)) {
Michal Vasko49168a22015-08-17 16:35:41 +02002197 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002198 }
2199 }
2200 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002201
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002202 /*
2203 * duplicate specific part of the structure
2204 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002205 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002206 case LYS_CONTAINER:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002207 if (cont_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002208 cont->when = lys_when_dup(ctx, cont_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002209 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002210 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002211
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002212 cont->must_size = cont_orig->must_size;
2213 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002214
Radek Krejci1d82ef62015-08-07 14:44:40 +02002215 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci1d82ef62015-08-07 14:44:40 +02002216 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002217 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002218
Radek Krejci76512572015-08-04 09:47:08 +02002219 case LYS_CHOICE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002220 if (choice_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002221 choice->when = lys_when_dup(ctx, choice_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002222 }
2223
2224 if (choice_orig->dflt) {
Michal Vaskof6dfae02015-10-20 13:47:06 +02002225 rc = lys_getsibling(choice->module, choice->child, NULL, 0, choice_orig->dflt->name, 0, LYS_ANYXML
Radek Krejci76512572015-08-04 09:47:08 +02002226 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002227 | LYS_LIST, &choice->dflt);
Michal Vasko49168a22015-08-17 16:35:41 +02002228 if (rc) {
2229 if (rc == EXIT_FAILURE) {
2230 LOGINT;
2231 }
2232 goto error;
2233 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002234 } else {
Michal Vaskoc68a2a22015-08-06 09:57:24 +02002235 /* useless to check return value, we don't know whether
2236 * there really wasn't any default defined or it just hasn't
2237 * been resolved, we just hope for the best :)
2238 */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002239 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002240 }
2241 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002242
Radek Krejci76512572015-08-04 09:47:08 +02002243 case LYS_LEAF:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002244 if (lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres)) {
2245 goto error;
2246 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002247 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2248
2249 if (leaf_orig->dflt) {
2250 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002251 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002252 goto error;
2253 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002254 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002255
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002256 leaf->must_size = leaf_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002257 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002258
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002259 if (leaf_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002260 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002261 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002262 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002263
Radek Krejci76512572015-08-04 09:47:08 +02002264 case LYS_LEAFLIST:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002265 if (lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres)) {
2266 goto error;
2267 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002268 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002269
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002270 llist->min = llist_orig->min;
2271 llist->max = llist_orig->max;
2272
2273 llist->must_size = llist_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002274 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002275
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002276 if (llist_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002277 llist->when = lys_when_dup(ctx, llist_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002278 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002279 break;
2280
Radek Krejci76512572015-08-04 09:47:08 +02002281 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002282 list->min = list_orig->min;
2283 list->max = list_orig->max;
2284
2285 list->must_size = list_orig->must_size;
2286 list->tpdf_size = list_orig->tpdf_size;
2287 list->keys_size = list_orig->keys_size;
2288 list->unique_size = list_orig->unique_size;
2289
Radek Krejci1d82ef62015-08-07 14:44:40 +02002290 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002291
Radek Krejci1d82ef62015-08-07 14:44:40 +02002292 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002293
2294 if (list->keys_size) {
2295 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002296
2297 /* we managed to resolve it before, resolve it again manually */
2298 if (list_orig->keys[0]) {
2299 for (i = 0; i < list->keys_size; ++i) {
Michal Vaskof6dfae02015-10-20 13:47:06 +02002300 rc = lys_getsibling(list->module, list->child, NULL, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2301 (struct lys_node **)&list->keys[i]);
Michal Vasko49168a22015-08-17 16:35:41 +02002302 if (rc) {
2303 if (rc == EXIT_FAILURE) {
2304 LOGINT;
2305 }
2306 goto error;
2307 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002308 }
2309 /* it was not resolved yet, add unres copy */
2310 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002311 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02002312 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002313 goto error;
Michal Vaskod23ce592015-08-06 09:55:37 +02002314 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002315 }
2316 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002317
2318 list->unique = calloc(list->unique_size, sizeof *list->unique);
2319 if (list_orig->unique) {
2320 for (i = 0; i < list->unique_size; ++i) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002321 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
2322 for (j = 0; j < list->unique[i].leafs_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002323 list->unique[i].leafs[j] = lys_uniq_find(list, list_orig->unique[i].leafs[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002324 }
2325 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002326 } else {
2327 for (i = 0; i < list->unique_size; ++i) {
2328 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02002329 list->unique[i].leafs = (struct lys_node_leaf **)list;
Michal Vasko0bd29d12015-08-19 11:45:49 +02002330 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002331 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002332 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002333
2334 if (list_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002335 list->when = lys_when_dup(ctx, list_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002336 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002337 break;
2338
Radek Krejci76512572015-08-04 09:47:08 +02002339 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002340 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002341 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002342
2343 if (anyxml_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002344 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002345 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002346 break;
2347
Radek Krejci76512572015-08-04 09:47:08 +02002348 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002349 uses->grp = uses_orig->grp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002350
2351 if (uses_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002352 uses->when = lys_when_dup(ctx, uses_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002353 }
2354
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002355 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002356 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002357 uses->augment_size = uses_orig->augment_size;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02002358 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Michal Vaskof8c128d2015-08-06 15:25:28 +02002359 if (!uses->child) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002360 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002361 goto error;
2362 }
Michal Vaskof8c128d2015-08-06 15:25:28 +02002363 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002364 break;
2365
Radek Krejci76512572015-08-04 09:47:08 +02002366 case LYS_CASE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002367 if (cs_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002368 cs->when = lys_when_dup(ctx, cs_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002369 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002370 break;
2371
Radek Krejci76512572015-08-04 09:47:08 +02002372 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002373 grp->tpdf_size = grp_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002374 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002375 break;
2376
Radek Krejci76512572015-08-04 09:47:08 +02002377 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002378 rpc->tpdf_size = rpc_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002379 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002380 break;
2381
Radek Krejci76512572015-08-04 09:47:08 +02002382 case LYS_INPUT:
2383 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002384 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002385 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002386 break;
2387
Radek Krejci76512572015-08-04 09:47:08 +02002388 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002389 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002390 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcia01e5432015-06-16 10:35:25 +02002391 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002392
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002393 default:
Radek Krejci00768f42015-06-18 17:04:04 +02002394 /* LY_NODE_AUGMENT */
Michal Vaskod23ce592015-08-06 09:55:37 +02002395 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002396 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002397 }
2398
2399 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002400
2401error:
2402
2403 lys_node_free(retval);
2404 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002405}
2406
Michal Vasko13b15832015-08-19 11:04:48 +02002407void
2408lys_free(struct lys_module *module, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02002409{
Radek Krejcidce51452015-06-16 15:20:08 +02002410 struct ly_ctx *ctx;
2411 int i;
2412
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002413 if (!module) {
2414 return;
2415 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002416
Radek Krejcidce51452015-06-16 15:20:08 +02002417 /* remove schema from the context */
2418 ctx = module->ctx;
2419 if (ctx->models.used) {
2420 for (i = 0; i < ctx->models.used; i++) {
2421 if (ctx->models.list[i] == module) {
2422 /* replace the position in the list by the last module in the list */
2423 ctx->models.used--;
2424 ctx->models.list[i] = ctx->models.list[ctx->models.used];
2425 ctx->models.list[ctx->models.used] = NULL;
2426 /* we are done */
2427 break;
2428 }
2429 }
2430 }
2431
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002432 /* common part with struct ly_submodule */
Michal Vasko13b15832015-08-19 11:04:48 +02002433 module_free_common(module, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02002434
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002435 /* specific items to free */
2436 lydict_remove(module->ctx, module->ns);
2437 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02002438
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002439 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002440}
Radek Krejci7e97c352015-06-19 16:26:34 +02002441
2442/*
2443 * op: 1 - enable, 0 - disable
2444 */
2445static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002446lys_features_change(struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002447{
2448 int all = 0;
2449 int i, j, k;
2450
2451 if (!module || !name || !strlen(name)) {
2452 return EXIT_FAILURE;
2453 }
2454
2455 if (!strcmp(name, "*")) {
2456 /* enable all */
2457 all = 1;
2458 }
2459
2460 /* module itself */
2461 for (i = 0; i < module->features_size; i++) {
2462 if (all || !strcmp(module->features[i].name, name)) {
2463 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002464 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002465 /* enable referenced features (recursion) */
2466 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002467 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002468 module->features[i].features[k]->name, op);
2469 }
2470 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002471 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002472 }
2473 if (!all) {
2474 return EXIT_SUCCESS;
2475 }
2476 }
2477 }
2478
2479 /* submodules */
2480 for (j = 0; j < module->inc_size; j++) {
2481 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2482 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2483 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002484 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002485 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002486 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002487 }
2488 if (!all) {
2489 return EXIT_SUCCESS;
2490 }
2491 }
2492 }
2493 }
2494
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002495 /* TODO submodules of submodules ... */
2496
Radek Krejci7e97c352015-06-19 16:26:34 +02002497 if (all) {
2498 return EXIT_SUCCESS;
2499 } else {
2500 return EXIT_FAILURE;
2501 }
2502}
2503
2504API int
Radek Krejcib8048692015-08-05 13:36:34 +02002505lys_features_enable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002506{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002507 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002508}
2509
2510API int
Radek Krejcib8048692015-08-05 13:36:34 +02002511lys_features_disable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002512{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002513 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002514}
2515
2516API int
Radek Krejcib8048692015-08-05 13:36:34 +02002517lys_features_state(struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002518{
2519 int i, j;
2520
2521 if (!module || !feature) {
2522 return -1;
2523 }
2524
2525 /* search for the specified feature */
2526 /* module itself */
2527 for (i = 0; i < module->features_size; i++) {
2528 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002529 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002530 return 1;
2531 } else {
2532 return 0;
2533 }
2534 }
2535 }
2536
2537 /* submodules */
2538 for (j = 0; j < module->inc_size; j++) {
2539 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2540 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002541 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002542 return 1;
2543 } else {
2544 return 0;
2545 }
2546 }
2547 }
2548 }
2549
2550 /* TODO submodules of submodules ... */
2551
2552 /* feature definition not found */
2553 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002554}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002555
Radek Krejci96a10da2015-07-30 11:00:14 +02002556API const char **
Radek Krejcib8048692015-08-05 13:36:34 +02002557lys_features_list(struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002558{
Radek Krejci96a10da2015-07-30 11:00:14 +02002559 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002560 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002561 unsigned int count;
2562
2563 if (!module) {
2564 return NULL;
2565 }
2566
2567 count = module->features_size;
2568 for (i = 0; i < module->inc_size; i++) {
2569 count += module->inc[i].submodule->features_size;
2570 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002571 result = malloc((count + 1) * sizeof *result);
2572 if (states) {
2573 *states = malloc((count + 1) * sizeof **states);
Michal Vasko2367e7c2015-07-07 11:33:44 +02002574 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002575 count = 0;
2576
2577 /* module itself */
2578 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002579 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002580 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002581 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002582 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002583 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002584 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002585 }
2586 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002587 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002588 }
2589
2590 /* submodules */
2591 for (j = 0; j < module->inc_size; j++) {
2592 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002593 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002594 if (states) {
2595 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2596 (*states)[count] = 1;
2597 } else {
2598 (*states)[count] = 0;
2599 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002600 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002601 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002602 }
2603 }
2604
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002605 /* TODO submodules of submodules ... */
2606
2607 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002608 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002609
2610 return result;
2611}
Michal Vaskobaefb032015-09-24 14:52:10 +02002612
2613API struct lys_node *
2614lys_parent(struct lys_node *node)
2615{
2616 if (!node || !node->parent) {
2617 return NULL;
2618 }
2619
2620 if (node->parent->nodetype == LYS_AUGMENT) {
2621 return ((struct lys_node_augment *)node->parent)->target;
2622 }
2623
2624 return node->parent;
2625}