blob: 4645fef4dec7ad8d039bb8ea0c733c82a1a3ec09 [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"
Radek Krejcic6704c82015-10-06 11:12:45 +020035#include "xml_private.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 Vasko1dca6882015-10-22 14:29:42 +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;
95 char *module_name;
96
97 assert(siblings && name);
98 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING)));
99
100 /* find the beginning */
101 while (siblings->prev->next) {
102 siblings = siblings->prev;
103 }
104
105 /* fill the name length in case the caller is so indifferent */
106 if (!nam_len) {
107 nam_len = strlen(name);
108 }
109
110 /* we start with the module itself, submodules come later */
111 in_submod = 0;
112
113 /* set prefix_mod correctly */
114 if (mod_name) {
115 module_name = strndup(mod_name, mod_name_len);
116 prefix_mod = ly_ctx_get_module(siblings->module->ctx, module_name, NULL);
117 free(module_name);
118 if (!prefix_mod) {
119 return -1;
120 }
121 cur_mod = prefix_mod;
122 /* it is not our module */
123 if (cur_mod != mod) {
124 old_siblings = siblings;
125 siblings = cur_mod->data;
126 }
127 } else {
128 if (mod) {
129 prefix_mod = mod;
130 } else {
131 prefix_mod = siblings->module;
132 }
133 if (prefix_mod->type) {
134 prefix_mod = ((struct lys_submodule *)prefix_mod)->belongsto;
135 }
136 cur_mod = prefix_mod;
137 }
138
139 while (1) {
140 /* try to find the node */
141 node = NULL;
142 while ((node = lys_getnext(node, siblings->parent, cur_mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
143 if (!type || (node->nodetype & type)) {
144 /* module check */
145 if (!node->module->type) {
146 if (cur_mod != node->module) {
147 continue;
148 }
149 } else {
150 /* both are submodules */
151 if (cur_mod->type) {
152 if (cur_mod != node->module) {
153 continue;
154 }
155 } else {
156 if (cur_mod != ((struct lys_submodule *)node->module)->belongsto) {
157 continue;
158 }
159 }
160 }
161
162 /* direct name check */
163 if ((node->name == name) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
164 if (ret) {
165 *ret = node;
166 }
167 return EXIT_SUCCESS;
168 }
169 }
170 }
171
172 /* The original siblings may be valid,
173 * it's a special case when we're looking
174 * for a node from an augment.
175 */
176 if (old_siblings) {
177 siblings = old_siblings;
178 old_siblings = NULL;
179 continue;
180 }
181
182 /* we're not top-level, search ended */
183 if (siblings->parent) {
184 break;
185 }
186
187 /* let's try the submodules */
188 if (in_submod == prefix_mod->inc_size) {
189 break;
190 }
191 cur_mod = (struct lys_module *)prefix_mod->inc[in_submod].submodule;
192 siblings = cur_mod->data;
193 ++in_submod;
194 }
195
196 return EXIT_FAILURE;
197}
198
199API struct lys_node *
Radek Krejci8bc87f62015-09-02 16:19:05 +0200200lys_getnext(struct lys_node *last, struct lys_node *parent, struct lys_module *module, int options)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200201{
202 struct lys_node *next;
203
Radek Krejci8bc87f62015-09-02 16:19:05 +0200204 if (!last) {
205 /* first call */
206
207 /* get know where to start */
208 if (parent) {
209 /* schema subtree */
210 next = last = parent->child;
211 } else {
212 /* top level data */
213 assert(module);
214 next = last = module->data;
215 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200216 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200217 /* continue after the last returned value */
218 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200219 }
220
221repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200222 while (next && (next->nodetype == LYS_GROUPING)) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200223 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200224 }
225
226 while (!next) {
Michal Vasko7c386e72015-10-07 15:13:33 +0200227 if (lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200228 /* no next element */
229 return NULL;
230 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200231 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200232 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200233 goto repeat;
234 }
235
236 switch (next->nodetype) {
Michal Vaskoa5835e92015-10-20 15:07:39 +0200237 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200238 if (options & LYS_GETNEXT_WITHCASE) {
239 return next;
240 }
241 /* fallthrough */
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200242 case LYS_INPUT:
243 case LYS_OUTPUT:
Michal Vasko1dca6882015-10-22 14:29:42 +0200244 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200245 /* go into */
246 next = next->child;
247 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200248
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200249 case LYS_RPC:
250 case LYS_NOTIF:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200251 case LYS_CONTAINER:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200252 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200253 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200254 case LYS_LIST:
255 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200256 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200257
258 case LYS_CHOICE:
259 if (options & LYS_GETNEXT_WITHCHOICE) {
260 return next;
261 } else {
262 /* go into */
263 next = next->child;
264 goto repeat;
265 }
266 break;
267
Radek Krejci7f40ce32015-08-12 20:38:46 +0200268 default:
269 /* we should not be here */
270 return NULL;
271 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200272
273
274}
275
276static struct lys_node *
277check_mand_getnext(struct lys_node *last, struct lys_node *parent)
278{
279 struct lys_node *next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200280 next = lys_getnext(last, parent, NULL, LYS_GETNEXT_WITHCHOICE);
281
Radek Krejci4b6c2112015-10-06 12:48:34 +0200282repeat:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200283 if (next && next->nodetype == LYS_CONTAINER) {
284 if (((struct lys_node_container *)next)->presence) {
285 /* mandatory elements under the non-existing presence
286 * container are not mandatory - 7.6.5, rule 1 */
287 next = next->next;
288 } else {
289 /* go into */
290 next = next->child;
291 }
292 goto repeat;
293 }
294
295 return next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200296}
297
298static struct lys_node *
299check_mand_check(struct lys_node *node, struct lys_node *stop, struct lyd_node *data)
300{
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200301 struct lys_node *siter = NULL, *parent = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200302 struct lyd_node *diter = NULL;
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200303 struct lyd_set *set = NULL;
304 unsigned int i;
Radek Krejci14a11a62015-08-17 17:27:38 +0200305 uint32_t minmax;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200306
307 if (node->flags & LYS_MAND_TRUE) {
308 switch (node->nodetype) {
309 case LYS_LEAF:
310 case LYS_ANYXML:
311 case LYS_CHOICE:
312 if (node->parent->nodetype == LYS_CASE) {
313 /* 7.6.5, rule 2 */
314 /* 7.9.4, rule 1 */
315 if (node->parent->parent->parent == data->schema) {
316 /* the only case the node's siblings can exist is that the
317 * data node passed originaly to ly_check_mandatory()
318 * had this choice as a child
319 */
320 /* try to find the node's siblings in data */
321 LY_TREE_FOR(data->child, diter) {
322 LY_TREE_FOR(node->parent->child, siter) {
323 if (siter == diter->schema) {
324 /* some sibling exists, rule applies */
325 break;
326 }
327 }
328 if (siter) {
329 break;
330 }
331 }
332 }
333 if (!siter) {
334 /* no sibling exists */
335 return NULL;
336 }
337 } else {
338 for(parent = node->parent; parent != stop; parent = parent->parent) {
339 if (parent->nodetype != LYS_CONTAINER) {
340 /* 7.6.5, rule 1, checking presence is not needed
341 * since it is done in check_mand_getnext()
342 */
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200343 lyd_set_free(set);
Radek Krejci7f40ce32015-08-12 20:38:46 +0200344 return NULL;
345 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200346 /* add the parent to the list for searching in data tree */
347 if (!set) {
348 set = lyd_set_new();
349 }
350 lyd_set_add(set, (struct lyd_node *)parent);
Radek Krejci7f40ce32015-08-12 20:38:46 +0200351 }
352 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200353
354 /* search for instance */
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200355 if (set) {
356 for (i = 0; i < set->number; i++) {
357 LY_TREE_FOR(data->child, diter) {
358 if (diter->schema == (struct lys_node *)(set->set[i])) {
359 break;
360 }
361 }
362 if (!diter) {
363 /* instance not found */
364 node = (struct lys_node *)(set->set[i]);
365 lyd_set_free(set);
366 return node;
367 }
368 data = diter;
369 }
370 lyd_set_free(set);
371 }
372
Radek Krejci14a11a62015-08-17 17:27:38 +0200373 LY_TREE_FOR(data->child, diter) {
374 if (diter->schema == node) {
375 return NULL;
376 }
377 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200378
Radek Krejci14a11a62015-08-17 17:27:38 +0200379 /* instance not found */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200380 /* 7.6.5, rule 3 (or 2) */
381 /* 7.9.4, rule 2 */
382 return node;
383 default:
384 /* error */
385 break;
386 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200387 } else if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
388 /* search for number of instances */
389 minmax = 0;
390 LY_TREE_FOR(data->child, diter) {
391 if (diter->schema == node) {
392 minmax++;
393 }
394 }
395
396 /* check the specified constraints */
397 if (node->nodetype == LYS_LIST) {
398 if (((struct lys_node_list *)node)->min && minmax < ((struct lys_node_list *)node)->min) {
399 return node;
400 }
401
402 if (((struct lys_node_list *)node)->max && minmax > ((struct lys_node_list *)node)->max) {
403 return node;
404 }
405 } else if (node->nodetype == LYS_LEAFLIST) {
406 if (((struct lys_node_leaflist *)node)->min && minmax < ((struct lys_node_leaflist *)node)->min) {
407 return node;
408 }
409
410 if (((struct lys_node_leaflist *)node)->max && minmax > ((struct lys_node_leaflist *)node)->max) {
411 return node;
412 }
413 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200414 }
415
416 return NULL;
417}
418
419struct lys_node *
420ly_check_mandatory(struct lyd_node *data)
421{
Radek Krejci14a11a62015-08-17 17:27:38 +0200422 struct lys_node *siter, *saux, *saux2, *result, *parent = NULL, *parent2;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200423 struct lyd_node *diter;
424 int found;
425
426 siter = data->schema->child;
427
428repeat:
429 while (siter) {
Radek Krejci074bf852015-08-19 14:22:16 +0200430 if (lys_is_disabled(siter, 2)) {
431 siter = siter->next;
432 continue;
433 }
434
Radek Krejci7f40ce32015-08-12 20:38:46 +0200435 switch (siter->nodetype) {
436 case LYS_CONTAINER:
437 case LYS_LEAF:
438 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200439 case LYS_LIST:
440 case LYS_LEAFLIST:
441 /* check if there is some mandatory node; first test the siter itself ... */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200442 result = check_mand_check(siter, siter->parent, data);
443 if (result) {
444 return result;
445 }
446 /* ... and then the subtree */
Radek Krejci14a11a62015-08-17 17:27:38 +0200447 if (parent && siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
448 saux = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200449 while ((saux = check_mand_getnext(saux, siter))) {
450 result = check_mand_check(saux, siter, data);
451 if (result) {
452 return result;
453 }
454 }
455 }
456 siter = siter->next;
457 break;
458 case LYS_CHOICE:
Radek Krejci14a11a62015-08-17 17:27:38 +0200459 /* search for instance */
460 saux = siter;
461 siter = siter->child;
462 found = 0;
463 parent2 = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200464repeat_choice:
Radek Krejci074bf852015-08-19 14:22:16 +0200465 while (siter) {
466 if (lys_is_disabled(siter, 2)) {
467 siter = siter->next;
468 continue;
469 }
470
Radek Krejci14a11a62015-08-17 17:27:38 +0200471 switch (siter->nodetype) {
472 case LYS_CONTAINER:
473 case LYS_LEAF:
474 case LYS_LEAFLIST:
475 case LYS_LIST:
476 case LYS_ANYXML:
477 LY_TREE_FOR(data->child, diter) {
478 if (diter->schema == siter) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200479 break;
480 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200481 }
482 if (diter) {
483 /* got instance */
484 /* check presence of mandatory siblings */
Radek Krejci65d0a652015-08-27 13:09:42 +0200485 if (parent2 && parent2->nodetype == LYS_CASE) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200486 saux2 = NULL;
Radek Krejci37bda002015-08-27 11:23:56 +0200487 while ((saux2 = check_mand_getnext(saux2, parent2))) {
488 result = check_mand_check(saux2, parent2, data);
Radek Krejci14a11a62015-08-17 17:27:38 +0200489 if (result) {
490 return result;
491 }
492 }
493 }
494 siter = parent2 = NULL;
495 found = 1;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200496 break;
497 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200498 siter = siter->next;
499 break;
500 case LYS_CASE:
501 case LYS_CHOICE:
502 case LYS_USES:
503 /* go into */
Radek Krejci37bda002015-08-27 11:23:56 +0200504 if (!parent2) {
505 parent2 = siter;
506 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200507 siter = siter->child;
508 break;
509 case LYS_AUGMENT:
510 case LYS_GROUPING:
511 /* skip */
512 siter = siter->next;
513 break;
514 default:
515 /* error */
516 break;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200517 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200518 }
519
Radek Krejci14a11a62015-08-17 17:27:38 +0200520 if (parent2) {
521 siter = parent2->next;
522 if (parent2->parent == saux) {
523 parent2 = NULL;
524 } else {
525 parent2 = parent2->parent;
526 }
527 goto repeat_choice;
528 }
529
Radek Krejci074bf852015-08-19 14:22:16 +0200530 if (!found && (saux->flags & LYS_MAND_TRUE)) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200531 return saux;
532 }
533
534 /* go to next */
535 siter = saux->next;
536
Radek Krejci7f40ce32015-08-12 20:38:46 +0200537 break;
538 case LYS_USES:
539 case LYS_CASE:
540 /* go into */
541 parent = siter;
542 siter = siter->child;
543 break;
544 default:
545 /* can ignore, go to next */
546 siter = siter->next;
547 break;
548 }
549 }
550
551 if (parent) {
552 siter = parent->next;
553 if (parent->parent == data->schema) {
554 parent = NULL;
555 } else {
556 parent = parent->parent;
557 }
558 goto repeat;
559 }
560
561 return NULL;
562}
563
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200564void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200565lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200566{
Radek Krejci76512572015-08-04 09:47:08 +0200567 struct lys_node *parent, *first;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200568
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200569 if (!node) {
570 return;
571 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200573 /* unlink from data model if necessary */
574 if (node->module) {
575 if (node->module->data == node) {
576 node->module->data = node->next;
577 }
578 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200579
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200580 /* store pointers to important nodes */
581 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200582 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200583 /* handle augments - first, unlink it from the augment parent ... */
584 if (parent->child == node) {
585 parent->child = node->next;
586 }
587 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200588 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200589 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200590
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200591 /* unlink from parent */
592 if (parent) {
593 if (parent->child == node) {
594 parent->child = node->next;
595 }
596 node->parent = NULL;
597 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200598
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200599 /* unlink from siblings */
600 if (node->prev == node) {
601 /* there are no more siblings */
602 return;
603 }
604 if (node->next) {
605 node->next->prev = node->prev;
606 } else {
607 /* unlinking the last element */
608 if (parent) {
609 first = parent->child;
610 } else {
611 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200612 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200613 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200614 }
615 }
616 first->prev = node->prev;
617 }
618 if (node->prev->next) {
619 node->prev->next = node->next;
620 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200621
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200622 /* clean up the unlinked element */
623 node->next = NULL;
624 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200625}
626
Michal Vasko563ef092015-09-04 13:17:23 +0200627struct lys_node_grp *
628lys_find_grouping_up(const char *name, struct lys_node *start, int in_submodules)
629{
630 struct lys_node *par_iter, *iter, *stop;
631 int i;
632
633 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vasko6f929da2015-10-02 16:23:25 +0200634 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200635 continue;
636 }
637
638 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
639 if (!stop) {
640 stop = par_iter;
641 } else if (iter == stop) {
642 break;
643 }
644 if (iter->nodetype != LYS_GROUPING) {
645 continue;
646 }
647
648 if (name == iter->name) {
649 return (struct lys_node_grp *)iter;
650 }
651 }
652 }
653
654 if (in_submodules) {
655 for (i = 0; i < start->module->inc_size; ++i) {
656 for (iter = start->module->inc[i].submodule->data; iter; iter = iter->next) {
657 if (iter->nodetype != LYS_GROUPING) {
658 continue;
659 }
660
661 if (name == iter->name) {
662 return (struct lys_node_grp *)iter;
663 }
664 }
665 }
666 }
667
668 return NULL;
669}
670
Radek Krejci10c760e2015-08-14 14:45:43 +0200671/*
672 * get next grouping in the root's subtree, in the
673 * first call, tha last is NULL
674 */
675static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200676lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200677{
Radek Krejci10c760e2015-08-14 14:45:43 +0200678 struct lys_node *last = (struct lys_node *)lastgrp;
679 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200680
Radek Krejci10c760e2015-08-14 14:45:43 +0200681 assert(root);
682
683 if (!last) {
684 last = root;
685 }
686
687 while (1) {
688 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
689 next = last->child;
690 } else {
691 next = NULL;
692 }
693 if (!next) {
694 if (last == root) {
695 /* we are done */
696 return NULL;
697 }
698
699 /* no children, go to siblings */
700 next = last->next;
701 }
702 while (!next) {
703 /* go back through parents */
704 if (last->parent == root) {
705 /* we are done */
706 return NULL;
707 }
708 last = last->parent;
709 next = last->next;
710 }
711
712 if (next->nodetype == LYS_GROUPING) {
713 return (struct lys_node_grp *)next;
714 }
715
716 last = next;
717 }
718}
719
Michal Vasko0d343d12015-08-24 14:57:36 +0200720/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200721int
Radek Krejci07911992015-08-14 15:13:31 +0200722lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
723{
Michal Vasko563ef092015-09-04 13:17:23 +0200724 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200725 struct lys_node_grp *grp;
726 int down;
727
728 assert(node);
729
730 if (!parent) {
731 assert(module);
732 } else {
733 module = parent->module;
734 }
735
736 switch (node->nodetype) {
737 case LYS_GROUPING:
738 /* 6.2.1, rule 6 */
739 if (parent) {
740 if (parent->child) {
741 down = 1;
742 start = parent->child;
743 } else {
744 down = 0;
745 start = parent;
746 }
747 } else {
748 down = 1;
749 start = module->data;
750 }
751 /* go up */
Michal Vasko563ef092015-09-04 13:17:23 +0200752 if (lys_find_grouping_up(node->name, start, 0)) {
753 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
754 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200755 }
756 /* go down, because grouping can be defined after e.g. container in which is collision */
757 if (down) {
758 for (iter = start, stop = NULL; iter; iter = iter->prev) {
759 if (!stop) {
760 stop = start;
761 } else if (iter == stop) {
762 break;
763 }
764 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
765 continue;
766 }
767
768 grp = NULL;
769 while ((grp = lys_get_next_grouping(grp, iter))) {
770 if (node->name == grp->name) {
771 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
772 return EXIT_FAILURE;
773 }
774 }
775 }
776 }
777 break;
778 case LYS_LEAF:
779 case LYS_LEAFLIST:
780 case LYS_LIST:
781 case LYS_CONTAINER:
782 case LYS_CHOICE:
783 case LYS_ANYXML:
784 /* 6.2.1, rule 7 */
785 if (parent) {
786 iter = parent;
787 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE))) {
788 iter = iter->parent;
789 }
790 if (!iter) {
791 stop = NULL;
792 iter = module->data;
793 } else {
794 stop = iter;
795 iter = iter->child;
796 }
797 } else {
798 stop = NULL;
799 iter = module->data;
800 }
801 while (iter) {
802 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
803 iter = iter->child;
804 continue;
805 }
806
807 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
808 if (iter->module == node->module && iter->name == node->name) {
809 LOGVAL(LYE_SPEC, 0, "Duplicated child identifier \"%s\" in \"%s\".", node->name,
810 stop ? stop->name : "(sub)module");
811 return EXIT_FAILURE;
812 }
813 }
814
815 /* special case for choice - we must check the choice's name as
816 * well as the names of nodes under the choice
817 */
818 if (iter->nodetype == LYS_CHOICE) {
819 iter = iter->child;
820 continue;
821 }
822
823 /* go to siblings */
824 if (!iter->next) {
825 /* no sibling, go to parent's sibling */
826 do {
827 iter = iter->parent;
828 if (iter && iter->next) {
829 break;
830 }
831 } while (iter != stop);
832
833 if (iter == stop) {
834 break;
835 }
836 }
837 iter = iter->next;
838 }
839 break;
840 case LYS_CASE:
841 /* 6.2.1, rule 8 */
842 LY_TREE_FOR(parent->child, iter) {
843 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
844 continue;
845 }
846
847 if (iter->module == node->module && iter->name == node->name) {
848 LOGVAL(LYE_DUPID, 0, "case", node->name);
849 return EXIT_FAILURE;
850 }
851 }
852 break;
853 default:
854 /* no check needed */
855 break;
856 }
857
858 return EXIT_SUCCESS;
859}
860
Michal Vasko0d343d12015-08-24 14:57:36 +0200861/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200862int
Radek Krejci10c760e2015-08-14 14:45:43 +0200863lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
864{
Radek Krejci92720552015-10-05 15:28:27 +0200865 struct lys_node *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200866 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200867
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200868 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200869
Radek Krejci10c760e2015-08-14 14:45:43 +0200870 if (parent) {
871 type = parent->nodetype;
872 module = parent->module;
873 } else {
874 assert(module);
875 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200876 }
877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200878 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200879 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200880 case LYS_CONTAINER:
881 case LYS_LIST:
882 case LYS_GROUPING:
883 case LYS_USES:
884 case LYS_INPUT:
885 case LYS_OUTPUT:
886 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200887 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200888 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
889 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200890 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200891 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
892 return EXIT_FAILURE;
893 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200894
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200895 break;
Radek Krejci76512572015-08-04 09:47:08 +0200896 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200897 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200898 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200899 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"choice\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200900 strnodetype(child->nodetype), parent->name);
901 return EXIT_FAILURE;
902 }
903 break;
Radek Krejci76512572015-08-04 09:47:08 +0200904 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200905 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200906 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200907 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"case\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200908 strnodetype(child->nodetype), parent->name);
909 return EXIT_FAILURE;
910 }
911 break;
Radek Krejci76512572015-08-04 09:47:08 +0200912 case LYS_RPC:
913 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200914 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"rpc\" %s.",
Michal Vasko38d01f72015-06-15 09:41:06 +0200915 strnodetype(child->nodetype), parent->name);
916 return EXIT_FAILURE;
917 }
918 break;
Radek Krejci76512572015-08-04 09:47:08 +0200919 case LYS_LEAF:
920 case LYS_LEAFLIST:
921 case LYS_ANYXML:
Radek Krejci10c760e2015-08-14 14:45:43 +0200922 LOGVAL(LYE_SPEC, 0, "The \"%s\" statement (%s) cannot have any data substatement.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200923 strnodetype(parent->nodetype), parent->name);
924 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200925 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200926 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200927 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
928 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200929 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200930 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
931 return EXIT_FAILURE;
932 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200933 break;
934 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200935 /* top level */
936 if (!(child->nodetype &
937 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
938 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci2c0ca272015-08-14 15:31:01 +0200939 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in (sub)module \"%s\"",
940 strnodetype(child->nodetype), module->name);
Radek Krejci10c760e2015-08-14 14:45:43 +0200941 return EXIT_FAILURE;
942 }
943
944 break;;
945 }
946
947 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200948 if (lys_check_id(child, parent, module)) {
949 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200950 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200951
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200952 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200953 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200954 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200955
Radek Krejci10c760e2015-08-14 14:45:43 +0200956 if (!parent) {
Radek Krejci92720552015-10-05 15:28:27 +0200957 if (module->data) {
958 module->data->prev->next = child;
959 child->prev = module->data->prev;
960 module->data->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200961 } else {
Radek Krejci92720552015-10-05 15:28:27 +0200962 module->data = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200963 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200964 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +0200965 if (!parent->child) {
966 /* the only/first child of the parent */
967 parent->child = child;
968 child->parent = parent;
969 iter = child;
970 } else {
971 /* add a new child at the end of parent's child list */
972 iter = parent->child->prev;
973 iter->next = child;
974 child->prev = iter;
975 }
976 while (iter->next) {
977 iter = iter->next;
978 iter->parent = parent;
979 }
980 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200981 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200982
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200983 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200984}
985
Radek Krejcib8048692015-08-05 13:36:34 +0200986API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +0200987lys_parse(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200988{
Michal Vaskof02e3742015-08-05 16:27:02 +0200989 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200990 struct lys_module *mod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200991
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200992 if (!ctx || !data) {
993 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
994 return NULL;
995 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200996
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200997 unres = calloc(1, sizeof *unres);
998
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200999 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001000 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001001 mod = yin_read_module(ctx, data, 1, unres);
1002 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001003 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001004 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001005 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001006 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001007 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001008
Michal Vasko0bd29d12015-08-19 11:45:49 +02001009 if (mod && unres->count && resolve_unres_schema(mod, unres)) {
Michal Vasko13b15832015-08-19 11:04:48 +02001010 lys_free(mod, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001011 mod = NULL;
1012 }
1013 free(unres->item);
1014 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +02001015 free(unres->str_snode);
Michal Vaskoc07187d2015-08-13 15:20:57 +02001016#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001017 free(unres->line);
Michal Vaskoc07187d2015-08-13 15:20:57 +02001018#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001019 free(unres);
1020
1021 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001022}
1023
Radek Krejcib8048692015-08-05 13:36:34 +02001024struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001025lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02001026{
Michal Vaskof02e3742015-08-05 16:27:02 +02001027 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +02001028 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001029
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001030 assert(module);
1031 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001032
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001033 unres = calloc(1, sizeof *unres);
1034
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001035 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001036 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001037 submod = yin_read_submodule(module, data, implement, unres);
1038 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001039 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001040 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001041 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001042 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001043 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001044
Michal Vasko0bd29d12015-08-19 11:45:49 +02001045 if (submod && unres->count && resolve_unres_schema((struct lys_module *)submod, unres)) {
Michal Vasko13b15832015-08-19 11:04:48 +02001046 lys_submodule_free(submod, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001047 submod = NULL;
1048 }
1049 free(unres->item);
1050 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +02001051 free(unres->str_snode);
Michal Vaskoc07187d2015-08-13 15:20:57 +02001052#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001053 free(unres->line);
Michal Vaskoc07187d2015-08-13 15:20:57 +02001054#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001055 free(unres);
1056
1057 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001058}
1059
Radek Krejcib8048692015-08-05 13:36:34 +02001060API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +02001061lys_read(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001062{
Radek Krejcib8048692015-08-05 13:36:34 +02001063 struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +02001064 struct stat sb;
1065 char *addr;
1066
1067 if (!ctx || fd < 0) {
1068 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1069 return NULL;
1070 }
1071
1072 /*
1073 * TODO
1074 * This is just a temporary solution to make working automatic search for
1075 * imported modules. This doesn't work e.g. for streams (stdin)
1076 */
1077 fstat(fd, &sb);
1078 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
1079 module = lys_parse(ctx, addr, format);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001080 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001081
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001082 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001083}
1084
Radek Krejcib8048692015-08-05 13:36:34 +02001085struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001086lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02001087{
Radek Krejcib8048692015-08-05 13:36:34 +02001088 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001089 struct stat sb;
1090 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001091
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001092 assert(module);
1093 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001094
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001095 /*
1096 * TODO
1097 * This is just a temporary solution to make working automatic search for
1098 * imported modules. This doesn't work e.g. for streams (stdin)
1099 */
1100 fstat(fd, &sb);
1101 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
1102 /* TODO addr error check */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001103 submodule = lys_submodule_parse(module, addr, format, implement);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001104 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +02001105
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001106 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02001107
1108}
1109
Radek Krejci1d82ef62015-08-07 14:44:40 +02001110static struct lys_restr *
1111lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001112{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001113 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001114 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001115
Radek Krejci3733a802015-06-19 13:43:21 +02001116 if (!size) {
1117 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001118 }
Radek Krejci3733a802015-06-19 13:43:21 +02001119
1120 result = calloc(size, sizeof *result);
1121 for (i = 0; i < size; i++) {
1122 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1123 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1124 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1125 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1126 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1127 }
1128
1129 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001130}
1131
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001132void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001133lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001134{
1135 assert(ctx);
1136 if (!restr) {
1137 return;
1138 }
1139
1140 lydict_remove(ctx, restr->expr);
1141 lydict_remove(ctx, restr->dsc);
1142 lydict_remove(ctx, restr->ref);
1143 lydict_remove(ctx, restr->eapptag);
1144 lydict_remove(ctx, restr->emsg);
1145}
1146
Michal Vaskob84f88a2015-09-24 13:16:10 +02001147static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001148lys_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 +02001149 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001150{
1151 int i;
1152
Michal Vasko1dca6882015-10-22 14:29:42 +02001153 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001154 new->base = old->base;
1155 new->der = old->der;
1156
Michal Vasko0bd29d12015-08-19 11:45:49 +02001157 i = unres_schema_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001158 if (i != -1) {
1159 /* HACK for unres */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001160 new->der = (struct lys_tpdf *)parent;
Michal Vaskob84f88a2015-09-24 13:16:10 +02001161 /* all these unres additions can fail even though they did not before */
Michal Vasko0bd29d12015-08-19 11:45:49 +02001162 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_DER, unres->str_snode[i], 0) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001163 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001164 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001165 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001166 }
1167
Radek Krejci3733a802015-06-19 13:43:21 +02001168 switch (new->base) {
1169 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +02001170 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001171 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001172 }
Radek Krejci3733a802015-06-19 13:43:21 +02001173 break;
1174
1175 case LY_TYPE_BITS:
1176 new->info.bits.count = old->info.bits.count;
1177 if (new->info.bits.count) {
1178 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1179 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001180 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1181 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1182 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001183 new->info.bits.bit[i].status = old->info.bits.bit[i].status;
1184 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1185 }
1186 }
1187 break;
1188
Radek Krejcif9401c32015-06-26 16:47:36 +02001189 case LY_TYPE_DEC64:
1190 new->info.dec64.dig = old->info.dec64.dig;
1191 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001192 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +02001193 }
1194 break;
1195
Radek Krejci3733a802015-06-19 13:43:21 +02001196 case LY_TYPE_ENUM:
1197 new->info.enums.count = old->info.enums.count;
1198 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001199 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Radek Krejci3733a802015-06-19 13:43:21 +02001200 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001201 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1202 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1203 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1204 new->info.enums.enm[i].status = old->info.enums.enm[i].status;
1205 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +02001206 }
1207 }
1208 break;
1209
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001210 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001211 if (old->info.ident.ref) {
1212 new->info.ident.ref = old->info.ident.ref;
1213 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001214 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001215 assert(i != -1);
Michal Vasko0bd29d12015-08-19 11:45:49 +02001216 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i], 0) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001217 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001218 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001219 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001220 break;
1221
Radek Krejciaf351422015-06-19 14:49:38 +02001222 case LY_TYPE_INST:
1223 new->info.inst.req = old->info.inst.req;
1224 break;
1225
Radek Krejcif2860132015-06-20 12:37:20 +02001226 case LY_TYPE_INT8:
1227 case LY_TYPE_INT16:
1228 case LY_TYPE_INT32:
1229 case LY_TYPE_INT64:
1230 case LY_TYPE_UINT8:
1231 case LY_TYPE_UINT16:
1232 case LY_TYPE_UINT32:
1233 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +02001234 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001235 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001236 }
Radek Krejcif2860132015-06-20 12:37:20 +02001237 break;
1238
Radek Krejcidc4c1412015-06-19 15:39:54 +02001239 case LY_TYPE_LEAFREF:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001240 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02001241 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001242 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001243 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001244 break;
1245
Radek Krejci3733a802015-06-19 13:43:21 +02001246 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +02001247 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001248 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001249 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001250 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 +02001251 break;
1252
Radek Krejcie4c366b2015-07-02 10:11:31 +02001253 case LY_TYPE_UNION:
1254 new->info.uni.count = old->info.uni.count;
1255 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001256 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001257 for (i = 0; i < new->info.uni.count; i++) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001258 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres)) {
1259 return -1;
1260 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001261 }
1262 }
1263 break;
1264
Radek Krejci3733a802015-06-19 13:43:21 +02001265 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001266 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001267 break;
1268 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001269
1270 return EXIT_SUCCESS;
Radek Krejci3733a802015-06-19 13:43:21 +02001271}
1272
1273void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001274lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001275{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001276 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001278 assert(ctx);
1279 if (!type) {
1280 return;
1281 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001282
Michal Vasko1dca6882015-10-22 14:29:42 +02001283 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001285 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001286 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001287 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001288 free(type->info.binary.length);
1289 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001290 case LY_TYPE_BITS:
1291 for (i = 0; i < type->info.bits.count; i++) {
1292 lydict_remove(ctx, type->info.bits.bit[i].name);
1293 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1294 lydict_remove(ctx, type->info.bits.bit[i].ref);
1295 }
1296 free(type->info.bits.bit);
1297 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001298
1299 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001300 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001301 free(type->info.dec64.range);
1302 break;
1303
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001304 case LY_TYPE_ENUM:
1305 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001306 lydict_remove(ctx, type->info.enums.enm[i].name);
1307 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1308 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001309 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001310 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001311 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001312
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001313 case LY_TYPE_INT8:
1314 case LY_TYPE_INT16:
1315 case LY_TYPE_INT32:
1316 case LY_TYPE_INT64:
1317 case LY_TYPE_UINT8:
1318 case LY_TYPE_UINT16:
1319 case LY_TYPE_UINT32:
1320 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001321 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001322 free(type->info.num.range);
1323 break;
1324
Radek Krejcidc4c1412015-06-19 15:39:54 +02001325 case LY_TYPE_LEAFREF:
1326 lydict_remove(ctx, type->info.lref.path);
1327 break;
1328
Radek Krejci3733a802015-06-19 13:43:21 +02001329 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001330 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001331 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001332 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001333 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001334 }
1335 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001336 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001337
Radek Krejcie4c366b2015-07-02 10:11:31 +02001338 case LY_TYPE_UNION:
1339 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001340 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001341 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001342 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001343 break;
1344
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001345 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001346 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001347 break;
1348 }
Radek Krejci5a065542015-05-22 15:02:07 +02001349}
1350
Radek Krejci1d82ef62015-08-07 14:44:40 +02001351static void
1352lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001353{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001354 assert(ctx);
1355 if (!tpdf) {
1356 return;
1357 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001358
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001359 lydict_remove(ctx, tpdf->name);
1360 lydict_remove(ctx, tpdf->dsc);
1361 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001362
Radek Krejci1d82ef62015-08-07 14:44:40 +02001363 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001364
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001365 lydict_remove(ctx, tpdf->units);
1366 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001367}
1368
Michal Vaskob84f88a2015-09-24 13:16:10 +02001369static struct lys_tpdf *
1370lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1371{
1372 struct lys_tpdf *result;
1373 int i, j;
1374
1375 if (!size) {
1376 return NULL;
1377 }
1378
1379 result = calloc(size, sizeof *result);
1380 for (i = 0; i < size; i++) {
1381 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1382 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1383 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1384 result[i].flags = old[i].flags;
1385 result[i].module = old[i].module;
1386
1387 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres)) {
1388 for (j = 0; j <= i; ++j) {
1389 lys_tpdf_free(mod->ctx, &result[j]);
1390 }
1391 free(result);
1392 return NULL;
1393 }
1394
1395 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1396 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1397 }
1398
1399 return result;
1400}
1401
Radek Krejci1d82ef62015-08-07 14:44:40 +02001402static struct lys_when *
1403lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001404{
Radek Krejci76512572015-08-04 09:47:08 +02001405 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001406
1407 if (!old) {
1408 return NULL;
1409 }
1410
1411 new = calloc(1, sizeof *new);
1412 new->cond = lydict_insert(ctx, old->cond, 0);
1413 new->dsc = lydict_insert(ctx, old->dsc, 0);
1414 new->ref = lydict_insert(ctx, old->ref, 0);
1415
1416 return new;
1417}
1418
Michal Vasko0308dd62015-10-07 09:14:40 +02001419void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001420lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001421{
1422 if (!w) {
1423 return;
1424 }
1425
1426 lydict_remove(ctx, w->cond);
1427 lydict_remove(ctx, w->dsc);
1428 lydict_remove(ctx, w->ref);
1429
1430 free(w);
1431}
1432
Radek Krejcib7f5e412015-08-13 10:15:51 +02001433static void
1434lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment aug)
1435{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001436 struct lys_node *next, *sub;
1437
1438 /* children from a resolved uses */
1439 LY_TREE_FOR_SAFE(aug.child, next, sub) {
1440 lys_node_free(sub);
1441 }
1442
Radek Krejcib7f5e412015-08-13 10:15:51 +02001443 lydict_remove(ctx, aug.target_name);
1444 lydict_remove(ctx, aug.dsc);
1445 lydict_remove(ctx, aug.ref);
1446
1447 free(aug.features);
1448
1449 lys_when_free(ctx, aug.when);
1450
Michal Vasko7d356a52015-08-19 15:06:31 +02001451 /* Do not free the children, they were appended somewhere and their
1452 * new parent will take care of them.
1453 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001454}
1455
Radek Krejci76512572015-08-04 09:47:08 +02001456static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001457lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001458{
Radek Krejci76512572015-08-04 09:47:08 +02001459 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001460 struct lys_node *old_child, *new_child;
1461 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001462
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001463 if (!size) {
1464 return NULL;
1465 }
Radek Krejci106efc02015-06-10 14:36:27 +02001466
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001467 new = calloc(size, sizeof *new);
1468 for (i = 0; i < size; i++) {
1469 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1470 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1471 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1472 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001473 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001474 new[i].nodetype = old[i].nodetype;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001475 /* this must succeed, it was already resolved once */
1476 if (resolve_schema_nodeid(new[i].target_name, parent->child, new[i].module, LYS_AUGMENT, &new[i].target)) {
1477 LOGINT;
1478 free(new);
1479 return NULL;
1480 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001481 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001482
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001483 /* Correct the augment nodes.
1484 * This function can only be called from lys_node_dup() with uses
1485 * being the node duplicated, so we must have a case of grouping
1486 * with a uses with augments. The augmented nodes have already been
1487 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001488 * (it was set to their actual data parent, not an augment), and
1489 * the new augment does not have child pointer to its augment nodes,
1490 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001491 */
1492 LY_TREE_FOR(new[i].target->child, new_child) {
1493 if (new_child->name == old[i].child->name) {
1494 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001495 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001496 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001497 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001498 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001499 LY_TREE_FOR(old[i].child, old_child) {
1500 /* all augment nodes were connected as siblings, there can be no more after this */
1501 if (old_child->parent != (struct lys_node *)&old[i]) {
1502 break;
1503 }
1504
1505 assert(old_child->name == new_child->name);
1506
1507 new_child->parent = (struct lys_node *)&new[i];
1508 new_child = new_child->next;
1509 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001510 }
Radek Krejci106efc02015-06-10 14:36:27 +02001511
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001512 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001513}
1514
Radek Krejci76512572015-08-04 09:47:08 +02001515static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001516lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001517{
Radek Krejci76512572015-08-04 09:47:08 +02001518 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001519 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001520
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001521 if (!size) {
1522 return NULL;
1523 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001524
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001525 result = calloc(size, sizeof *result);
1526 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001527 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001528 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1529 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001530 result[i].flags = old[i].flags;
1531 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001532
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001533 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001534 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001535
Radek Krejci76512572015-08-04 09:47:08 +02001536 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001537 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001538 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001539 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001540 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001541 result[i].mod.list = old[i].mod.list;
1542 }
1543 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001544
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001545 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001546}
1547
Radek Krejci1d82ef62015-08-07 14:44:40 +02001548static void
1549lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001550{
Radek Krejcia52656e2015-08-05 13:41:50 +02001551 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001552
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001553 assert(ctx);
1554 if (!ident) {
1555 return;
1556 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001557
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001558 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001559 * if caller free only a single data model which is used (its identity is
1560 * reference from identity in another module), this silly freeing can lead
1561 * to segmentation fault. But without noting if the module is used by some
1562 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001563 *
1564 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001565 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001566 */
1567 while (ident->der) {
1568 der = ident->der;
1569 ident->der = der->next;
1570 free(der);
1571 }
Radek Krejci6793db02015-05-22 17:49:54 +02001572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001573 lydict_remove(ctx, ident->name);
1574 lydict_remove(ctx, ident->dsc);
1575 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001576
1577}
1578
Radek Krejci1d82ef62015-08-07 14:44:40 +02001579static void
1580lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001581{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001582 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001583
Radek Krejcid12f57b2015-08-06 10:43:39 +02001584 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001585 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001586 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001587 }
1588 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001589}
1590
Radek Krejci1d82ef62015-08-07 14:44:40 +02001591static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001592lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1593{
1594 int i;
1595
1596 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1597 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001598 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001599 }
1600 free(io->tpdf);
1601}
1602
Radek Krejci1d82ef62015-08-07 14:44:40 +02001603static void
1604lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001605{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001606 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001607
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001608 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001609 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001610 }
1611 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001612
Radek Krejci1d82ef62015-08-07 14:44:40 +02001613 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001614}
1615
Radek Krejci1d82ef62015-08-07 14:44:40 +02001616static void
1617lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001618{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001619 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001620
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001621 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001622 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001623 }
1624 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001625
Radek Krejci1d82ef62015-08-07 14:44:40 +02001626 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001627
Radek Krejci1d82ef62015-08-07 14:44:40 +02001628 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001629 lydict_remove(ctx, leaf->units);
1630 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001631}
1632
Radek Krejci1d82ef62015-08-07 14:44:40 +02001633static void
1634lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001635{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001636 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001638 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001639 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001640 }
1641 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001642
Radek Krejci1d82ef62015-08-07 14:44:40 +02001643 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001644
Radek Krejci1d82ef62015-08-07 14:44:40 +02001645 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001646 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001647}
1648
Radek Krejci1d82ef62015-08-07 14:44:40 +02001649static void
1650lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001651{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001652 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001653
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001654 /* handle only specific parts for LY_NODE_LIST */
1655 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001656 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001657 }
1658 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001659
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001660 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001661 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001662 }
1663 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001664
Radek Krejci1d82ef62015-08-07 14:44:40 +02001665 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001666
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001667 for (i = 0; i < list->unique_size; i++) {
1668 free(list->unique[i].leafs);
1669 }
1670 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001671
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001672 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001673}
1674
Radek Krejci1d82ef62015-08-07 14:44:40 +02001675static void
1676lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001677{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001678 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001679
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001680 /* handle only specific parts for LY_NODE_CONTAINER */
1681 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001682
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001683 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001684 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001685 }
1686 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001687
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001688 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001689 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001690 }
1691 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001692
Radek Krejci1d82ef62015-08-07 14:44:40 +02001693 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001694}
1695
Radek Krejci1d82ef62015-08-07 14:44:40 +02001696static void
1697lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001698{
1699 lydict_remove(ctx, f->name);
1700 lydict_remove(ctx, f->dsc);
1701 lydict_remove(ctx, f->ref);
1702 free(f->features);
1703}
1704
Radek Krejci1d82ef62015-08-07 14:44:40 +02001705static void
1706lys_deviation_free(struct ly_ctx *ctx, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001707{
1708 int i, j;
1709
1710 lydict_remove(ctx, dev->target_name);
1711 lydict_remove(ctx, dev->dsc);
1712 lydict_remove(ctx, dev->ref);
1713
1714 for (i = 0; i < dev->deviate_size; i++) {
1715 lydict_remove(ctx, dev->deviate[i].dflt);
1716 lydict_remove(ctx, dev->deviate[i].units);
1717
1718 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1719 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001720 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001721 }
1722 free(dev->deviate[i].must);
1723
1724 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1725 free(dev->deviate[j].unique[j].leafs);
1726 }
1727 free(dev->deviate[i].unique);
1728 }
1729 }
1730 free(dev->deviate);
1731}
1732
Radek Krejci1d82ef62015-08-07 14:44:40 +02001733static void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001734lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +02001735{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001736 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001737
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001738 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001739 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001740 lydict_remove(ctx, uses->refine[i].dsc);
1741 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001742
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001743 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001744 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001745 }
1746 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001747
Radek Krejci76512572015-08-04 09:47:08 +02001748 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001749 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001750 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001751 lydict_remove(ctx, uses->refine[i].mod.presence);
1752 }
1753 }
1754 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001755
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001756 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001757 lys_augment_free(ctx, uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001758 }
1759 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001760
Radek Krejci1d82ef62015-08-07 14:44:40 +02001761 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001762}
1763
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001764void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001765lys_node_free(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001766{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001767 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001768 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001770 if (!node) {
1771 return;
1772 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001773
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001774 assert(node->module);
1775 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001776
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001777 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001778
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001779 /* common part */
1780 LY_TREE_FOR_SAFE(node->child, next, sub) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001781 lys_node_free(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001782 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001783
Radek Krejcid12f57b2015-08-06 10:43:39 +02001784 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1785 free(node->features);
1786 lydict_remove(ctx, node->name);
1787 lydict_remove(ctx, node->dsc);
1788 lydict_remove(ctx, node->ref);
1789 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001790
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001791 /* specific part */
1792 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001793 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001794 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001795 break;
Radek Krejci76512572015-08-04 09:47:08 +02001796 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001797 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001798 break;
Radek Krejci76512572015-08-04 09:47:08 +02001799 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001800 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001801 break;
Radek Krejci76512572015-08-04 09:47:08 +02001802 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001803 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001804 break;
Radek Krejci76512572015-08-04 09:47:08 +02001805 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001806 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001807 break;
Radek Krejci76512572015-08-04 09:47:08 +02001808 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001809 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001810 break;
Radek Krejci76512572015-08-04 09:47:08 +02001811 case LYS_USES:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001812 lys_uses_free(ctx, (struct lys_node_uses *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001813 break;
Radek Krejci76512572015-08-04 09:47:08 +02001814 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001815 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001816 break;
Radek Krejci76512572015-08-04 09:47:08 +02001817 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001818 /* do nothing */
1819 break;
Radek Krejci76512572015-08-04 09:47:08 +02001820 case LYS_GROUPING:
1821 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001822 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001823 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001824 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001825
1826 case LYS_INPUT:
1827 case LYS_OUTPUT:
1828 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1829 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001830 case LYS_UNKNOWN:
1831 LOGINT;
1832 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001833 }
Radek Krejci5a065542015-05-22 15:02:07 +02001834
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001835 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001836 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001837 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001838}
1839
Michal Vasko13b15832015-08-19 11:04:48 +02001840/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001841static void
Michal Vasko13b15832015-08-19 11:04:48 +02001842module_free_common(struct lys_module *module, int free_int_mods)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001843{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001844 struct ly_ctx *ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001845 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001846 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001847
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001848 assert(module->ctx);
1849 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001850
Radek Krejcidce51452015-06-16 15:20:08 +02001851 /* as first step, free the imported modules */
1852 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa76ee152015-08-17 15:38:22 +02001853 /* do not free internal modules */
Michal Vasko18bd09b2015-08-19 15:07:00 +02001854 if (!free_int_mods) {
1855 for (j = 0; j < int_mods.count; ++j) {
Michal Vaskod83c03a2015-08-21 09:09:24 +02001856 if (module->imp[i].module && !strcmp(int_mods.modules[j].name, module->imp[i].module->name)
Michal Vasko18bd09b2015-08-19 15:07:00 +02001857 && module->imp[i].module->rev
1858 && !strcmp(int_mods.modules[j].revision, module->imp[i].module->rev[0].date)) {
1859 break;
1860 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02001861 }
Michal Vasko18bd09b2015-08-19 15:07:00 +02001862 if (j < int_mods.count) {
1863 continue;
1864 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02001865 }
1866
Radek Krejcidce51452015-06-16 15:20:08 +02001867 /* get the imported module from the context and then free,
1868 * this check is necessary because the imported module can
1869 * be already removed
1870 */
1871 l = ctx->models.used;
1872 for (j = 0; j < l; j++) {
1873 if (ctx->models.list[j] == module->imp[i].module) {
Michal Vasko13b15832015-08-19 11:04:48 +02001874 lys_free(module->imp[i].module, free_int_mods);
Radek Krejcidce51452015-06-16 15:20:08 +02001875 break;
1876 }
1877 }
1878 }
1879 free(module->imp);
1880
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001881 while (module->data) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001882 lys_node_free(module->data);
Radek Krejci21181962015-06-30 14:11:00 +02001883 }
Radek Krejci5a065542015-05-22 15:02:07 +02001884
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001885 lydict_remove(ctx, module->dsc);
1886 lydict_remove(ctx, module->ref);
1887 lydict_remove(ctx, module->org);
1888 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001889
Radek Krejcieb00f512015-07-01 16:44:58 +02001890 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001891 for (i = 0; i < module->rev_size; i++) {
1892 lydict_remove(ctx, module->rev[i].dsc);
1893 lydict_remove(ctx, module->rev[i].ref);
1894 }
1895 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001896
Radek Krejcieb00f512015-07-01 16:44:58 +02001897 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001898 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001899 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001900 }
1901 module->ident_size = 0;
1902 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001903
Radek Krejcieb00f512015-07-01 16:44:58 +02001904 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001905 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001906 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001907 }
1908 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001909
Radek Krejcieb00f512015-07-01 16:44:58 +02001910 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001911 for (i = 0; i < module->inc_size; i++) {
Michal Vasko13b15832015-08-19 11:04:48 +02001912 lys_submodule_free(module->inc[i].submodule, free_int_mods);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001913 }
1914 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001915
Radek Krejcieb00f512015-07-01 16:44:58 +02001916 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02001917 for (i = 0; i < module->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001918 lys_augment_free(ctx, module->augment[i]);
Radek Krejcif5be10f2015-06-16 13:29:36 +02001919 }
1920 free(module->augment);
1921
Radek Krejcieb00f512015-07-01 16:44:58 +02001922 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001923 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001924 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001925 }
1926 free(module->features);
1927
Radek Krejcieb00f512015-07-01 16:44:58 +02001928 /* deviations */
1929 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001930 lys_deviation_free(ctx, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001931 }
1932 free(module->deviation);
1933
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001934 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02001935}
1936
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001937void
Michal Vasko13b15832015-08-19 11:04:48 +02001938lys_submodule_free(struct lys_submodule *submodule, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02001939{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001940 if (!submodule) {
1941 return;
1942 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001943
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001944 submodule->inc_size = 0;
1945 free(submodule->inc);
1946 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02001947
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001948 /* common part with struct ly_module */
Michal Vasko13b15832015-08-19 11:04:48 +02001949 module_free_common((struct lys_module *)submodule, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02001950
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001951 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02001952
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001953 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001954}
1955
Radek Krejcib8048692015-08-05 13:36:34 +02001956static struct lys_node_leaf *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001957lys_uniq_find(struct lys_node_list *list, struct lys_node_leaf *orig_leaf)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001958{
Radek Krejci1d82ef62015-08-07 14:44:40 +02001959 struct lys_node *node, *node2, *ret = NULL, *parent1, *parent2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001960 int depth = 1, i;
1961
1962 /* find the correct direct descendant of list in orig_leaf */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001963 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001964 while (1) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001965 if (!node->parent) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001966 return NULL;
1967 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001968 if (!strcmp(node->parent->name, list->name)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001969 break;
1970 }
1971
Radek Krejci1d82ef62015-08-07 14:44:40 +02001972 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001973 ++depth;
1974 }
1975
1976 /* make sure the nodes are equal */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001977 parent1 = node->parent->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001978 parent2 = list->parent;
1979 while (1) {
1980 if ((parent1 && !parent2) || (!parent1 && parent2)) {
1981 return NULL;
1982 }
1983
1984 if (parent1 == parent2) {
1985 break;
1986 }
1987
1988 parent1 = parent1->parent;
1989 parent2 = parent2->parent;
1990 }
1991
1992 /* find the descendant in the list */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001993 LY_TREE_FOR(list->child, node2) {
1994 if (!strcmp(node2->name, node->name)) {
1995 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001996 break;
1997 }
1998 }
1999
2000 if (!ret) {
2001 return NULL;
2002 }
2003
2004 /* continue traversing both trees, the nodes are always truly equal */
2005 while (1) {
2006 --depth;
2007 if (!depth) {
Radek Krejci76512572015-08-04 09:47:08 +02002008 if (ret->nodetype != LYS_LEAF) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002009 return NULL;
2010 }
Radek Krejcib8048692015-08-05 13:36:34 +02002011 return (struct lys_node_leaf *)ret;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002012 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002013 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002014 for (i = 0; i < depth-1; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002015 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002016 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002017 LY_TREE_FOR(ret->child, node2) {
2018 if (!strcmp(node2->name, node->name)) {
2019 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002020 break;
2021 }
2022 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002023 if (!node2) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002024 return NULL;
2025 }
2026 }
2027}
2028
Radek Krejci76512572015-08-04 09:47:08 +02002029struct lys_node *
Michal Vasko71e1aa82015-08-12 12:17:51 +02002030lys_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 +02002031 struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002032{
Radek Krejci76512572015-08-04 09:47:08 +02002033 struct lys_node *retval = NULL, *aux, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002034 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002035 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002036
Michal Vaskoc07187d2015-08-13 15:20:57 +02002037 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002038 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002039 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002040 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002041 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002042 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002043 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002044 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002045 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002046 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002047 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002048 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002049 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002050 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002051 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002052 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002053 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002054 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002055 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002056 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002057 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002058 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002059 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002060 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002061
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002062 /* we cannot just duplicate memory since the strings are stored in
2063 * dictionary and we need to update dictionary counters.
2064 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002065
Radek Krejci1d82ef62015-08-07 14:44:40 +02002066 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002067 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002068 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002069 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002070 break;
2071
Radek Krejci76512572015-08-04 09:47:08 +02002072 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002073 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002074 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002075 break;
2076
Radek Krejci76512572015-08-04 09:47:08 +02002077 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002078 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002079 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002080 break;
2081
Radek Krejci76512572015-08-04 09:47:08 +02002082 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002083 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002084 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002085 break;
2086
Radek Krejci76512572015-08-04 09:47:08 +02002087 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002088 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002089 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002090 break;
2091
Radek Krejci76512572015-08-04 09:47:08 +02002092 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002093 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002094 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002095 break;
2096
Radek Krejci76512572015-08-04 09:47:08 +02002097 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002098 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002099 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002100 break;
2101
Radek Krejci76512572015-08-04 09:47:08 +02002102 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002103 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002104 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002105 break;
2106
Radek Krejci76512572015-08-04 09:47:08 +02002107 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002108 grp = calloc(1, sizeof *grp);
2109 retval = (struct lys_node *)grp;
2110 break;
2111
Radek Krejci76512572015-08-04 09:47:08 +02002112 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002113 rpc = calloc(1, sizeof *rpc);
2114 retval = (struct lys_node *)rpc;
2115 break;
2116
Radek Krejci76512572015-08-04 09:47:08 +02002117 case LYS_INPUT:
2118 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002119 io = calloc(1, sizeof *io);
2120 retval = (struct lys_node *)io;
2121 break;
2122
Radek Krejci76512572015-08-04 09:47:08 +02002123 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002124 ntf = calloc(1, sizeof *ntf);
2125 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002126 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002127
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002128 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002129 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002130 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002131 }
Radek Krejcib388c152015-06-04 17:03:03 +02002132
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002133 /*
2134 * duplicate generic part of the structure
2135 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002136 retval->name = lydict_insert(ctx, node->name, 0);
2137 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2138 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002139 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002140 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002141 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002142 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002143 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002144 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002145
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002146 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002147 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002148
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002149 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002150
Radek Krejci1d82ef62015-08-07 14:44:40 +02002151 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002152 retval->features = calloc(retval->features_size, sizeof *retval->features);
Radek Krejci1d82ef62015-08-07 14:44:40 +02002153 for (i = 0; i < node->features_size; ++i) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002154 if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002155 retval->features[i] = node->features[i];
Michal Vaskod23ce592015-08-06 09:55:37 +02002156 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002157 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002158
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002159 if (recursive) {
2160 /* go recursively */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002161 LY_TREE_FOR(node->child, child) {
Michal Vasko71e1aa82015-08-12 12:17:51 +02002162 aux = lys_node_dup(module, child, retval->flags, retval->nacm, 1, unres);
Radek Krejci10c760e2015-08-14 14:45:43 +02002163 if (!aux || lys_node_addchild(retval, NULL, aux)) {
Michal Vasko49168a22015-08-17 16:35:41 +02002164 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002165 }
2166 }
2167 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002168
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002169 /*
2170 * duplicate specific part of the structure
2171 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002172 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002173 case LYS_CONTAINER:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002174 if (cont_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002175 cont->when = lys_when_dup(ctx, cont_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002176 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002177 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002178
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002179 cont->must_size = cont_orig->must_size;
2180 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002181
Radek Krejci1d82ef62015-08-07 14:44:40 +02002182 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci1d82ef62015-08-07 14:44:40 +02002183 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002184 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002185
Radek Krejci76512572015-08-04 09:47:08 +02002186 case LYS_CHOICE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002187 if (choice_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002188 choice->when = lys_when_dup(ctx, choice_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002189 }
2190
2191 if (choice_orig->dflt) {
Michal Vasko1dca6882015-10-22 14:29:42 +02002192 rc = lys_getsibling(choice->module, choice->child, NULL, 0, choice_orig->dflt->name, 0, LYS_ANYXML
Radek Krejci76512572015-08-04 09:47:08 +02002193 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002194 | LYS_LIST, &choice->dflt);
Michal Vasko49168a22015-08-17 16:35:41 +02002195 if (rc) {
2196 if (rc == EXIT_FAILURE) {
2197 LOGINT;
2198 }
2199 goto error;
2200 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002201 } else {
Michal Vaskoc68a2a22015-08-06 09:57:24 +02002202 /* useless to check return value, we don't know whether
2203 * there really wasn't any default defined or it just hasn't
2204 * been resolved, we just hope for the best :)
2205 */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002206 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002207 }
2208 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002209
Radek Krejci76512572015-08-04 09:47:08 +02002210 case LYS_LEAF:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002211 if (lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres)) {
2212 goto error;
2213 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002214 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2215
2216 if (leaf_orig->dflt) {
2217 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002218 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002219 goto error;
2220 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002221 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002222
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002223 leaf->must_size = leaf_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002224 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002225
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002226 if (leaf_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002227 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002228 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002229 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002230
Radek Krejci76512572015-08-04 09:47:08 +02002231 case LYS_LEAFLIST:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002232 if (lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres)) {
2233 goto error;
2234 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002235 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002237 llist->min = llist_orig->min;
2238 llist->max = llist_orig->max;
2239
2240 llist->must_size = llist_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002241 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002242
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002243 if (llist_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002244 llist->when = lys_when_dup(ctx, llist_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002245 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002246 break;
2247
Radek Krejci76512572015-08-04 09:47:08 +02002248 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002249 list->min = list_orig->min;
2250 list->max = list_orig->max;
2251
2252 list->must_size = list_orig->must_size;
2253 list->tpdf_size = list_orig->tpdf_size;
2254 list->keys_size = list_orig->keys_size;
2255 list->unique_size = list_orig->unique_size;
2256
Radek Krejci1d82ef62015-08-07 14:44:40 +02002257 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002258
Radek Krejci1d82ef62015-08-07 14:44:40 +02002259 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002260
2261 if (list->keys_size) {
2262 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002263
2264 /* we managed to resolve it before, resolve it again manually */
2265 if (list_orig->keys[0]) {
2266 for (i = 0; i < list->keys_size; ++i) {
Michal Vasko1dca6882015-10-22 14:29:42 +02002267 rc = lys_getsibling(list->module, list->child, NULL, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2268 (struct lys_node **)&list->keys[i]);
Michal Vasko49168a22015-08-17 16:35:41 +02002269 if (rc) {
2270 if (rc == EXIT_FAILURE) {
2271 LOGINT;
2272 }
2273 goto error;
2274 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002275 }
2276 /* it was not resolved yet, add unres copy */
2277 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002278 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02002279 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002280 goto error;
Michal Vaskod23ce592015-08-06 09:55:37 +02002281 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002282 }
2283 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002284
2285 list->unique = calloc(list->unique_size, sizeof *list->unique);
2286 if (list_orig->unique) {
2287 for (i = 0; i < list->unique_size; ++i) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002288 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
2289 for (j = 0; j < list->unique[i].leafs_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002290 list->unique[i].leafs[j] = lys_uniq_find(list, list_orig->unique[i].leafs[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002291 }
2292 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002293 } else {
2294 for (i = 0; i < list->unique_size; ++i) {
2295 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02002296 list->unique[i].leafs = (struct lys_node_leaf **)list;
Michal Vasko0bd29d12015-08-19 11:45:49 +02002297 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002298 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002299 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002300
2301 if (list_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002302 list->when = lys_when_dup(ctx, list_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002303 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002304 break;
2305
Radek Krejci76512572015-08-04 09:47:08 +02002306 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002307 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002308 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002309
2310 if (anyxml_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002311 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002312 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002313 break;
2314
Radek Krejci76512572015-08-04 09:47:08 +02002315 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002316 uses->grp = uses_orig->grp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002317
2318 if (uses_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002319 uses->when = lys_when_dup(ctx, uses_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002320 }
2321
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002322 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002323 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002324 uses->augment_size = uses_orig->augment_size;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02002325 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Michal Vaskof8c128d2015-08-06 15:25:28 +02002326 if (!uses->child) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002327 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002328 goto error;
2329 }
Michal Vaskof8c128d2015-08-06 15:25:28 +02002330 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002331 break;
2332
Radek Krejci76512572015-08-04 09:47:08 +02002333 case LYS_CASE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002334 if (cs_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002335 cs->when = lys_when_dup(ctx, cs_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_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002340 grp->tpdf_size = grp_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002341 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002342 break;
2343
Radek Krejci76512572015-08-04 09:47:08 +02002344 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002345 rpc->tpdf_size = rpc_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002346 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002347 break;
2348
Radek Krejci76512572015-08-04 09:47:08 +02002349 case LYS_INPUT:
2350 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002351 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002352 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002353 break;
2354
Radek Krejci76512572015-08-04 09:47:08 +02002355 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002356 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002357 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcia01e5432015-06-16 10:35:25 +02002358 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002359
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002360 default:
Radek Krejci00768f42015-06-18 17:04:04 +02002361 /* LY_NODE_AUGMENT */
Michal Vaskod23ce592015-08-06 09:55:37 +02002362 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002363 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002364 }
2365
2366 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002367
2368error:
2369
2370 lys_node_free(retval);
2371 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002372}
2373
Michal Vasko13b15832015-08-19 11:04:48 +02002374void
2375lys_free(struct lys_module *module, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02002376{
Radek Krejcidce51452015-06-16 15:20:08 +02002377 struct ly_ctx *ctx;
2378 int i;
2379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002380 if (!module) {
2381 return;
2382 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002383
Radek Krejcidce51452015-06-16 15:20:08 +02002384 /* remove schema from the context */
2385 ctx = module->ctx;
2386 if (ctx->models.used) {
2387 for (i = 0; i < ctx->models.used; i++) {
2388 if (ctx->models.list[i] == module) {
2389 /* replace the position in the list by the last module in the list */
2390 ctx->models.used--;
2391 ctx->models.list[i] = ctx->models.list[ctx->models.used];
2392 ctx->models.list[ctx->models.used] = NULL;
2393 /* we are done */
2394 break;
2395 }
2396 }
2397 }
2398
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002399 /* common part with struct ly_submodule */
Michal Vasko13b15832015-08-19 11:04:48 +02002400 module_free_common(module, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02002401
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002402 /* specific items to free */
2403 lydict_remove(module->ctx, module->ns);
2404 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02002405
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002406 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002407}
Radek Krejci7e97c352015-06-19 16:26:34 +02002408
2409/*
2410 * op: 1 - enable, 0 - disable
2411 */
2412static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002413lys_features_change(struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002414{
2415 int all = 0;
2416 int i, j, k;
2417
2418 if (!module || !name || !strlen(name)) {
2419 return EXIT_FAILURE;
2420 }
2421
2422 if (!strcmp(name, "*")) {
2423 /* enable all */
2424 all = 1;
2425 }
2426
2427 /* module itself */
2428 for (i = 0; i < module->features_size; i++) {
2429 if (all || !strcmp(module->features[i].name, name)) {
2430 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002431 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002432 /* enable referenced features (recursion) */
2433 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002434 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002435 module->features[i].features[k]->name, op);
2436 }
2437 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002438 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002439 }
2440 if (!all) {
2441 return EXIT_SUCCESS;
2442 }
2443 }
2444 }
2445
2446 /* submodules */
2447 for (j = 0; j < module->inc_size; j++) {
2448 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2449 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2450 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002451 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002452 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002453 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002454 }
2455 if (!all) {
2456 return EXIT_SUCCESS;
2457 }
2458 }
2459 }
2460 }
2461
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002462 /* TODO submodules of submodules ... */
2463
Radek Krejci7e97c352015-06-19 16:26:34 +02002464 if (all) {
2465 return EXIT_SUCCESS;
2466 } else {
2467 return EXIT_FAILURE;
2468 }
2469}
2470
2471API int
Radek Krejcib8048692015-08-05 13:36:34 +02002472lys_features_enable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002473{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002474 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002475}
2476
2477API int
Radek Krejcib8048692015-08-05 13:36:34 +02002478lys_features_disable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002479{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002480 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002481}
2482
2483API int
Radek Krejcib8048692015-08-05 13:36:34 +02002484lys_features_state(struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002485{
2486 int i, j;
2487
2488 if (!module || !feature) {
2489 return -1;
2490 }
2491
2492 /* search for the specified feature */
2493 /* module itself */
2494 for (i = 0; i < module->features_size; i++) {
2495 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002496 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002497 return 1;
2498 } else {
2499 return 0;
2500 }
2501 }
2502 }
2503
2504 /* submodules */
2505 for (j = 0; j < module->inc_size; j++) {
2506 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2507 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002508 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002509 return 1;
2510 } else {
2511 return 0;
2512 }
2513 }
2514 }
2515 }
2516
2517 /* TODO submodules of submodules ... */
2518
2519 /* feature definition not found */
2520 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002521}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002522
Radek Krejci96a10da2015-07-30 11:00:14 +02002523API const char **
Radek Krejcib8048692015-08-05 13:36:34 +02002524lys_features_list(struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002525{
Radek Krejci96a10da2015-07-30 11:00:14 +02002526 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002527 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002528 unsigned int count;
2529
2530 if (!module) {
2531 return NULL;
2532 }
2533
2534 count = module->features_size;
2535 for (i = 0; i < module->inc_size; i++) {
2536 count += module->inc[i].submodule->features_size;
2537 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002538 result = malloc((count + 1) * sizeof *result);
2539 if (states) {
2540 *states = malloc((count + 1) * sizeof **states);
Michal Vasko2367e7c2015-07-07 11:33:44 +02002541 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002542 count = 0;
2543
2544 /* module itself */
2545 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002546 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002547 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002548 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002549 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002550 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002551 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002552 }
2553 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002554 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002555 }
2556
2557 /* submodules */
2558 for (j = 0; j < module->inc_size; j++) {
2559 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002560 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002561 if (states) {
2562 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2563 (*states)[count] = 1;
2564 } else {
2565 (*states)[count] = 0;
2566 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002567 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002568 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002569 }
2570 }
2571
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002572 /* TODO submodules of submodules ... */
2573
2574 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002575 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002576
2577 return result;
2578}
Michal Vaskobaefb032015-09-24 14:52:10 +02002579
2580API struct lys_node *
2581lys_parent(struct lys_node *node)
2582{
2583 if (!node || !node->parent) {
2584 return NULL;
2585 }
2586
2587 if (node->parent->nodetype == LYS_AUGMENT) {
2588 return ((struct lys_node_augment *)node->parent)->target;
2589 }
2590
2591 return node->parent;
2592}