blob: e4a2edd6286b207dce85080fd9922c5863d5155e [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 Vasko88c29542015-11-27 14:57:53 +010035#include "xml.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020036#include "xml_internal.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020037#include "tree_internal.h"
Radek Krejcieab784a2015-08-27 09:56:53 +020038#include "validation.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020039
Michal Vaskoa76ee152015-08-17 15:38:22 +020040static const struct internal_modules int_mods = {
41 .modules = {
42 {"ietf-yang-types", "2013-07-15"},
43 {"ietf-inet-types", "2013-07-15"},
44 {"ietf-yang-library", "2015-07-03"}
45 },
46 .count = LY_INTERNAL_MODULE_COUNT
47};
48
Michal Vasko1e62a092015-12-01 12:27:20 +010049API const struct lys_feature *
50lys_is_disabled(const struct lys_node *node, int recursive)
Radek Krejci48061fb2015-08-05 15:41:07 +020051{
52 int i;
53
54check:
55 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
56 /* input/output does not have if-feature, so skip them */
57
58 /* check local if-features */
59 for (i = 0; i < node->features_size; i++) {
60 if (!(node->features[i]->flags & LYS_FENABLED)) {
61 return node->features[i];
62 }
63 }
64 }
65
66 if (!recursive) {
67 return NULL;
68 }
69
70 /* go through parents */
71 if (node->nodetype == LYS_AUGMENT) {
72 /* go to parent actually means go to the target node */
73 node = ((struct lys_node_augment *)node)->target;
Radek Krejci48061fb2015-08-05 15:41:07 +020074 } else if (node->parent) {
75 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020076 } else {
77 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020078 }
79
Radek Krejci074bf852015-08-19 14:22:16 +020080 if (recursive == 2) {
81 /* continue only if the node cannot have a data instance */
82 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
83 return NULL;
84 }
85 }
86 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020087}
88
Michal Vasko1dca6882015-10-22 14:29:42 +020089int
Michal Vasko1e62a092015-12-01 12:27:20 +010090lys_get_sibling(struct lys_module *mod, const struct lys_node *siblings, const char *mod_name, int mod_name_len,
91 const char *name, int nam_len, LYS_NODE type, const struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +020092{
Michal Vasko1e62a092015-12-01 12:27:20 +010093 const struct lys_node *node, *old_siblings = NULL;
94 const struct lys_module *prefix_mod, *cur_mod;
Michal Vasko1dca6882015-10-22 14:29:42 +020095 int in_submod;
Michal Vasko1dca6882015-10-22 14:29:42 +020096
97 assert(siblings && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +020098 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +020099
100 /* find the beginning */
101 while (siblings->prev->next) {
102 siblings = siblings->prev;
103 }
104
105 /* fill the name length in case the caller is so indifferent */
106 if (!nam_len) {
107 nam_len = strlen(name);
108 }
109
110 /* we start with the module itself, submodules come later */
111 in_submod = 0;
112
113 /* set prefix_mod correctly */
114 if (mod_name) {
Michal Vaskob6729c62015-10-21 12:09:47 +0200115 prefix_mod = lys_get_import_module(siblings->module, NULL, 0, mod_name, mod_name_len);
Michal Vasko1dca6882015-10-22 14:29:42 +0200116 if (!prefix_mod) {
117 return -1;
118 }
119 cur_mod = prefix_mod;
120 /* it is not our module */
121 if (cur_mod != mod) {
122 old_siblings = siblings;
123 siblings = cur_mod->data;
124 }
125 } else {
126 if (mod) {
127 prefix_mod = mod;
128 } else {
129 prefix_mod = siblings->module;
130 }
131 if (prefix_mod->type) {
132 prefix_mod = ((struct lys_submodule *)prefix_mod)->belongsto;
133 }
134 cur_mod = prefix_mod;
135 }
136
137 while (1) {
138 /* try to find the node */
139 node = NULL;
140 while ((node = lys_getnext(node, siblings->parent, cur_mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
141 if (!type || (node->nodetype & type)) {
142 /* module check */
143 if (!node->module->type) {
144 if (cur_mod != node->module) {
145 continue;
146 }
147 } else {
148 /* both are submodules */
149 if (cur_mod->type) {
150 if (cur_mod != node->module) {
151 continue;
152 }
153 } else {
154 if (cur_mod != ((struct lys_submodule *)node->module)->belongsto) {
155 continue;
156 }
157 }
158 }
159
160 /* direct name check */
161 if ((node->name == name) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
162 if (ret) {
163 *ret = node;
164 }
165 return EXIT_SUCCESS;
166 }
167 }
168 }
169
170 /* The original siblings may be valid,
171 * it's a special case when we're looking
172 * for a node from an augment.
173 */
Michal Vasko165dc4a2015-10-23 09:44:27 +0200174 if ((type & LYS_AUGMENT) && old_siblings) {
Michal Vasko1dca6882015-10-22 14:29:42 +0200175 siblings = old_siblings;
176 old_siblings = NULL;
177 continue;
178 }
179
180 /* we're not top-level, search ended */
181 if (siblings->parent) {
182 break;
183 }
184
185 /* let's try the submodules */
186 if (in_submod == prefix_mod->inc_size) {
187 break;
188 }
189 cur_mod = (struct lys_module *)prefix_mod->inc[in_submod].submodule;
190 siblings = cur_mod->data;
191 ++in_submod;
192 }
193
194 return EXIT_FAILURE;
195}
196
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200197int
Michal Vasko1e62a092015-12-01 12:27:20 +0100198lys_get_data_sibling(const struct lys_module *mod, const struct lys_node *siblings, const char *name, LYS_NODE type,
199 const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200200{
Michal Vasko1e62a092015-12-01 12:27:20 +0100201 const struct lys_node *node;
202 const struct lys_module *cur_mod;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200203 int in_submod;
204
205 assert(siblings && name);
206 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
207
208 /* find the beginning */
209 while (siblings->prev->next) {
210 siblings = siblings->prev;
211 }
212
213 /* we start with the module itself, submodules come later */
214 in_submod = 0;
215
216 if (!mod) {
217 mod = siblings->module;
218 }
219 cur_mod = mod;
220
221 while (1) {
222 /* try to find the node */
223 node = NULL;
224 while ((node = lys_getnext(node, siblings->parent, cur_mod, 0))) {
225 if (!type || (node->nodetype & type)) {
226 /* module check */
227 if (!node->module->type) {
228 if (cur_mod != node->module) {
229 continue;
230 }
231 } else {
232 /* both are submodules */
233 if (cur_mod->type) {
234 if (cur_mod != node->module) {
235 continue;
236 }
237 } else {
238 if (cur_mod != ((struct lys_submodule *)node->module)->belongsto) {
239 continue;
240 }
241 }
242 }
243
244 /* direct name check */
245 if ((node->name == name) || !strcmp(node->name, name)) {
246 if (ret) {
247 *ret = node;
248 }
249 return EXIT_SUCCESS;
250 }
251 }
252 }
253
254 /* we're not top-level, search ended */
255 if (siblings->parent) {
256 break;
257 }
258
259 /* let's try the submodules */
260 if (in_submod == mod->inc_size) {
261 break;
262 }
263 cur_mod = (struct lys_module *)mod->inc[in_submod].submodule;
264 siblings = cur_mod->data;
265 ++in_submod;
266 }
267
268 return EXIT_FAILURE;
269}
270
Michal Vasko1e62a092015-12-01 12:27:20 +0100271API const struct lys_node *
272lys_getnext(const struct lys_node *last, const struct lys_node *parent, const struct lys_module *module, int options)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200273{
Michal Vasko1e62a092015-12-01 12:27:20 +0100274 const struct lys_node *next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200275
Radek Krejci8bc87f62015-09-02 16:19:05 +0200276 if (!last) {
277 /* first call */
278
279 /* get know where to start */
280 if (parent) {
281 /* schema subtree */
282 next = last = parent->child;
283 } else {
284 /* top level data */
285 assert(module);
286 next = last = module->data;
287 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200288 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200289 /* continue after the last returned value */
290 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200291 }
292
293repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200294 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200295 if (options & LYS_GETNEXT_WITHGROUPING) {
296 return next;
297 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200298 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200299 }
300
301 while (!next) {
Michal Vasko7c386e72015-10-07 15:13:33 +0200302 if (lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200303 /* no next element */
304 return NULL;
305 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200306 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200307 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200308 goto repeat;
309 }
310
311 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200312 case LYS_INPUT:
313 case LYS_OUTPUT:
314 if (options & LYS_GETNEXT_WITHINOUT) {
315 return next;
316 } else {
317 next = next->child;
318 goto repeat;
319 }
320 break;
321
Michal Vaskoa5835e92015-10-20 15:07:39 +0200322 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200323 if (options & LYS_GETNEXT_WITHCASE) {
324 return next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200325 } else {
326 next = next->child;
327 goto repeat;
Michal Vasko1dca6882015-10-22 14:29:42 +0200328 }
Michal Vaskob6eedf02015-10-22 16:07:03 +0200329 break;
330
Michal Vasko1dca6882015-10-22 14:29:42 +0200331 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200332 /* go into */
333 next = next->child;
334 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200335
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200336 case LYS_RPC:
337 case LYS_NOTIF:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200338 case LYS_CONTAINER:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200339 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200340 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200341 case LYS_LIST:
342 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200343 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200344
345 case LYS_CHOICE:
346 if (options & LYS_GETNEXT_WITHCHOICE) {
347 return next;
348 } else {
349 /* go into */
350 next = next->child;
351 goto repeat;
352 }
353 break;
354
Radek Krejci7f40ce32015-08-12 20:38:46 +0200355 default:
356 /* we should not be here */
357 return NULL;
358 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200359
360
361}
362
Michal Vasko1e62a092015-12-01 12:27:20 +0100363static const struct lys_node *
364check_mand_getnext(const struct lys_node *last, const struct lys_node *parent)
Radek Krejci8bc87f62015-09-02 16:19:05 +0200365{
Michal Vasko1e62a092015-12-01 12:27:20 +0100366 const struct lys_node *next;
367
Radek Krejci8bc87f62015-09-02 16:19:05 +0200368 next = lys_getnext(last, parent, NULL, LYS_GETNEXT_WITHCHOICE);
369
Radek Krejci4b6c2112015-10-06 12:48:34 +0200370repeat:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200371 if (next && next->nodetype == LYS_CONTAINER) {
372 if (((struct lys_node_container *)next)->presence) {
373 /* mandatory elements under the non-existing presence
374 * container are not mandatory - 7.6.5, rule 1 */
375 next = next->next;
376 } else {
377 /* go into */
378 next = next->child;
379 }
380 goto repeat;
381 }
382
383 return next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200384}
385
Michal Vasko1e62a092015-12-01 12:27:20 +0100386static const struct lys_node *
387check_mand_check(const struct lys_node *node, const struct lys_node *stop, const struct lyd_node *data)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200388{
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200389 struct lys_node *siter = NULL, *parent = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200390 struct lyd_node *diter = NULL;
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200391 struct lyd_set *set = NULL;
392 unsigned int i;
Radek Krejci14a11a62015-08-17 17:27:38 +0200393 uint32_t minmax;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200394
395 if (node->flags & LYS_MAND_TRUE) {
396 switch (node->nodetype) {
397 case LYS_LEAF:
398 case LYS_ANYXML:
399 case LYS_CHOICE:
400 if (node->parent->nodetype == LYS_CASE) {
401 /* 7.6.5, rule 2 */
402 /* 7.9.4, rule 1 */
403 if (node->parent->parent->parent == data->schema) {
404 /* the only case the node's siblings can exist is that the
405 * data node passed originaly to ly_check_mandatory()
406 * had this choice as a child
407 */
408 /* try to find the node's siblings in data */
409 LY_TREE_FOR(data->child, diter) {
410 LY_TREE_FOR(node->parent->child, siter) {
411 if (siter == diter->schema) {
412 /* some sibling exists, rule applies */
413 break;
414 }
415 }
416 if (siter) {
417 break;
418 }
419 }
420 }
421 if (!siter) {
422 /* no sibling exists */
423 return NULL;
424 }
425 } else {
426 for(parent = node->parent; parent != stop; parent = parent->parent) {
427 if (parent->nodetype != LYS_CONTAINER) {
428 /* 7.6.5, rule 1, checking presence is not needed
429 * since it is done in check_mand_getnext()
430 */
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200431 lyd_set_free(set);
Radek Krejci7f40ce32015-08-12 20:38:46 +0200432 return NULL;
433 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200434 /* add the parent to the list for searching in data tree */
435 if (!set) {
436 set = lyd_set_new();
437 }
438 lyd_set_add(set, (struct lyd_node *)parent);
Radek Krejci7f40ce32015-08-12 20:38:46 +0200439 }
440 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200441
442 /* search for instance */
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200443 if (set) {
444 for (i = 0; i < set->number; i++) {
445 LY_TREE_FOR(data->child, diter) {
446 if (diter->schema == (struct lys_node *)(set->set[i])) {
447 break;
448 }
449 }
450 if (!diter) {
451 /* instance not found */
452 node = (struct lys_node *)(set->set[i]);
453 lyd_set_free(set);
454 return node;
455 }
456 data = diter;
457 }
458 lyd_set_free(set);
459 }
460
Radek Krejci14a11a62015-08-17 17:27:38 +0200461 LY_TREE_FOR(data->child, diter) {
462 if (diter->schema == node) {
463 return NULL;
464 }
465 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200466
Radek Krejci14a11a62015-08-17 17:27:38 +0200467 /* instance not found */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200468 /* 7.6.5, rule 3 (or 2) */
469 /* 7.9.4, rule 2 */
470 return node;
471 default:
472 /* error */
473 break;
474 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200475 } else if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
476 /* search for number of instances */
477 minmax = 0;
478 LY_TREE_FOR(data->child, diter) {
479 if (diter->schema == node) {
480 minmax++;
481 }
482 }
483
484 /* check the specified constraints */
485 if (node->nodetype == LYS_LIST) {
486 if (((struct lys_node_list *)node)->min && minmax < ((struct lys_node_list *)node)->min) {
487 return node;
488 }
489
490 if (((struct lys_node_list *)node)->max && minmax > ((struct lys_node_list *)node)->max) {
491 return node;
492 }
493 } else if (node->nodetype == LYS_LEAFLIST) {
494 if (((struct lys_node_leaflist *)node)->min && minmax < ((struct lys_node_leaflist *)node)->min) {
495 return node;
496 }
497
498 if (((struct lys_node_leaflist *)node)->max && minmax > ((struct lys_node_leaflist *)node)->max) {
499 return node;
500 }
501 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200502 }
503
504 return NULL;
505}
506
Michal Vasko1e62a092015-12-01 12:27:20 +0100507const struct lys_node *
508ly_check_mandatory(const struct lyd_node *data)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200509{
Michal Vasko1e62a092015-12-01 12:27:20 +0100510 const struct lys_node *siter, *saux, *saux2, *result, *parent = NULL, *parent2;
511 const struct lyd_node *diter;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200512 int found;
513
514 siter = data->schema->child;
515
516repeat:
517 while (siter) {
Radek Krejci074bf852015-08-19 14:22:16 +0200518 if (lys_is_disabled(siter, 2)) {
519 siter = siter->next;
520 continue;
521 }
522
Radek Krejci7f40ce32015-08-12 20:38:46 +0200523 switch (siter->nodetype) {
524 case LYS_CONTAINER:
525 case LYS_LEAF:
526 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200527 case LYS_LIST:
528 case LYS_LEAFLIST:
529 /* check if there is some mandatory node; first test the siter itself ... */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200530 result = check_mand_check(siter, siter->parent, data);
531 if (result) {
532 return result;
533 }
534 /* ... and then the subtree */
Radek Krejci14a11a62015-08-17 17:27:38 +0200535 if (parent && siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
536 saux = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200537 while ((saux = check_mand_getnext(saux, siter))) {
538 result = check_mand_check(saux, siter, data);
539 if (result) {
540 return result;
541 }
542 }
543 }
544 siter = siter->next;
545 break;
546 case LYS_CHOICE:
Radek Krejci14a11a62015-08-17 17:27:38 +0200547 /* search for instance */
548 saux = siter;
549 siter = siter->child;
550 found = 0;
551 parent2 = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200552repeat_choice:
Radek Krejci074bf852015-08-19 14:22:16 +0200553 while (siter) {
554 if (lys_is_disabled(siter, 2)) {
555 siter = siter->next;
556 continue;
557 }
558
Radek Krejci14a11a62015-08-17 17:27:38 +0200559 switch (siter->nodetype) {
560 case LYS_CONTAINER:
561 case LYS_LEAF:
562 case LYS_LEAFLIST:
563 case LYS_LIST:
564 case LYS_ANYXML:
565 LY_TREE_FOR(data->child, diter) {
566 if (diter->schema == siter) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200567 break;
568 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200569 }
570 if (diter) {
571 /* got instance */
572 /* check presence of mandatory siblings */
Radek Krejci65d0a652015-08-27 13:09:42 +0200573 if (parent2 && parent2->nodetype == LYS_CASE) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200574 saux2 = NULL;
Radek Krejci37bda002015-08-27 11:23:56 +0200575 while ((saux2 = check_mand_getnext(saux2, parent2))) {
576 result = check_mand_check(saux2, parent2, data);
Radek Krejci14a11a62015-08-17 17:27:38 +0200577 if (result) {
578 return result;
579 }
580 }
581 }
582 siter = parent2 = NULL;
583 found = 1;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200584 break;
585 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200586 siter = siter->next;
587 break;
588 case LYS_CASE:
589 case LYS_CHOICE:
590 case LYS_USES:
591 /* go into */
Radek Krejci37bda002015-08-27 11:23:56 +0200592 if (!parent2) {
593 parent2 = siter;
594 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200595 siter = siter->child;
596 break;
597 case LYS_AUGMENT:
598 case LYS_GROUPING:
599 /* skip */
600 siter = siter->next;
601 break;
602 default:
603 /* error */
604 break;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200605 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200606 }
607
Radek Krejci14a11a62015-08-17 17:27:38 +0200608 if (parent2) {
609 siter = parent2->next;
610 if (parent2->parent == saux) {
611 parent2 = NULL;
612 } else {
613 parent2 = parent2->parent;
614 }
615 goto repeat_choice;
616 }
617
Radek Krejci074bf852015-08-19 14:22:16 +0200618 if (!found && (saux->flags & LYS_MAND_TRUE)) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200619 return saux;
620 }
621
622 /* go to next */
623 siter = saux->next;
624
Radek Krejci7f40ce32015-08-12 20:38:46 +0200625 break;
626 case LYS_USES:
627 case LYS_CASE:
628 /* go into */
629 parent = siter;
630 siter = siter->child;
631 break;
632 default:
633 /* can ignore, go to next */
634 siter = siter->next;
635 break;
636 }
637 }
638
639 if (parent) {
640 siter = parent->next;
641 if (parent->parent == data->schema) {
642 parent = NULL;
643 } else {
644 parent = parent->parent;
645 }
646 goto repeat;
647 }
648
649 return NULL;
650}
651
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200652void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200653lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200654{
Radek Krejci76512572015-08-04 09:47:08 +0200655 struct lys_node *parent, *first;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200657 if (!node) {
658 return;
659 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200660
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200661 /* unlink from data model if necessary */
662 if (node->module) {
663 if (node->module->data == node) {
664 node->module->data = node->next;
665 }
666 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200667
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200668 /* store pointers to important nodes */
669 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200670 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200671 /* handle augments - first, unlink it from the augment parent ... */
672 if (parent->child == node) {
673 parent->child = node->next;
674 }
675 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200676 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200677 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200678
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200679 /* unlink from parent */
680 if (parent) {
681 if (parent->child == node) {
682 parent->child = node->next;
683 }
684 node->parent = NULL;
685 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200686
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200687 /* unlink from siblings */
688 if (node->prev == node) {
689 /* there are no more siblings */
690 return;
691 }
692 if (node->next) {
693 node->next->prev = node->prev;
694 } else {
695 /* unlinking the last element */
696 if (parent) {
697 first = parent->child;
698 } else {
699 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200700 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200701 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200702 }
703 }
704 first->prev = node->prev;
705 }
706 if (node->prev->next) {
707 node->prev->next = node->next;
708 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200709
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200710 /* clean up the unlinked element */
711 node->next = NULL;
712 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200713}
714
Michal Vasko563ef092015-09-04 13:17:23 +0200715struct lys_node_grp *
716lys_find_grouping_up(const char *name, struct lys_node *start, int in_submodules)
717{
718 struct lys_node *par_iter, *iter, *stop;
719 int i;
720
721 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200722 /* top-level augment, look into module (uses augment is handled correctly below) */
723 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
724 par_iter = par_iter->parent->module->data;
725 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200726 break;
727 }
728 }
729
Michal Vasko6f929da2015-10-02 16:23:25 +0200730 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200731 continue;
732 }
733
734 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
735 if (!stop) {
736 stop = par_iter;
737 } else if (iter == stop) {
738 break;
739 }
740 if (iter->nodetype != LYS_GROUPING) {
741 continue;
742 }
743
Radek Krejcif8426a72015-10-31 23:14:03 +0100744 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200745 return (struct lys_node_grp *)iter;
746 }
747 }
748 }
749
750 if (in_submodules) {
751 for (i = 0; i < start->module->inc_size; ++i) {
752 for (iter = start->module->inc[i].submodule->data; iter; iter = iter->next) {
753 if (iter->nodetype != LYS_GROUPING) {
754 continue;
755 }
756
Radek Krejcif8426a72015-10-31 23:14:03 +0100757 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200758 return (struct lys_node_grp *)iter;
759 }
760 }
761 }
762 }
763
764 return NULL;
765}
766
Radek Krejci10c760e2015-08-14 14:45:43 +0200767/*
768 * get next grouping in the root's subtree, in the
769 * first call, tha last is NULL
770 */
771static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200772lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200773{
Radek Krejci10c760e2015-08-14 14:45:43 +0200774 struct lys_node *last = (struct lys_node *)lastgrp;
775 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200776
Radek Krejci10c760e2015-08-14 14:45:43 +0200777 assert(root);
778
779 if (!last) {
780 last = root;
781 }
782
783 while (1) {
784 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
785 next = last->child;
786 } else {
787 next = NULL;
788 }
789 if (!next) {
790 if (last == root) {
791 /* we are done */
792 return NULL;
793 }
794
795 /* no children, go to siblings */
796 next = last->next;
797 }
798 while (!next) {
799 /* go back through parents */
800 if (last->parent == root) {
801 /* we are done */
802 return NULL;
803 }
804 last = last->parent;
805 next = last->next;
806 }
807
808 if (next->nodetype == LYS_GROUPING) {
809 return (struct lys_node_grp *)next;
810 }
811
812 last = next;
813 }
814}
815
Michal Vasko0d343d12015-08-24 14:57:36 +0200816/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200817int
Radek Krejci07911992015-08-14 15:13:31 +0200818lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
819{
Michal Vasko563ef092015-09-04 13:17:23 +0200820 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200821 struct lys_node_grp *grp;
822 int down;
823
824 assert(node);
825
826 if (!parent) {
827 assert(module);
828 } else {
829 module = parent->module;
830 }
831
832 switch (node->nodetype) {
833 case LYS_GROUPING:
834 /* 6.2.1, rule 6 */
835 if (parent) {
836 if (parent->child) {
837 down = 1;
838 start = parent->child;
839 } else {
840 down = 0;
841 start = parent;
842 }
843 } else {
844 down = 1;
845 start = module->data;
846 }
847 /* go up */
Michal Vasko563ef092015-09-04 13:17:23 +0200848 if (lys_find_grouping_up(node->name, start, 0)) {
849 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
850 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200851 }
852 /* go down, because grouping can be defined after e.g. container in which is collision */
853 if (down) {
854 for (iter = start, stop = NULL; iter; iter = iter->prev) {
855 if (!stop) {
856 stop = start;
857 } else if (iter == stop) {
858 break;
859 }
860 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
861 continue;
862 }
863
864 grp = NULL;
865 while ((grp = lys_get_next_grouping(grp, iter))) {
866 if (node->name == grp->name) {
867 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
868 return EXIT_FAILURE;
869 }
870 }
871 }
872 }
873 break;
874 case LYS_LEAF:
875 case LYS_LEAFLIST:
876 case LYS_LIST:
877 case LYS_CONTAINER:
878 case LYS_CHOICE:
879 case LYS_ANYXML:
880 /* 6.2.1, rule 7 */
881 if (parent) {
882 iter = parent;
883 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE))) {
884 iter = iter->parent;
885 }
886 if (!iter) {
887 stop = NULL;
888 iter = module->data;
889 } else {
890 stop = iter;
891 iter = iter->child;
892 }
893 } else {
894 stop = NULL;
895 iter = module->data;
896 }
897 while (iter) {
898 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
899 iter = iter->child;
900 continue;
901 }
902
903 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
904 if (iter->module == node->module && iter->name == node->name) {
905 LOGVAL(LYE_SPEC, 0, "Duplicated child identifier \"%s\" in \"%s\".", node->name,
906 stop ? stop->name : "(sub)module");
907 return EXIT_FAILURE;
908 }
909 }
910
911 /* special case for choice - we must check the choice's name as
912 * well as the names of nodes under the choice
913 */
914 if (iter->nodetype == LYS_CHOICE) {
915 iter = iter->child;
916 continue;
917 }
918
919 /* go to siblings */
920 if (!iter->next) {
921 /* no sibling, go to parent's sibling */
922 do {
923 iter = iter->parent;
924 if (iter && iter->next) {
925 break;
926 }
927 } while (iter != stop);
928
929 if (iter == stop) {
930 break;
931 }
932 }
933 iter = iter->next;
934 }
935 break;
936 case LYS_CASE:
937 /* 6.2.1, rule 8 */
938 LY_TREE_FOR(parent->child, iter) {
939 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
940 continue;
941 }
942
943 if (iter->module == node->module && iter->name == node->name) {
944 LOGVAL(LYE_DUPID, 0, "case", node->name);
945 return EXIT_FAILURE;
946 }
947 }
948 break;
949 default:
950 /* no check needed */
951 break;
952 }
953
954 return EXIT_SUCCESS;
955}
956
Michal Vasko0d343d12015-08-24 14:57:36 +0200957/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200958int
Radek Krejci10c760e2015-08-14 14:45:43 +0200959lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
960{
Radek Krejci92720552015-10-05 15:28:27 +0200961 struct lys_node *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200962 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200963
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200964 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200965
Radek Krejci10c760e2015-08-14 14:45:43 +0200966 if (parent) {
967 type = parent->nodetype;
968 module = parent->module;
969 } else {
970 assert(module);
971 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200972 }
973
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200974 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200975 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200976 case LYS_CONTAINER:
977 case LYS_LIST:
978 case LYS_GROUPING:
979 case LYS_USES:
980 case LYS_INPUT:
981 case LYS_OUTPUT:
982 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200983 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200984 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
985 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200986 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200987 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
988 return EXIT_FAILURE;
989 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200990
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200991 break;
Radek Krejci76512572015-08-04 09:47:08 +0200992 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200993 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200994 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200995 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"choice\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200996 strnodetype(child->nodetype), parent->name);
997 return EXIT_FAILURE;
998 }
999 break;
Radek Krejci76512572015-08-04 09:47:08 +02001000 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001001 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +02001002 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001003 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"case\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001004 strnodetype(child->nodetype), parent->name);
1005 return EXIT_FAILURE;
1006 }
1007 break;
Radek Krejci76512572015-08-04 09:47:08 +02001008 case LYS_RPC:
1009 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001010 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"rpc\" %s.",
Michal Vasko38d01f72015-06-15 09:41:06 +02001011 strnodetype(child->nodetype), parent->name);
1012 return EXIT_FAILURE;
1013 }
1014 break;
Radek Krejci76512572015-08-04 09:47:08 +02001015 case LYS_LEAF:
1016 case LYS_LEAFLIST:
1017 case LYS_ANYXML:
Radek Krejci10c760e2015-08-14 14:45:43 +02001018 LOGVAL(LYE_SPEC, 0, "The \"%s\" statement (%s) cannot have any data substatement.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001019 strnodetype(parent->nodetype), parent->name);
1020 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +02001021 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001022 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +02001023 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
1024 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001025 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001026 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
1027 return EXIT_FAILURE;
1028 }
Michal Vasko591e0b22015-08-13 13:53:43 +02001029 break;
1030 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +02001031 /* top level */
1032 if (!(child->nodetype &
1033 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
1034 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci2c0ca272015-08-14 15:31:01 +02001035 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in (sub)module \"%s\"",
1036 strnodetype(child->nodetype), module->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02001037 return EXIT_FAILURE;
1038 }
1039
1040 break;;
1041 }
1042
1043 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +02001044 if (lys_check_id(child, parent, module)) {
1045 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001046 }
Radek Krejcib7155b52015-06-10 17:03:01 +02001047
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001048 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001049 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001050 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001051
Radek Krejci10c760e2015-08-14 14:45:43 +02001052 if (!parent) {
Radek Krejci92720552015-10-05 15:28:27 +02001053 if (module->data) {
1054 module->data->prev->next = child;
1055 child->prev = module->data->prev;
1056 module->data->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +02001057 } else {
Radek Krejci92720552015-10-05 15:28:27 +02001058 module->data = child;
Radek Krejci10c760e2015-08-14 14:45:43 +02001059 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001060 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +02001061 if (!parent->child) {
1062 /* the only/first child of the parent */
1063 parent->child = child;
1064 child->parent = parent;
1065 iter = child;
1066 } else {
1067 /* add a new child at the end of parent's child list */
1068 iter = parent->child->prev;
1069 iter->next = child;
1070 child->prev = iter;
1071 }
1072 while (iter->next) {
1073 iter = iter->next;
1074 iter->parent = parent;
1075 }
1076 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001077 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001078
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001079 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001080}
1081
Michal Vasko1e62a092015-12-01 12:27:20 +01001082API const struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +02001083lys_parse(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001084{
Michal Vaskof02e3742015-08-05 16:27:02 +02001085 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +02001086 struct lys_module *mod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001087
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001088 if (!ctx || !data) {
1089 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1090 return NULL;
1091 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001092
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001093 unres = calloc(1, sizeof *unres);
1094
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001095 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001096 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001097 mod = yin_read_module(ctx, data, 1, unres);
1098 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001099 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001100 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001101 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001102 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001103 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001104
Michal Vasko0bd29d12015-08-19 11:45:49 +02001105 if (mod && unres->count && resolve_unres_schema(mod, unres)) {
Michal Vasko13b15832015-08-19 11:04:48 +02001106 lys_free(mod, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001107 mod = NULL;
1108 }
Michal Vasko88c29542015-11-27 14:57:53 +01001109 unres_schema_free(ctx, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001110
1111 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001112}
1113
Radek Krejcib8048692015-08-05 13:36:34 +02001114struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001115lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02001116{
Michal Vaskof02e3742015-08-05 16:27:02 +02001117 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +02001118 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001119
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001120 assert(module);
1121 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001122
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001123 unres = calloc(1, sizeof *unres);
1124
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001125 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001126 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001127 submod = yin_read_submodule(module, data, implement, unres);
1128 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001129 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001130 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001131 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001132 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001133 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001134
Michal Vasko0bd29d12015-08-19 11:45:49 +02001135 if (submod && unres->count && resolve_unres_schema((struct lys_module *)submod, unres)) {
Michal Vasko13b15832015-08-19 11:04:48 +02001136 lys_submodule_free(submod, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001137 submod = NULL;
1138 }
Michal Vasko88c29542015-11-27 14:57:53 +01001139 unres_schema_free(module->ctx, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001140
1141 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001142}
1143
Michal Vasko1e62a092015-12-01 12:27:20 +01001144API const struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +02001145lys_read(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001146{
Michal Vasko1e62a092015-12-01 12:27:20 +01001147 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +02001148 struct stat sb;
1149 char *addr;
1150
1151 if (!ctx || fd < 0) {
1152 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1153 return NULL;
1154 }
1155
Radek Krejci63a91a92015-07-29 13:31:04 +02001156 fstat(fd, &sb);
1157 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001158 if (addr == MAP_FAILED) {
1159 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
1160 return NULL;
1161 }
Radek Krejci63a91a92015-07-29 13:31:04 +02001162 module = lys_parse(ctx, addr, format);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001163 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001164
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001165 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001166}
1167
Radek Krejcib8048692015-08-05 13:36:34 +02001168struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001169lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02001170{
Radek Krejcib8048692015-08-05 13:36:34 +02001171 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001172 struct stat sb;
1173 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001174
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001175 assert(module);
1176 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001177
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001178 fstat(fd, &sb);
1179 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001180 if (addr == MAP_FAILED) {
1181 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
1182 return NULL;
1183 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001184 submodule = lys_submodule_parse(module, addr, format, implement);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001185 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +02001186
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001187 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02001188
1189}
1190
Radek Krejci1d82ef62015-08-07 14:44:40 +02001191static struct lys_restr *
1192lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001193{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001194 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001195 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001196
Radek Krejci3733a802015-06-19 13:43:21 +02001197 if (!size) {
1198 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001199 }
Radek Krejci3733a802015-06-19 13:43:21 +02001200
1201 result = calloc(size, sizeof *result);
1202 for (i = 0; i < size; i++) {
1203 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1204 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1205 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1206 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1207 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1208 }
1209
1210 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001211}
1212
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001213void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001214lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001215{
1216 assert(ctx);
1217 if (!restr) {
1218 return;
1219 }
1220
1221 lydict_remove(ctx, restr->expr);
1222 lydict_remove(ctx, restr->dsc);
1223 lydict_remove(ctx, restr->ref);
1224 lydict_remove(ctx, restr->eapptag);
1225 lydict_remove(ctx, restr->emsg);
1226}
1227
Michal Vaskob84f88a2015-09-24 13:16:10 +02001228static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001229lys_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 +02001230 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001231{
1232 int i;
1233
Michal Vasko1dca6882015-10-22 14:29:42 +02001234 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001235 new->base = old->base;
1236 new->der = old->der;
1237
Michal Vasko0bd29d12015-08-19 11:45:49 +02001238 i = unres_schema_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001239 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001240 /* HACK (serious one) for unres */
1241 /* nothing else we can do but duplicate it immediately */
1242 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
Michal Vaskob84f88a2015-09-24 13:16:10 +02001243 /* all these unres additions can fail even though they did not before */
Michal Vasko88c29542015-11-27 14:57:53 +01001244 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_DER, parent, 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001245 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001246 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001247 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001248 }
1249
Radek Krejci3733a802015-06-19 13:43:21 +02001250 switch (new->base) {
1251 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +02001252 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001253 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001254 }
Radek Krejci3733a802015-06-19 13:43:21 +02001255 break;
1256
1257 case LY_TYPE_BITS:
1258 new->info.bits.count = old->info.bits.count;
1259 if (new->info.bits.count) {
1260 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1261 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001262 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1263 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1264 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001265 new->info.bits.bit[i].status = old->info.bits.bit[i].status;
1266 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1267 }
1268 }
1269 break;
1270
Radek Krejcif9401c32015-06-26 16:47:36 +02001271 case LY_TYPE_DEC64:
1272 new->info.dec64.dig = old->info.dec64.dig;
1273 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001274 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +02001275 }
1276 break;
1277
Radek Krejci3733a802015-06-19 13:43:21 +02001278 case LY_TYPE_ENUM:
1279 new->info.enums.count = old->info.enums.count;
1280 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001281 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Radek Krejci3733a802015-06-19 13:43:21 +02001282 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001283 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1284 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1285 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1286 new->info.enums.enm[i].status = old->info.enums.enm[i].status;
1287 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +02001288 }
1289 }
1290 break;
1291
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001292 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001293 if (old->info.ident.ref) {
1294 new->info.ident.ref = old->info.ident.ref;
1295 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001296 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001297 assert(i != -1);
Michal Vasko88c29542015-11-27 14:57:53 +01001298 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i], 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001299 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001300 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001301 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001302 break;
1303
Radek Krejciaf351422015-06-19 14:49:38 +02001304 case LY_TYPE_INST:
1305 new->info.inst.req = old->info.inst.req;
1306 break;
1307
Radek Krejcif2860132015-06-20 12:37:20 +02001308 case LY_TYPE_INT8:
1309 case LY_TYPE_INT16:
1310 case LY_TYPE_INT32:
1311 case LY_TYPE_INT64:
1312 case LY_TYPE_UINT8:
1313 case LY_TYPE_UINT16:
1314 case LY_TYPE_UINT32:
1315 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +02001316 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001317 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001318 }
Radek Krejcif2860132015-06-20 12:37:20 +02001319 break;
1320
Radek Krejcidc4c1412015-06-19 15:39:54 +02001321 case LY_TYPE_LEAFREF:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001322 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko88c29542015-11-27 14:57:53 +01001323 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001324 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001325 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001326 break;
1327
Radek Krejci3733a802015-06-19 13:43:21 +02001328 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +02001329 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001330 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001331 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001332 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 +02001333 break;
1334
Radek Krejcie4c366b2015-07-02 10:11:31 +02001335 case LY_TYPE_UNION:
1336 new->info.uni.count = old->info.uni.count;
1337 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001338 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001339 for (i = 0; i < new->info.uni.count; i++) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001340 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres)) {
1341 return -1;
1342 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001343 }
1344 }
1345 break;
1346
Radek Krejci3733a802015-06-19 13:43:21 +02001347 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001348 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001349 break;
1350 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001351
1352 return EXIT_SUCCESS;
Radek Krejci3733a802015-06-19 13:43:21 +02001353}
1354
1355void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001356lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001357{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001358 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001359
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001360 assert(ctx);
1361 if (!type) {
1362 return;
1363 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001364
Michal Vasko1dca6882015-10-22 14:29:42 +02001365 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001366
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001367 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001368 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001369 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001370 free(type->info.binary.length);
1371 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001372 case LY_TYPE_BITS:
1373 for (i = 0; i < type->info.bits.count; i++) {
1374 lydict_remove(ctx, type->info.bits.bit[i].name);
1375 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1376 lydict_remove(ctx, type->info.bits.bit[i].ref);
1377 }
1378 free(type->info.bits.bit);
1379 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001380
1381 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001382 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001383 free(type->info.dec64.range);
1384 break;
1385
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001386 case LY_TYPE_ENUM:
1387 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001388 lydict_remove(ctx, type->info.enums.enm[i].name);
1389 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1390 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001391 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001392 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001393 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001394
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001395 case LY_TYPE_INT8:
1396 case LY_TYPE_INT16:
1397 case LY_TYPE_INT32:
1398 case LY_TYPE_INT64:
1399 case LY_TYPE_UINT8:
1400 case LY_TYPE_UINT16:
1401 case LY_TYPE_UINT32:
1402 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001403 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001404 free(type->info.num.range);
1405 break;
1406
Radek Krejcidc4c1412015-06-19 15:39:54 +02001407 case LY_TYPE_LEAFREF:
1408 lydict_remove(ctx, type->info.lref.path);
1409 break;
1410
Radek Krejci3733a802015-06-19 13:43:21 +02001411 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001412 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001413 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001414 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001415 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001416 }
1417 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001418 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001419
Radek Krejcie4c366b2015-07-02 10:11:31 +02001420 case LY_TYPE_UNION:
1421 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001422 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001423 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001424 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001425 break;
1426
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001427 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001428 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001429 break;
1430 }
Radek Krejci5a065542015-05-22 15:02:07 +02001431}
1432
Radek Krejci1d82ef62015-08-07 14:44:40 +02001433static void
1434lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001435{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001436 assert(ctx);
1437 if (!tpdf) {
1438 return;
1439 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001440
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001441 lydict_remove(ctx, tpdf->name);
1442 lydict_remove(ctx, tpdf->dsc);
1443 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001444
Radek Krejci1d82ef62015-08-07 14:44:40 +02001445 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001446
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001447 lydict_remove(ctx, tpdf->units);
1448 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001449}
1450
Michal Vaskob84f88a2015-09-24 13:16:10 +02001451static struct lys_tpdf *
1452lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1453{
1454 struct lys_tpdf *result;
1455 int i, j;
1456
1457 if (!size) {
1458 return NULL;
1459 }
1460
1461 result = calloc(size, sizeof *result);
1462 for (i = 0; i < size; i++) {
1463 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1464 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1465 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1466 result[i].flags = old[i].flags;
1467 result[i].module = old[i].module;
1468
1469 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres)) {
1470 for (j = 0; j <= i; ++j) {
1471 lys_tpdf_free(mod->ctx, &result[j]);
1472 }
1473 free(result);
1474 return NULL;
1475 }
1476
1477 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1478 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1479 }
1480
1481 return result;
1482}
1483
Radek Krejci1d82ef62015-08-07 14:44:40 +02001484static struct lys_when *
1485lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001486{
Radek Krejci76512572015-08-04 09:47:08 +02001487 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001488
1489 if (!old) {
1490 return NULL;
1491 }
1492
1493 new = calloc(1, sizeof *new);
1494 new->cond = lydict_insert(ctx, old->cond, 0);
1495 new->dsc = lydict_insert(ctx, old->dsc, 0);
1496 new->ref = lydict_insert(ctx, old->ref, 0);
1497
1498 return new;
1499}
1500
Michal Vasko0308dd62015-10-07 09:14:40 +02001501void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001502lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001503{
1504 if (!w) {
1505 return;
1506 }
1507
1508 lydict_remove(ctx, w->cond);
1509 lydict_remove(ctx, w->dsc);
1510 lydict_remove(ctx, w->ref);
1511
1512 free(w);
1513}
1514
Radek Krejcib7f5e412015-08-13 10:15:51 +02001515static void
1516lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment aug)
1517{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001518 struct lys_node *next, *sub;
1519
1520 /* children from a resolved uses */
1521 LY_TREE_FOR_SAFE(aug.child, next, sub) {
1522 lys_node_free(sub);
1523 }
1524
Radek Krejcib7f5e412015-08-13 10:15:51 +02001525 lydict_remove(ctx, aug.target_name);
1526 lydict_remove(ctx, aug.dsc);
1527 lydict_remove(ctx, aug.ref);
1528
1529 free(aug.features);
1530
1531 lys_when_free(ctx, aug.when);
1532
Michal Vasko7d356a52015-08-19 15:06:31 +02001533 /* Do not free the children, they were appended somewhere and their
1534 * new parent will take care of them.
1535 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001536}
1537
Radek Krejci76512572015-08-04 09:47:08 +02001538static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001539lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001540{
Radek Krejci76512572015-08-04 09:47:08 +02001541 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001542 struct lys_node *old_child, *new_child;
1543 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001544
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001545 if (!size) {
1546 return NULL;
1547 }
Radek Krejci106efc02015-06-10 14:36:27 +02001548
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001549 new = calloc(size, sizeof *new);
1550 for (i = 0; i < size; i++) {
1551 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1552 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1553 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1554 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001555 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001556 new[i].nodetype = old[i].nodetype;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001557 /* this must succeed, it was already resolved once */
Michal Vasko1e62a092015-12-01 12:27:20 +01001558 if (resolve_schema_nodeid(new[i].target_name, parent->child, new[i].module, LYS_AUGMENT,
1559 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001560 LOGINT;
1561 free(new);
1562 return NULL;
1563 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001564 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001565
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001566 /* Correct the augment nodes.
1567 * This function can only be called from lys_node_dup() with uses
1568 * being the node duplicated, so we must have a case of grouping
1569 * with a uses with augments. The augmented nodes have already been
1570 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001571 * (it was set to their actual data parent, not an augment), and
1572 * the new augment does not have child pointer to its augment nodes,
1573 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001574 */
1575 LY_TREE_FOR(new[i].target->child, new_child) {
1576 if (new_child->name == old[i].child->name) {
1577 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001578 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001579 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001580 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001581 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001582 LY_TREE_FOR(old[i].child, old_child) {
1583 /* all augment nodes were connected as siblings, there can be no more after this */
1584 if (old_child->parent != (struct lys_node *)&old[i]) {
1585 break;
1586 }
1587
1588 assert(old_child->name == new_child->name);
1589
1590 new_child->parent = (struct lys_node *)&new[i];
1591 new_child = new_child->next;
1592 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001593 }
Radek Krejci106efc02015-06-10 14:36:27 +02001594
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001595 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001596}
1597
Radek Krejci76512572015-08-04 09:47:08 +02001598static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001599lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001600{
Radek Krejci76512572015-08-04 09:47:08 +02001601 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001602 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001603
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001604 if (!size) {
1605 return NULL;
1606 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001607
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001608 result = calloc(size, sizeof *result);
1609 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001610 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001611 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1612 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001613 result[i].flags = old[i].flags;
1614 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001615
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001616 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001617 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001618
Radek Krejci76512572015-08-04 09:47:08 +02001619 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001620 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001621 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001622 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001623 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001624 result[i].mod.list = old[i].mod.list;
1625 }
1626 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001627
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001628 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001629}
1630
Radek Krejci1d82ef62015-08-07 14:44:40 +02001631static void
1632lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001633{
Radek Krejcia52656e2015-08-05 13:41:50 +02001634 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001635
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001636 assert(ctx);
1637 if (!ident) {
1638 return;
1639 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001640
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001641 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001642 * if caller free only a single data model which is used (its identity is
1643 * reference from identity in another module), this silly freeing can lead
1644 * to segmentation fault. But without noting if the module is used by some
1645 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001646 *
1647 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001648 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001649 */
1650 while (ident->der) {
1651 der = ident->der;
1652 ident->der = der->next;
1653 free(der);
1654 }
Radek Krejci6793db02015-05-22 17:49:54 +02001655
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001656 lydict_remove(ctx, ident->name);
1657 lydict_remove(ctx, ident->dsc);
1658 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001659
1660}
1661
Radek Krejci1d82ef62015-08-07 14:44:40 +02001662static void
1663lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001664{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001665 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001666
Radek Krejcid12f57b2015-08-06 10:43:39 +02001667 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001668 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001669 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001670 }
1671 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001672}
1673
Radek Krejci1d82ef62015-08-07 14:44:40 +02001674static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001675lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1676{
1677 int i;
1678
1679 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1680 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001681 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001682 }
1683 free(io->tpdf);
1684}
1685
Radek Krejci1d82ef62015-08-07 14:44:40 +02001686static void
1687lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001688{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001689 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001690
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001691 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001692 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001693 }
1694 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001695
Radek Krejci1d82ef62015-08-07 14:44:40 +02001696 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001697}
1698
Radek Krejci1d82ef62015-08-07 14:44:40 +02001699static void
1700lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001701{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001702 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001703
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001704 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001705 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001706 }
1707 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001708
Radek Krejci1d82ef62015-08-07 14:44:40 +02001709 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001710
Radek Krejci1d82ef62015-08-07 14:44:40 +02001711 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001712 lydict_remove(ctx, leaf->units);
1713 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001714}
1715
Radek Krejci1d82ef62015-08-07 14:44:40 +02001716static void
1717lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001718{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001719 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001720
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001721 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001722 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001723 }
1724 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001725
Radek Krejci1d82ef62015-08-07 14:44:40 +02001726 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001727
Radek Krejci1d82ef62015-08-07 14:44:40 +02001728 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001729 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001730}
1731
Radek Krejci1d82ef62015-08-07 14:44:40 +02001732static void
1733lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001734{
Radek Krejci581ce772015-11-10 17:22:40 +01001735 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001736
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001737 /* handle only specific parts for LY_NODE_LIST */
1738 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001739 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001740 }
1741 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001742
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001743 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001744 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001745 }
1746 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001747
Radek Krejci1d82ef62015-08-07 14:44:40 +02001748 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001749
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001750 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001751 for (j = 0; j > list->unique[i].expr_size; j++) {
1752 lydict_remove(ctx, list->unique[i].expr[j]);
1753 }
1754 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001755 }
1756 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001757
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001758 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001759}
1760
Radek Krejci1d82ef62015-08-07 14:44:40 +02001761static void
1762lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001763{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001764 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001765
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001766 /* handle only specific parts for LY_NODE_CONTAINER */
1767 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001768
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001769 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001770 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001771 }
1772 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001773
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001774 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001775 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001776 }
1777 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001778
Radek Krejci1d82ef62015-08-07 14:44:40 +02001779 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001780}
1781
Radek Krejci1d82ef62015-08-07 14:44:40 +02001782static void
1783lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001784{
1785 lydict_remove(ctx, f->name);
1786 lydict_remove(ctx, f->dsc);
1787 lydict_remove(ctx, f->ref);
1788 free(f->features);
1789}
1790
Radek Krejci1d82ef62015-08-07 14:44:40 +02001791static void
1792lys_deviation_free(struct ly_ctx *ctx, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001793{
Radek Krejci581ce772015-11-10 17:22:40 +01001794 int i, j, k;
Radek Krejcieb00f512015-07-01 16:44:58 +02001795
1796 lydict_remove(ctx, dev->target_name);
1797 lydict_remove(ctx, dev->dsc);
1798 lydict_remove(ctx, dev->ref);
1799
1800 for (i = 0; i < dev->deviate_size; i++) {
1801 lydict_remove(ctx, dev->deviate[i].dflt);
1802 lydict_remove(ctx, dev->deviate[i].units);
1803
1804 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1805 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001806 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001807 }
1808 free(dev->deviate[i].must);
1809
1810 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001811 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1812 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1813 }
1814 free(dev->deviate[j].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001815 }
1816 free(dev->deviate[i].unique);
1817 }
1818 }
1819 free(dev->deviate);
1820}
1821
Radek Krejci1d82ef62015-08-07 14:44:40 +02001822static void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001823lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +02001824{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001825 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001826
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001827 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001828 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001829 lydict_remove(ctx, uses->refine[i].dsc);
1830 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001831
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001832 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001833 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001834 }
1835 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001836
Radek Krejci76512572015-08-04 09:47:08 +02001837 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001838 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001839 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001840 lydict_remove(ctx, uses->refine[i].mod.presence);
1841 }
1842 }
1843 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001844
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001845 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001846 lys_augment_free(ctx, uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001847 }
1848 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001849
Radek Krejci1d82ef62015-08-07 14:44:40 +02001850 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001851}
1852
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001853void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001854lys_node_free(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001855{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001856 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001857 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001858
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001859 if (!node) {
1860 return;
1861 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001862
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001863 assert(node->module);
1864 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001865
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001866 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001867
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001868 /* common part */
1869 LY_TREE_FOR_SAFE(node->child, next, sub) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001870 lys_node_free(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001871 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001872
Radek Krejcid12f57b2015-08-06 10:43:39 +02001873 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1874 free(node->features);
1875 lydict_remove(ctx, node->name);
1876 lydict_remove(ctx, node->dsc);
1877 lydict_remove(ctx, node->ref);
1878 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001879
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001880 /* specific part */
1881 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001882 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001883 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001884 break;
Radek Krejci76512572015-08-04 09:47:08 +02001885 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001886 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001887 break;
Radek Krejci76512572015-08-04 09:47:08 +02001888 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001889 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001890 break;
Radek Krejci76512572015-08-04 09:47:08 +02001891 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001892 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001893 break;
Radek Krejci76512572015-08-04 09:47:08 +02001894 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001895 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001896 break;
Radek Krejci76512572015-08-04 09:47:08 +02001897 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001898 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001899 break;
Radek Krejci76512572015-08-04 09:47:08 +02001900 case LYS_USES:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001901 lys_uses_free(ctx, (struct lys_node_uses *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001902 break;
Radek Krejci76512572015-08-04 09:47:08 +02001903 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001904 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001905 break;
Radek Krejci76512572015-08-04 09:47:08 +02001906 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001907 /* do nothing */
1908 break;
Radek Krejci76512572015-08-04 09:47:08 +02001909 case LYS_GROUPING:
1910 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001911 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001912 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001913 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001914
1915 case LYS_INPUT:
1916 case LYS_OUTPUT:
1917 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1918 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001919 case LYS_UNKNOWN:
1920 LOGINT;
1921 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001922 }
Radek Krejci5a065542015-05-22 15:02:07 +02001923
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001924 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001925 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001926 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001927}
1928
Michal Vasko1e62a092015-12-01 12:27:20 +01001929const struct lys_module *
1930lys_get_import_module(const struct lys_module *module, const char *prefix, int pref_len, const char *name, int name_len)
Michal Vasko8ce24d72015-10-21 11:27:26 +02001931{
Michal Vaskob6729c62015-10-21 12:09:47 +02001932 int i, match;
1933
1934 assert(prefix || name);
1935 if (prefix && !pref_len) {
1936 pref_len = strlen(prefix);
1937 }
1938 if (name && !name_len) {
1939 name_len = strlen(name);
1940 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02001941
Michal Vaskod8da86b2015-10-21 13:35:37 +02001942 if ((!prefix || (!strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
1943 && (!name || (!strncmp(module->name, name, name_len) && !module->name[name_len]))) {
1944 return module;
1945 }
1946
Michal Vasko8ce24d72015-10-21 11:27:26 +02001947 for (i = 0; i < module->imp_size; ++i) {
Michal Vaskob6729c62015-10-21 12:09:47 +02001948 match = 0;
1949 if (!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len])) {
1950 match = 1;
1951 }
1952 if (match && (!name
1953 || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02001954 return module->imp[i].module;
1955 }
1956 }
1957
1958 return NULL;
1959}
1960
Michal Vasko13b15832015-08-19 11:04:48 +02001961/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001962static void
Michal Vasko13b15832015-08-19 11:04:48 +02001963module_free_common(struct lys_module *module, int free_int_mods)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001964{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001965 struct ly_ctx *ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001966 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001967 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001968
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001969 assert(module->ctx);
1970 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001971
Radek Krejcidce51452015-06-16 15:20:08 +02001972 /* as first step, free the imported modules */
1973 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa76ee152015-08-17 15:38:22 +02001974 /* do not free internal modules */
Michal Vasko18bd09b2015-08-19 15:07:00 +02001975 if (!free_int_mods) {
1976 for (j = 0; j < int_mods.count; ++j) {
Michal Vaskod83c03a2015-08-21 09:09:24 +02001977 if (module->imp[i].module && !strcmp(int_mods.modules[j].name, module->imp[i].module->name)
Michal Vasko18bd09b2015-08-19 15:07:00 +02001978 && module->imp[i].module->rev
1979 && !strcmp(int_mods.modules[j].revision, module->imp[i].module->rev[0].date)) {
1980 break;
1981 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02001982 }
Michal Vasko18bd09b2015-08-19 15:07:00 +02001983 if (j < int_mods.count) {
1984 continue;
1985 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02001986 }
1987
Radek Krejcidce51452015-06-16 15:20:08 +02001988 /* get the imported module from the context and then free,
1989 * this check is necessary because the imported module can
1990 * be already removed
1991 */
1992 l = ctx->models.used;
1993 for (j = 0; j < l; j++) {
1994 if (ctx->models.list[j] == module->imp[i].module) {
Michal Vasko13b15832015-08-19 11:04:48 +02001995 lys_free(module->imp[i].module, free_int_mods);
Radek Krejcidce51452015-06-16 15:20:08 +02001996 break;
1997 }
1998 }
1999 }
2000 free(module->imp);
2001
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002002 while (module->data) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002003 lys_node_free(module->data);
Radek Krejci21181962015-06-30 14:11:00 +02002004 }
Radek Krejci5a065542015-05-22 15:02:07 +02002005
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002006 lydict_remove(ctx, module->dsc);
2007 lydict_remove(ctx, module->ref);
2008 lydict_remove(ctx, module->org);
2009 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002010
Radek Krejcieb00f512015-07-01 16:44:58 +02002011 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002012 for (i = 0; i < module->rev_size; i++) {
2013 lydict_remove(ctx, module->rev[i].dsc);
2014 lydict_remove(ctx, module->rev[i].ref);
2015 }
2016 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002017
Radek Krejcieb00f512015-07-01 16:44:58 +02002018 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002019 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002020 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002021 }
2022 module->ident_size = 0;
2023 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002024
Radek Krejcieb00f512015-07-01 16:44:58 +02002025 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002026 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002027 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002028 }
2029 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002030
Radek Krejcieb00f512015-07-01 16:44:58 +02002031 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002032 for (i = 0; i < module->inc_size; i++) {
Michal Vasko13b15832015-08-19 11:04:48 +02002033 lys_submodule_free(module->inc[i].submodule, free_int_mods);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002034 }
2035 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002036
Radek Krejcieb00f512015-07-01 16:44:58 +02002037 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002038 for (i = 0; i < module->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02002039 lys_augment_free(ctx, module->augment[i]);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002040 }
2041 free(module->augment);
2042
Radek Krejcieb00f512015-07-01 16:44:58 +02002043 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002044 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002045 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002046 }
2047 free(module->features);
2048
Radek Krejcieb00f512015-07-01 16:44:58 +02002049 /* deviations */
2050 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002051 lys_deviation_free(ctx, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002052 }
2053 free(module->deviation);
2054
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002055 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02002056}
2057
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002058void
Michal Vasko13b15832015-08-19 11:04:48 +02002059lys_submodule_free(struct lys_submodule *submodule, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02002060{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002061 if (!submodule) {
2062 return;
2063 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002064
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002065 submodule->inc_size = 0;
2066 free(submodule->inc);
2067 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02002068
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002069 /* common part with struct ly_module */
Michal Vasko13b15832015-08-19 11:04:48 +02002070 module_free_common((struct lys_module *)submodule, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02002071
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002072 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002073
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002074 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002075}
2076
Radek Krejci76512572015-08-04 09:47:08 +02002077struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002078lys_node_dup(struct lys_module *module, const struct lys_node *node, uint8_t flags, uint8_t nacm, int recursive,
Michal Vaskof02e3742015-08-05 16:27:02 +02002079 struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002080{
Radek Krejci76512572015-08-04 09:47:08 +02002081 struct lys_node *retval = NULL, *aux, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002082 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002083 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002084
Michal Vaskoc07187d2015-08-13 15:20:57 +02002085 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002086 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002087 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002088 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002089 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002090 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002091 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002092 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002093 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002094 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002095 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002096 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002097 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002098 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002099 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002100 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002101 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002102 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002103 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002104 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002105 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002106 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002107 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002108 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002109
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002110 /* we cannot just duplicate memory since the strings are stored in
2111 * dictionary and we need to update dictionary counters.
2112 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002113
Radek Krejci1d82ef62015-08-07 14:44:40 +02002114 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002115 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002116 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002117 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002118 break;
2119
Radek Krejci76512572015-08-04 09:47:08 +02002120 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002121 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002122 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002123 break;
2124
Radek Krejci76512572015-08-04 09:47:08 +02002125 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002126 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002127 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002128 break;
2129
Radek Krejci76512572015-08-04 09:47:08 +02002130 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002131 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002132 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002133 break;
2134
Radek Krejci76512572015-08-04 09:47:08 +02002135 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002136 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002137 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002138 break;
2139
Radek Krejci76512572015-08-04 09:47:08 +02002140 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002141 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002142 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002143 break;
2144
Radek Krejci76512572015-08-04 09:47:08 +02002145 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002146 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002147 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002148 break;
2149
Radek Krejci76512572015-08-04 09:47:08 +02002150 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002151 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002152 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002153 break;
2154
Radek Krejci76512572015-08-04 09:47:08 +02002155 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002156 grp = calloc(1, sizeof *grp);
2157 retval = (struct lys_node *)grp;
2158 break;
2159
Radek Krejci76512572015-08-04 09:47:08 +02002160 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002161 rpc = calloc(1, sizeof *rpc);
2162 retval = (struct lys_node *)rpc;
2163 break;
2164
Radek Krejci76512572015-08-04 09:47:08 +02002165 case LYS_INPUT:
2166 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002167 io = calloc(1, sizeof *io);
2168 retval = (struct lys_node *)io;
2169 break;
2170
Radek Krejci76512572015-08-04 09:47:08 +02002171 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002172 ntf = calloc(1, sizeof *ntf);
2173 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002174 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002175
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002176 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002177 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002178 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002179 }
Radek Krejcib388c152015-06-04 17:03:03 +02002180
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002181 /*
2182 * duplicate generic part of the structure
2183 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002184 retval->name = lydict_insert(ctx, node->name, 0);
2185 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2186 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002187 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002188 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002189 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002190 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002191 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002192 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002194 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002195 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002196
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002197 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002198
Radek Krejci1d82ef62015-08-07 14:44:40 +02002199 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002200 retval->features = calloc(retval->features_size, sizeof *retval->features);
Radek Krejci1d82ef62015-08-07 14:44:40 +02002201 for (i = 0; i < node->features_size; ++i) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002202 if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002203 retval->features[i] = node->features[i];
Michal Vaskod23ce592015-08-06 09:55:37 +02002204 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002205 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002206
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002207 if (recursive) {
2208 /* go recursively */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002209 LY_TREE_FOR(node->child, child) {
Michal Vasko71e1aa82015-08-12 12:17:51 +02002210 aux = lys_node_dup(module, child, retval->flags, retval->nacm, 1, unres);
Radek Krejci10c760e2015-08-14 14:45:43 +02002211 if (!aux || lys_node_addchild(retval, NULL, aux)) {
Michal Vasko49168a22015-08-17 16:35:41 +02002212 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002213 }
2214 }
2215 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002216
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002217 /*
2218 * duplicate specific part of the structure
2219 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002220 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002221 case LYS_CONTAINER:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002222 if (cont_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002223 cont->when = lys_when_dup(ctx, cont_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002224 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002225 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002226
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002227 cont->must_size = cont_orig->must_size;
2228 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002229
Radek Krejci1d82ef62015-08-07 14:44:40 +02002230 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci1d82ef62015-08-07 14:44:40 +02002231 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002232 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002233
Radek Krejci76512572015-08-04 09:47:08 +02002234 case LYS_CHOICE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002235 if (choice_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002236 choice->when = lys_when_dup(ctx, choice_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002237 }
2238
2239 if (choice_orig->dflt) {
Michal Vasko165dc4a2015-10-23 09:44:27 +02002240 rc = lys_get_sibling(choice->module, choice->child, NULL, 0, choice_orig->dflt->name, 0, LYS_ANYXML
Radek Krejci76512572015-08-04 09:47:08 +02002241 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
Michal Vasko1e62a092015-12-01 12:27:20 +01002242 | LYS_LIST, (const struct lys_node **)&choice->dflt);
Michal Vasko49168a22015-08-17 16:35:41 +02002243 if (rc) {
2244 if (rc == EXIT_FAILURE) {
2245 LOGINT;
2246 }
2247 goto error;
2248 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002249 } else {
Michal Vaskoc68a2a22015-08-06 09:57:24 +02002250 /* useless to check return value, we don't know whether
2251 * there really wasn't any default defined or it just hasn't
2252 * been resolved, we just hope for the best :)
2253 */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002254 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002255 }
2256 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002257
Radek Krejci76512572015-08-04 09:47:08 +02002258 case LYS_LEAF:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002259 if (lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres)) {
2260 goto error;
2261 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002262 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2263
2264 if (leaf_orig->dflt) {
2265 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002266 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002267 goto error;
2268 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002269 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002270
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002271 leaf->must_size = leaf_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002272 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002273
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002274 if (leaf_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002275 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002276 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002277 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002278
Radek Krejci76512572015-08-04 09:47:08 +02002279 case LYS_LEAFLIST:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002280 if (lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres)) {
2281 goto error;
2282 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002283 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002285 llist->min = llist_orig->min;
2286 llist->max = llist_orig->max;
2287
2288 llist->must_size = llist_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002289 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002290
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002291 if (llist_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002292 llist->when = lys_when_dup(ctx, llist_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002293 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002294 break;
2295
Radek Krejci76512572015-08-04 09:47:08 +02002296 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002297 list->min = list_orig->min;
2298 list->max = list_orig->max;
2299
2300 list->must_size = list_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002301 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002302
Radek Krejci581ce772015-11-10 17:22:40 +01002303 list->tpdf_size = list_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002304 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002305
Radek Krejci581ce772015-11-10 17:22:40 +01002306 list->keys_size = list_orig->keys_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002307 if (list->keys_size) {
2308 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002309
2310 /* we managed to resolve it before, resolve it again manually */
2311 if (list_orig->keys[0]) {
2312 for (i = 0; i < list->keys_size; ++i) {
Michal Vasko165dc4a2015-10-23 09:44:27 +02002313 rc = lys_get_sibling(list->module, list->child, NULL, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
Michal Vasko1e62a092015-12-01 12:27:20 +01002314 (const struct lys_node **)&list->keys[i]);
Michal Vasko49168a22015-08-17 16:35:41 +02002315 if (rc) {
2316 if (rc == EXIT_FAILURE) {
2317 LOGINT;
2318 }
2319 goto error;
2320 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002321 }
2322 /* it was not resolved yet, add unres copy */
2323 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002324 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02002325 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002326 goto error;
Michal Vaskod23ce592015-08-06 09:55:37 +02002327 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002328 }
2329 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002330
Radek Krejci581ce772015-11-10 17:22:40 +01002331 list->unique_size = list_orig->unique_size;
2332 list->unique = malloc(list->unique_size * sizeof *list->unique);
2333 for (i = 0; i < list->unique_size; ++i) {
2334 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2335 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
2336 for (j = 0; j < list->unique[i].expr_size; j++) {
2337 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2338
2339 /* if it stays in unres list, duplicate it also there */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002340 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002341 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002342 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002343
2344 if (list_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002345 list->when = lys_when_dup(ctx, list_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002346 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002347 break;
2348
Radek Krejci76512572015-08-04 09:47:08 +02002349 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002350 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002351 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002352
2353 if (anyxml_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002354 anyxml->when = lys_when_dup(ctx, anyxml_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_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002359 uses->grp = uses_orig->grp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002360
2361 if (uses_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002362 uses->when = lys_when_dup(ctx, uses_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002363 }
2364
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002365 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002366 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002367 uses->augment_size = uses_orig->augment_size;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02002368 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Michal Vaskof8c128d2015-08-06 15:25:28 +02002369 if (!uses->child) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002370 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002371 goto error;
2372 }
Michal Vaskof8c128d2015-08-06 15:25:28 +02002373 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002374 break;
2375
Radek Krejci76512572015-08-04 09:47:08 +02002376 case LYS_CASE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002377 if (cs_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002378 cs->when = lys_when_dup(ctx, cs_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002379 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002380 break;
2381
Radek Krejci76512572015-08-04 09:47:08 +02002382 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002383 grp->tpdf_size = grp_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002384 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002385 break;
2386
Radek Krejci76512572015-08-04 09:47:08 +02002387 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002388 rpc->tpdf_size = rpc_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002389 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002390 break;
2391
Radek Krejci76512572015-08-04 09:47:08 +02002392 case LYS_INPUT:
2393 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002394 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002395 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002396 break;
2397
Radek Krejci76512572015-08-04 09:47:08 +02002398 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002399 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002400 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcia01e5432015-06-16 10:35:25 +02002401 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002402
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002403 default:
Radek Krejci00768f42015-06-18 17:04:04 +02002404 /* LY_NODE_AUGMENT */
Michal Vaskod23ce592015-08-06 09:55:37 +02002405 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002406 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002407 }
2408
2409 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002410
2411error:
2412
2413 lys_node_free(retval);
2414 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002415}
2416
Michal Vasko13b15832015-08-19 11:04:48 +02002417void
2418lys_free(struct lys_module *module, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02002419{
Radek Krejcidce51452015-06-16 15:20:08 +02002420 struct ly_ctx *ctx;
2421 int i;
2422
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002423 if (!module) {
2424 return;
2425 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002426
Radek Krejcidce51452015-06-16 15:20:08 +02002427 /* remove schema from the context */
2428 ctx = module->ctx;
2429 if (ctx->models.used) {
2430 for (i = 0; i < ctx->models.used; i++) {
2431 if (ctx->models.list[i] == module) {
2432 /* replace the position in the list by the last module in the list */
2433 ctx->models.used--;
2434 ctx->models.list[i] = ctx->models.list[ctx->models.used];
2435 ctx->models.list[ctx->models.used] = NULL;
2436 /* we are done */
2437 break;
2438 }
2439 }
2440 }
2441
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002442 /* common part with struct ly_submodule */
Michal Vasko13b15832015-08-19 11:04:48 +02002443 module_free_common(module, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02002444
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002445 /* specific items to free */
2446 lydict_remove(module->ctx, module->ns);
2447 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02002448
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002449 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002450}
Radek Krejci7e97c352015-06-19 16:26:34 +02002451
2452/*
2453 * op: 1 - enable, 0 - disable
2454 */
2455static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002456lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002457{
2458 int all = 0;
2459 int i, j, k;
2460
2461 if (!module || !name || !strlen(name)) {
2462 return EXIT_FAILURE;
2463 }
2464
2465 if (!strcmp(name, "*")) {
2466 /* enable all */
2467 all = 1;
2468 }
2469
2470 /* module itself */
2471 for (i = 0; i < module->features_size; i++) {
2472 if (all || !strcmp(module->features[i].name, name)) {
2473 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002474 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002475 /* enable referenced features (recursion) */
2476 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002477 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002478 module->features[i].features[k]->name, op);
2479 }
2480 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002481 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002482 }
2483 if (!all) {
2484 return EXIT_SUCCESS;
2485 }
2486 }
2487 }
2488
2489 /* submodules */
2490 for (j = 0; j < module->inc_size; j++) {
2491 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2492 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2493 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002494 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002495 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002496 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002497 }
2498 if (!all) {
2499 return EXIT_SUCCESS;
2500 }
2501 }
2502 }
2503 }
2504
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002505 /* TODO submodules of submodules ... */
2506
Radek Krejci7e97c352015-06-19 16:26:34 +02002507 if (all) {
2508 return EXIT_SUCCESS;
2509 } else {
2510 return EXIT_FAILURE;
2511 }
2512}
2513
2514API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002515lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002516{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002517 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002518}
2519
2520API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002521lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002522{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002523 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002524}
2525
2526API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002527lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002528{
2529 int i, j;
2530
2531 if (!module || !feature) {
2532 return -1;
2533 }
2534
2535 /* search for the specified feature */
2536 /* module itself */
2537 for (i = 0; i < module->features_size; i++) {
2538 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002539 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002540 return 1;
2541 } else {
2542 return 0;
2543 }
2544 }
2545 }
2546
2547 /* submodules */
2548 for (j = 0; j < module->inc_size; j++) {
2549 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2550 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002551 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002552 return 1;
2553 } else {
2554 return 0;
2555 }
2556 }
2557 }
2558 }
2559
2560 /* TODO submodules of submodules ... */
2561
2562 /* feature definition not found */
2563 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002564}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002565
Radek Krejci96a10da2015-07-30 11:00:14 +02002566API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01002567lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002568{
Radek Krejci96a10da2015-07-30 11:00:14 +02002569 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002570 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002571 unsigned int count;
2572
2573 if (!module) {
2574 return NULL;
2575 }
2576
2577 count = module->features_size;
2578 for (i = 0; i < module->inc_size; i++) {
2579 count += module->inc[i].submodule->features_size;
2580 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002581 result = malloc((count + 1) * sizeof *result);
2582 if (states) {
2583 *states = malloc((count + 1) * sizeof **states);
Michal Vasko2367e7c2015-07-07 11:33:44 +02002584 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002585 count = 0;
2586
2587 /* module itself */
2588 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002589 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002590 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002591 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002592 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002593 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002594 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002595 }
2596 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002597 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002598 }
2599
2600 /* submodules */
2601 for (j = 0; j < module->inc_size; j++) {
2602 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002603 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002604 if (states) {
2605 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2606 (*states)[count] = 1;
2607 } else {
2608 (*states)[count] = 0;
2609 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002610 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002611 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002612 }
2613 }
2614
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002615 /* TODO submodules of submodules ... */
2616
2617 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002618 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002619
2620 return result;
2621}
Michal Vaskobaefb032015-09-24 14:52:10 +02002622
2623API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002624lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02002625{
2626 if (!node || !node->parent) {
2627 return NULL;
2628 }
2629
2630 if (node->parent->nodetype == LYS_AUGMENT) {
2631 return ((struct lys_node_augment *)node->parent)->target;
2632 }
2633
2634 return node->parent;
2635}