blob: f8ae308c1620dcaa207ab25e46a3f66503c964c3 [file] [log] [blame]
Radek Krejcic6704c82015-10-06 11:12:45 +02001
Radek Krejcida04f4a2015-05-21 12:54:09 +02002/**
Michal Vasko2d162e12015-09-24 14:33:29 +02003 * @file tree_schema.c
Radek Krejcida04f4a2015-05-21 12:54:09 +02004 * @author Radek Krejci <rkrejci@cesnet.cz>
Michal Vasko2d162e12015-09-24 14:33:29 +02005 * @brief Manipulation with libyang schema data structures
Radek Krejcida04f4a2015-05-21 12:54:09 +02006 *
7 * Copyright (c) 2015 CESNET, z.s.p.o.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * 3. Neither the name of the Company nor the names of its contributors
19 * may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
21 */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020022#define _GNU_SOURCE
Radek Krejcida04f4a2015-05-21 12:54:09 +020023
Radek Krejci812b10a2015-05-28 16:48:25 +020024#include <assert.h>
Radek Krejci5a988152015-07-15 11:16:26 +020025#include <ctype.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020026#include <stdlib.h>
27#include <sys/mman.h>
28#include <sys/stat.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020029#include <string.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020030
31#include "common.h"
32#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020033#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020034#include "resolve.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020035#include "xml_internal.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020036#include "tree_internal.h"
Radek Krejcieab784a2015-08-27 09:56:53 +020037#include "validation.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020038
Michal Vaskoa76ee152015-08-17 15:38:22 +020039static const struct internal_modules int_mods = {
40 .modules = {
41 {"ietf-yang-types", "2013-07-15"},
42 {"ietf-inet-types", "2013-07-15"},
43 {"ietf-yang-library", "2015-07-03"}
44 },
45 .count = LY_INTERNAL_MODULE_COUNT
46};
47
Radek Krejci48061fb2015-08-05 15:41:07 +020048API struct lys_feature *
49lys_is_disabled(struct lys_node *node, int recursive)
50{
51 int i;
52
53check:
54 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
55 /* input/output does not have if-feature, so skip them */
56
57 /* check local if-features */
58 for (i = 0; i < node->features_size; i++) {
59 if (!(node->features[i]->flags & LYS_FENABLED)) {
60 return node->features[i];
61 }
62 }
63 }
64
65 if (!recursive) {
66 return NULL;
67 }
68
69 /* go through parents */
70 if (node->nodetype == LYS_AUGMENT) {
71 /* go to parent actually means go to the target node */
72 node = ((struct lys_node_augment *)node)->target;
Radek Krejci48061fb2015-08-05 15:41:07 +020073 } else if (node->parent) {
74 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020075 } else {
76 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020077 }
78
Radek Krejci074bf852015-08-19 14:22:16 +020079 if (recursive == 2) {
80 /* continue only if the node cannot have a data instance */
81 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
82 return NULL;
83 }
84 }
85 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020086}
87
Michal Vasko1dca6882015-10-22 14:29:42 +020088int
Michal Vasko165dc4a2015-10-23 09:44:27 +020089lys_get_sibling(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)
Michal Vasko1dca6882015-10-22 14:29:42 +020091{
92 struct lys_node *node, *old_siblings = NULL;
93 struct lys_module *prefix_mod, *cur_mod;
94 int in_submod;
Michal Vasko1dca6882015-10-22 14:29:42 +020095
96 assert(siblings && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +020097 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +020098
99 /* find the beginning */
100 while (siblings->prev->next) {
101 siblings = siblings->prev;
102 }
103
104 /* fill the name length in case the caller is so indifferent */
105 if (!nam_len) {
106 nam_len = strlen(name);
107 }
108
109 /* we start with the module itself, submodules come later */
110 in_submod = 0;
111
112 /* set prefix_mod correctly */
113 if (mod_name) {
Michal Vaskob6729c62015-10-21 12:09:47 +0200114 prefix_mod = lys_get_import_module(siblings->module, NULL, 0, mod_name, mod_name_len);
Michal Vasko1dca6882015-10-22 14:29:42 +0200115 if (!prefix_mod) {
116 return -1;
117 }
118 cur_mod = prefix_mod;
119 /* it is not our module */
120 if (cur_mod != mod) {
121 old_siblings = siblings;
122 siblings = cur_mod->data;
123 }
124 } else {
125 if (mod) {
126 prefix_mod = mod;
127 } else {
128 prefix_mod = siblings->module;
129 }
130 if (prefix_mod->type) {
131 prefix_mod = ((struct lys_submodule *)prefix_mod)->belongsto;
132 }
133 cur_mod = prefix_mod;
134 }
135
136 while (1) {
137 /* try to find the node */
138 node = NULL;
139 while ((node = lys_getnext(node, siblings->parent, cur_mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
140 if (!type || (node->nodetype & type)) {
141 /* module check */
142 if (!node->module->type) {
143 if (cur_mod != node->module) {
144 continue;
145 }
146 } else {
147 /* both are submodules */
148 if (cur_mod->type) {
149 if (cur_mod != node->module) {
150 continue;
151 }
152 } else {
153 if (cur_mod != ((struct lys_submodule *)node->module)->belongsto) {
154 continue;
155 }
156 }
157 }
158
159 /* direct name check */
160 if ((node->name == name) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
161 if (ret) {
162 *ret = node;
163 }
164 return EXIT_SUCCESS;
165 }
166 }
167 }
168
169 /* The original siblings may be valid,
170 * it's a special case when we're looking
171 * for a node from an augment.
172 */
Michal Vasko165dc4a2015-10-23 09:44:27 +0200173 if ((type & LYS_AUGMENT) && old_siblings) {
Michal Vasko1dca6882015-10-22 14:29:42 +0200174 siblings = old_siblings;
175 old_siblings = NULL;
176 continue;
177 }
178
179 /* we're not top-level, search ended */
180 if (siblings->parent) {
181 break;
182 }
183
184 /* let's try the submodules */
185 if (in_submod == prefix_mod->inc_size) {
186 break;
187 }
188 cur_mod = (struct lys_module *)prefix_mod->inc[in_submod].submodule;
189 siblings = cur_mod->data;
190 ++in_submod;
191 }
192
193 return EXIT_FAILURE;
194}
195
196API struct lys_node *
Radek Krejci8bc87f62015-09-02 16:19:05 +0200197lys_getnext(struct lys_node *last, struct lys_node *parent, struct lys_module *module, int options)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200198{
199 struct lys_node *next;
200
Radek Krejci8bc87f62015-09-02 16:19:05 +0200201 if (!last) {
202 /* first call */
203
204 /* get know where to start */
205 if (parent) {
206 /* schema subtree */
207 next = last = parent->child;
208 } else {
209 /* top level data */
210 assert(module);
211 next = last = module->data;
212 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200213 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200214 /* continue after the last returned value */
215 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200216 }
217
218repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200219 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200220 if (options & LYS_GETNEXT_WITHGROUPING) {
221 return next;
222 }
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 Vaskob6eedf02015-10-22 16:07:03 +0200237 case LYS_INPUT:
238 case LYS_OUTPUT:
239 if (options & LYS_GETNEXT_WITHINOUT) {
240 return next;
241 } else {
242 next = next->child;
243 goto repeat;
244 }
245 break;
246
Michal Vaskoa5835e92015-10-20 15:07:39 +0200247 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200248 if (options & LYS_GETNEXT_WITHCASE) {
249 return next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200250 } else {
251 next = next->child;
252 goto repeat;
Michal Vasko1dca6882015-10-22 14:29:42 +0200253 }
Michal Vaskob6eedf02015-10-22 16:07:03 +0200254 break;
255
Michal Vasko1dca6882015-10-22 14:29:42 +0200256 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200257 /* go into */
258 next = next->child;
259 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200260
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200261 case LYS_RPC:
262 case LYS_NOTIF:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200263 case LYS_CONTAINER:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200264 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200265 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200266 case LYS_LIST:
267 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200268 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200269
270 case LYS_CHOICE:
271 if (options & LYS_GETNEXT_WITHCHOICE) {
272 return next;
273 } else {
274 /* go into */
275 next = next->child;
276 goto repeat;
277 }
278 break;
279
Radek Krejci7f40ce32015-08-12 20:38:46 +0200280 default:
281 /* we should not be here */
282 return NULL;
283 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200284
285
286}
287
288static struct lys_node *
289check_mand_getnext(struct lys_node *last, struct lys_node *parent)
290{
291 struct lys_node *next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200292 next = lys_getnext(last, parent, NULL, LYS_GETNEXT_WITHCHOICE);
293
Radek Krejci4b6c2112015-10-06 12:48:34 +0200294repeat:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200295 if (next && next->nodetype == LYS_CONTAINER) {
296 if (((struct lys_node_container *)next)->presence) {
297 /* mandatory elements under the non-existing presence
298 * container are not mandatory - 7.6.5, rule 1 */
299 next = next->next;
300 } else {
301 /* go into */
302 next = next->child;
303 }
304 goto repeat;
305 }
306
307 return next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200308}
309
310static struct lys_node *
311check_mand_check(struct lys_node *node, struct lys_node *stop, struct lyd_node *data)
312{
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200313 struct lys_node *siter = NULL, *parent = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200314 struct lyd_node *diter = NULL;
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200315 struct lyd_set *set = NULL;
316 unsigned int i;
Radek Krejci14a11a62015-08-17 17:27:38 +0200317 uint32_t minmax;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200318
319 if (node->flags & LYS_MAND_TRUE) {
320 switch (node->nodetype) {
321 case LYS_LEAF:
322 case LYS_ANYXML:
323 case LYS_CHOICE:
324 if (node->parent->nodetype == LYS_CASE) {
325 /* 7.6.5, rule 2 */
326 /* 7.9.4, rule 1 */
327 if (node->parent->parent->parent == data->schema) {
328 /* the only case the node's siblings can exist is that the
329 * data node passed originaly to ly_check_mandatory()
330 * had this choice as a child
331 */
332 /* try to find the node's siblings in data */
333 LY_TREE_FOR(data->child, diter) {
334 LY_TREE_FOR(node->parent->child, siter) {
335 if (siter == diter->schema) {
336 /* some sibling exists, rule applies */
337 break;
338 }
339 }
340 if (siter) {
341 break;
342 }
343 }
344 }
345 if (!siter) {
346 /* no sibling exists */
347 return NULL;
348 }
349 } else {
350 for(parent = node->parent; parent != stop; parent = parent->parent) {
351 if (parent->nodetype != LYS_CONTAINER) {
352 /* 7.6.5, rule 1, checking presence is not needed
353 * since it is done in check_mand_getnext()
354 */
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200355 lyd_set_free(set);
Radek Krejci7f40ce32015-08-12 20:38:46 +0200356 return NULL;
357 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200358 /* add the parent to the list for searching in data tree */
359 if (!set) {
360 set = lyd_set_new();
361 }
362 lyd_set_add(set, (struct lyd_node *)parent);
Radek Krejci7f40ce32015-08-12 20:38:46 +0200363 }
364 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200365
366 /* search for instance */
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200367 if (set) {
368 for (i = 0; i < set->number; i++) {
369 LY_TREE_FOR(data->child, diter) {
370 if (diter->schema == (struct lys_node *)(set->set[i])) {
371 break;
372 }
373 }
374 if (!diter) {
375 /* instance not found */
376 node = (struct lys_node *)(set->set[i]);
377 lyd_set_free(set);
378 return node;
379 }
380 data = diter;
381 }
382 lyd_set_free(set);
383 }
384
Radek Krejci14a11a62015-08-17 17:27:38 +0200385 LY_TREE_FOR(data->child, diter) {
386 if (diter->schema == node) {
387 return NULL;
388 }
389 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200390
Radek Krejci14a11a62015-08-17 17:27:38 +0200391 /* instance not found */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200392 /* 7.6.5, rule 3 (or 2) */
393 /* 7.9.4, rule 2 */
394 return node;
395 default:
396 /* error */
397 break;
398 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200399 } else if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
400 /* search for number of instances */
401 minmax = 0;
402 LY_TREE_FOR(data->child, diter) {
403 if (diter->schema == node) {
404 minmax++;
405 }
406 }
407
408 /* check the specified constraints */
409 if (node->nodetype == LYS_LIST) {
410 if (((struct lys_node_list *)node)->min && minmax < ((struct lys_node_list *)node)->min) {
411 return node;
412 }
413
414 if (((struct lys_node_list *)node)->max && minmax > ((struct lys_node_list *)node)->max) {
415 return node;
416 }
417 } else if (node->nodetype == LYS_LEAFLIST) {
418 if (((struct lys_node_leaflist *)node)->min && minmax < ((struct lys_node_leaflist *)node)->min) {
419 return node;
420 }
421
422 if (((struct lys_node_leaflist *)node)->max && minmax > ((struct lys_node_leaflist *)node)->max) {
423 return node;
424 }
425 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200426 }
427
428 return NULL;
429}
430
431struct lys_node *
432ly_check_mandatory(struct lyd_node *data)
433{
Radek Krejci14a11a62015-08-17 17:27:38 +0200434 struct lys_node *siter, *saux, *saux2, *result, *parent = NULL, *parent2;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200435 struct lyd_node *diter;
436 int found;
437
438 siter = data->schema->child;
439
440repeat:
441 while (siter) {
Radek Krejci074bf852015-08-19 14:22:16 +0200442 if (lys_is_disabled(siter, 2)) {
443 siter = siter->next;
444 continue;
445 }
446
Radek Krejci7f40ce32015-08-12 20:38:46 +0200447 switch (siter->nodetype) {
448 case LYS_CONTAINER:
449 case LYS_LEAF:
450 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200451 case LYS_LIST:
452 case LYS_LEAFLIST:
453 /* check if there is some mandatory node; first test the siter itself ... */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200454 result = check_mand_check(siter, siter->parent, data);
455 if (result) {
456 return result;
457 }
458 /* ... and then the subtree */
Radek Krejci14a11a62015-08-17 17:27:38 +0200459 if (parent && siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
460 saux = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200461 while ((saux = check_mand_getnext(saux, siter))) {
462 result = check_mand_check(saux, siter, data);
463 if (result) {
464 return result;
465 }
466 }
467 }
468 siter = siter->next;
469 break;
470 case LYS_CHOICE:
Radek Krejci14a11a62015-08-17 17:27:38 +0200471 /* search for instance */
472 saux = siter;
473 siter = siter->child;
474 found = 0;
475 parent2 = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200476repeat_choice:
Radek Krejci074bf852015-08-19 14:22:16 +0200477 while (siter) {
478 if (lys_is_disabled(siter, 2)) {
479 siter = siter->next;
480 continue;
481 }
482
Radek Krejci14a11a62015-08-17 17:27:38 +0200483 switch (siter->nodetype) {
484 case LYS_CONTAINER:
485 case LYS_LEAF:
486 case LYS_LEAFLIST:
487 case LYS_LIST:
488 case LYS_ANYXML:
489 LY_TREE_FOR(data->child, diter) {
490 if (diter->schema == siter) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200491 break;
492 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200493 }
494 if (diter) {
495 /* got instance */
496 /* check presence of mandatory siblings */
Radek Krejci65d0a652015-08-27 13:09:42 +0200497 if (parent2 && parent2->nodetype == LYS_CASE) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200498 saux2 = NULL;
Radek Krejci37bda002015-08-27 11:23:56 +0200499 while ((saux2 = check_mand_getnext(saux2, parent2))) {
500 result = check_mand_check(saux2, parent2, data);
Radek Krejci14a11a62015-08-17 17:27:38 +0200501 if (result) {
502 return result;
503 }
504 }
505 }
506 siter = parent2 = NULL;
507 found = 1;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200508 break;
509 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200510 siter = siter->next;
511 break;
512 case LYS_CASE:
513 case LYS_CHOICE:
514 case LYS_USES:
515 /* go into */
Radek Krejci37bda002015-08-27 11:23:56 +0200516 if (!parent2) {
517 parent2 = siter;
518 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200519 siter = siter->child;
520 break;
521 case LYS_AUGMENT:
522 case LYS_GROUPING:
523 /* skip */
524 siter = siter->next;
525 break;
526 default:
527 /* error */
528 break;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200529 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200530 }
531
Radek Krejci14a11a62015-08-17 17:27:38 +0200532 if (parent2) {
533 siter = parent2->next;
534 if (parent2->parent == saux) {
535 parent2 = NULL;
536 } else {
537 parent2 = parent2->parent;
538 }
539 goto repeat_choice;
540 }
541
Radek Krejci074bf852015-08-19 14:22:16 +0200542 if (!found && (saux->flags & LYS_MAND_TRUE)) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200543 return saux;
544 }
545
546 /* go to next */
547 siter = saux->next;
548
Radek Krejci7f40ce32015-08-12 20:38:46 +0200549 break;
550 case LYS_USES:
551 case LYS_CASE:
552 /* go into */
553 parent = siter;
554 siter = siter->child;
555 break;
556 default:
557 /* can ignore, go to next */
558 siter = siter->next;
559 break;
560 }
561 }
562
563 if (parent) {
564 siter = parent->next;
565 if (parent->parent == data->schema) {
566 parent = NULL;
567 } else {
568 parent = parent->parent;
569 }
570 goto repeat;
571 }
572
573 return NULL;
574}
575
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200576void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200577lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200578{
Radek Krejci76512572015-08-04 09:47:08 +0200579 struct lys_node *parent, *first;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200580
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200581 if (!node) {
582 return;
583 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200584
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200585 /* unlink from data model if necessary */
586 if (node->module) {
587 if (node->module->data == node) {
588 node->module->data = node->next;
589 }
590 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200591
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200592 /* store pointers to important nodes */
593 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200594 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200595 /* handle augments - first, unlink it from the augment parent ... */
596 if (parent->child == node) {
597 parent->child = node->next;
598 }
599 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200600 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200601 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200602
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200603 /* unlink from parent */
604 if (parent) {
605 if (parent->child == node) {
606 parent->child = node->next;
607 }
608 node->parent = NULL;
609 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200610
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200611 /* unlink from siblings */
612 if (node->prev == node) {
613 /* there are no more siblings */
614 return;
615 }
616 if (node->next) {
617 node->next->prev = node->prev;
618 } else {
619 /* unlinking the last element */
620 if (parent) {
621 first = parent->child;
622 } else {
623 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200624 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200625 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200626 }
627 }
628 first->prev = node->prev;
629 }
630 if (node->prev->next) {
631 node->prev->next = node->next;
632 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200633
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200634 /* clean up the unlinked element */
635 node->next = NULL;
636 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200637}
638
Michal Vasko563ef092015-09-04 13:17:23 +0200639struct lys_node_grp *
640lys_find_grouping_up(const char *name, struct lys_node *start, int in_submodules)
641{
642 struct lys_node *par_iter, *iter, *stop;
643 int i;
644
645 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200646 /* top-level augment, look into module (uses augment is handled correctly below) */
647 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
648 par_iter = par_iter->parent->module->data;
649 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200650 break;
651 }
652 }
653
Michal Vasko6f929da2015-10-02 16:23:25 +0200654 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200655 continue;
656 }
657
658 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
659 if (!stop) {
660 stop = par_iter;
661 } else if (iter == stop) {
662 break;
663 }
664 if (iter->nodetype != LYS_GROUPING) {
665 continue;
666 }
667
668 if (name == iter->name) {
669 return (struct lys_node_grp *)iter;
670 }
671 }
672 }
673
674 if (in_submodules) {
675 for (i = 0; i < start->module->inc_size; ++i) {
676 for (iter = start->module->inc[i].submodule->data; iter; iter = iter->next) {
677 if (iter->nodetype != LYS_GROUPING) {
678 continue;
679 }
680
681 if (name == iter->name) {
682 return (struct lys_node_grp *)iter;
683 }
684 }
685 }
686 }
687
688 return NULL;
689}
690
Radek Krejci10c760e2015-08-14 14:45:43 +0200691/*
692 * get next grouping in the root's subtree, in the
693 * first call, tha last is NULL
694 */
695static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200696lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200697{
Radek Krejci10c760e2015-08-14 14:45:43 +0200698 struct lys_node *last = (struct lys_node *)lastgrp;
699 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200700
Radek Krejci10c760e2015-08-14 14:45:43 +0200701 assert(root);
702
703 if (!last) {
704 last = root;
705 }
706
707 while (1) {
708 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
709 next = last->child;
710 } else {
711 next = NULL;
712 }
713 if (!next) {
714 if (last == root) {
715 /* we are done */
716 return NULL;
717 }
718
719 /* no children, go to siblings */
720 next = last->next;
721 }
722 while (!next) {
723 /* go back through parents */
724 if (last->parent == root) {
725 /* we are done */
726 return NULL;
727 }
728 last = last->parent;
729 next = last->next;
730 }
731
732 if (next->nodetype == LYS_GROUPING) {
733 return (struct lys_node_grp *)next;
734 }
735
736 last = next;
737 }
738}
739
Michal Vasko0d343d12015-08-24 14:57:36 +0200740/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200741int
Radek Krejci07911992015-08-14 15:13:31 +0200742lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
743{
Michal Vasko563ef092015-09-04 13:17:23 +0200744 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200745 struct lys_node_grp *grp;
746 int down;
747
748 assert(node);
749
750 if (!parent) {
751 assert(module);
752 } else {
753 module = parent->module;
754 }
755
756 switch (node->nodetype) {
757 case LYS_GROUPING:
758 /* 6.2.1, rule 6 */
759 if (parent) {
760 if (parent->child) {
761 down = 1;
762 start = parent->child;
763 } else {
764 down = 0;
765 start = parent;
766 }
767 } else {
768 down = 1;
769 start = module->data;
770 }
771 /* go up */
Michal Vasko563ef092015-09-04 13:17:23 +0200772 if (lys_find_grouping_up(node->name, start, 0)) {
773 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
774 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200775 }
776 /* go down, because grouping can be defined after e.g. container in which is collision */
777 if (down) {
778 for (iter = start, stop = NULL; iter; iter = iter->prev) {
779 if (!stop) {
780 stop = start;
781 } else if (iter == stop) {
782 break;
783 }
784 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
785 continue;
786 }
787
788 grp = NULL;
789 while ((grp = lys_get_next_grouping(grp, iter))) {
790 if (node->name == grp->name) {
791 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
792 return EXIT_FAILURE;
793 }
794 }
795 }
796 }
797 break;
798 case LYS_LEAF:
799 case LYS_LEAFLIST:
800 case LYS_LIST:
801 case LYS_CONTAINER:
802 case LYS_CHOICE:
803 case LYS_ANYXML:
804 /* 6.2.1, rule 7 */
805 if (parent) {
806 iter = parent;
807 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE))) {
808 iter = iter->parent;
809 }
810 if (!iter) {
811 stop = NULL;
812 iter = module->data;
813 } else {
814 stop = iter;
815 iter = iter->child;
816 }
817 } else {
818 stop = NULL;
819 iter = module->data;
820 }
821 while (iter) {
822 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
823 iter = iter->child;
824 continue;
825 }
826
827 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
828 if (iter->module == node->module && iter->name == node->name) {
829 LOGVAL(LYE_SPEC, 0, "Duplicated child identifier \"%s\" in \"%s\".", node->name,
830 stop ? stop->name : "(sub)module");
831 return EXIT_FAILURE;
832 }
833 }
834
835 /* special case for choice - we must check the choice's name as
836 * well as the names of nodes under the choice
837 */
838 if (iter->nodetype == LYS_CHOICE) {
839 iter = iter->child;
840 continue;
841 }
842
843 /* go to siblings */
844 if (!iter->next) {
845 /* no sibling, go to parent's sibling */
846 do {
847 iter = iter->parent;
848 if (iter && iter->next) {
849 break;
850 }
851 } while (iter != stop);
852
853 if (iter == stop) {
854 break;
855 }
856 }
857 iter = iter->next;
858 }
859 break;
860 case LYS_CASE:
861 /* 6.2.1, rule 8 */
862 LY_TREE_FOR(parent->child, iter) {
863 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
864 continue;
865 }
866
867 if (iter->module == node->module && iter->name == node->name) {
868 LOGVAL(LYE_DUPID, 0, "case", node->name);
869 return EXIT_FAILURE;
870 }
871 }
872 break;
873 default:
874 /* no check needed */
875 break;
876 }
877
878 return EXIT_SUCCESS;
879}
880
Michal Vasko0d343d12015-08-24 14:57:36 +0200881/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200882int
Radek Krejci10c760e2015-08-14 14:45:43 +0200883lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
884{
Radek Krejci92720552015-10-05 15:28:27 +0200885 struct lys_node *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200886 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200887
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200888 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200889
Radek Krejci10c760e2015-08-14 14:45:43 +0200890 if (parent) {
891 type = parent->nodetype;
892 module = parent->module;
893 } else {
894 assert(module);
895 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200896 }
897
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200898 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200899 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200900 case LYS_CONTAINER:
901 case LYS_LIST:
902 case LYS_GROUPING:
903 case LYS_USES:
904 case LYS_INPUT:
905 case LYS_OUTPUT:
906 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200907 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200908 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
909 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200910 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200911 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
912 return EXIT_FAILURE;
913 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200914
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200915 break;
Radek Krejci76512572015-08-04 09:47:08 +0200916 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200917 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200918 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200919 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"choice\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200920 strnodetype(child->nodetype), parent->name);
921 return EXIT_FAILURE;
922 }
923 break;
Radek Krejci76512572015-08-04 09:47:08 +0200924 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200925 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200926 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200927 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"case\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200928 strnodetype(child->nodetype), parent->name);
929 return EXIT_FAILURE;
930 }
931 break;
Radek Krejci76512572015-08-04 09:47:08 +0200932 case LYS_RPC:
933 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200934 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"rpc\" %s.",
Michal Vasko38d01f72015-06-15 09:41:06 +0200935 strnodetype(child->nodetype), parent->name);
936 return EXIT_FAILURE;
937 }
938 break;
Radek Krejci76512572015-08-04 09:47:08 +0200939 case LYS_LEAF:
940 case LYS_LEAFLIST:
941 case LYS_ANYXML:
Radek Krejci10c760e2015-08-14 14:45:43 +0200942 LOGVAL(LYE_SPEC, 0, "The \"%s\" statement (%s) cannot have any data substatement.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200943 strnodetype(parent->nodetype), parent->name);
944 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200945 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200946 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200947 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
948 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200949 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200950 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
951 return EXIT_FAILURE;
952 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200953 break;
954 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200955 /* top level */
956 if (!(child->nodetype &
957 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
958 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci2c0ca272015-08-14 15:31:01 +0200959 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in (sub)module \"%s\"",
960 strnodetype(child->nodetype), module->name);
Radek Krejci10c760e2015-08-14 14:45:43 +0200961 return EXIT_FAILURE;
962 }
963
964 break;;
965 }
966
967 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200968 if (lys_check_id(child, parent, module)) {
969 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200970 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200971
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200972 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200973 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200974 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200975
Radek Krejci10c760e2015-08-14 14:45:43 +0200976 if (!parent) {
Radek Krejci92720552015-10-05 15:28:27 +0200977 if (module->data) {
978 module->data->prev->next = child;
979 child->prev = module->data->prev;
980 module->data->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200981 } else {
Radek Krejci92720552015-10-05 15:28:27 +0200982 module->data = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200983 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200984 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +0200985 if (!parent->child) {
986 /* the only/first child of the parent */
987 parent->child = child;
988 child->parent = parent;
989 iter = child;
990 } else {
991 /* add a new child at the end of parent's child list */
992 iter = parent->child->prev;
993 iter->next = child;
994 child->prev = iter;
995 }
996 while (iter->next) {
997 iter = iter->next;
998 iter->parent = parent;
999 }
1000 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001001 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001002
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001003 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001004}
1005
Radek Krejcib8048692015-08-05 13:36:34 +02001006API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +02001007lys_parse(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001008{
Michal Vaskof02e3742015-08-05 16:27:02 +02001009 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +02001010 struct lys_module *mod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001011
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001012 if (!ctx || !data) {
1013 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1014 return NULL;
1015 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001016
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001017 unres = calloc(1, sizeof *unres);
1018
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001019 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001020 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001021 mod = yin_read_module(ctx, data, 1, unres);
1022 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001023 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001024 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001025 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001026 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001027 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001028
Michal Vasko0bd29d12015-08-19 11:45:49 +02001029 if (mod && unres->count && resolve_unres_schema(mod, unres)) {
Michal Vasko13b15832015-08-19 11:04:48 +02001030 lys_free(mod, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001031 mod = NULL;
1032 }
1033 free(unres->item);
1034 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +02001035 free(unres->str_snode);
Michal Vaskoc07187d2015-08-13 15:20:57 +02001036#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001037 free(unres->line);
Michal Vaskoc07187d2015-08-13 15:20:57 +02001038#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001039 free(unres);
1040
1041 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001042}
1043
Radek Krejcib8048692015-08-05 13:36:34 +02001044struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001045lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02001046{
Michal Vaskof02e3742015-08-05 16:27:02 +02001047 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +02001048 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001049
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001050 assert(module);
1051 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001052
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001053 unres = calloc(1, sizeof *unres);
1054
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001055 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001056 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001057 submod = yin_read_submodule(module, data, implement, unres);
1058 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001059 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001060 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001061 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001062 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001063 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001064
Michal Vasko0bd29d12015-08-19 11:45:49 +02001065 if (submod && unres->count && resolve_unres_schema((struct lys_module *)submod, unres)) {
Michal Vasko13b15832015-08-19 11:04:48 +02001066 lys_submodule_free(submod, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001067 submod = NULL;
1068 }
1069 free(unres->item);
1070 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +02001071 free(unres->str_snode);
Michal Vaskoc07187d2015-08-13 15:20:57 +02001072#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001073 free(unres->line);
Michal Vaskoc07187d2015-08-13 15:20:57 +02001074#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001075 free(unres);
1076
1077 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001078}
1079
Radek Krejcib8048692015-08-05 13:36:34 +02001080API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +02001081lys_read(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001082{
Radek Krejcib8048692015-08-05 13:36:34 +02001083 struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +02001084 struct stat sb;
1085 char *addr;
1086
1087 if (!ctx || fd < 0) {
1088 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1089 return NULL;
1090 }
1091
1092 /*
1093 * TODO
1094 * This is just a temporary solution to make working automatic search for
1095 * imported modules. This doesn't work e.g. for streams (stdin)
1096 */
1097 fstat(fd, &sb);
1098 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
1099 module = lys_parse(ctx, addr, format);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001100 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001101
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001102 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001103}
1104
Radek Krejcib8048692015-08-05 13:36:34 +02001105struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001106lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02001107{
Radek Krejcib8048692015-08-05 13:36:34 +02001108 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001109 struct stat sb;
1110 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001111
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001112 assert(module);
1113 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001114
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001115 /*
1116 * TODO
1117 * This is just a temporary solution to make working automatic search for
1118 * imported modules. This doesn't work e.g. for streams (stdin)
1119 */
1120 fstat(fd, &sb);
1121 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
1122 /* TODO addr error check */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001123 submodule = lys_submodule_parse(module, addr, format, implement);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001124 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +02001125
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001126 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02001127
1128}
1129
Radek Krejci1d82ef62015-08-07 14:44:40 +02001130static struct lys_restr *
1131lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001132{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001133 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001134 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001135
Radek Krejci3733a802015-06-19 13:43:21 +02001136 if (!size) {
1137 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001138 }
Radek Krejci3733a802015-06-19 13:43:21 +02001139
1140 result = calloc(size, sizeof *result);
1141 for (i = 0; i < size; i++) {
1142 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1143 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1144 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1145 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1146 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1147 }
1148
1149 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001150}
1151
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001152void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001153lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001154{
1155 assert(ctx);
1156 if (!restr) {
1157 return;
1158 }
1159
1160 lydict_remove(ctx, restr->expr);
1161 lydict_remove(ctx, restr->dsc);
1162 lydict_remove(ctx, restr->ref);
1163 lydict_remove(ctx, restr->eapptag);
1164 lydict_remove(ctx, restr->emsg);
1165}
1166
Michal Vaskob84f88a2015-09-24 13:16:10 +02001167static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001168lys_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 +02001169 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001170{
1171 int i;
1172
Michal Vasko1dca6882015-10-22 14:29:42 +02001173 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001174 new->base = old->base;
1175 new->der = old->der;
1176
Michal Vasko0bd29d12015-08-19 11:45:49 +02001177 i = unres_schema_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001178 if (i != -1) {
1179 /* HACK for unres */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001180 new->der = (struct lys_tpdf *)parent;
Michal Vaskob84f88a2015-09-24 13:16:10 +02001181 /* all these unres additions can fail even though they did not before */
Michal Vasko0bd29d12015-08-19 11:45:49 +02001182 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_DER, unres->str_snode[i], 0) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001183 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001184 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001185 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001186 }
1187
Radek Krejci3733a802015-06-19 13:43:21 +02001188 switch (new->base) {
1189 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +02001190 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001191 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001192 }
Radek Krejci3733a802015-06-19 13:43:21 +02001193 break;
1194
1195 case LY_TYPE_BITS:
1196 new->info.bits.count = old->info.bits.count;
1197 if (new->info.bits.count) {
1198 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1199 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001200 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1201 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1202 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001203 new->info.bits.bit[i].status = old->info.bits.bit[i].status;
1204 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1205 }
1206 }
1207 break;
1208
Radek Krejcif9401c32015-06-26 16:47:36 +02001209 case LY_TYPE_DEC64:
1210 new->info.dec64.dig = old->info.dec64.dig;
1211 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001212 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +02001213 }
1214 break;
1215
Radek Krejci3733a802015-06-19 13:43:21 +02001216 case LY_TYPE_ENUM:
1217 new->info.enums.count = old->info.enums.count;
1218 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001219 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Radek Krejci3733a802015-06-19 13:43:21 +02001220 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001221 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1222 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1223 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1224 new->info.enums.enm[i].status = old->info.enums.enm[i].status;
1225 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +02001226 }
1227 }
1228 break;
1229
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001230 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001231 if (old->info.ident.ref) {
1232 new->info.ident.ref = old->info.ident.ref;
1233 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001234 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001235 assert(i != -1);
Michal Vasko0bd29d12015-08-19 11:45:49 +02001236 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i], 0) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001237 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001238 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001239 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001240 break;
1241
Radek Krejciaf351422015-06-19 14:49:38 +02001242 case LY_TYPE_INST:
1243 new->info.inst.req = old->info.inst.req;
1244 break;
1245
Radek Krejcif2860132015-06-20 12:37:20 +02001246 case LY_TYPE_INT8:
1247 case LY_TYPE_INT16:
1248 case LY_TYPE_INT32:
1249 case LY_TYPE_INT64:
1250 case LY_TYPE_UINT8:
1251 case LY_TYPE_UINT16:
1252 case LY_TYPE_UINT32:
1253 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +02001254 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001255 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001256 }
Radek Krejcif2860132015-06-20 12:37:20 +02001257 break;
1258
Radek Krejcidc4c1412015-06-19 15:39:54 +02001259 case LY_TYPE_LEAFREF:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001260 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02001261 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001262 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001263 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001264 break;
1265
Radek Krejci3733a802015-06-19 13:43:21 +02001266 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +02001267 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001268 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001269 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001270 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 +02001271 break;
1272
Radek Krejcie4c366b2015-07-02 10:11:31 +02001273 case LY_TYPE_UNION:
1274 new->info.uni.count = old->info.uni.count;
1275 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001276 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001277 for (i = 0; i < new->info.uni.count; i++) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001278 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres)) {
1279 return -1;
1280 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001281 }
1282 }
1283 break;
1284
Radek Krejci3733a802015-06-19 13:43:21 +02001285 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001286 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001287 break;
1288 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001289
1290 return EXIT_SUCCESS;
Radek Krejci3733a802015-06-19 13:43:21 +02001291}
1292
1293void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001294lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001295{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001296 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001298 assert(ctx);
1299 if (!type) {
1300 return;
1301 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001302
Michal Vasko1dca6882015-10-22 14:29:42 +02001303 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001304
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001305 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001306 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001307 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001308 free(type->info.binary.length);
1309 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001310 case LY_TYPE_BITS:
1311 for (i = 0; i < type->info.bits.count; i++) {
1312 lydict_remove(ctx, type->info.bits.bit[i].name);
1313 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1314 lydict_remove(ctx, type->info.bits.bit[i].ref);
1315 }
1316 free(type->info.bits.bit);
1317 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001318
1319 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001320 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001321 free(type->info.dec64.range);
1322 break;
1323
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001324 case LY_TYPE_ENUM:
1325 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001326 lydict_remove(ctx, type->info.enums.enm[i].name);
1327 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1328 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001329 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001330 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001331 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001332
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001333 case LY_TYPE_INT8:
1334 case LY_TYPE_INT16:
1335 case LY_TYPE_INT32:
1336 case LY_TYPE_INT64:
1337 case LY_TYPE_UINT8:
1338 case LY_TYPE_UINT16:
1339 case LY_TYPE_UINT32:
1340 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001341 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001342 free(type->info.num.range);
1343 break;
1344
Radek Krejcidc4c1412015-06-19 15:39:54 +02001345 case LY_TYPE_LEAFREF:
1346 lydict_remove(ctx, type->info.lref.path);
1347 break;
1348
Radek Krejci3733a802015-06-19 13:43:21 +02001349 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001350 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001351 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001352 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001353 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001354 }
1355 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001356 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001357
Radek Krejcie4c366b2015-07-02 10:11:31 +02001358 case LY_TYPE_UNION:
1359 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001360 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001361 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001362 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001363 break;
1364
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001365 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001366 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001367 break;
1368 }
Radek Krejci5a065542015-05-22 15:02:07 +02001369}
1370
Radek Krejci1d82ef62015-08-07 14:44:40 +02001371static void
1372lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001373{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001374 assert(ctx);
1375 if (!tpdf) {
1376 return;
1377 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001378
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001379 lydict_remove(ctx, tpdf->name);
1380 lydict_remove(ctx, tpdf->dsc);
1381 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001382
Radek Krejci1d82ef62015-08-07 14:44:40 +02001383 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001384
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001385 lydict_remove(ctx, tpdf->units);
1386 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001387}
1388
Michal Vaskob84f88a2015-09-24 13:16:10 +02001389static struct lys_tpdf *
1390lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1391{
1392 struct lys_tpdf *result;
1393 int i, j;
1394
1395 if (!size) {
1396 return NULL;
1397 }
1398
1399 result = calloc(size, sizeof *result);
1400 for (i = 0; i < size; i++) {
1401 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1402 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1403 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1404 result[i].flags = old[i].flags;
1405 result[i].module = old[i].module;
1406
1407 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres)) {
1408 for (j = 0; j <= i; ++j) {
1409 lys_tpdf_free(mod->ctx, &result[j]);
1410 }
1411 free(result);
1412 return NULL;
1413 }
1414
1415 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1416 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1417 }
1418
1419 return result;
1420}
1421
Radek Krejci1d82ef62015-08-07 14:44:40 +02001422static struct lys_when *
1423lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001424{
Radek Krejci76512572015-08-04 09:47:08 +02001425 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001426
1427 if (!old) {
1428 return NULL;
1429 }
1430
1431 new = calloc(1, sizeof *new);
1432 new->cond = lydict_insert(ctx, old->cond, 0);
1433 new->dsc = lydict_insert(ctx, old->dsc, 0);
1434 new->ref = lydict_insert(ctx, old->ref, 0);
1435
1436 return new;
1437}
1438
Michal Vasko0308dd62015-10-07 09:14:40 +02001439void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001440lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001441{
1442 if (!w) {
1443 return;
1444 }
1445
1446 lydict_remove(ctx, w->cond);
1447 lydict_remove(ctx, w->dsc);
1448 lydict_remove(ctx, w->ref);
1449
1450 free(w);
1451}
1452
Radek Krejcib7f5e412015-08-13 10:15:51 +02001453static void
1454lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment aug)
1455{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001456 struct lys_node *next, *sub;
1457
1458 /* children from a resolved uses */
1459 LY_TREE_FOR_SAFE(aug.child, next, sub) {
1460 lys_node_free(sub);
1461 }
1462
Radek Krejcib7f5e412015-08-13 10:15:51 +02001463 lydict_remove(ctx, aug.target_name);
1464 lydict_remove(ctx, aug.dsc);
1465 lydict_remove(ctx, aug.ref);
1466
1467 free(aug.features);
1468
1469 lys_when_free(ctx, aug.when);
1470
Michal Vasko7d356a52015-08-19 15:06:31 +02001471 /* Do not free the children, they were appended somewhere and their
1472 * new parent will take care of them.
1473 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001474}
1475
Radek Krejci76512572015-08-04 09:47:08 +02001476static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001477lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001478{
Radek Krejci76512572015-08-04 09:47:08 +02001479 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001480 struct lys_node *old_child, *new_child;
1481 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001482
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001483 if (!size) {
1484 return NULL;
1485 }
Radek Krejci106efc02015-06-10 14:36:27 +02001486
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001487 new = calloc(size, sizeof *new);
1488 for (i = 0; i < size; i++) {
1489 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1490 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1491 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1492 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001493 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001494 new[i].nodetype = old[i].nodetype;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001495 /* this must succeed, it was already resolved once */
1496 if (resolve_schema_nodeid(new[i].target_name, parent->child, new[i].module, LYS_AUGMENT, &new[i].target)) {
1497 LOGINT;
1498 free(new);
1499 return NULL;
1500 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001501 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001502
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001503 /* Correct the augment nodes.
1504 * This function can only be called from lys_node_dup() with uses
1505 * being the node duplicated, so we must have a case of grouping
1506 * with a uses with augments. The augmented nodes have already been
1507 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001508 * (it was set to their actual data parent, not an augment), and
1509 * the new augment does not have child pointer to its augment nodes,
1510 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001511 */
1512 LY_TREE_FOR(new[i].target->child, new_child) {
1513 if (new_child->name == old[i].child->name) {
1514 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001515 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001516 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001517 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001518 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001519 LY_TREE_FOR(old[i].child, old_child) {
1520 /* all augment nodes were connected as siblings, there can be no more after this */
1521 if (old_child->parent != (struct lys_node *)&old[i]) {
1522 break;
1523 }
1524
1525 assert(old_child->name == new_child->name);
1526
1527 new_child->parent = (struct lys_node *)&new[i];
1528 new_child = new_child->next;
1529 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001530 }
Radek Krejci106efc02015-06-10 14:36:27 +02001531
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001532 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001533}
1534
Radek Krejci76512572015-08-04 09:47:08 +02001535static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001536lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001537{
Radek Krejci76512572015-08-04 09:47:08 +02001538 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001539 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001540
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001541 if (!size) {
1542 return NULL;
1543 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001544
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001545 result = calloc(size, sizeof *result);
1546 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001547 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001548 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1549 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001550 result[i].flags = old[i].flags;
1551 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001552
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001553 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001554 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001555
Radek Krejci76512572015-08-04 09:47:08 +02001556 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001557 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001558 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001559 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001560 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001561 result[i].mod.list = old[i].mod.list;
1562 }
1563 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001564
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001565 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001566}
1567
Radek Krejci1d82ef62015-08-07 14:44:40 +02001568static void
1569lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001570{
Radek Krejcia52656e2015-08-05 13:41:50 +02001571 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001573 assert(ctx);
1574 if (!ident) {
1575 return;
1576 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001577
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001578 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001579 * if caller free only a single data model which is used (its identity is
1580 * reference from identity in another module), this silly freeing can lead
1581 * to segmentation fault. But without noting if the module is used by some
1582 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001583 *
1584 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001585 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001586 */
1587 while (ident->der) {
1588 der = ident->der;
1589 ident->der = der->next;
1590 free(der);
1591 }
Radek Krejci6793db02015-05-22 17:49:54 +02001592
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001593 lydict_remove(ctx, ident->name);
1594 lydict_remove(ctx, ident->dsc);
1595 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001596
1597}
1598
Radek Krejci1d82ef62015-08-07 14:44:40 +02001599static void
1600lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001601{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001602 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001603
Radek Krejcid12f57b2015-08-06 10:43:39 +02001604 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001605 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001606 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001607 }
1608 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001609}
1610
Radek Krejci1d82ef62015-08-07 14:44:40 +02001611static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001612lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1613{
1614 int i;
1615
1616 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1617 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001618 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001619 }
1620 free(io->tpdf);
1621}
1622
Radek Krejci1d82ef62015-08-07 14:44:40 +02001623static void
1624lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001625{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001626 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001627
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001628 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001629 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001630 }
1631 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001632
Radek Krejci1d82ef62015-08-07 14:44:40 +02001633 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001634}
1635
Radek Krejci1d82ef62015-08-07 14:44:40 +02001636static void
1637lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001638{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001639 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001640
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001641 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001642 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001643 }
1644 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001645
Radek Krejci1d82ef62015-08-07 14:44:40 +02001646 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001647
Radek Krejci1d82ef62015-08-07 14:44:40 +02001648 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001649 lydict_remove(ctx, leaf->units);
1650 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001651}
1652
Radek Krejci1d82ef62015-08-07 14:44:40 +02001653static void
1654lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001655{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001656 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001657
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001658 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001659 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001660 }
1661 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001662
Radek Krejci1d82ef62015-08-07 14:44:40 +02001663 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001664
Radek Krejci1d82ef62015-08-07 14:44:40 +02001665 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001666 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001667}
1668
Radek Krejci1d82ef62015-08-07 14:44:40 +02001669static void
1670lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001671{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001672 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001673
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001674 /* handle only specific parts for LY_NODE_LIST */
1675 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001676 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001677 }
1678 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001679
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001680 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001681 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001682 }
1683 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001684
Radek Krejci1d82ef62015-08-07 14:44:40 +02001685 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001686
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001687 for (i = 0; i < list->unique_size; i++) {
1688 free(list->unique[i].leafs);
1689 }
1690 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001691
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001692 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001693}
1694
Radek Krejci1d82ef62015-08-07 14:44:40 +02001695static void
1696lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001697{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001698 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001699
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001700 /* handle only specific parts for LY_NODE_CONTAINER */
1701 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001702
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001703 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001704 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001705 }
1706 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001707
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001708 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001709 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001710 }
1711 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001712
Radek Krejci1d82ef62015-08-07 14:44:40 +02001713 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001714}
1715
Radek Krejci1d82ef62015-08-07 14:44:40 +02001716static void
1717lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001718{
1719 lydict_remove(ctx, f->name);
1720 lydict_remove(ctx, f->dsc);
1721 lydict_remove(ctx, f->ref);
1722 free(f->features);
1723}
1724
Radek Krejci1d82ef62015-08-07 14:44:40 +02001725static void
1726lys_deviation_free(struct ly_ctx *ctx, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001727{
1728 int i, j;
1729
1730 lydict_remove(ctx, dev->target_name);
1731 lydict_remove(ctx, dev->dsc);
1732 lydict_remove(ctx, dev->ref);
1733
1734 for (i = 0; i < dev->deviate_size; i++) {
1735 lydict_remove(ctx, dev->deviate[i].dflt);
1736 lydict_remove(ctx, dev->deviate[i].units);
1737
1738 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1739 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001740 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001741 }
1742 free(dev->deviate[i].must);
1743
1744 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1745 free(dev->deviate[j].unique[j].leafs);
1746 }
1747 free(dev->deviate[i].unique);
1748 }
1749 }
1750 free(dev->deviate);
1751}
1752
Radek Krejci1d82ef62015-08-07 14:44:40 +02001753static void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001754lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +02001755{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001756 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001757
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001758 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001759 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001760 lydict_remove(ctx, uses->refine[i].dsc);
1761 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001762
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001763 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001764 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001765 }
1766 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001767
Radek Krejci76512572015-08-04 09:47:08 +02001768 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001769 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001770 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001771 lydict_remove(ctx, uses->refine[i].mod.presence);
1772 }
1773 }
1774 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001775
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001776 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001777 lys_augment_free(ctx, uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001778 }
1779 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001780
Radek Krejci1d82ef62015-08-07 14:44:40 +02001781 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001782}
1783
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001784void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001785lys_node_free(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001786{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001787 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001788 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001789
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001790 if (!node) {
1791 return;
1792 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001793
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001794 assert(node->module);
1795 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001796
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001797 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001798
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001799 /* common part */
1800 LY_TREE_FOR_SAFE(node->child, next, sub) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001801 lys_node_free(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001802 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001803
Radek Krejcid12f57b2015-08-06 10:43:39 +02001804 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1805 free(node->features);
1806 lydict_remove(ctx, node->name);
1807 lydict_remove(ctx, node->dsc);
1808 lydict_remove(ctx, node->ref);
1809 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001810
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001811 /* specific part */
1812 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001813 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001814 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001815 break;
Radek Krejci76512572015-08-04 09:47:08 +02001816 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001817 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001818 break;
Radek Krejci76512572015-08-04 09:47:08 +02001819 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001820 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001821 break;
Radek Krejci76512572015-08-04 09:47:08 +02001822 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001823 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001824 break;
Radek Krejci76512572015-08-04 09:47:08 +02001825 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001826 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001827 break;
Radek Krejci76512572015-08-04 09:47:08 +02001828 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001829 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001830 break;
Radek Krejci76512572015-08-04 09:47:08 +02001831 case LYS_USES:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001832 lys_uses_free(ctx, (struct lys_node_uses *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001833 break;
Radek Krejci76512572015-08-04 09:47:08 +02001834 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001835 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001836 break;
Radek Krejci76512572015-08-04 09:47:08 +02001837 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001838 /* do nothing */
1839 break;
Radek Krejci76512572015-08-04 09:47:08 +02001840 case LYS_GROUPING:
1841 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001842 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001843 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001844 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001845
1846 case LYS_INPUT:
1847 case LYS_OUTPUT:
1848 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1849 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001850 case LYS_UNKNOWN:
1851 LOGINT;
1852 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001853 }
Radek Krejci5a065542015-05-22 15:02:07 +02001854
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001855 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001856 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001857 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001858}
1859
Michal Vasko8ce24d72015-10-21 11:27:26 +02001860struct lys_module *
Michal Vaskob6729c62015-10-21 12:09:47 +02001861lys_get_import_module(struct lys_module *module, const char *prefix, int pref_len, const char *name, int name_len)
Michal Vasko8ce24d72015-10-21 11:27:26 +02001862{
Michal Vaskob6729c62015-10-21 12:09:47 +02001863 int i, match;
1864
1865 assert(prefix || name);
1866 if (prefix && !pref_len) {
1867 pref_len = strlen(prefix);
1868 }
1869 if (name && !name_len) {
1870 name_len = strlen(name);
1871 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02001872
Michal Vaskod8da86b2015-10-21 13:35:37 +02001873 if ((!prefix || (!strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
1874 && (!name || (!strncmp(module->name, name, name_len) && !module->name[name_len]))) {
1875 return module;
1876 }
1877
Michal Vasko8ce24d72015-10-21 11:27:26 +02001878 for (i = 0; i < module->imp_size; ++i) {
Michal Vaskob6729c62015-10-21 12:09:47 +02001879 match = 0;
1880 if (!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len])) {
1881 match = 1;
1882 }
1883 if (match && (!name
1884 || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02001885 return module->imp[i].module;
1886 }
1887 }
1888
1889 return NULL;
1890}
1891
Michal Vasko13b15832015-08-19 11:04:48 +02001892/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001893static void
Michal Vasko13b15832015-08-19 11:04:48 +02001894module_free_common(struct lys_module *module, int free_int_mods)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001895{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001896 struct ly_ctx *ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001897 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001898 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001899
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001900 assert(module->ctx);
1901 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001902
Radek Krejcidce51452015-06-16 15:20:08 +02001903 /* as first step, free the imported modules */
1904 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa76ee152015-08-17 15:38:22 +02001905 /* do not free internal modules */
Michal Vasko18bd09b2015-08-19 15:07:00 +02001906 if (!free_int_mods) {
1907 for (j = 0; j < int_mods.count; ++j) {
Michal Vaskod83c03a2015-08-21 09:09:24 +02001908 if (module->imp[i].module && !strcmp(int_mods.modules[j].name, module->imp[i].module->name)
Michal Vasko18bd09b2015-08-19 15:07:00 +02001909 && module->imp[i].module->rev
1910 && !strcmp(int_mods.modules[j].revision, module->imp[i].module->rev[0].date)) {
1911 break;
1912 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02001913 }
Michal Vasko18bd09b2015-08-19 15:07:00 +02001914 if (j < int_mods.count) {
1915 continue;
1916 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02001917 }
1918
Radek Krejcidce51452015-06-16 15:20:08 +02001919 /* get the imported module from the context and then free,
1920 * this check is necessary because the imported module can
1921 * be already removed
1922 */
1923 l = ctx->models.used;
1924 for (j = 0; j < l; j++) {
1925 if (ctx->models.list[j] == module->imp[i].module) {
Michal Vasko13b15832015-08-19 11:04:48 +02001926 lys_free(module->imp[i].module, free_int_mods);
Radek Krejcidce51452015-06-16 15:20:08 +02001927 break;
1928 }
1929 }
1930 }
1931 free(module->imp);
1932
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001933 while (module->data) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001934 lys_node_free(module->data);
Radek Krejci21181962015-06-30 14:11:00 +02001935 }
Radek Krejci5a065542015-05-22 15:02:07 +02001936
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001937 lydict_remove(ctx, module->dsc);
1938 lydict_remove(ctx, module->ref);
1939 lydict_remove(ctx, module->org);
1940 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001941
Radek Krejcieb00f512015-07-01 16:44:58 +02001942 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001943 for (i = 0; i < module->rev_size; i++) {
1944 lydict_remove(ctx, module->rev[i].dsc);
1945 lydict_remove(ctx, module->rev[i].ref);
1946 }
1947 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001948
Radek Krejcieb00f512015-07-01 16:44:58 +02001949 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001950 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001951 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001952 }
1953 module->ident_size = 0;
1954 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001955
Radek Krejcieb00f512015-07-01 16:44:58 +02001956 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001957 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001958 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001959 }
1960 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001961
Radek Krejcieb00f512015-07-01 16:44:58 +02001962 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001963 for (i = 0; i < module->inc_size; i++) {
Michal Vasko13b15832015-08-19 11:04:48 +02001964 lys_submodule_free(module->inc[i].submodule, free_int_mods);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001965 }
1966 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001967
Radek Krejcieb00f512015-07-01 16:44:58 +02001968 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02001969 for (i = 0; i < module->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001970 lys_augment_free(ctx, module->augment[i]);
Radek Krejcif5be10f2015-06-16 13:29:36 +02001971 }
1972 free(module->augment);
1973
Radek Krejcieb00f512015-07-01 16:44:58 +02001974 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001975 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001976 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001977 }
1978 free(module->features);
1979
Radek Krejcieb00f512015-07-01 16:44:58 +02001980 /* deviations */
1981 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001982 lys_deviation_free(ctx, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001983 }
1984 free(module->deviation);
1985
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001986 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02001987}
1988
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001989void
Michal Vasko13b15832015-08-19 11:04:48 +02001990lys_submodule_free(struct lys_submodule *submodule, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02001991{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001992 if (!submodule) {
1993 return;
1994 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001995
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001996 submodule->inc_size = 0;
1997 free(submodule->inc);
1998 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02001999
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002000 /* common part with struct ly_module */
Michal Vasko13b15832015-08-19 11:04:48 +02002001 module_free_common((struct lys_module *)submodule, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02002002
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002003 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002004
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002005 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002006}
2007
Radek Krejcib8048692015-08-05 13:36:34 +02002008static struct lys_node_leaf *
Radek Krejci1d82ef62015-08-07 14:44:40 +02002009lys_uniq_find(struct lys_node_list *list, struct lys_node_leaf *orig_leaf)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002010{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002011 struct lys_node *node, *node2, *ret = NULL, *parent1, *parent2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002012 int depth = 1, i;
2013
2014 /* find the correct direct descendant of list in orig_leaf */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002015 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002016 while (1) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002017 if (!node->parent) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002018 return NULL;
2019 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002020 if (!strcmp(node->parent->name, list->name)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002021 break;
2022 }
2023
Radek Krejci1d82ef62015-08-07 14:44:40 +02002024 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002025 ++depth;
2026 }
2027
2028 /* make sure the nodes are equal */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002029 parent1 = node->parent->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002030 parent2 = list->parent;
2031 while (1) {
2032 if ((parent1 && !parent2) || (!parent1 && parent2)) {
2033 return NULL;
2034 }
2035
2036 if (parent1 == parent2) {
2037 break;
2038 }
2039
2040 parent1 = parent1->parent;
2041 parent2 = parent2->parent;
2042 }
2043
2044 /* find the descendant in the list */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002045 LY_TREE_FOR(list->child, node2) {
2046 if (!strcmp(node2->name, node->name)) {
2047 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002048 break;
2049 }
2050 }
2051
2052 if (!ret) {
2053 return NULL;
2054 }
2055
2056 /* continue traversing both trees, the nodes are always truly equal */
2057 while (1) {
2058 --depth;
2059 if (!depth) {
Radek Krejci76512572015-08-04 09:47:08 +02002060 if (ret->nodetype != LYS_LEAF) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002061 return NULL;
2062 }
Radek Krejcib8048692015-08-05 13:36:34 +02002063 return (struct lys_node_leaf *)ret;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002064 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002065 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002066 for (i = 0; i < depth-1; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002067 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002068 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002069 LY_TREE_FOR(ret->child, node2) {
2070 if (!strcmp(node2->name, node->name)) {
2071 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002072 break;
2073 }
2074 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002075 if (!node2) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002076 return NULL;
2077 }
2078 }
2079}
2080
Radek Krejci76512572015-08-04 09:47:08 +02002081struct lys_node *
Michal Vasko71e1aa82015-08-12 12:17:51 +02002082lys_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 +02002083 struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002084{
Radek Krejci76512572015-08-04 09:47:08 +02002085 struct lys_node *retval = NULL, *aux, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002086 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002087 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002088
Michal Vaskoc07187d2015-08-13 15:20:57 +02002089 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002090 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002091 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002092 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002093 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002094 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002095 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002096 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002097 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002098 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002099 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002100 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002101 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002102 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002103 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002104 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002105 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002106 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002107 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002108 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002109 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002110 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002111 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002112 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002113
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002114 /* we cannot just duplicate memory since the strings are stored in
2115 * dictionary and we need to update dictionary counters.
2116 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002117
Radek Krejci1d82ef62015-08-07 14:44:40 +02002118 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002119 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002120 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002121 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002122 break;
2123
Radek Krejci76512572015-08-04 09:47:08 +02002124 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002125 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002126 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002127 break;
2128
Radek Krejci76512572015-08-04 09:47:08 +02002129 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002130 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002131 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002132 break;
2133
Radek Krejci76512572015-08-04 09:47:08 +02002134 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002135 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002136 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002137 break;
2138
Radek Krejci76512572015-08-04 09:47:08 +02002139 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002140 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002141 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002142 break;
2143
Radek Krejci76512572015-08-04 09:47:08 +02002144 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002145 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002146 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002147 break;
2148
Radek Krejci76512572015-08-04 09:47:08 +02002149 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002150 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002151 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002152 break;
2153
Radek Krejci76512572015-08-04 09:47:08 +02002154 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002155 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002156 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002157 break;
2158
Radek Krejci76512572015-08-04 09:47:08 +02002159 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002160 grp = calloc(1, sizeof *grp);
2161 retval = (struct lys_node *)grp;
2162 break;
2163
Radek Krejci76512572015-08-04 09:47:08 +02002164 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002165 rpc = calloc(1, sizeof *rpc);
2166 retval = (struct lys_node *)rpc;
2167 break;
2168
Radek Krejci76512572015-08-04 09:47:08 +02002169 case LYS_INPUT:
2170 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002171 io = calloc(1, sizeof *io);
2172 retval = (struct lys_node *)io;
2173 break;
2174
Radek Krejci76512572015-08-04 09:47:08 +02002175 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002176 ntf = calloc(1, sizeof *ntf);
2177 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002178 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002180 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002181 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002182 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002183 }
Radek Krejcib388c152015-06-04 17:03:03 +02002184
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002185 /*
2186 * duplicate generic part of the structure
2187 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002188 retval->name = lydict_insert(ctx, node->name, 0);
2189 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2190 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002191 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002192 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002193 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002194 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002195 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002196 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002198 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002199 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002200
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002201 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002202
Radek Krejci1d82ef62015-08-07 14:44:40 +02002203 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002204 retval->features = calloc(retval->features_size, sizeof *retval->features);
Radek Krejci1d82ef62015-08-07 14:44:40 +02002205 for (i = 0; i < node->features_size; ++i) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002206 if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002207 retval->features[i] = node->features[i];
Michal Vaskod23ce592015-08-06 09:55:37 +02002208 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002209 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002210
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002211 if (recursive) {
2212 /* go recursively */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002213 LY_TREE_FOR(node->child, child) {
Michal Vasko71e1aa82015-08-12 12:17:51 +02002214 aux = lys_node_dup(module, child, retval->flags, retval->nacm, 1, unres);
Radek Krejci10c760e2015-08-14 14:45:43 +02002215 if (!aux || lys_node_addchild(retval, NULL, aux)) {
Michal Vasko49168a22015-08-17 16:35:41 +02002216 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002217 }
2218 }
2219 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002220
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002221 /*
2222 * duplicate specific part of the structure
2223 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002224 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002225 case LYS_CONTAINER:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002226 if (cont_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002227 cont->when = lys_when_dup(ctx, cont_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002228 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002229 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002230
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002231 cont->must_size = cont_orig->must_size;
2232 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002233
Radek Krejci1d82ef62015-08-07 14:44:40 +02002234 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci1d82ef62015-08-07 14:44:40 +02002235 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002236 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002237
Radek Krejci76512572015-08-04 09:47:08 +02002238 case LYS_CHOICE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002239 if (choice_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002240 choice->when = lys_when_dup(ctx, choice_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002241 }
2242
2243 if (choice_orig->dflt) {
Michal Vasko165dc4a2015-10-23 09:44:27 +02002244 rc = lys_get_sibling(choice->module, choice->child, NULL, 0, choice_orig->dflt->name, 0, LYS_ANYXML
Radek Krejci76512572015-08-04 09:47:08 +02002245 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002246 | LYS_LIST, &choice->dflt);
Michal Vasko49168a22015-08-17 16:35:41 +02002247 if (rc) {
2248 if (rc == EXIT_FAILURE) {
2249 LOGINT;
2250 }
2251 goto error;
2252 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002253 } else {
Michal Vaskoc68a2a22015-08-06 09:57:24 +02002254 /* useless to check return value, we don't know whether
2255 * there really wasn't any default defined or it just hasn't
2256 * been resolved, we just hope for the best :)
2257 */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002258 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002259 }
2260 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002261
Radek Krejci76512572015-08-04 09:47:08 +02002262 case LYS_LEAF:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002263 if (lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres)) {
2264 goto error;
2265 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002266 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2267
2268 if (leaf_orig->dflt) {
2269 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002270 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002271 goto error;
2272 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002273 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002274
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002275 leaf->must_size = leaf_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002276 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002277
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002278 if (leaf_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002279 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002280 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002281 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002282
Radek Krejci76512572015-08-04 09:47:08 +02002283 case LYS_LEAFLIST:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002284 if (lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres)) {
2285 goto error;
2286 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002287 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002288
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002289 llist->min = llist_orig->min;
2290 llist->max = llist_orig->max;
2291
2292 llist->must_size = llist_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002293 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002294
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002295 if (llist_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002296 llist->when = lys_when_dup(ctx, llist_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002297 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002298 break;
2299
Radek Krejci76512572015-08-04 09:47:08 +02002300 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002301 list->min = list_orig->min;
2302 list->max = list_orig->max;
2303
2304 list->must_size = list_orig->must_size;
2305 list->tpdf_size = list_orig->tpdf_size;
2306 list->keys_size = list_orig->keys_size;
2307 list->unique_size = list_orig->unique_size;
2308
Radek Krejci1d82ef62015-08-07 14:44:40 +02002309 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002310
Radek Krejci1d82ef62015-08-07 14:44:40 +02002311 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002312
2313 if (list->keys_size) {
2314 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002315
2316 /* we managed to resolve it before, resolve it again manually */
2317 if (list_orig->keys[0]) {
2318 for (i = 0; i < list->keys_size; ++i) {
Michal Vasko165dc4a2015-10-23 09:44:27 +02002319 rc = lys_get_sibling(list->module, list->child, NULL, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2320 (struct lys_node **)&list->keys[i]);
Michal Vasko49168a22015-08-17 16:35:41 +02002321 if (rc) {
2322 if (rc == EXIT_FAILURE) {
2323 LOGINT;
2324 }
2325 goto error;
2326 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002327 }
2328 /* it was not resolved yet, add unres copy */
2329 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002330 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02002331 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002332 goto error;
Michal Vaskod23ce592015-08-06 09:55:37 +02002333 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002334 }
2335 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002336
2337 list->unique = calloc(list->unique_size, sizeof *list->unique);
2338 if (list_orig->unique) {
2339 for (i = 0; i < list->unique_size; ++i) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002340 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
2341 for (j = 0; j < list->unique[i].leafs_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002342 list->unique[i].leafs[j] = lys_uniq_find(list, list_orig->unique[i].leafs[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002343 }
2344 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002345 } else {
2346 for (i = 0; i < list->unique_size; ++i) {
2347 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02002348 list->unique[i].leafs = (struct lys_node_leaf **)list;
Michal Vasko0bd29d12015-08-19 11:45:49 +02002349 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002350 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002351 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002352
2353 if (list_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002354 list->when = lys_when_dup(ctx, list_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002355 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002356 break;
2357
Radek Krejci76512572015-08-04 09:47:08 +02002358 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002359 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002360 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002361
2362 if (anyxml_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002363 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002364 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002365 break;
2366
Radek Krejci76512572015-08-04 09:47:08 +02002367 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002368 uses->grp = uses_orig->grp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002369
2370 if (uses_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002371 uses->when = lys_when_dup(ctx, uses_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002372 }
2373
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002374 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002375 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002376 uses->augment_size = uses_orig->augment_size;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02002377 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Michal Vaskof8c128d2015-08-06 15:25:28 +02002378 if (!uses->child) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002379 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002380 goto error;
2381 }
Michal Vaskof8c128d2015-08-06 15:25:28 +02002382 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002383 break;
2384
Radek Krejci76512572015-08-04 09:47:08 +02002385 case LYS_CASE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002386 if (cs_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002387 cs->when = lys_when_dup(ctx, cs_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002388 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002389 break;
2390
Radek Krejci76512572015-08-04 09:47:08 +02002391 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002392 grp->tpdf_size = grp_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002393 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002394 break;
2395
Radek Krejci76512572015-08-04 09:47:08 +02002396 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002397 rpc->tpdf_size = rpc_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002398 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002399 break;
2400
Radek Krejci76512572015-08-04 09:47:08 +02002401 case LYS_INPUT:
2402 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002403 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002404 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002405 break;
2406
Radek Krejci76512572015-08-04 09:47:08 +02002407 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002408 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002409 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcia01e5432015-06-16 10:35:25 +02002410 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002411
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002412 default:
Radek Krejci00768f42015-06-18 17:04:04 +02002413 /* LY_NODE_AUGMENT */
Michal Vaskod23ce592015-08-06 09:55:37 +02002414 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002415 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002416 }
2417
2418 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002419
2420error:
2421
2422 lys_node_free(retval);
2423 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002424}
2425
Michal Vasko13b15832015-08-19 11:04:48 +02002426void
2427lys_free(struct lys_module *module, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02002428{
Radek Krejcidce51452015-06-16 15:20:08 +02002429 struct ly_ctx *ctx;
2430 int i;
2431
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002432 if (!module) {
2433 return;
2434 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002435
Radek Krejcidce51452015-06-16 15:20:08 +02002436 /* remove schema from the context */
2437 ctx = module->ctx;
2438 if (ctx->models.used) {
2439 for (i = 0; i < ctx->models.used; i++) {
2440 if (ctx->models.list[i] == module) {
2441 /* replace the position in the list by the last module in the list */
2442 ctx->models.used--;
2443 ctx->models.list[i] = ctx->models.list[ctx->models.used];
2444 ctx->models.list[ctx->models.used] = NULL;
2445 /* we are done */
2446 break;
2447 }
2448 }
2449 }
2450
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002451 /* common part with struct ly_submodule */
Michal Vasko13b15832015-08-19 11:04:48 +02002452 module_free_common(module, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02002453
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002454 /* specific items to free */
2455 lydict_remove(module->ctx, module->ns);
2456 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02002457
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002458 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002459}
Radek Krejci7e97c352015-06-19 16:26:34 +02002460
2461/*
2462 * op: 1 - enable, 0 - disable
2463 */
2464static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002465lys_features_change(struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002466{
2467 int all = 0;
2468 int i, j, k;
2469
2470 if (!module || !name || !strlen(name)) {
2471 return EXIT_FAILURE;
2472 }
2473
2474 if (!strcmp(name, "*")) {
2475 /* enable all */
2476 all = 1;
2477 }
2478
2479 /* module itself */
2480 for (i = 0; i < module->features_size; i++) {
2481 if (all || !strcmp(module->features[i].name, name)) {
2482 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002483 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002484 /* enable referenced features (recursion) */
2485 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002486 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002487 module->features[i].features[k]->name, op);
2488 }
2489 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002490 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002491 }
2492 if (!all) {
2493 return EXIT_SUCCESS;
2494 }
2495 }
2496 }
2497
2498 /* submodules */
2499 for (j = 0; j < module->inc_size; j++) {
2500 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2501 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2502 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002503 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002504 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002505 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002506 }
2507 if (!all) {
2508 return EXIT_SUCCESS;
2509 }
2510 }
2511 }
2512 }
2513
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002514 /* TODO submodules of submodules ... */
2515
Radek Krejci7e97c352015-06-19 16:26:34 +02002516 if (all) {
2517 return EXIT_SUCCESS;
2518 } else {
2519 return EXIT_FAILURE;
2520 }
2521}
2522
2523API int
Radek Krejcib8048692015-08-05 13:36:34 +02002524lys_features_enable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002525{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002526 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002527}
2528
2529API int
Radek Krejcib8048692015-08-05 13:36:34 +02002530lys_features_disable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002531{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002532 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002533}
2534
2535API int
Radek Krejcib8048692015-08-05 13:36:34 +02002536lys_features_state(struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002537{
2538 int i, j;
2539
2540 if (!module || !feature) {
2541 return -1;
2542 }
2543
2544 /* search for the specified feature */
2545 /* module itself */
2546 for (i = 0; i < module->features_size; i++) {
2547 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002548 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002549 return 1;
2550 } else {
2551 return 0;
2552 }
2553 }
2554 }
2555
2556 /* submodules */
2557 for (j = 0; j < module->inc_size; j++) {
2558 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2559 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002560 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002561 return 1;
2562 } else {
2563 return 0;
2564 }
2565 }
2566 }
2567 }
2568
2569 /* TODO submodules of submodules ... */
2570
2571 /* feature definition not found */
2572 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002573}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002574
Radek Krejci96a10da2015-07-30 11:00:14 +02002575API const char **
Radek Krejcib8048692015-08-05 13:36:34 +02002576lys_features_list(struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002577{
Radek Krejci96a10da2015-07-30 11:00:14 +02002578 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002579 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002580 unsigned int count;
2581
2582 if (!module) {
2583 return NULL;
2584 }
2585
2586 count = module->features_size;
2587 for (i = 0; i < module->inc_size; i++) {
2588 count += module->inc[i].submodule->features_size;
2589 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002590 result = malloc((count + 1) * sizeof *result);
2591 if (states) {
2592 *states = malloc((count + 1) * sizeof **states);
Michal Vasko2367e7c2015-07-07 11:33:44 +02002593 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002594 count = 0;
2595
2596 /* module itself */
2597 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002598 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002599 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002600 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002601 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002602 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002603 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002604 }
2605 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002606 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002607 }
2608
2609 /* submodules */
2610 for (j = 0; j < module->inc_size; j++) {
2611 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002612 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002613 if (states) {
2614 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2615 (*states)[count] = 1;
2616 } else {
2617 (*states)[count] = 0;
2618 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002619 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002620 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002621 }
2622 }
2623
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002624 /* TODO submodules of submodules ... */
2625
2626 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002627 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002628
2629 return result;
2630}
Michal Vaskobaefb032015-09-24 14:52:10 +02002631
2632API struct lys_node *
2633lys_parent(struct lys_node *node)
2634{
2635 if (!node || !node->parent) {
2636 return NULL;
2637 }
2638
2639 if (node->parent->nodetype == LYS_AUGMENT) {
2640 return ((struct lys_node_augment *)node->parent)->target;
2641 }
2642
2643 return node->parent;
2644}