blob: 69914328ccf9642c6c0d8f8b35c5d0313ab10f74 [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>
Michal Vasko662610a2015-12-07 11:25:45 +010028#include <sys/types.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020029#include <sys/stat.h>
Michal Vasko662610a2015-12-07 11:25:45 +010030#include <fcntl.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020031#include <string.h>
Michal Vasko662610a2015-12-07 11:25:45 +010032#include <unistd.h>
33#include <errno.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020034
35#include "common.h"
36#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020037#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020038#include "resolve.h"
Michal Vasko88c29542015-11-27 14:57:53 +010039#include "xml.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020040#include "xml_internal.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020041#include "tree_internal.h"
Radek Krejcieab784a2015-08-27 09:56:53 +020042#include "validation.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020043
Michal Vasko1e62a092015-12-01 12:27:20 +010044API const struct lys_feature *
45lys_is_disabled(const struct lys_node *node, int recursive)
Radek Krejci48061fb2015-08-05 15:41:07 +020046{
47 int i;
48
49check:
50 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
51 /* input/output does not have if-feature, so skip them */
52
53 /* check local if-features */
54 for (i = 0; i < node->features_size; i++) {
55 if (!(node->features[i]->flags & LYS_FENABLED)) {
56 return node->features[i];
57 }
58 }
59 }
60
61 if (!recursive) {
62 return NULL;
63 }
64
65 /* go through parents */
66 if (node->nodetype == LYS_AUGMENT) {
67 /* go to parent actually means go to the target node */
68 node = ((struct lys_node_augment *)node)->target;
Radek Krejci48061fb2015-08-05 15:41:07 +020069 } else if (node->parent) {
70 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020071 } else {
72 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020073 }
74
Radek Krejci074bf852015-08-19 14:22:16 +020075 if (recursive == 2) {
76 /* continue only if the node cannot have a data instance */
77 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
78 return NULL;
79 }
80 }
81 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020082}
83
Michal Vasko1dca6882015-10-22 14:29:42 +020084int
Michal Vasko36cbaa42015-12-14 13:15:48 +010085lys_get_sibling(const struct lys_node *siblings, const char *mod_name, int mod_name_len, const char *name,
86 int nam_len, LYS_NODE type, const struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +020087{
Radek Krejcic071c542016-01-27 14:57:51 +010088 const struct lys_node *node, *parent = NULL;
89 const struct lys_module *mod = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +010090 const char *node_mod_name;
Michal Vasko1dca6882015-10-22 14:29:42 +020091
Michal Vasko36cbaa42015-12-14 13:15:48 +010092 assert(siblings && mod_name && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +020093 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +020094
Michal Vasko36cbaa42015-12-14 13:15:48 +010095 /* fill the lengths in case the caller is so indifferent */
96 if (!mod_name_len) {
97 mod_name_len = strlen(mod_name);
98 }
Michal Vasko1dca6882015-10-22 14:29:42 +020099 if (!nam_len) {
100 nam_len = strlen(name);
101 }
102
Michal Vasko36cbaa42015-12-14 13:15:48 +0100103 /* set mod correctly */
Radek Krejcic071c542016-01-27 14:57:51 +0100104 parent = lys_parent(siblings);
105 if (!parent) {
Michal Vasko36cbaa42015-12-14 13:15:48 +0100106 mod = siblings->module;
Michal Vasko1dca6882015-10-22 14:29:42 +0200107 }
108
Radek Krejcic071c542016-01-27 14:57:51 +0100109 /* try to find the node */
110 node = NULL;
111 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
112 if (!type || (node->nodetype & type)) {
113 /* modules need to always be checked, we want to skip augments (no other reason to check them) */
114 if (node->module->type) {
115 node_mod_name = ((struct lys_submodule *)node->module)->belongsto->name;
116 } else {
117 node_mod_name = node->module->name;
118 }
119 if (strncmp(node_mod_name, mod_name, mod_name_len) || node_mod_name[mod_name_len]) {
120 continue;
121 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200122
Radek Krejcic071c542016-01-27 14:57:51 +0100123 /* direct name check */
124 if ((node->name == name) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
125 if (ret) {
126 *ret = node;
Michal Vasko1dca6882015-10-22 14:29:42 +0200127 }
Radek Krejcic071c542016-01-27 14:57:51 +0100128 return EXIT_SUCCESS;
Michal Vasko1dca6882015-10-22 14:29:42 +0200129 }
130 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200131 }
132
133 return EXIT_FAILURE;
134}
135
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200136int
Michal Vasko1e62a092015-12-01 12:27:20 +0100137lys_get_data_sibling(const struct lys_module *mod, const struct lys_node *siblings, const char *name, LYS_NODE type,
138 const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200139{
Michal Vasko1e62a092015-12-01 12:27:20 +0100140 const struct lys_node *node;
141 const struct lys_module *cur_mod;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200142 int in_submod;
143
144 assert(siblings && name);
145 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
146
147 /* find the beginning */
148 while (siblings->prev->next) {
149 siblings = siblings->prev;
150 }
151
152 /* we start with the module itself, submodules come later */
153 in_submod = 0;
154
155 if (!mod) {
156 mod = siblings->module;
157 }
158 cur_mod = mod;
159
160 while (1) {
161 /* try to find the node */
162 node = NULL;
163 while ((node = lys_getnext(node, siblings->parent, cur_mod, 0))) {
164 if (!type || (node->nodetype & type)) {
165 /* module check */
166 if (!node->module->type) {
167 if (cur_mod != node->module) {
168 continue;
169 }
170 } else {
171 /* both are submodules */
172 if (cur_mod->type) {
173 if (cur_mod != node->module) {
174 continue;
175 }
176 } else {
177 if (cur_mod != ((struct lys_submodule *)node->module)->belongsto) {
178 continue;
179 }
180 }
181 }
182
183 /* direct name check */
184 if ((node->name == name) || !strcmp(node->name, name)) {
185 if (ret) {
186 *ret = node;
187 }
188 return EXIT_SUCCESS;
189 }
190 }
191 }
192
193 /* we're not top-level, search ended */
194 if (siblings->parent) {
195 break;
196 }
197
198 /* let's try the submodules */
Radek Krejcic071c542016-01-27 14:57:51 +0100199 while(in_submod != mod->inc_size) {
200 if (!mod->inc[in_submod].submodule) {
201 in_submod++;
202 continue;
203 }
204
205 cur_mod = (struct lys_module *)mod->inc[in_submod].submodule;
206 siblings = cur_mod->data;
207 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200208 if (in_submod == mod->inc_size) {
209 break;
210 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200211 ++in_submod;
212 }
213
214 return EXIT_FAILURE;
215}
216
Michal Vasko1e62a092015-12-01 12:27:20 +0100217API const struct lys_node *
218lys_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 +0200219{
Michal Vasko1e62a092015-12-01 12:27:20 +0100220 const struct lys_node *next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200221
Radek Krejci8bc87f62015-09-02 16:19:05 +0200222 if (!last) {
223 /* first call */
224
225 /* get know where to start */
226 if (parent) {
227 /* schema subtree */
228 next = last = parent->child;
229 } else {
230 /* top level data */
231 assert(module);
232 next = last = module->data;
233 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200234 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200235 /* continue after the last returned value */
236 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200237 }
238
239repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200240 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200241 if (options & LYS_GETNEXT_WITHGROUPING) {
242 return next;
243 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200244 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200245 }
246
Radek Krejcic4ccbd92016-01-07 13:13:33 +0100247 if (!next) {
Michal Vasko7c386e72015-10-07 15:13:33 +0200248 if (lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200249 /* no next element */
250 return NULL;
251 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200252 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200253 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200254 goto repeat;
255 }
256
257 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200258 case LYS_INPUT:
259 case LYS_OUTPUT:
260 if (options & LYS_GETNEXT_WITHINOUT) {
261 return next;
262 } else {
263 next = next->child;
264 goto repeat;
265 }
266 break;
267
Michal Vaskoa5835e92015-10-20 15:07:39 +0200268 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200269 if (options & LYS_GETNEXT_WITHCASE) {
270 return next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200271 } else {
272 next = next->child;
273 goto repeat;
Michal Vasko1dca6882015-10-22 14:29:42 +0200274 }
Michal Vaskob6eedf02015-10-22 16:07:03 +0200275 break;
276
Michal Vasko1dca6882015-10-22 14:29:42 +0200277 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200278 /* go into */
279 next = next->child;
280 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200281
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200282 case LYS_RPC:
283 case LYS_NOTIF:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200284 case LYS_CONTAINER:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200285 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200286 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200287 case LYS_LIST:
288 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200289 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200290
291 case LYS_CHOICE:
292 if (options & LYS_GETNEXT_WITHCHOICE) {
293 return next;
294 } else {
295 /* go into */
296 next = next->child;
297 goto repeat;
298 }
299 break;
300
Radek Krejci7f40ce32015-08-12 20:38:46 +0200301 default:
302 /* we should not be here */
303 return NULL;
304 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200305
306
307}
308
Michal Vasko1e62a092015-12-01 12:27:20 +0100309static const struct lys_node *
Radek Krejci2342cf62016-01-29 16:48:23 +0100310check_mand_getnext(const struct lys_node *last, const struct lys_node *parent, const struct lys_module *module)
Radek Krejci8bc87f62015-09-02 16:19:05 +0200311{
Michal Vasko1e62a092015-12-01 12:27:20 +0100312 const struct lys_node *next;
313
Radek Krejci2342cf62016-01-29 16:48:23 +0100314 next = lys_getnext(last, parent, module, LYS_GETNEXT_WITHCHOICE);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200315
Radek Krejci4b6c2112015-10-06 12:48:34 +0200316repeat:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200317 if (next && next->nodetype == LYS_CONTAINER) {
318 if (((struct lys_node_container *)next)->presence) {
319 /* mandatory elements under the non-existing presence
320 * container are not mandatory - 7.6.5, rule 1 */
321 next = next->next;
322 } else {
323 /* go into */
324 next = next->child;
325 }
326 goto repeat;
327 }
328
329 return next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200330}
331
Michal Vasko1e62a092015-12-01 12:27:20 +0100332static const struct lys_node *
333check_mand_check(const struct lys_node *node, const struct lys_node *stop, const struct lyd_node *data)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200334{
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200335 struct lys_node *siter = NULL, *parent = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200336 struct lyd_node *diter = NULL;
Radek Krejcidc154432016-01-21 11:10:59 +0100337 struct ly_set *set = NULL;
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200338 unsigned int i;
Radek Krejci14a11a62015-08-17 17:27:38 +0200339 uint32_t minmax;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200340
341 if (node->flags & LYS_MAND_TRUE) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100342 if (!data) {
343 /* we have no data but a mandatory node */
344 return node;
345 }
346 switch (node->nodetype) {
347 case LYS_LEAF:
348 case LYS_ANYXML:
349 case LYS_CHOICE:
350 if (node->parent && node->parent->nodetype == LYS_CASE) {
351 /* 7.6.5, rule 2 */
352 /* 7.9.4, rule 1 */
353 if (node->parent->parent->parent == data->schema) {
354 /* the only case the node's siblings can exist is that the
355 * data node passed originally to ly_check_mandatory()
356 * had this choice as a child
357 */
358 /* try to find the node's siblings in data */
359 LY_TREE_FOR(data->child, diter) {
360 LY_TREE_FOR(node->parent->child, siter) {
361 if (siter == diter->schema) {
362 /* some sibling exists, rule applies */
363 break;
364 }
365 }
366 if (siter) {
367 break;
368 }
369 }
370 }
371 if (!siter) {
372 /* no sibling exists */
373 return NULL;
374 }
375 } else {
Radek Krejci7eb12132016-02-01 10:55:23 +0100376 for (parent = node->parent; parent && parent != stop; parent = parent->parent) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100377 if (parent->nodetype != LYS_CONTAINER) {
378 /* 7.6.5, rule 1, checking presence is not needed
379 * since it is done in check_mand_getnext()
380 */
381 ly_set_free(set);
382 return NULL;
383 }
384 /* add the parent to the list for searching in data tree */
385 if (!set) {
386 set = ly_set_new();
387 }
388 /* ignore return - memory error is logged and we will
389 * check at least the rest of nodes we have */
390 (void)ly_set_add(set, parent);
391 }
392 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200393
Radek Krejci2342cf62016-01-29 16:48:23 +0100394 /* search for instance */
395 if (set) {
396 for (i = 0; i < set->number; i++) {
397 LY_TREE_FOR(data->child, diter) {
398 if (diter->schema == set->sset[i]) {
399 break;
400 }
401 }
402 if (!diter) {
403 /* instance not found */
404 node = set->sset[i];
405 ly_set_free(set);
406 return node;
407 }
408 data = diter;
409 }
410 ly_set_free(set);
411 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200412
Radek Krejci2342cf62016-01-29 16:48:23 +0100413 LY_TREE_FOR(data->child, diter) {
414 if (diter->schema == node) {
415 return NULL;
416 }
417 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200418
Radek Krejci2342cf62016-01-29 16:48:23 +0100419 /* instance not found */
420 /* 7.6.5, rule 3 (or 2) */
421 /* 7.9.4, rule 2 */
422 return node;
423 default:
424 /* error */
425 break;
426 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200427 } else if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
428 /* search for number of instances */
429 minmax = 0;
Radek Krejci2342cf62016-01-29 16:48:23 +0100430 if (data) {
431 LY_TREE_FOR(data->child, diter) {
432 if (diter->schema == node) {
433 minmax++;
434 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200435 }
436 }
437
438 /* check the specified constraints */
439 if (node->nodetype == LYS_LIST) {
440 if (((struct lys_node_list *)node)->min && minmax < ((struct lys_node_list *)node)->min) {
441 return node;
442 }
443
444 if (((struct lys_node_list *)node)->max && minmax > ((struct lys_node_list *)node)->max) {
445 return node;
446 }
447 } else if (node->nodetype == LYS_LEAFLIST) {
448 if (((struct lys_node_leaflist *)node)->min && minmax < ((struct lys_node_leaflist *)node)->min) {
449 return node;
450 }
451
452 if (((struct lys_node_leaflist *)node)->max && minmax > ((struct lys_node_leaflist *)node)->max) {
453 return node;
454 }
455 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200456 }
457
458 return NULL;
459}
460
Michal Vasko1e62a092015-12-01 12:27:20 +0100461const struct lys_node *
Radek Krejci2342cf62016-01-29 16:48:23 +0100462ly_check_mandatory(const struct lyd_node *data, const struct lys_node *schema)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200463{
Michal Vasko1e62a092015-12-01 12:27:20 +0100464 const struct lys_node *siter, *saux, *saux2, *result, *parent = NULL, *parent2;
465 const struct lyd_node *diter;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200466 int found;
467
Radek Krejci2342cf62016-01-29 16:48:23 +0100468 assert(data || schema);
469
470 if (!data) { /* !data && schema */
471 siter = schema;
472 } else { /* data && !schema */
473 schema = siter = data->schema->child;
474 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200475
476repeat:
477 while (siter) {
Radek Krejci074bf852015-08-19 14:22:16 +0200478 if (lys_is_disabled(siter, 2)) {
479 siter = siter->next;
480 continue;
481 }
482
Radek Krejci7f40ce32015-08-12 20:38:46 +0200483 switch (siter->nodetype) {
484 case LYS_CONTAINER:
485 case LYS_LEAF:
486 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200487 case LYS_LIST:
488 case LYS_LEAFLIST:
489 /* check if there is some mandatory node; first test the siter itself ... */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200490 result = check_mand_check(siter, siter->parent, data);
491 if (result) {
492 return result;
493 }
494 /* ... and then the subtree */
Radek Krejci14a11a62015-08-17 17:27:38 +0200495 if (parent && siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
496 saux = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100497 while ((saux = check_mand_getnext(saux, siter, NULL))) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200498 result = check_mand_check(saux, siter, data);
499 if (result) {
500 return result;
501 }
502 }
503 }
504 siter = siter->next;
505 break;
506 case LYS_CHOICE:
Radek Krejci14a11a62015-08-17 17:27:38 +0200507 /* search for instance */
508 saux = siter;
509 siter = siter->child;
510 found = 0;
511 parent2 = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200512repeat_choice:
Radek Krejci2342cf62016-01-29 16:48:23 +0100513 while (siter && data) {
Radek Krejci074bf852015-08-19 14:22:16 +0200514 if (lys_is_disabled(siter, 2)) {
515 siter = siter->next;
516 continue;
517 }
518
Radek Krejci14a11a62015-08-17 17:27:38 +0200519 switch (siter->nodetype) {
520 case LYS_CONTAINER:
521 case LYS_LEAF:
522 case LYS_LEAFLIST:
523 case LYS_LIST:
524 case LYS_ANYXML:
525 LY_TREE_FOR(data->child, diter) {
526 if (diter->schema == siter) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200527 break;
528 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200529 }
530 if (diter) {
531 /* got instance */
532 /* check presence of mandatory siblings */
Radek Krejci65d0a652015-08-27 13:09:42 +0200533 if (parent2 && parent2->nodetype == LYS_CASE) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200534 saux2 = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100535 while ((saux2 = check_mand_getnext(saux2, parent2, NULL))) {
Radek Krejci37bda002015-08-27 11:23:56 +0200536 result = check_mand_check(saux2, parent2, data);
Radek Krejci14a11a62015-08-17 17:27:38 +0200537 if (result) {
538 return result;
539 }
540 }
541 }
542 siter = parent2 = NULL;
543 found = 1;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200544 break;
545 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200546 siter = siter->next;
547 break;
548 case LYS_CASE:
549 case LYS_CHOICE:
550 case LYS_USES:
551 /* go into */
Radek Krejci37bda002015-08-27 11:23:56 +0200552 if (!parent2) {
553 parent2 = siter;
554 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200555 siter = siter->child;
556 break;
557 case LYS_AUGMENT:
558 case LYS_GROUPING:
559 /* skip */
560 siter = siter->next;
561 break;
562 default:
563 /* error */
564 break;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200565 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200566 }
567
Radek Krejci14a11a62015-08-17 17:27:38 +0200568 if (parent2) {
569 siter = parent2->next;
570 if (parent2->parent == saux) {
571 parent2 = NULL;
572 } else {
573 parent2 = parent2->parent;
574 }
575 goto repeat_choice;
576 }
577
Radek Krejci074bf852015-08-19 14:22:16 +0200578 if (!found && (saux->flags & LYS_MAND_TRUE)) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200579 return saux;
580 }
581
582 /* go to next */
583 siter = saux->next;
584
Radek Krejci7f40ce32015-08-12 20:38:46 +0200585 break;
586 case LYS_USES:
587 case LYS_CASE:
588 /* go into */
589 parent = siter;
590 siter = siter->child;
591 break;
592 default:
593 /* can ignore, go to next */
594 siter = siter->next;
595 break;
596 }
597 }
598
599 if (parent) {
600 siter = parent->next;
Radek Krejci2342cf62016-01-29 16:48:23 +0100601 if (parent->parent == schema) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200602 parent = NULL;
603 } else {
604 parent = parent->parent;
605 }
606 goto repeat;
607 }
608
609 return NULL;
610}
611
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200612void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200613lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200614{
Radek Krejci76512572015-08-04 09:47:08 +0200615 struct lys_node *parent, *first;
Radek Krejcic071c542016-01-27 14:57:51 +0100616 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200617
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200618 if (!node) {
619 return;
620 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200621
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200622 /* unlink from data model if necessary */
623 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100624 /* get main module with data tree */
625 for (main_module = node->module; main_module->type; main_module = ((struct lys_submodule *)main_module)->belongsto);
626 if (main_module->data == node) {
627 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200628 }
629 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200630
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200631 /* store pointers to important nodes */
632 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200633 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200634 /* handle augments - first, unlink it from the augment parent ... */
635 if (parent->child == node) {
636 parent->child = node->next;
637 }
638 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200639 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200640 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200641
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200642 /* unlink from parent */
643 if (parent) {
644 if (parent->child == node) {
645 parent->child = node->next;
646 }
647 node->parent = NULL;
648 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200649
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200650 /* unlink from siblings */
651 if (node->prev == node) {
652 /* there are no more siblings */
653 return;
654 }
655 if (node->next) {
656 node->next->prev = node->prev;
657 } else {
658 /* unlinking the last element */
659 if (parent) {
660 first = parent->child;
661 } else {
662 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200663 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200664 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200665 }
666 }
667 first->prev = node->prev;
668 }
669 if (node->prev->next) {
670 node->prev->next = node->next;
671 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200672
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200673 /* clean up the unlinked element */
674 node->next = NULL;
675 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200676}
677
Michal Vasko563ef092015-09-04 13:17:23 +0200678struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100679lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200680{
681 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200682
683 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200684 /* top-level augment, look into module (uses augment is handled correctly below) */
685 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
686 par_iter = par_iter->parent->module->data;
687 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200688 break;
689 }
690 }
691
Michal Vasko6f929da2015-10-02 16:23:25 +0200692 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200693 continue;
694 }
695
696 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
697 if (!stop) {
698 stop = par_iter;
699 } else if (iter == stop) {
700 break;
701 }
702 if (iter->nodetype != LYS_GROUPING) {
703 continue;
704 }
705
Radek Krejcif8426a72015-10-31 23:14:03 +0100706 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200707 return (struct lys_node_grp *)iter;
708 }
709 }
710 }
711
Michal Vasko563ef092015-09-04 13:17:23 +0200712 return NULL;
713}
714
Radek Krejci10c760e2015-08-14 14:45:43 +0200715/*
716 * get next grouping in the root's subtree, in the
717 * first call, tha last is NULL
718 */
719static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200720lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200721{
Radek Krejci10c760e2015-08-14 14:45:43 +0200722 struct lys_node *last = (struct lys_node *)lastgrp;
723 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200724
Radek Krejci10c760e2015-08-14 14:45:43 +0200725 assert(root);
726
727 if (!last) {
728 last = root;
729 }
730
731 while (1) {
732 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
733 next = last->child;
734 } else {
735 next = NULL;
736 }
737 if (!next) {
738 if (last == root) {
739 /* we are done */
740 return NULL;
741 }
742
743 /* no children, go to siblings */
744 next = last->next;
745 }
746 while (!next) {
747 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100748 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200749 /* we are done */
750 return NULL;
751 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200752 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100753 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200754 }
755
756 if (next->nodetype == LYS_GROUPING) {
757 return (struct lys_node_grp *)next;
758 }
759
760 last = next;
761 }
762}
763
Michal Vasko0d343d12015-08-24 14:57:36 +0200764/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200765int
Radek Krejci07911992015-08-14 15:13:31 +0200766lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
767{
Michal Vasko563ef092015-09-04 13:17:23 +0200768 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200769 struct lys_node_grp *grp;
770 int down;
771
772 assert(node);
773
774 if (!parent) {
775 assert(module);
776 } else {
777 module = parent->module;
778 }
779
780 switch (node->nodetype) {
781 case LYS_GROUPING:
782 /* 6.2.1, rule 6 */
783 if (parent) {
784 if (parent->child) {
785 down = 1;
786 start = parent->child;
787 } else {
788 down = 0;
789 start = parent;
790 }
791 } else {
792 down = 1;
793 start = module->data;
794 }
795 /* go up */
Radek Krejcic071c542016-01-27 14:57:51 +0100796 if (lys_find_grouping_up(node->name, start)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200797 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
798 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200799 }
800 /* go down, because grouping can be defined after e.g. container in which is collision */
801 if (down) {
802 for (iter = start, stop = NULL; iter; iter = iter->prev) {
803 if (!stop) {
804 stop = start;
805 } else if (iter == stop) {
806 break;
807 }
808 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
809 continue;
810 }
811
812 grp = NULL;
813 while ((grp = lys_get_next_grouping(grp, iter))) {
814 if (node->name == grp->name) {
815 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
816 return EXIT_FAILURE;
817 }
818 }
819 }
820 }
821 break;
822 case LYS_LEAF:
823 case LYS_LEAFLIST:
824 case LYS_LIST:
825 case LYS_CONTAINER:
826 case LYS_CHOICE:
827 case LYS_ANYXML:
828 /* 6.2.1, rule 7 */
829 if (parent) {
830 iter = parent;
831 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE))) {
832 iter = iter->parent;
833 }
834 if (!iter) {
835 stop = NULL;
836 iter = module->data;
837 } else {
838 stop = iter;
839 iter = iter->child;
840 }
841 } else {
842 stop = NULL;
843 iter = module->data;
844 }
845 while (iter) {
846 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
847 iter = iter->child;
848 continue;
849 }
850
851 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
852 if (iter->module == node->module && iter->name == node->name) {
853 LOGVAL(LYE_SPEC, 0, "Duplicated child identifier \"%s\" in \"%s\".", node->name,
854 stop ? stop->name : "(sub)module");
855 return EXIT_FAILURE;
856 }
857 }
858
859 /* special case for choice - we must check the choice's name as
860 * well as the names of nodes under the choice
861 */
862 if (iter->nodetype == LYS_CHOICE) {
863 iter = iter->child;
864 continue;
865 }
866
867 /* go to siblings */
868 if (!iter->next) {
869 /* no sibling, go to parent's sibling */
870 do {
871 iter = iter->parent;
872 if (iter && iter->next) {
873 break;
874 }
875 } while (iter != stop);
876
877 if (iter == stop) {
878 break;
879 }
880 }
881 iter = iter->next;
882 }
883 break;
884 case LYS_CASE:
885 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100886 if (parent) {
887 start = parent->child;
888 } else {
889 start = module->data;
890 }
891
892 LY_TREE_FOR(start, iter) {
Radek Krejci07911992015-08-14 15:13:31 +0200893 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
894 continue;
895 }
896
897 if (iter->module == node->module && iter->name == node->name) {
898 LOGVAL(LYE_DUPID, 0, "case", node->name);
899 return EXIT_FAILURE;
900 }
901 }
902 break;
903 default:
904 /* no check needed */
905 break;
906 }
907
908 return EXIT_SUCCESS;
909}
910
Michal Vasko0d343d12015-08-24 14:57:36 +0200911/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200912int
Radek Krejci10c760e2015-08-14 14:45:43 +0200913lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
914{
Radek Krejci92720552015-10-05 15:28:27 +0200915 struct lys_node *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200916 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200917
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200918 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200919
Radek Krejci10c760e2015-08-14 14:45:43 +0200920 if (parent) {
921 type = parent->nodetype;
922 module = parent->module;
923 } else {
924 assert(module);
925 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200926 }
927
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200928 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200929 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200930 case LYS_CONTAINER:
931 case LYS_LIST:
932 case LYS_GROUPING:
933 case LYS_USES:
934 case LYS_INPUT:
935 case LYS_OUTPUT:
936 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200937 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200938 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
939 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200940 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200941 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
942 return EXIT_FAILURE;
943 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200944
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200945 break;
Radek Krejci76512572015-08-04 09:47:08 +0200946 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200947 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200948 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200949 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"choice\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200950 strnodetype(child->nodetype), parent->name);
951 return EXIT_FAILURE;
952 }
953 break;
Radek Krejci76512572015-08-04 09:47:08 +0200954 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200955 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200956 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200957 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"case\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200958 strnodetype(child->nodetype), parent->name);
959 return EXIT_FAILURE;
960 }
961 break;
Radek Krejci76512572015-08-04 09:47:08 +0200962 case LYS_RPC:
963 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200964 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"rpc\" %s.",
Michal Vasko38d01f72015-06-15 09:41:06 +0200965 strnodetype(child->nodetype), parent->name);
966 return EXIT_FAILURE;
967 }
968 break;
Radek Krejci76512572015-08-04 09:47:08 +0200969 case LYS_LEAF:
970 case LYS_LEAFLIST:
971 case LYS_ANYXML:
Radek Krejci10c760e2015-08-14 14:45:43 +0200972 LOGVAL(LYE_SPEC, 0, "The \"%s\" statement (%s) cannot have any data substatement.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200973 strnodetype(parent->nodetype), parent->name);
974 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200975 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200976 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200977 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
978 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200979 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200980 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
981 return EXIT_FAILURE;
982 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200983 break;
984 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200985 /* top level */
986 if (!(child->nodetype &
987 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
988 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci2c0ca272015-08-14 15:31:01 +0200989 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in (sub)module \"%s\"",
990 strnodetype(child->nodetype), module->name);
Radek Krejci10c760e2015-08-14 14:45:43 +0200991 return EXIT_FAILURE;
992 }
993
Radek Krejcic071c542016-01-27 14:57:51 +0100994 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200995 }
996
997 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200998 if (lys_check_id(child, parent, module)) {
999 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001000 }
Radek Krejcib7155b52015-06-10 17:03:01 +02001001
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001002 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001003 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001004 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001005
Radek Krejci10c760e2015-08-14 14:45:43 +02001006 if (!parent) {
Radek Krejci92720552015-10-05 15:28:27 +02001007 if (module->data) {
1008 module->data->prev->next = child;
1009 child->prev = module->data->prev;
1010 module->data->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +02001011 } else {
Radek Krejci92720552015-10-05 15:28:27 +02001012 module->data = child;
Radek Krejci10c760e2015-08-14 14:45:43 +02001013 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001014 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +02001015 if (!parent->child) {
1016 /* the only/first child of the parent */
1017 parent->child = child;
1018 child->parent = parent;
1019 iter = child;
1020 } else {
1021 /* add a new child at the end of parent's child list */
1022 iter = parent->child->prev;
1023 iter->next = child;
1024 child->prev = iter;
1025 }
1026 while (iter->next) {
1027 iter = iter->next;
1028 iter->parent = parent;
1029 }
1030 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001031 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001032
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001033 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001034}
1035
Michal Vasko1e62a092015-12-01 12:27:20 +01001036API const struct lys_module *
Radek Krejci722b0072016-02-01 17:09:45 +01001037lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001038{
Radek Krejci0b5805d2015-08-13 09:38:02 +02001039 struct lys_module *mod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001040
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001041 if (!ctx || !data) {
1042 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1043 return NULL;
1044 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001045
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001046 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001047 case LYS_IN_YIN:
Radek Krejcic071c542016-01-27 14:57:51 +01001048 mod = yin_read_module(ctx, data, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001049 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001050 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001051 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001052 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001053 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001054 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001055
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001056 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001057}
1058
Radek Krejcib8048692015-08-05 13:36:34 +02001059struct lys_submodule *
Radek Krejcic071c542016-01-27 14:57:51 +01001060lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001061{
Radek Krejci0b5805d2015-08-13 09:38:02 +02001062 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001063
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001064 assert(module);
1065 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001066
Radek Krejcic071c542016-01-27 14:57:51 +01001067 /* get the main module */
1068 while(module->type) {
1069 module = ((struct lys_submodule *)module)->belongsto;
Michal Vasko253035f2015-12-17 16:58:13 +01001070 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001071
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001072 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001073 case LYS_IN_YIN:
Radek Krejcic071c542016-01-27 14:57:51 +01001074 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001075 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001076 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001077 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001078 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001079 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001080 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001081
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001082 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001083}
1084
Michal Vasko1e62a092015-12-01 12:27:20 +01001085API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +01001086lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1087{
1088 int fd;
1089 const struct lys_module *ret;
1090
1091 if (!ctx || !path) {
1092 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1093 return NULL;
1094 }
1095
1096 fd = open(path, O_RDONLY);
1097 if (fd == -1) {
1098 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
1099 return NULL;
1100 }
1101
1102 ret = lys_parse_fd(ctx, fd, format);
1103 close(fd);
1104 return ret;
1105}
1106
1107API const struct lys_module *
1108lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001109{
Michal Vasko1e62a092015-12-01 12:27:20 +01001110 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +02001111 struct stat sb;
1112 char *addr;
1113
1114 if (!ctx || fd < 0) {
1115 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1116 return NULL;
1117 }
1118
Radek Krejci10a833c2015-12-16 15:28:37 +01001119 if (fstat(fd, &sb) == -1) {
1120 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
1121 return NULL;
1122 }
Radek Krejci3006be02015-12-17 11:24:33 +01001123 addr = mmap(NULL, sb.st_size + 1, PROT_READ, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001124 if (addr == MAP_FAILED) {
Michal Vasko662610a2015-12-07 11:25:45 +01001125 LOGERR(LY_EMEM, "Map file into memory failed (%s()).",__func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001126 return NULL;
1127 }
Radek Krejci722b0072016-02-01 17:09:45 +01001128 module = lys_parse_mem(ctx, addr, format);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001129 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001130
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001131 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001132}
1133
Radek Krejcib8048692015-08-05 13:36:34 +02001134struct lys_submodule *
Radek Krejcic071c542016-01-27 14:57:51 +01001135lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001136{
Radek Krejcib8048692015-08-05 13:36:34 +02001137 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001138 struct stat sb;
1139 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001140
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001141 assert(module);
1142 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001143
Radek Krejci10a833c2015-12-16 15:28:37 +01001144 if (fstat(fd, &sb) == -1) {
1145 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
1146 return NULL;
1147 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001148 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001149 if (addr == MAP_FAILED) {
1150 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
1151 return NULL;
1152 }
Radek Krejcic071c542016-01-27 14:57:51 +01001153 submodule = lys_submodule_parse(module, addr, format, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001154 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +02001155
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001156 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02001157
1158}
1159
Radek Krejci1d82ef62015-08-07 14:44:40 +02001160static struct lys_restr *
1161lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001162{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001163 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001164 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001165
Radek Krejci3733a802015-06-19 13:43:21 +02001166 if (!size) {
1167 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001168 }
Radek Krejci3733a802015-06-19 13:43:21 +02001169
1170 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001171 if (!result) {
1172 return NULL;
1173 }
Radek Krejci3733a802015-06-19 13:43:21 +02001174 for (i = 0; i < size; i++) {
1175 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1176 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1177 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1178 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1179 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1180 }
1181
1182 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001183}
1184
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001185void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001186lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001187{
1188 assert(ctx);
1189 if (!restr) {
1190 return;
1191 }
1192
1193 lydict_remove(ctx, restr->expr);
1194 lydict_remove(ctx, restr->dsc);
1195 lydict_remove(ctx, restr->ref);
1196 lydict_remove(ctx, restr->eapptag);
1197 lydict_remove(ctx, restr->emsg);
1198}
1199
Michal Vaskob84f88a2015-09-24 13:16:10 +02001200static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001201lys_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 +02001202 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001203{
1204 int i;
1205
Michal Vasko1dca6882015-10-22 14:29:42 +02001206 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001207 new->base = old->base;
1208 new->der = old->der;
1209
Michal Vasko0bd29d12015-08-19 11:45:49 +02001210 i = unres_schema_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001211 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001212 /* HACK (serious one) for unres */
1213 /* nothing else we can do but duplicate it immediately */
1214 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
Radek Krejcic071c542016-01-27 14:57:51 +01001215 new->parent = (struct lys_tpdf *)parent;
Michal Vaskob84f88a2015-09-24 13:16:10 +02001216 /* all these unres additions can fail even though they did not before */
Michal Vasko88c29542015-11-27 14:57:53 +01001217 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_DER, parent, 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001218 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001219 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001220 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001221 }
1222
Radek Krejci3733a802015-06-19 13:43:21 +02001223 switch (new->base) {
1224 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +02001225 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001226 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001227 }
Radek Krejci3733a802015-06-19 13:43:21 +02001228 break;
1229
1230 case LY_TYPE_BITS:
1231 new->info.bits.count = old->info.bits.count;
1232 if (new->info.bits.count) {
1233 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +01001234 if (!new->info.bits.bit) {
1235 LOGMEM;
1236 return -1;
1237 }
Radek Krejci3733a802015-06-19 13:43:21 +02001238 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001239 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1240 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1241 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001242 new->info.bits.bit[i].status = old->info.bits.bit[i].status;
1243 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1244 }
1245 }
1246 break;
1247
Radek Krejcif9401c32015-06-26 16:47:36 +02001248 case LY_TYPE_DEC64:
1249 new->info.dec64.dig = old->info.dec64.dig;
1250 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001251 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +02001252 }
1253 break;
1254
Radek Krejci3733a802015-06-19 13:43:21 +02001255 case LY_TYPE_ENUM:
1256 new->info.enums.count = old->info.enums.count;
1257 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001258 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +01001259 if (!new->info.enums.enm) {
1260 LOGMEM;
1261 return -1;
1262 }
Radek Krejci3733a802015-06-19 13:43:21 +02001263 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001264 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1265 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1266 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1267 new->info.enums.enm[i].status = old->info.enums.enm[i].status;
1268 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +02001269 }
1270 }
1271 break;
1272
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001273 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001274 if (old->info.ident.ref) {
1275 new->info.ident.ref = old->info.ident.ref;
1276 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001277 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001278 assert(i != -1);
Michal Vasko88c29542015-11-27 14:57:53 +01001279 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i], 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001280 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001281 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001282 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001283 break;
1284
Radek Krejciaf351422015-06-19 14:49:38 +02001285 case LY_TYPE_INST:
1286 new->info.inst.req = old->info.inst.req;
1287 break;
1288
Radek Krejcif2860132015-06-20 12:37:20 +02001289 case LY_TYPE_INT8:
1290 case LY_TYPE_INT16:
1291 case LY_TYPE_INT32:
1292 case LY_TYPE_INT64:
1293 case LY_TYPE_UINT8:
1294 case LY_TYPE_UINT16:
1295 case LY_TYPE_UINT32:
1296 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +02001297 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001298 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001299 }
Radek Krejcif2860132015-06-20 12:37:20 +02001300 break;
1301
Radek Krejcidc4c1412015-06-19 15:39:54 +02001302 case LY_TYPE_LEAFREF:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001303 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko88c29542015-11-27 14:57:53 +01001304 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001305 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001306 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001307 break;
1308
Radek Krejci3733a802015-06-19 13:43:21 +02001309 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +02001310 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001311 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001312 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001313 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 +02001314 break;
1315
Radek Krejcie4c366b2015-07-02 10:11:31 +02001316 case LY_TYPE_UNION:
1317 new->info.uni.count = old->info.uni.count;
1318 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001319 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +01001320 if (!new->info.uni.types) {
1321 LOGMEM;
1322 return -1;
1323 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001324 for (i = 0; i < new->info.uni.count; i++) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001325 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres)) {
1326 return -1;
1327 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001328 }
1329 }
1330 break;
1331
Radek Krejci3733a802015-06-19 13:43:21 +02001332 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001333 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001334 break;
1335 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001336
1337 return EXIT_SUCCESS;
Radek Krejci3733a802015-06-19 13:43:21 +02001338}
1339
1340void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001341lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001342{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001343 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001344
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001345 assert(ctx);
1346 if (!type) {
1347 return;
1348 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001349
Michal Vasko1dca6882015-10-22 14:29:42 +02001350 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001351
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001352 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001353 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001354 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001355 free(type->info.binary.length);
1356 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001357 case LY_TYPE_BITS:
1358 for (i = 0; i < type->info.bits.count; i++) {
1359 lydict_remove(ctx, type->info.bits.bit[i].name);
1360 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1361 lydict_remove(ctx, type->info.bits.bit[i].ref);
1362 }
1363 free(type->info.bits.bit);
1364 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001365
1366 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001367 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001368 free(type->info.dec64.range);
1369 break;
1370
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001371 case LY_TYPE_ENUM:
1372 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001373 lydict_remove(ctx, type->info.enums.enm[i].name);
1374 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1375 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001376 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001377 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001378 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001379
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001380 case LY_TYPE_INT8:
1381 case LY_TYPE_INT16:
1382 case LY_TYPE_INT32:
1383 case LY_TYPE_INT64:
1384 case LY_TYPE_UINT8:
1385 case LY_TYPE_UINT16:
1386 case LY_TYPE_UINT32:
1387 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001388 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001389 free(type->info.num.range);
1390 break;
1391
Radek Krejcidc4c1412015-06-19 15:39:54 +02001392 case LY_TYPE_LEAFREF:
1393 lydict_remove(ctx, type->info.lref.path);
1394 break;
1395
Radek Krejci3733a802015-06-19 13:43:21 +02001396 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001397 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001398 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001399 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001400 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001401 }
1402 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001403 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001404
Radek Krejcie4c366b2015-07-02 10:11:31 +02001405 case LY_TYPE_UNION:
1406 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001407 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001408 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001409 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001410 break;
1411
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001412 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001413 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001414 break;
1415 }
Radek Krejci5a065542015-05-22 15:02:07 +02001416}
1417
Radek Krejci1d82ef62015-08-07 14:44:40 +02001418static void
1419lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001420{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001421 assert(ctx);
1422 if (!tpdf) {
1423 return;
1424 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001425
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001426 lydict_remove(ctx, tpdf->name);
1427 lydict_remove(ctx, tpdf->dsc);
1428 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001429
Radek Krejci1d82ef62015-08-07 14:44:40 +02001430 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001431
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001432 lydict_remove(ctx, tpdf->units);
1433 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001434}
1435
Michal Vaskob84f88a2015-09-24 13:16:10 +02001436static struct lys_tpdf *
1437lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1438{
1439 struct lys_tpdf *result;
1440 int i, j;
1441
1442 if (!size) {
1443 return NULL;
1444 }
1445
1446 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001447 if (!result) {
1448 LOGMEM;
1449 return NULL;
1450 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001451 for (i = 0; i < size; i++) {
1452 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1453 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1454 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1455 result[i].flags = old[i].flags;
1456 result[i].module = old[i].module;
1457
1458 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres)) {
1459 for (j = 0; j <= i; ++j) {
1460 lys_tpdf_free(mod->ctx, &result[j]);
1461 }
1462 free(result);
1463 return NULL;
1464 }
1465
1466 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1467 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1468 }
1469
1470 return result;
1471}
1472
Radek Krejci1d82ef62015-08-07 14:44:40 +02001473static struct lys_when *
1474lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001475{
Radek Krejci76512572015-08-04 09:47:08 +02001476 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001477
1478 if (!old) {
1479 return NULL;
1480 }
1481
1482 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001483 if (!new) {
1484 LOGMEM;
1485 return NULL;
1486 }
Radek Krejci00768f42015-06-18 17:04:04 +02001487 new->cond = lydict_insert(ctx, old->cond, 0);
1488 new->dsc = lydict_insert(ctx, old->dsc, 0);
1489 new->ref = lydict_insert(ctx, old->ref, 0);
1490
1491 return new;
1492}
1493
Michal Vasko0308dd62015-10-07 09:14:40 +02001494void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001495lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001496{
1497 if (!w) {
1498 return;
1499 }
1500
1501 lydict_remove(ctx, w->cond);
1502 lydict_remove(ctx, w->dsc);
1503 lydict_remove(ctx, w->ref);
1504
1505 free(w);
1506}
1507
Radek Krejcib7f5e412015-08-13 10:15:51 +02001508static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001509lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment aug, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcib7f5e412015-08-13 10:15:51 +02001510{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001511 struct lys_node *next, *sub;
1512
Radek Krejcic071c542016-01-27 14:57:51 +01001513 /* children from a resolved augment are freed under the target node */
1514 if (!aug.target) {
1515 LY_TREE_FOR_SAFE(aug.child, next, sub) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001516 lys_node_free(sub, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01001517 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001518 }
1519
Radek Krejcib7f5e412015-08-13 10:15:51 +02001520 lydict_remove(ctx, aug.target_name);
1521 lydict_remove(ctx, aug.dsc);
1522 lydict_remove(ctx, aug.ref);
1523
1524 free(aug.features);
1525
1526 lys_when_free(ctx, aug.when);
1527
Michal Vasko7d356a52015-08-19 15:06:31 +02001528 /* Do not free the children, they were appended somewhere and their
1529 * new parent will take care of them.
1530 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001531}
1532
Radek Krejci76512572015-08-04 09:47:08 +02001533static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001534lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001535{
Radek Krejci76512572015-08-04 09:47:08 +02001536 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001537 struct lys_node *old_child, *new_child;
1538 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001539
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001540 if (!size) {
1541 return NULL;
1542 }
Radek Krejci106efc02015-06-10 14:36:27 +02001543
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001544 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001545 if (!new) {
1546 LOGMEM;
1547 return NULL;
1548 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001549 for (i = 0; i < size; i++) {
1550 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1551 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1552 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1553 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001554 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001555 new[i].nodetype = old[i].nodetype;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001556 /* this must succeed, it was already resolved once */
Michal Vasko3edeaf72016-02-11 13:17:43 +01001557 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL,
1558 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001559 LOGINT;
1560 free(new);
1561 return NULL;
1562 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001563 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001564
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001565 /* Correct the augment nodes.
1566 * This function can only be called from lys_node_dup() with uses
1567 * being the node duplicated, so we must have a case of grouping
1568 * with a uses with augments. The augmented nodes have already been
1569 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001570 * (it was set to their actual data parent, not an augment), and
1571 * the new augment does not have child pointer to its augment nodes,
1572 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001573 */
1574 LY_TREE_FOR(new[i].target->child, new_child) {
1575 if (new_child->name == old[i].child->name) {
1576 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001577 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001578 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001579 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001580 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001581 LY_TREE_FOR(old[i].child, old_child) {
1582 /* all augment nodes were connected as siblings, there can be no more after this */
1583 if (old_child->parent != (struct lys_node *)&old[i]) {
1584 break;
1585 }
1586
1587 assert(old_child->name == new_child->name);
1588
1589 new_child->parent = (struct lys_node *)&new[i];
1590 new_child = new_child->next;
1591 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001592 }
Radek Krejci106efc02015-06-10 14:36:27 +02001593
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001594 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001595}
1596
Radek Krejci76512572015-08-04 09:47:08 +02001597static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001598lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001599{
Radek Krejci76512572015-08-04 09:47:08 +02001600 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001601 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001602
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001603 if (!size) {
1604 return NULL;
1605 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001606
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001607 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001608 if (!result) {
1609 LOGMEM;
1610 return NULL;
1611 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001612 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001613 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001614 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1615 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001616 result[i].flags = old[i].flags;
1617 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001618
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001619 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001620 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001621
Radek Krejci76512572015-08-04 09:47:08 +02001622 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001623 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001624 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001625 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001626 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001627 result[i].mod.list = old[i].mod.list;
1628 }
1629 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001630
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001631 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001632}
1633
Radek Krejci1d82ef62015-08-07 14:44:40 +02001634static void
1635lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001636{
Radek Krejcia52656e2015-08-05 13:41:50 +02001637 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001638
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001639 assert(ctx);
1640 if (!ident) {
1641 return;
1642 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001643
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001644 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001645 * if caller free only a single data model which is used (its identity is
1646 * reference from identity in another module), this silly freeing can lead
1647 * to segmentation fault. But without noting if the module is used by some
1648 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001649 *
1650 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001651 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001652 */
1653 while (ident->der) {
1654 der = ident->der;
1655 ident->der = der->next;
1656 free(der);
1657 }
Radek Krejci6793db02015-05-22 17:49:54 +02001658
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001659 lydict_remove(ctx, ident->name);
1660 lydict_remove(ctx, ident->dsc);
1661 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001662
1663}
1664
Radek Krejci1d82ef62015-08-07 14:44:40 +02001665static void
1666lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001667{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001668 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001669
Radek Krejcid12f57b2015-08-06 10:43:39 +02001670 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001671 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001672 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001673 }
1674 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001675}
1676
Radek Krejci1d82ef62015-08-07 14:44:40 +02001677static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001678lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1679{
1680 int i;
1681
1682 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1683 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001684 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001685 }
1686 free(io->tpdf);
1687}
1688
Radek Krejci1d82ef62015-08-07 14:44:40 +02001689static void
1690lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001691{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001692 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001693
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001694 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001695 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001696 }
1697 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001698
Radek Krejci1d82ef62015-08-07 14:44:40 +02001699 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001700}
1701
Radek Krejci1d82ef62015-08-07 14:44:40 +02001702static void
1703lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001704{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001705 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001706
Radek Krejci46c4cd72016-01-21 15:13:52 +01001707 if (leaf->child) {
1708 /* leafref backlinks */
1709 ly_set_free((struct ly_set *)leaf->child);
1710 }
1711
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001712 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001713 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001714 }
1715 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001716
Radek Krejci1d82ef62015-08-07 14:44:40 +02001717 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001718
Radek Krejci1d82ef62015-08-07 14:44:40 +02001719 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001720 lydict_remove(ctx, leaf->units);
1721 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001722}
1723
Radek Krejci1d82ef62015-08-07 14:44:40 +02001724static void
1725lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001726{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001727 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001728
Radek Krejci46c4cd72016-01-21 15:13:52 +01001729 if (llist->child) {
1730 /* leafref backlinks */
1731 ly_set_free((struct ly_set *)llist->child);
1732 }
1733
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001734 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001735 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001736 }
1737 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001738
Radek Krejci1d82ef62015-08-07 14:44:40 +02001739 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001740
Radek Krejci1d82ef62015-08-07 14:44:40 +02001741 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001742 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001743}
1744
Radek Krejci1d82ef62015-08-07 14:44:40 +02001745static void
1746lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001747{
Radek Krejci581ce772015-11-10 17:22:40 +01001748 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001749
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001750 /* handle only specific parts for LY_NODE_LIST */
1751 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001752 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001753 }
1754 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001755
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001756 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001757 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001758 }
1759 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001760
Radek Krejci1d82ef62015-08-07 14:44:40 +02001761 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001762
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001763 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001764 for (j = 0; j > list->unique[i].expr_size; j++) {
1765 lydict_remove(ctx, list->unique[i].expr[j]);
1766 }
1767 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001768 }
1769 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001770
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001771 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001772}
1773
Radek Krejci1d82ef62015-08-07 14:44:40 +02001774static void
1775lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001776{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001777 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001778
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001779 /* handle only specific parts for LY_NODE_CONTAINER */
1780 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001781
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001782 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001783 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001784 }
1785 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001786
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001787 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001788 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001789 }
1790 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001791
Radek Krejci1d82ef62015-08-07 14:44:40 +02001792 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001793}
1794
Radek Krejci1d82ef62015-08-07 14:44:40 +02001795static void
1796lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001797{
1798 lydict_remove(ctx, f->name);
1799 lydict_remove(ctx, f->dsc);
1800 lydict_remove(ctx, f->ref);
1801 free(f->features);
1802}
1803
Radek Krejci1d82ef62015-08-07 14:44:40 +02001804static void
1805lys_deviation_free(struct ly_ctx *ctx, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001806{
Radek Krejci581ce772015-11-10 17:22:40 +01001807 int i, j, k;
Radek Krejcieb00f512015-07-01 16:44:58 +02001808
1809 lydict_remove(ctx, dev->target_name);
1810 lydict_remove(ctx, dev->dsc);
1811 lydict_remove(ctx, dev->ref);
1812
1813 for (i = 0; i < dev->deviate_size; i++) {
1814 lydict_remove(ctx, dev->deviate[i].dflt);
1815 lydict_remove(ctx, dev->deviate[i].units);
1816
1817 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1818 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001819 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001820 }
1821 free(dev->deviate[i].must);
1822
1823 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001824 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1825 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1826 }
1827 free(dev->deviate[j].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001828 }
1829 free(dev->deviate[i].unique);
1830 }
1831 }
1832 free(dev->deviate);
1833}
1834
Radek Krejci1d82ef62015-08-07 14:44:40 +02001835static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001836lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcie1fa8582015-06-08 09:46:45 +02001837{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001838 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001839
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001840 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001841 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001842 lydict_remove(ctx, uses->refine[i].dsc);
1843 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001844
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001845 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001846 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001847 }
1848 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001849
Radek Krejci76512572015-08-04 09:47:08 +02001850 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001851 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001852 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001853 lydict_remove(ctx, uses->refine[i].mod.presence);
1854 }
1855 }
1856 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001857
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001858 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001859 lys_augment_free(ctx, uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001860 }
1861 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001862
Radek Krejci1d82ef62015-08-07 14:44:40 +02001863 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001864}
1865
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001866void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001867lys_node_free(struct lys_node *node, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02001868{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001869 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001870 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001871
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001872 if (!node) {
1873 return;
1874 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001875
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001876 assert(node->module);
1877 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001878
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001879 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001880
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001881 /* remove private object */
1882 if (node->private && private_destructor) {
1883 private_destructor(node, node->private);
1884 }
1885
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001886 /* common part */
Radek Krejcid12f57b2015-08-06 10:43:39 +02001887 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1888 free(node->features);
1889 lydict_remove(ctx, node->name);
1890 lydict_remove(ctx, node->dsc);
1891 lydict_remove(ctx, node->ref);
1892 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001893
Radek Krejci46c4cd72016-01-21 15:13:52 +01001894 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
1895 LY_TREE_FOR_SAFE(node->child, next, sub) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001896 lys_node_free(sub, private_destructor);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001897 }
1898 }
1899
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001900 /* specific part */
1901 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001902 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001903 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001904 break;
Radek Krejci76512572015-08-04 09:47:08 +02001905 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001906 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001907 break;
Radek Krejci76512572015-08-04 09:47:08 +02001908 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001909 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001910 break;
Radek Krejci76512572015-08-04 09:47:08 +02001911 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001912 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001913 break;
Radek Krejci76512572015-08-04 09:47:08 +02001914 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001915 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001916 break;
Radek Krejci76512572015-08-04 09:47:08 +02001917 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001918 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001919 break;
Radek Krejci76512572015-08-04 09:47:08 +02001920 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001921 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001922 break;
Radek Krejci76512572015-08-04 09:47:08 +02001923 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001924 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001925 break;
Radek Krejci76512572015-08-04 09:47:08 +02001926 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001927 /* do nothing */
1928 break;
Radek Krejci76512572015-08-04 09:47:08 +02001929 case LYS_GROUPING:
1930 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001931 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001932 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001933 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001934
1935 case LYS_INPUT:
1936 case LYS_OUTPUT:
1937 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1938 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001939 case LYS_UNKNOWN:
1940 LOGINT;
1941 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001942 }
Radek Krejci5a065542015-05-22 15:02:07 +02001943
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001944 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001945 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001946 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001947}
1948
Michal Vasko1e62a092015-12-01 12:27:20 +01001949const struct lys_module *
1950lys_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 +02001951{
Radek Krejcic071c542016-01-27 14:57:51 +01001952 const struct lys_module *main_module;
Michal Vasko3edeaf72016-02-11 13:17:43 +01001953 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02001954
Michal Vaskoa7789a82016-02-11 15:42:55 +01001955 assert(!prefix || !name);
1956
Michal Vaskob6729c62015-10-21 12:09:47 +02001957 if (prefix && !pref_len) {
1958 pref_len = strlen(prefix);
1959 }
1960 if (name && !name_len) {
1961 name_len = strlen(name);
1962 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02001963
Michal Vasko3edeaf72016-02-11 13:17:43 +01001964 main_module = (module->type ? ((struct lys_submodule *)module)->belongsto : module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01001965
1966 /* module own prefix, submodule own prefix, (sub)module own name */
1967 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
1968 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01001969 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01001970 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02001971 }
1972
Michal Vasko8ce24d72015-10-21 11:27:26 +02001973 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01001974 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
1975 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02001976 return module->imp[i].module;
1977 }
1978 }
1979
1980 return NULL;
1981}
1982
Michal Vasko13b15832015-08-19 11:04:48 +02001983/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001984static void
Michal Vaskob746fff2016-02-11 11:37:50 +01001985module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02001986{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001987 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01001988 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001989 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001990
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001991 assert(module->ctx);
1992 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001993
Michal Vaskob746fff2016-02-11 11:37:50 +01001994 /* just free the import array, imported modules will stay in the context */
Radek Krejcidce51452015-06-16 15:20:08 +02001995 free(module->imp);
1996
Radek Krejcic071c542016-01-27 14:57:51 +01001997 /* submodules don't have data tree, the data nodes
1998 * are placed in the main module altogether */
1999 if (!module->type) {
2000 LY_TREE_FOR_SAFE(module->data, next, iter) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002001 lys_node_free(iter, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002002 }
Radek Krejci21181962015-06-30 14:11:00 +02002003 }
Radek Krejci5a065542015-05-22 15:02:07 +02002004
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002005 lydict_remove(ctx, module->dsc);
2006 lydict_remove(ctx, module->ref);
2007 lydict_remove(ctx, module->org);
2008 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002009
Radek Krejcieb00f512015-07-01 16:44:58 +02002010 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002011 for (i = 0; i < module->rev_size; i++) {
2012 lydict_remove(ctx, module->rev[i].dsc);
2013 lydict_remove(ctx, module->rev[i].ref);
2014 }
2015 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002016
Radek Krejcieb00f512015-07-01 16:44:58 +02002017 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002018 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002019 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002020 }
2021 module->ident_size = 0;
2022 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002023
Radek Krejcieb00f512015-07-01 16:44:58 +02002024 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002025 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002026 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002027 }
2028 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002029
Radek Krejcieb00f512015-07-01 16:44:58 +02002030 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002031 for (i = 0; i < module->inc_size; i++) {
Radek Krejcic071c542016-01-27 14:57:51 +01002032 /* complete submodule free is done only from main module since
2033 * submodules propagate their includes to the main module */
2034 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002035 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002036 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002037 }
2038 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002039
Radek Krejcieb00f512015-07-01 16:44:58 +02002040 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002041 for (i = 0; i < module->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002042 lys_augment_free(ctx, module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002043 }
2044 free(module->augment);
2045
Radek Krejcieb00f512015-07-01 16:44:58 +02002046 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002047 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002048 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002049 }
2050 free(module->features);
2051
Radek Krejcieb00f512015-07-01 16:44:58 +02002052 /* deviations */
2053 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002054 lys_deviation_free(ctx, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002055 }
2056 free(module->deviation);
2057
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002058 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02002059}
2060
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002061void
Michal Vaskob746fff2016-02-11 11:37:50 +01002062lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002063{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002064 if (!submodule) {
2065 return;
2066 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002067
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002068 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002069 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002070
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002071 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002073 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002074}
2075
Radek Krejci76512572015-08-04 09:47:08 +02002076struct lys_node *
Radek Krejcic071c542016-01-27 14:57:51 +01002077lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node, uint8_t flags,
2078 uint8_t nacm, struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002079{
Radek Krejcic071c542016-01-27 14:57:51 +01002080 struct lys_node *retval = NULL, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002081 struct ly_ctx *ctx = module->ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01002082 const char *modname;
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
Michal Vasko253035f2015-12-17 16:58:13 +01002181 if (!retval) {
2182 LOGMEM;
2183 return NULL;
2184 }
2185
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002186 /*
2187 * duplicate generic part of the structure
2188 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002189 retval->name = lydict_insert(ctx, node->name, 0);
2190 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2191 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002192 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002193 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002194 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002195 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002196 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002197 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002198
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002199 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002200 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002201
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002202 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002203
Radek Krejci1d82ef62015-08-07 14:44:40 +02002204 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002205 retval->features = calloc(retval->features_size, sizeof *retval->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002206 if (!retval->features) {
2207 LOGMEM;
2208 goto error;
2209 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002210 for (i = 0; i < node->features_size; ++i) {
Radek Krejcicf509982015-12-15 09:22:44 +01002211 retval->features[i] = (struct lys_feature *)retval;
Michal Vasko0bd29d12015-08-19 11:45:49 +02002212 if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002213 retval->features[i] = node->features[i];
Michal Vaskod23ce592015-08-06 09:55:37 +02002214 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002215 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002216
Radek Krejcic071c542016-01-27 14:57:51 +01002217 /* connect it to the parent */
2218 if (lys_node_addchild(parent, retval->module, retval)) {
2219 goto error;
2220 }
2221
2222 /* go recursively */
2223 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002224 LY_TREE_FOR(node->child, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01002225 if (!lys_node_dup(module, retval, child, retval->flags, retval->nacm, unres)) {
Michal Vasko49168a22015-08-17 16:35:41 +02002226 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002227 }
2228 }
2229 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002230
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002231 /*
2232 * duplicate specific part of the structure
2233 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002234 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002235 case LYS_CONTAINER:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002236 if (cont_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002237 cont->when = lys_when_dup(ctx, cont_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002238 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002239 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002240
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002241 cont->must_size = cont_orig->must_size;
2242 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002243
Radek Krejci1d82ef62015-08-07 14:44:40 +02002244 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci1d82ef62015-08-07 14:44:40 +02002245 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002246 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002247
Radek Krejci76512572015-08-04 09:47:08 +02002248 case LYS_CHOICE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002249 if (choice_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002250 choice->when = lys_when_dup(ctx, choice_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002251 }
2252
2253 if (choice_orig->dflt) {
Radek Krejcif70a3a62016-01-27 16:39:58 +01002254 modname = choice->module->type ? ((struct lys_submodule *)choice->module)->belongsto->name : choice->module->name;
Radek Krejcic071c542016-01-27 14:57:51 +01002255 rc = lys_get_sibling(choice->child, modname, 0, choice_orig->dflt->name, 0, LYS_ANYXML
Radek Krejci76512572015-08-04 09:47:08 +02002256 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
Michal Vasko1e62a092015-12-01 12:27:20 +01002257 | LYS_LIST, (const struct lys_node **)&choice->dflt);
Michal Vasko49168a22015-08-17 16:35:41 +02002258 if (rc) {
2259 if (rc == EXIT_FAILURE) {
2260 LOGINT;
2261 }
2262 goto error;
2263 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002264 } else {
Michal Vaskoc68a2a22015-08-06 09:57:24 +02002265 /* useless to check return value, we don't know whether
2266 * there really wasn't any default defined or it just hasn't
2267 * been resolved, we just hope for the best :)
2268 */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002269 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002270 }
2271 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002272
Radek Krejci76512572015-08-04 09:47:08 +02002273 case LYS_LEAF:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002274 if (lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres)) {
2275 goto error;
2276 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002277 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2278
2279 if (leaf_orig->dflt) {
2280 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002281 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002282 goto error;
2283 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002284 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002286 leaf->must_size = leaf_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002287 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002288
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002289 if (leaf_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002290 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002291 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002292 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002293
Radek Krejci76512572015-08-04 09:47:08 +02002294 case LYS_LEAFLIST:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002295 if (lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres)) {
2296 goto error;
2297 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002298 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002299
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002300 llist->min = llist_orig->min;
2301 llist->max = llist_orig->max;
2302
2303 llist->must_size = llist_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002304 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002305
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002306 if (llist_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002307 llist->when = lys_when_dup(ctx, llist_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002308 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002309 break;
2310
Radek Krejci76512572015-08-04 09:47:08 +02002311 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002312 list->min = list_orig->min;
2313 list->max = list_orig->max;
2314
2315 list->must_size = list_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002316 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002317
Radek Krejci581ce772015-11-10 17:22:40 +01002318 list->tpdf_size = list_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002319 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002320
Radek Krejci581ce772015-11-10 17:22:40 +01002321 list->keys_size = list_orig->keys_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002322 if (list->keys_size) {
2323 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01002324 if (!list->keys) {
2325 LOGMEM;
2326 goto error;
2327 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002328
2329 /* we managed to resolve it before, resolve it again manually */
2330 if (list_orig->keys[0]) {
Radek Krejcic071c542016-01-27 14:57:51 +01002331 modname = list->module->type ? ((struct lys_submodule *)list->module)->belongsto->name : list->module->name;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002332 for (i = 0; i < list->keys_size; ++i) {
Radek Krejcic071c542016-01-27 14:57:51 +01002333 rc = lys_get_sibling(list->child, modname, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
Michal Vasko1e62a092015-12-01 12:27:20 +01002334 (const struct lys_node **)&list->keys[i]);
Michal Vasko49168a22015-08-17 16:35:41 +02002335 if (rc) {
2336 if (rc == EXIT_FAILURE) {
2337 LOGINT;
2338 }
2339 goto error;
2340 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002341 }
2342 /* it was not resolved yet, add unres copy */
2343 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002344 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02002345 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002346 goto error;
Michal Vaskod23ce592015-08-06 09:55:37 +02002347 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002348 }
2349 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002350
Radek Krejci581ce772015-11-10 17:22:40 +01002351 list->unique_size = list_orig->unique_size;
2352 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002353 if (!list->unique) {
2354 LOGMEM;
2355 goto error;
2356 }
Radek Krejci581ce772015-11-10 17:22:40 +01002357 for (i = 0; i < list->unique_size; ++i) {
2358 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2359 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002360 if (!list->unique[i].expr) {
2361 LOGMEM;
2362 goto error;
2363 }
Radek Krejci581ce772015-11-10 17:22:40 +01002364 for (j = 0; j < list->unique[i].expr_size; j++) {
2365 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2366
2367 /* if it stays in unres list, duplicate it also there */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002368 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002369 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002370 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002371
2372 if (list_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002373 list->when = lys_when_dup(ctx, list_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002374 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002375 break;
2376
Radek Krejci76512572015-08-04 09:47:08 +02002377 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002378 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002379 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002380
2381 if (anyxml_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002382 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002383 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002384 break;
2385
Radek Krejci76512572015-08-04 09:47:08 +02002386 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002387 uses->grp = uses_orig->grp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002388
2389 if (uses_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002390 uses->when = lys_when_dup(ctx, uses_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002391 }
2392
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002393 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002394 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002395 uses->augment_size = uses_orig->augment_size;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02002396 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Michal Vaskof8c128d2015-08-06 15:25:28 +02002397 if (!uses->child) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002398 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002399 goto error;
2400 }
Michal Vaskof8c128d2015-08-06 15:25:28 +02002401 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002402 break;
2403
Radek Krejci76512572015-08-04 09:47:08 +02002404 case LYS_CASE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002405 if (cs_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002406 cs->when = lys_when_dup(ctx, cs_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002407 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002408 break;
2409
Radek Krejci76512572015-08-04 09:47:08 +02002410 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002411 grp->tpdf_size = grp_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002412 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002413 break;
2414
Radek Krejci76512572015-08-04 09:47:08 +02002415 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002416 rpc->tpdf_size = rpc_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002417 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002418 break;
2419
Radek Krejci76512572015-08-04 09:47:08 +02002420 case LYS_INPUT:
2421 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002422 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002423 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002424 break;
2425
Radek Krejci76512572015-08-04 09:47:08 +02002426 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002427 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002428 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcia01e5432015-06-16 10:35:25 +02002429 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002430
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002431 default:
Radek Krejci00768f42015-06-18 17:04:04 +02002432 /* LY_NODE_AUGMENT */
Michal Vaskod23ce592015-08-06 09:55:37 +02002433 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002434 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002435 }
2436
2437 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002438
2439error:
2440
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002441 lys_node_free(retval, NULL);
Michal Vasko49168a22015-08-17 16:35:41 +02002442 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002443}
2444
Michal Vasko13b15832015-08-19 11:04:48 +02002445void
Michal Vasko627975a2016-02-11 11:39:03 +01002446lys_free(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv), int remove_from_ctx)
Radek Krejciefaeba32015-05-27 14:30:57 +02002447{
Radek Krejcidce51452015-06-16 15:20:08 +02002448 struct ly_ctx *ctx;
2449 int i;
2450
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002451 if (!module) {
2452 return;
2453 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002454
Radek Krejcidce51452015-06-16 15:20:08 +02002455 /* remove schema from the context */
2456 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01002457 if (remove_from_ctx && ctx->models.used) {
Radek Krejcidce51452015-06-16 15:20:08 +02002458 for (i = 0; i < ctx->models.used; i++) {
2459 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01002460 /* move all the models to not change the order in the list */
Radek Krejcidce51452015-06-16 15:20:08 +02002461 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01002462 memmove(&ctx->models.list[i], ctx->models.list[i + 1], (ctx->models.used - i) * sizeof *ctx->models.list);
Radek Krejcidce51452015-06-16 15:20:08 +02002463 ctx->models.list[ctx->models.used] = NULL;
2464 /* we are done */
2465 break;
2466 }
2467 }
2468 }
2469
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002470 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01002471 module_free_common(module, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002472
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002473 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01002474 lydict_remove(ctx, module->ns);
2475 lydict_remove(ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02002476
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002477 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002478}
Radek Krejci7e97c352015-06-19 16:26:34 +02002479
2480/*
2481 * op: 1 - enable, 0 - disable
2482 */
2483static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002484lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002485{
2486 int all = 0;
2487 int i, j, k;
2488
2489 if (!module || !name || !strlen(name)) {
2490 return EXIT_FAILURE;
2491 }
2492
2493 if (!strcmp(name, "*")) {
2494 /* enable all */
2495 all = 1;
2496 }
2497
2498 /* module itself */
2499 for (i = 0; i < module->features_size; i++) {
2500 if (all || !strcmp(module->features[i].name, name)) {
2501 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002502 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002503 /* enable referenced features (recursion) */
2504 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002505 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002506 module->features[i].features[k]->name, op);
2507 }
2508 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002509 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002510 }
2511 if (!all) {
2512 return EXIT_SUCCESS;
2513 }
2514 }
2515 }
2516
2517 /* submodules */
2518 for (j = 0; j < module->inc_size; j++) {
2519 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2520 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2521 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002522 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002523 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002524 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002525 }
2526 if (!all) {
2527 return EXIT_SUCCESS;
2528 }
2529 }
2530 }
2531 }
2532
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002533 /* TODO submodules of submodules ... */
2534
Radek Krejci7e97c352015-06-19 16:26:34 +02002535 if (all) {
2536 return EXIT_SUCCESS;
2537 } else {
2538 return EXIT_FAILURE;
2539 }
2540}
2541
2542API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002543lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002544{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002545 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002546}
2547
2548API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002549lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002550{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002551 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002552}
2553
2554API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002555lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002556{
2557 int i, j;
2558
2559 if (!module || !feature) {
2560 return -1;
2561 }
2562
2563 /* search for the specified feature */
2564 /* module itself */
2565 for (i = 0; i < module->features_size; i++) {
2566 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002567 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002568 return 1;
2569 } else {
2570 return 0;
2571 }
2572 }
2573 }
2574
2575 /* submodules */
2576 for (j = 0; j < module->inc_size; j++) {
2577 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2578 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002579 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002580 return 1;
2581 } else {
2582 return 0;
2583 }
2584 }
2585 }
2586 }
2587
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002588 /* feature definition not found */
2589 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002590}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002591
Radek Krejci96a10da2015-07-30 11:00:14 +02002592API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01002593lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002594{
Radek Krejci96a10da2015-07-30 11:00:14 +02002595 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002596 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002597 unsigned int count;
2598
2599 if (!module) {
2600 return NULL;
2601 }
2602
2603 count = module->features_size;
2604 for (i = 0; i < module->inc_size; i++) {
2605 count += module->inc[i].submodule->features_size;
2606 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002607 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01002608 if (!result) {
2609 LOGMEM;
2610 return NULL;
2611 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002612 if (states) {
2613 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01002614 if (!(*states)) {
2615 LOGMEM;
2616 free(result);
2617 return NULL;
2618 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002619 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002620 count = 0;
2621
2622 /* module itself */
2623 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002624 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002625 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002626 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002627 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002628 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002629 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002630 }
2631 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002632 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002633 }
2634
2635 /* submodules */
2636 for (j = 0; j < module->inc_size; j++) {
2637 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002638 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002639 if (states) {
2640 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2641 (*states)[count] = 1;
2642 } else {
2643 (*states)[count] = 0;
2644 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002645 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002646 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002647 }
2648 }
2649
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002650 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002651 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002652
2653 return result;
2654}
Michal Vaskobaefb032015-09-24 14:52:10 +02002655
Radek Krejcic071c542016-01-27 14:57:51 +01002656struct lys_module *
2657lys_mainmodule(const struct lys_node *node)
2658{
2659 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
2660}
2661
Michal Vaskobaefb032015-09-24 14:52:10 +02002662API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002663lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02002664{
2665 if (!node || !node->parent) {
2666 return NULL;
2667 }
2668
2669 if (node->parent->nodetype == LYS_AUGMENT) {
2670 return ((struct lys_node_augment *)node->parent)->target;
2671 }
2672
2673 return node->parent;
2674}
Michal Vasko1b229152016-01-13 11:28:38 +01002675
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002676API void *
Michal Vasko1b229152016-01-13 11:28:38 +01002677lys_set_private(const struct lys_node *node, void *priv)
2678{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002679 void *prev;
2680
Michal Vasko1b229152016-01-13 11:28:38 +01002681 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002682 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2683 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01002684 }
2685
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002686 prev = node->private;
Michal Vasko1b229152016-01-13 11:28:38 +01002687 ((struct lys_node *)node)->private = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002688
2689 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01002690}