blob: 26e64e930334dcac8374ab44ccace430b29100b0 [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 Vasko4f0dad02016-02-15 14:08:23 +0100106 mod = lys_node_module(siblings);
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)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100113 /* module name comparison */
114 node_mod_name = lys_node_module(node)->name;
115 if ((node_mod_name != mod_name) && (strncmp(node_mod_name, mod_name, mod_name_len) || node_mod_name[mod_name_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100116 continue;
117 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200118
Radek Krejcic071c542016-01-27 14:57:51 +0100119 /* direct name check */
120 if ((node->name == name) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
121 if (ret) {
122 *ret = node;
Michal Vasko1dca6882015-10-22 14:29:42 +0200123 }
Radek Krejcic071c542016-01-27 14:57:51 +0100124 return EXIT_SUCCESS;
Michal Vasko1dca6882015-10-22 14:29:42 +0200125 }
126 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200127 }
128
129 return EXIT_FAILURE;
130}
131
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200132int
Michal Vasko1e62a092015-12-01 12:27:20 +0100133lys_get_data_sibling(const struct lys_module *mod, const struct lys_node *siblings, const char *name, LYS_NODE type,
134 const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200135{
Michal Vasko1e62a092015-12-01 12:27:20 +0100136 const struct lys_node *node;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200137
138 assert(siblings && name);
139 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
140
141 /* find the beginning */
142 while (siblings->prev->next) {
143 siblings = siblings->prev;
144 }
145
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200146 if (!mod) {
147 mod = siblings->module;
148 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200149
Michal Vasko4f0dad02016-02-15 14:08:23 +0100150 /* try to find the node */
151 node = NULL;
152 while ((node = lys_getnext(node, siblings->parent, mod, 0))) {
153 if (!type || (node->nodetype & type)) {
154 /* module check */
155 if (lys_node_module(node) != lys_module(mod)) {
Radek Krejcic071c542016-01-27 14:57:51 +0100156 continue;
157 }
158
Michal Vasko4f0dad02016-02-15 14:08:23 +0100159 /* direct name check */
160 if ((node->name == name) || !strcmp(node->name, name)) {
161 if (ret) {
162 *ret = node;
163 }
164 return EXIT_SUCCESS;
165 }
Radek Krejcic071c542016-01-27 14:57:51 +0100166 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200167 }
168
169 return EXIT_FAILURE;
170}
171
Michal Vasko1e62a092015-12-01 12:27:20 +0100172API const struct lys_node *
173lys_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 +0200174{
Michal Vasko1e62a092015-12-01 12:27:20 +0100175 const struct lys_node *next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200176
Radek Krejci8bc87f62015-09-02 16:19:05 +0200177 if (!last) {
178 /* first call */
179
180 /* get know where to start */
181 if (parent) {
182 /* schema subtree */
183 next = last = parent->child;
184 } else {
185 /* top level data */
186 assert(module);
187 next = last = module->data;
188 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200189 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200190 /* continue after the last returned value */
191 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200192 }
193
194repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200195 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200196 if (options & LYS_GETNEXT_WITHGROUPING) {
197 return next;
198 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200199 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200200 }
201
Radek Krejcic4ccbd92016-01-07 13:13:33 +0100202 if (!next) {
Radek Krejci63318e82016-02-12 09:43:12 +0100203 if (!last || lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200204 /* no next element */
205 return NULL;
206 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200207 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200208 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200209 goto repeat;
210 }
211
212 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200213 case LYS_INPUT:
214 case LYS_OUTPUT:
215 if (options & LYS_GETNEXT_WITHINOUT) {
216 return next;
217 } else {
218 next = next->child;
219 goto repeat;
220 }
221 break;
222
Michal Vaskoa5835e92015-10-20 15:07:39 +0200223 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200224 if (options & LYS_GETNEXT_WITHCASE) {
225 return next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200226 } else {
227 next = next->child;
228 goto repeat;
Michal Vasko1dca6882015-10-22 14:29:42 +0200229 }
Michal Vaskob6eedf02015-10-22 16:07:03 +0200230 break;
231
Michal Vasko1dca6882015-10-22 14:29:42 +0200232 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200233 /* go into */
234 next = next->child;
235 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200236
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200237 case LYS_RPC:
238 case LYS_NOTIF:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200239 case LYS_CONTAINER:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200240 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200241 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200242 case LYS_LIST:
243 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200244 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200245
246 case LYS_CHOICE:
247 if (options & LYS_GETNEXT_WITHCHOICE) {
248 return next;
249 } else {
250 /* go into */
251 next = next->child;
252 goto repeat;
253 }
254 break;
255
Radek Krejci7f40ce32015-08-12 20:38:46 +0200256 default:
257 /* we should not be here */
258 return NULL;
259 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200260
261
262}
263
Michal Vasko1e62a092015-12-01 12:27:20 +0100264static const struct lys_node *
Radek Krejci2342cf62016-01-29 16:48:23 +0100265check_mand_getnext(const struct lys_node *last, const struct lys_node *parent, const struct lys_module *module)
Radek Krejci8bc87f62015-09-02 16:19:05 +0200266{
Michal Vasko1e62a092015-12-01 12:27:20 +0100267 const struct lys_node *next;
268
Radek Krejci2342cf62016-01-29 16:48:23 +0100269 next = lys_getnext(last, parent, module, LYS_GETNEXT_WITHCHOICE);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200270
Radek Krejci4b6c2112015-10-06 12:48:34 +0200271repeat:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200272 if (next && next->nodetype == LYS_CONTAINER) {
273 if (((struct lys_node_container *)next)->presence) {
274 /* mandatory elements under the non-existing presence
275 * container are not mandatory - 7.6.5, rule 1 */
276 next = next->next;
277 } else {
278 /* go into */
279 next = next->child;
280 }
281 goto repeat;
282 }
283
284 return next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200285}
286
Michal Vasko1e62a092015-12-01 12:27:20 +0100287static const struct lys_node *
288check_mand_check(const struct lys_node *node, const struct lys_node *stop, const struct lyd_node *data)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200289{
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200290 struct lys_node *siter = NULL, *parent = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200291 struct lyd_node *diter = NULL;
Radek Krejcidc154432016-01-21 11:10:59 +0100292 struct ly_set *set = NULL;
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200293 unsigned int i;
Radek Krejci14a11a62015-08-17 17:27:38 +0200294 uint32_t minmax;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200295
296 if (node->flags & LYS_MAND_TRUE) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100297 if (!data) {
298 /* we have no data but a mandatory node */
299 return node;
300 }
301 switch (node->nodetype) {
302 case LYS_LEAF:
303 case LYS_ANYXML:
304 case LYS_CHOICE:
305 if (node->parent && node->parent->nodetype == LYS_CASE) {
306 /* 7.6.5, rule 2 */
307 /* 7.9.4, rule 1 */
308 if (node->parent->parent->parent == data->schema) {
309 /* the only case the node's siblings can exist is that the
310 * data node passed originally to ly_check_mandatory()
311 * had this choice as a child
312 */
313 /* try to find the node's siblings in data */
314 LY_TREE_FOR(data->child, diter) {
315 LY_TREE_FOR(node->parent->child, siter) {
316 if (siter == diter->schema) {
317 /* some sibling exists, rule applies */
318 break;
319 }
320 }
321 if (siter) {
322 break;
323 }
324 }
325 }
326 if (!siter) {
327 /* no sibling exists */
328 return NULL;
329 }
330 } else {
Radek Krejci7eb12132016-02-01 10:55:23 +0100331 for (parent = node->parent; parent && parent != stop; parent = parent->parent) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100332 if (parent->nodetype != LYS_CONTAINER) {
333 /* 7.6.5, rule 1, checking presence is not needed
334 * since it is done in check_mand_getnext()
335 */
336 ly_set_free(set);
337 return NULL;
338 }
339 /* add the parent to the list for searching in data tree */
340 if (!set) {
341 set = ly_set_new();
342 }
343 /* ignore return - memory error is logged and we will
344 * check at least the rest of nodes we have */
345 (void)ly_set_add(set, parent);
346 }
347 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200348
Radek Krejci2342cf62016-01-29 16:48:23 +0100349 /* search for instance */
350 if (set) {
351 for (i = 0; i < set->number; i++) {
352 LY_TREE_FOR(data->child, diter) {
353 if (diter->schema == set->sset[i]) {
354 break;
355 }
356 }
357 if (!diter) {
358 /* instance not found */
359 node = set->sset[i];
360 ly_set_free(set);
361 return node;
362 }
363 data = diter;
364 }
365 ly_set_free(set);
366 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200367
Radek Krejci2342cf62016-01-29 16:48:23 +0100368 LY_TREE_FOR(data->child, diter) {
369 if (diter->schema == node) {
370 return NULL;
371 }
372 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200373
Radek Krejci2342cf62016-01-29 16:48:23 +0100374 /* instance not found */
375 /* 7.6.5, rule 3 (or 2) */
376 /* 7.9.4, rule 2 */
377 return node;
378 default:
379 /* error */
380 break;
381 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200382 } else if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
383 /* search for number of instances */
384 minmax = 0;
Radek Krejci2342cf62016-01-29 16:48:23 +0100385 if (data) {
386 LY_TREE_FOR(data->child, diter) {
387 if (diter->schema == node) {
388 minmax++;
389 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200390 }
391 }
392
393 /* check the specified constraints */
394 if (node->nodetype == LYS_LIST) {
395 if (((struct lys_node_list *)node)->min && minmax < ((struct lys_node_list *)node)->min) {
396 return node;
397 }
398
399 if (((struct lys_node_list *)node)->max && minmax > ((struct lys_node_list *)node)->max) {
400 return node;
401 }
402 } else if (node->nodetype == LYS_LEAFLIST) {
403 if (((struct lys_node_leaflist *)node)->min && minmax < ((struct lys_node_leaflist *)node)->min) {
404 return node;
405 }
406
407 if (((struct lys_node_leaflist *)node)->max && minmax > ((struct lys_node_leaflist *)node)->max) {
408 return node;
409 }
410 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200411 }
412
413 return NULL;
414}
415
Michal Vasko1e62a092015-12-01 12:27:20 +0100416const struct lys_node *
Radek Krejci2342cf62016-01-29 16:48:23 +0100417ly_check_mandatory(const struct lyd_node *data, const struct lys_node *schema)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200418{
Michal Vasko1e62a092015-12-01 12:27:20 +0100419 const struct lys_node *siter, *saux, *saux2, *result, *parent = NULL, *parent2;
420 const struct lyd_node *diter;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200421 int found;
422
Radek Krejci2342cf62016-01-29 16:48:23 +0100423 assert(data || schema);
424
425 if (!data) { /* !data && schema */
426 siter = schema;
427 } else { /* data && !schema */
Radek Krejcie2f12212016-02-12 13:50:22 +0100428 schema = data->schema;
429 siter = data->schema->child;
Radek Krejci2342cf62016-01-29 16:48:23 +0100430 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200431
432repeat:
433 while (siter) {
Radek Krejci074bf852015-08-19 14:22:16 +0200434 if (lys_is_disabled(siter, 2)) {
435 siter = siter->next;
436 continue;
437 }
438
Radek Krejci7f40ce32015-08-12 20:38:46 +0200439 switch (siter->nodetype) {
440 case LYS_CONTAINER:
441 case LYS_LEAF:
442 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200443 case LYS_LIST:
444 case LYS_LEAFLIST:
445 /* check if there is some mandatory node; first test the siter itself ... */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200446 result = check_mand_check(siter, siter->parent, data);
447 if (result) {
448 return result;
449 }
450 /* ... and then the subtree */
Radek Krejci14a11a62015-08-17 17:27:38 +0200451 if (parent && siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
452 saux = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100453 while ((saux = check_mand_getnext(saux, siter, NULL))) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200454 result = check_mand_check(saux, siter, data);
455 if (result) {
456 return result;
457 }
458 }
459 }
460 siter = siter->next;
461 break;
462 case LYS_CHOICE:
Radek Krejci14a11a62015-08-17 17:27:38 +0200463 /* search for instance */
464 saux = siter;
465 siter = siter->child;
466 found = 0;
467 parent2 = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200468repeat_choice:
Radek Krejci2342cf62016-01-29 16:48:23 +0100469 while (siter && data) {
Radek Krejci074bf852015-08-19 14:22:16 +0200470 if (lys_is_disabled(siter, 2)) {
471 siter = siter->next;
472 continue;
473 }
474
Radek Krejci14a11a62015-08-17 17:27:38 +0200475 switch (siter->nodetype) {
476 case LYS_CONTAINER:
477 case LYS_LEAF:
478 case LYS_LEAFLIST:
479 case LYS_LIST:
480 case LYS_ANYXML:
481 LY_TREE_FOR(data->child, diter) {
482 if (diter->schema == siter) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200483 break;
484 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200485 }
486 if (diter) {
487 /* got instance */
488 /* check presence of mandatory siblings */
Radek Krejci65d0a652015-08-27 13:09:42 +0200489 if (parent2 && parent2->nodetype == LYS_CASE) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200490 saux2 = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100491 while ((saux2 = check_mand_getnext(saux2, parent2, NULL))) {
Radek Krejci37bda002015-08-27 11:23:56 +0200492 result = check_mand_check(saux2, parent2, data);
Radek Krejci14a11a62015-08-17 17:27:38 +0200493 if (result) {
494 return result;
495 }
496 }
497 }
498 siter = parent2 = NULL;
499 found = 1;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200500 break;
501 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200502 siter = siter->next;
503 break;
504 case LYS_CASE:
505 case LYS_CHOICE:
506 case LYS_USES:
507 /* go into */
Radek Krejci37bda002015-08-27 11:23:56 +0200508 if (!parent2) {
509 parent2 = siter;
510 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200511 siter = siter->child;
512 break;
513 case LYS_AUGMENT:
514 case LYS_GROUPING:
515 /* skip */
516 siter = siter->next;
517 break;
518 default:
519 /* error */
520 break;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200521 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200522 }
523
Radek Krejci14a11a62015-08-17 17:27:38 +0200524 if (parent2) {
525 siter = parent2->next;
526 if (parent2->parent == saux) {
527 parent2 = NULL;
528 } else {
529 parent2 = parent2->parent;
530 }
531 goto repeat_choice;
532 }
533
Radek Krejci074bf852015-08-19 14:22:16 +0200534 if (!found && (saux->flags & LYS_MAND_TRUE)) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200535 return saux;
536 }
537
538 /* go to next */
539 siter = saux->next;
540
Radek Krejci7f40ce32015-08-12 20:38:46 +0200541 break;
542 case LYS_USES:
543 case LYS_CASE:
544 /* go into */
545 parent = siter;
546 siter = siter->child;
547 break;
548 default:
549 /* can ignore, go to next */
550 siter = siter->next;
551 break;
552 }
553 }
554
555 if (parent) {
556 siter = parent->next;
Radek Krejci2342cf62016-01-29 16:48:23 +0100557 if (parent->parent == schema) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200558 parent = NULL;
559 } else {
560 parent = parent->parent;
561 }
562 goto repeat;
563 }
564
565 return NULL;
566}
567
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200568void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200569lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200570{
Radek Krejci76512572015-08-04 09:47:08 +0200571 struct lys_node *parent, *first;
Radek Krejcic071c542016-01-27 14:57:51 +0100572 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200573
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200574 if (!node) {
575 return;
576 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200577
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200578 /* unlink from data model if necessary */
579 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100580 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100581 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100582 if (main_module->data == node) {
583 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200584 }
585 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200586
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200587 /* store pointers to important nodes */
588 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200589 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200590 /* handle augments - first, unlink it from the augment parent ... */
591 if (parent->child == node) {
592 parent->child = node->next;
593 }
594 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200595 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200596 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200597
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200598 /* unlink from parent */
599 if (parent) {
600 if (parent->child == node) {
601 parent->child = node->next;
602 }
603 node->parent = NULL;
604 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200605
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200606 /* unlink from siblings */
607 if (node->prev == node) {
608 /* there are no more siblings */
609 return;
610 }
611 if (node->next) {
612 node->next->prev = node->prev;
613 } else {
614 /* unlinking the last element */
615 if (parent) {
616 first = parent->child;
617 } else {
618 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200619 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200620 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200621 }
622 }
623 first->prev = node->prev;
624 }
625 if (node->prev->next) {
626 node->prev->next = node->next;
627 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200628
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200629 /* clean up the unlinked element */
630 node->next = NULL;
631 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200632}
633
Michal Vasko563ef092015-09-04 13:17:23 +0200634struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100635lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200636{
637 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200638
639 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200640 /* top-level augment, look into module (uses augment is handled correctly below) */
641 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
642 par_iter = par_iter->parent->module->data;
643 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200644 break;
645 }
646 }
647
Michal Vasko6f929da2015-10-02 16:23:25 +0200648 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200649 continue;
650 }
651
652 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
653 if (!stop) {
654 stop = par_iter;
655 } else if (iter == stop) {
656 break;
657 }
658 if (iter->nodetype != LYS_GROUPING) {
659 continue;
660 }
661
Radek Krejcif8426a72015-10-31 23:14:03 +0100662 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200663 return (struct lys_node_grp *)iter;
664 }
665 }
666 }
667
Michal Vasko563ef092015-09-04 13:17:23 +0200668 return NULL;
669}
670
Radek Krejci10c760e2015-08-14 14:45:43 +0200671/*
672 * get next grouping in the root's subtree, in the
673 * first call, tha last is NULL
674 */
675static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200676lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200677{
Radek Krejci10c760e2015-08-14 14:45:43 +0200678 struct lys_node *last = (struct lys_node *)lastgrp;
679 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200680
Radek Krejci10c760e2015-08-14 14:45:43 +0200681 assert(root);
682
683 if (!last) {
684 last = root;
685 }
686
687 while (1) {
688 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
689 next = last->child;
690 } else {
691 next = NULL;
692 }
693 if (!next) {
694 if (last == root) {
695 /* we are done */
696 return NULL;
697 }
698
699 /* no children, go to siblings */
700 next = last->next;
701 }
702 while (!next) {
703 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100704 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200705 /* we are done */
706 return NULL;
707 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200708 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100709 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200710 }
711
712 if (next->nodetype == LYS_GROUPING) {
713 return (struct lys_node_grp *)next;
714 }
715
716 last = next;
717 }
718}
719
Michal Vasko0d343d12015-08-24 14:57:36 +0200720/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200721int
Radek Krejci07911992015-08-14 15:13:31 +0200722lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
723{
Michal Vasko563ef092015-09-04 13:17:23 +0200724 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200725 struct lys_node_grp *grp;
726 int down;
727
728 assert(node);
729
730 if (!parent) {
731 assert(module);
732 } else {
733 module = parent->module;
734 }
735
736 switch (node->nodetype) {
737 case LYS_GROUPING:
738 /* 6.2.1, rule 6 */
739 if (parent) {
740 if (parent->child) {
741 down = 1;
742 start = parent->child;
743 } else {
744 down = 0;
745 start = parent;
746 }
747 } else {
748 down = 1;
749 start = module->data;
750 }
751 /* go up */
Radek Krejcic071c542016-01-27 14:57:51 +0100752 if (lys_find_grouping_up(node->name, start)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100753 LOGVAL(LYE_DUPID, 0, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200754 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200755 }
756 /* go down, because grouping can be defined after e.g. container in which is collision */
757 if (down) {
758 for (iter = start, stop = NULL; iter; iter = iter->prev) {
759 if (!stop) {
760 stop = start;
761 } else if (iter == stop) {
762 break;
763 }
764 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
765 continue;
766 }
767
768 grp = NULL;
769 while ((grp = lys_get_next_grouping(grp, iter))) {
770 if (node->name == grp->name) {
Radek Krejciadb57612016-02-16 13:34:34 +0100771 LOGVAL(LYE_DUPID, 0, LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200772 return EXIT_FAILURE;
773 }
774 }
775 }
776 }
777 break;
778 case LYS_LEAF:
779 case LYS_LEAFLIST:
780 case LYS_LIST:
781 case LYS_CONTAINER:
782 case LYS_CHOICE:
783 case LYS_ANYXML:
784 /* 6.2.1, rule 7 */
785 if (parent) {
786 iter = parent;
787 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE))) {
788 iter = iter->parent;
789 }
790 if (!iter) {
791 stop = NULL;
792 iter = module->data;
793 } else {
794 stop = iter;
795 iter = iter->child;
796 }
797 } else {
798 stop = NULL;
799 iter = module->data;
800 }
801 while (iter) {
802 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
803 iter = iter->child;
804 continue;
805 }
806
807 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
808 if (iter->module == node->module && iter->name == node->name) {
Radek Krejciadb57612016-02-16 13:34:34 +0100809 LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, node, "Duplicated child identifier \"%s\" in \"%s\".", node->name,
Radek Krejci07911992015-08-14 15:13:31 +0200810 stop ? stop->name : "(sub)module");
811 return EXIT_FAILURE;
812 }
813 }
814
815 /* special case for choice - we must check the choice's name as
816 * well as the names of nodes under the choice
817 */
818 if (iter->nodetype == LYS_CHOICE) {
819 iter = iter->child;
820 continue;
821 }
822
823 /* go to siblings */
824 if (!iter->next) {
825 /* no sibling, go to parent's sibling */
826 do {
827 iter = iter->parent;
828 if (iter && iter->next) {
829 break;
830 }
831 } while (iter != stop);
832
833 if (iter == stop) {
834 break;
835 }
836 }
837 iter = iter->next;
838 }
839 break;
840 case LYS_CASE:
841 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100842 if (parent) {
843 start = parent->child;
844 } else {
845 start = module->data;
846 }
847
848 LY_TREE_FOR(start, iter) {
Radek Krejci07911992015-08-14 15:13:31 +0200849 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
850 continue;
851 }
852
853 if (iter->module == node->module && iter->name == node->name) {
Radek Krejciadb57612016-02-16 13:34:34 +0100854 LOGVAL(LYE_DUPID, 0, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200855 return EXIT_FAILURE;
856 }
857 }
858 break;
859 default:
860 /* no check needed */
861 break;
862 }
863
864 return EXIT_SUCCESS;
865}
866
Michal Vasko0d343d12015-08-24 14:57:36 +0200867/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200868int
Radek Krejci10c760e2015-08-14 14:45:43 +0200869lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
870{
Radek Krejci92720552015-10-05 15:28:27 +0200871 struct lys_node *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200872 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200873
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200874 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200875
Radek Krejci10c760e2015-08-14 14:45:43 +0200876 if (parent) {
877 type = parent->nodetype;
878 module = parent->module;
879 } else {
880 assert(module);
881 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200882 }
883
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200884 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200885 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200886 case LYS_CONTAINER:
887 case LYS_LIST:
888 case LYS_GROUPING:
889 case LYS_USES:
890 case LYS_INPUT:
891 case LYS_OUTPUT:
892 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200893 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200894 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
895 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejciadb57612016-02-16 13:34:34 +0100896 LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200897 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
898 return EXIT_FAILURE;
899 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200900
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200901 break;
Radek Krejci76512572015-08-04 09:47:08 +0200902 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200903 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200904 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejciadb57612016-02-16 13:34:34 +0100905 LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "Unexpected substatement \"%s\" in \"choice\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200906 strnodetype(child->nodetype), parent->name);
907 return EXIT_FAILURE;
908 }
909 break;
Radek Krejci76512572015-08-04 09:47:08 +0200910 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200911 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200912 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejciadb57612016-02-16 13:34:34 +0100913 LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "Unexpected substatement \"%s\" in \"case\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200914 strnodetype(child->nodetype), parent->name);
915 return EXIT_FAILURE;
916 }
917 break;
Radek Krejci76512572015-08-04 09:47:08 +0200918 case LYS_RPC:
919 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Radek Krejciadb57612016-02-16 13:34:34 +0100920 LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "Unexpected substatement \"%s\" in \"rpc\" %s.",
Michal Vasko38d01f72015-06-15 09:41:06 +0200921 strnodetype(child->nodetype), parent->name);
922 return EXIT_FAILURE;
923 }
924 break;
Radek Krejci76512572015-08-04 09:47:08 +0200925 case LYS_LEAF:
926 case LYS_LEAFLIST:
927 case LYS_ANYXML:
Radek Krejciadb57612016-02-16 13:34:34 +0100928 LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "The \"%s\" statement (%s) cannot have any data substatement.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200929 strnodetype(parent->nodetype), parent->name);
930 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200931 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200932 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200933 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
934 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejciadb57612016-02-16 13:34:34 +0100935 LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200936 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
937 return EXIT_FAILURE;
938 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200939 break;
940 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200941 /* top level */
942 if (!(child->nodetype &
943 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
944 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejciadb57612016-02-16 13:34:34 +0100945 LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "Unexpected substatement \"%s\" in (sub)module \"%s\"",
Radek Krejci2c0ca272015-08-14 15:31:01 +0200946 strnodetype(child->nodetype), module->name);
Radek Krejci10c760e2015-08-14 14:45:43 +0200947 return EXIT_FAILURE;
948 }
949
Radek Krejcic071c542016-01-27 14:57:51 +0100950 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200951 }
952
953 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200954 if (lys_check_id(child, parent, module)) {
955 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200956 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200957
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200958 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200959 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200960 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200961
Radek Krejci10c760e2015-08-14 14:45:43 +0200962 if (!parent) {
Radek Krejci92720552015-10-05 15:28:27 +0200963 if (module->data) {
964 module->data->prev->next = child;
965 child->prev = module->data->prev;
966 module->data->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200967 } else {
Radek Krejci92720552015-10-05 15:28:27 +0200968 module->data = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200969 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200970 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +0200971 if (!parent->child) {
972 /* the only/first child of the parent */
973 parent->child = child;
974 child->parent = parent;
975 iter = child;
976 } else {
977 /* add a new child at the end of parent's child list */
978 iter = parent->child->prev;
979 iter->next = child;
980 child->prev = iter;
981 }
982 while (iter->next) {
983 iter = iter->next;
984 iter->parent = parent;
985 }
986 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200987 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200988
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200989 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200990}
991
Michal Vasko1e62a092015-12-01 12:27:20 +0100992API const struct lys_module *
Radek Krejci722b0072016-02-01 17:09:45 +0100993lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200994{
Radek Krejci0b5805d2015-08-13 09:38:02 +0200995 struct lys_module *mod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200996
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200997 if (!ctx || !data) {
998 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
999 return NULL;
1000 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001001
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001002 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001003 case LYS_IN_YIN:
Radek Krejcic071c542016-01-27 14:57:51 +01001004 mod = yin_read_module(ctx, data, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001005 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001006 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001007 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001008 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001009 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001010 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001011
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001012 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001013}
1014
Michal Vasko2e7241e2016-02-15 16:06:34 +01001015int
1016lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres, struct lys_submodule **submodule)
Radek Krejciefaeba32015-05-27 14:30:57 +02001017{
Michal Vasko2e7241e2016-02-15 16:06:34 +01001018 int ret;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001019
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001020 assert(module);
1021 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001022
Radek Krejcic071c542016-01-27 14:57:51 +01001023 /* get the main module */
Michal Vasko4f0dad02016-02-15 14:08:23 +01001024 module = lys_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001025
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001026 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001027 case LYS_IN_YIN:
Michal Vasko2e7241e2016-02-15 16:06:34 +01001028 ret = yin_read_submodule(module, data, unres, submodule);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001029 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001030 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001031 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001032 /* TODO */
Michal Vasko7a17a462016-02-16 11:11:39 +01001033 ret = EXIT_FAILURE;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001034 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001035 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001036
Michal Vasko2e7241e2016-02-15 16:06:34 +01001037 return ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02001038}
1039
Michal Vasko1e62a092015-12-01 12:27:20 +01001040API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +01001041lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1042{
1043 int fd;
1044 const struct lys_module *ret;
1045
1046 if (!ctx || !path) {
1047 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1048 return NULL;
1049 }
1050
1051 fd = open(path, O_RDONLY);
1052 if (fd == -1) {
1053 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
1054 return NULL;
1055 }
1056
1057 ret = lys_parse_fd(ctx, fd, format);
1058 close(fd);
1059 return ret;
1060}
1061
1062API const struct lys_module *
1063lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001064{
Michal Vasko1e62a092015-12-01 12:27:20 +01001065 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +02001066 struct stat sb;
1067 char *addr;
1068
1069 if (!ctx || fd < 0) {
1070 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1071 return NULL;
1072 }
1073
Radek Krejci10a833c2015-12-16 15:28:37 +01001074 if (fstat(fd, &sb) == -1) {
1075 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
1076 return NULL;
1077 }
Radek Krejci3006be02015-12-17 11:24:33 +01001078 addr = mmap(NULL, sb.st_size + 1, PROT_READ, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001079 if (addr == MAP_FAILED) {
Michal Vasko662610a2015-12-07 11:25:45 +01001080 LOGERR(LY_EMEM, "Map file into memory failed (%s()).",__func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001081 return NULL;
1082 }
Radek Krejci722b0072016-02-01 17:09:45 +01001083 module = lys_parse_mem(ctx, addr, format);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001084 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001086 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001087}
1088
Michal Vasko2e7241e2016-02-15 16:06:34 +01001089int
1090lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres, struct lys_submodule **submodule)
Radek Krejciefaeba32015-05-27 14:30:57 +02001091{
Michal Vasko2e7241e2016-02-15 16:06:34 +01001092 int ret;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001093 struct stat sb;
1094 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001095
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001096 assert(module);
1097 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001098
Radek Krejci10a833c2015-12-16 15:28:37 +01001099 if (fstat(fd, &sb) == -1) {
1100 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
Michal Vasko2e7241e2016-02-15 16:06:34 +01001101 return -1;
Radek Krejci10a833c2015-12-16 15:28:37 +01001102 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001103 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001104 if (addr == MAP_FAILED) {
1105 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
Michal Vasko2e7241e2016-02-15 16:06:34 +01001106 return -1;
Pavol Vicane36ea262015-11-12 11:57:47 +01001107 }
Michal Vasko2e7241e2016-02-15 16:06:34 +01001108 ret = lys_submodule_parse(module, addr, format, unres, submodule);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001109 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +02001110
Michal Vasko2e7241e2016-02-15 16:06:34 +01001111 return ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02001112}
1113
Radek Krejci1d82ef62015-08-07 14:44:40 +02001114static struct lys_restr *
1115lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001116{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001117 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001118 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001119
Radek Krejci3733a802015-06-19 13:43:21 +02001120 if (!size) {
1121 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001122 }
Radek Krejci3733a802015-06-19 13:43:21 +02001123
1124 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001125 if (!result) {
1126 return NULL;
1127 }
Radek Krejci3733a802015-06-19 13:43:21 +02001128 for (i = 0; i < size; i++) {
1129 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1130 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1131 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1132 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1133 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1134 }
1135
1136 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001137}
1138
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001139void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001140lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001141{
1142 assert(ctx);
1143 if (!restr) {
1144 return;
1145 }
1146
1147 lydict_remove(ctx, restr->expr);
1148 lydict_remove(ctx, restr->dsc);
1149 lydict_remove(ctx, restr->ref);
1150 lydict_remove(ctx, restr->eapptag);
1151 lydict_remove(ctx, restr->emsg);
1152}
1153
Michal Vaskob84f88a2015-09-24 13:16:10 +02001154static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001155lys_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 +02001156 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001157{
1158 int i;
1159
Michal Vasko1dca6882015-10-22 14:29:42 +02001160 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001161 new->base = old->base;
1162 new->der = old->der;
1163
Michal Vasko0bd29d12015-08-19 11:45:49 +02001164 i = unres_schema_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001165 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001166 /* HACK (serious one) for unres */
1167 /* nothing else we can do but duplicate it immediately */
1168 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
Radek Krejcic071c542016-01-27 14:57:51 +01001169 new->parent = (struct lys_tpdf *)parent;
Michal Vaskob84f88a2015-09-24 13:16:10 +02001170 /* all these unres additions can fail even though they did not before */
Michal Vasko88c29542015-11-27 14:57:53 +01001171 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_DER, parent, 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001172 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001173 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001174 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001175 }
1176
Radek Krejci3733a802015-06-19 13:43:21 +02001177 switch (new->base) {
1178 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +02001179 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001180 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001181 }
Radek Krejci3733a802015-06-19 13:43:21 +02001182 break;
1183
1184 case LY_TYPE_BITS:
1185 new->info.bits.count = old->info.bits.count;
1186 if (new->info.bits.count) {
1187 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +01001188 if (!new->info.bits.bit) {
1189 LOGMEM;
1190 return -1;
1191 }
Radek Krejci3733a802015-06-19 13:43:21 +02001192 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001193 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1194 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1195 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Michal Vasko3f053ef2016-02-12 14:27:13 +01001196 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
Radek Krejci3733a802015-06-19 13:43:21 +02001197 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1198 }
1199 }
1200 break;
1201
Radek Krejcif9401c32015-06-26 16:47:36 +02001202 case LY_TYPE_DEC64:
1203 new->info.dec64.dig = old->info.dec64.dig;
1204 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001205 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +02001206 }
1207 break;
1208
Radek Krejci3733a802015-06-19 13:43:21 +02001209 case LY_TYPE_ENUM:
1210 new->info.enums.count = old->info.enums.count;
1211 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001212 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +01001213 if (!new->info.enums.enm) {
1214 LOGMEM;
1215 return -1;
1216 }
Radek Krejci3733a802015-06-19 13:43:21 +02001217 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001218 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1219 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1220 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
Michal Vasko3f053ef2016-02-12 14:27:13 +01001221 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001222 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +02001223 }
1224 }
1225 break;
1226
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001227 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001228 if (old->info.ident.ref) {
1229 new->info.ident.ref = old->info.ident.ref;
1230 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001231 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001232 assert(i != -1);
Michal Vasko88c29542015-11-27 14:57:53 +01001233 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i], 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001234 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001235 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001236 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001237 break;
1238
Radek Krejciaf351422015-06-19 14:49:38 +02001239 case LY_TYPE_INST:
1240 new->info.inst.req = old->info.inst.req;
1241 break;
1242
Radek Krejcif2860132015-06-20 12:37:20 +02001243 case LY_TYPE_INT8:
1244 case LY_TYPE_INT16:
1245 case LY_TYPE_INT32:
1246 case LY_TYPE_INT64:
1247 case LY_TYPE_UINT8:
1248 case LY_TYPE_UINT16:
1249 case LY_TYPE_UINT32:
1250 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +02001251 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001252 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001253 }
Radek Krejcif2860132015-06-20 12:37:20 +02001254 break;
1255
Radek Krejcidc4c1412015-06-19 15:39:54 +02001256 case LY_TYPE_LEAFREF:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001257 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko88c29542015-11-27 14:57:53 +01001258 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001259 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001260 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001261 break;
1262
Radek Krejci3733a802015-06-19 13:43:21 +02001263 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +02001264 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001265 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001266 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001267 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 +02001268 break;
1269
Radek Krejcie4c366b2015-07-02 10:11:31 +02001270 case LY_TYPE_UNION:
1271 new->info.uni.count = old->info.uni.count;
1272 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001273 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +01001274 if (!new->info.uni.types) {
1275 LOGMEM;
1276 return -1;
1277 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001278 for (i = 0; i < new->info.uni.count; i++) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001279 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres)) {
1280 return -1;
1281 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001282 }
1283 }
1284 break;
1285
Radek Krejci3733a802015-06-19 13:43:21 +02001286 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001287 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001288 break;
1289 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001290
1291 return EXIT_SUCCESS;
Radek Krejci3733a802015-06-19 13:43:21 +02001292}
1293
1294void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001295lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001296{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001297 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001298
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001299 assert(ctx);
1300 if (!type) {
1301 return;
1302 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001303
Michal Vasko1dca6882015-10-22 14:29:42 +02001304 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001305
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001306 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001307 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001308 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001309 free(type->info.binary.length);
1310 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001311 case LY_TYPE_BITS:
1312 for (i = 0; i < type->info.bits.count; i++) {
1313 lydict_remove(ctx, type->info.bits.bit[i].name);
1314 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1315 lydict_remove(ctx, type->info.bits.bit[i].ref);
1316 }
1317 free(type->info.bits.bit);
1318 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001319
1320 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001321 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001322 free(type->info.dec64.range);
1323 break;
1324
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001325 case LY_TYPE_ENUM:
1326 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001327 lydict_remove(ctx, type->info.enums.enm[i].name);
1328 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1329 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001330 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001331 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001332 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001333
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001334 case LY_TYPE_INT8:
1335 case LY_TYPE_INT16:
1336 case LY_TYPE_INT32:
1337 case LY_TYPE_INT64:
1338 case LY_TYPE_UINT8:
1339 case LY_TYPE_UINT16:
1340 case LY_TYPE_UINT32:
1341 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001342 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001343 free(type->info.num.range);
1344 break;
1345
Radek Krejcidc4c1412015-06-19 15:39:54 +02001346 case LY_TYPE_LEAFREF:
1347 lydict_remove(ctx, type->info.lref.path);
1348 break;
1349
Radek Krejci3733a802015-06-19 13:43:21 +02001350 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001351 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001352 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001353 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001354 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001355 }
1356 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001357 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001358
Radek Krejcie4c366b2015-07-02 10:11:31 +02001359 case LY_TYPE_UNION:
1360 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001361 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001362 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001363 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001364 break;
1365
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001366 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001367 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001368 break;
1369 }
Radek Krejci5a065542015-05-22 15:02:07 +02001370}
1371
Radek Krejci1d82ef62015-08-07 14:44:40 +02001372static void
1373lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001374{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001375 assert(ctx);
1376 if (!tpdf) {
1377 return;
1378 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001380 lydict_remove(ctx, tpdf->name);
1381 lydict_remove(ctx, tpdf->dsc);
1382 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001383
Radek Krejci1d82ef62015-08-07 14:44:40 +02001384 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001385
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001386 lydict_remove(ctx, tpdf->units);
1387 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001388}
1389
Michal Vaskob84f88a2015-09-24 13:16:10 +02001390static struct lys_tpdf *
1391lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1392{
1393 struct lys_tpdf *result;
1394 int i, j;
1395
1396 if (!size) {
1397 return NULL;
1398 }
1399
1400 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001401 if (!result) {
1402 LOGMEM;
1403 return NULL;
1404 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001405 for (i = 0; i < size; i++) {
1406 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1407 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1408 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1409 result[i].flags = old[i].flags;
1410 result[i].module = old[i].module;
1411
1412 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres)) {
1413 for (j = 0; j <= i; ++j) {
1414 lys_tpdf_free(mod->ctx, &result[j]);
1415 }
1416 free(result);
1417 return NULL;
1418 }
1419
1420 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1421 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1422 }
1423
1424 return result;
1425}
1426
Radek Krejci1d82ef62015-08-07 14:44:40 +02001427static struct lys_when *
1428lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001429{
Radek Krejci76512572015-08-04 09:47:08 +02001430 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001431
1432 if (!old) {
1433 return NULL;
1434 }
1435
1436 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001437 if (!new) {
1438 LOGMEM;
1439 return NULL;
1440 }
Radek Krejci00768f42015-06-18 17:04:04 +02001441 new->cond = lydict_insert(ctx, old->cond, 0);
1442 new->dsc = lydict_insert(ctx, old->dsc, 0);
1443 new->ref = lydict_insert(ctx, old->ref, 0);
1444
1445 return new;
1446}
1447
Michal Vasko0308dd62015-10-07 09:14:40 +02001448void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001449lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001450{
1451 if (!w) {
1452 return;
1453 }
1454
1455 lydict_remove(ctx, w->cond);
1456 lydict_remove(ctx, w->dsc);
1457 lydict_remove(ctx, w->ref);
1458
1459 free(w);
1460}
1461
Radek Krejcib7f5e412015-08-13 10:15:51 +02001462static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001463lys_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 +02001464{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001465 struct lys_node *next, *sub;
1466
Radek Krejcic071c542016-01-27 14:57:51 +01001467 /* children from a resolved augment are freed under the target node */
1468 if (!aug.target) {
1469 LY_TREE_FOR_SAFE(aug.child, next, sub) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001470 lys_node_free(sub, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01001471 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001472 }
1473
Radek Krejcib7f5e412015-08-13 10:15:51 +02001474 lydict_remove(ctx, aug.target_name);
1475 lydict_remove(ctx, aug.dsc);
1476 lydict_remove(ctx, aug.ref);
1477
1478 free(aug.features);
1479
1480 lys_when_free(ctx, aug.when);
1481
Michal Vasko7d356a52015-08-19 15:06:31 +02001482 /* Do not free the children, they were appended somewhere and their
1483 * new parent will take care of them.
1484 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001485}
1486
Radek Krejci76512572015-08-04 09:47:08 +02001487static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001488lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001489{
Radek Krejci76512572015-08-04 09:47:08 +02001490 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001491 struct lys_node *old_child, *new_child;
1492 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001493
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001494 if (!size) {
1495 return NULL;
1496 }
Radek Krejci106efc02015-06-10 14:36:27 +02001497
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001498 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001499 if (!new) {
1500 LOGMEM;
1501 return NULL;
1502 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001503 for (i = 0; i < size; i++) {
1504 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1505 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1506 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1507 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001508 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001509 new[i].nodetype = old[i].nodetype;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001510 /* this must succeed, it was already resolved once */
Michal Vasko3edeaf72016-02-11 13:17:43 +01001511 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL,
1512 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001513 LOGINT;
1514 free(new);
1515 return NULL;
1516 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001517 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001518
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001519 /* Correct the augment nodes.
1520 * This function can only be called from lys_node_dup() with uses
1521 * being the node duplicated, so we must have a case of grouping
1522 * with a uses with augments. The augmented nodes have already been
1523 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001524 * (it was set to their actual data parent, not an augment), and
1525 * the new augment does not have child pointer to its augment nodes,
1526 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001527 */
1528 LY_TREE_FOR(new[i].target->child, new_child) {
1529 if (new_child->name == old[i].child->name) {
1530 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001531 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001532 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001533 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001534 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001535 LY_TREE_FOR(old[i].child, old_child) {
1536 /* all augment nodes were connected as siblings, there can be no more after this */
1537 if (old_child->parent != (struct lys_node *)&old[i]) {
1538 break;
1539 }
1540
1541 assert(old_child->name == new_child->name);
1542
1543 new_child->parent = (struct lys_node *)&new[i];
1544 new_child = new_child->next;
1545 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001546 }
Radek Krejci106efc02015-06-10 14:36:27 +02001547
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001548 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001549}
1550
Radek Krejci76512572015-08-04 09:47:08 +02001551static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001552lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001553{
Radek Krejci76512572015-08-04 09:47:08 +02001554 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001555 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001556
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001557 if (!size) {
1558 return NULL;
1559 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001560
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001561 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001562 if (!result) {
1563 LOGMEM;
1564 return NULL;
1565 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001566 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001567 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001568 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1569 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001570 result[i].flags = old[i].flags;
1571 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001573 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001574 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001575
Radek Krejci76512572015-08-04 09:47:08 +02001576 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001577 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001578 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001579 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001580 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001581 result[i].mod.list = old[i].mod.list;
1582 }
1583 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001584
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001585 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001586}
1587
Radek Krejci1d82ef62015-08-07 14:44:40 +02001588static void
1589lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001590{
Radek Krejcia52656e2015-08-05 13:41:50 +02001591 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001592
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001593 assert(ctx);
1594 if (!ident) {
1595 return;
1596 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001597
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001598 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001599 * if caller free only a single data model which is used (its identity is
1600 * reference from identity in another module), this silly freeing can lead
1601 * to segmentation fault. But without noting if the module is used by some
1602 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001603 *
1604 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001605 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001606 */
1607 while (ident->der) {
1608 der = ident->der;
1609 ident->der = der->next;
1610 free(der);
1611 }
Radek Krejci6793db02015-05-22 17:49:54 +02001612
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001613 lydict_remove(ctx, ident->name);
1614 lydict_remove(ctx, ident->dsc);
1615 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001616
1617}
1618
Radek Krejci1d82ef62015-08-07 14:44:40 +02001619static void
1620lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001621{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001622 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001623
Radek Krejcid12f57b2015-08-06 10:43:39 +02001624 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001625 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001626 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001627 }
1628 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001629}
1630
Radek Krejci1d82ef62015-08-07 14:44:40 +02001631static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001632lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1633{
1634 int i;
1635
1636 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1637 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001638 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001639 }
1640 free(io->tpdf);
1641}
1642
Radek Krejci1d82ef62015-08-07 14:44:40 +02001643static void
1644lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001645{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001646 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001647
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001648 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001649 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001650 }
1651 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001652
Radek Krejci1d82ef62015-08-07 14:44:40 +02001653 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001654}
1655
Radek Krejci1d82ef62015-08-07 14:44:40 +02001656static void
1657lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001658{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001659 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001660
Radek Krejci46c4cd72016-01-21 15:13:52 +01001661 if (leaf->child) {
1662 /* leafref backlinks */
1663 ly_set_free((struct ly_set *)leaf->child);
1664 }
1665
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001666 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001667 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001668 }
1669 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001670
Radek Krejci1d82ef62015-08-07 14:44:40 +02001671 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001672
Radek Krejci1d82ef62015-08-07 14:44:40 +02001673 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001674 lydict_remove(ctx, leaf->units);
1675 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001676}
1677
Radek Krejci1d82ef62015-08-07 14:44:40 +02001678static void
1679lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001680{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001681 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001682
Radek Krejci46c4cd72016-01-21 15:13:52 +01001683 if (llist->child) {
1684 /* leafref backlinks */
1685 ly_set_free((struct ly_set *)llist->child);
1686 }
1687
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001688 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001689 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001690 }
1691 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001692
Radek Krejci1d82ef62015-08-07 14:44:40 +02001693 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001694
Radek Krejci1d82ef62015-08-07 14:44:40 +02001695 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001696 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001697}
1698
Radek Krejci1d82ef62015-08-07 14:44:40 +02001699static void
1700lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001701{
Radek Krejci581ce772015-11-10 17:22:40 +01001702 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001703
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001704 /* handle only specific parts for LY_NODE_LIST */
1705 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001706 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001707 }
1708 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001709
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001710 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001711 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001712 }
1713 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001714
Radek Krejci1d82ef62015-08-07 14:44:40 +02001715 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001716
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001717 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001718 for (j = 0; j > list->unique[i].expr_size; j++) {
1719 lydict_remove(ctx, list->unique[i].expr[j]);
1720 }
1721 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001722 }
1723 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001724
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001725 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001726}
1727
Radek Krejci1d82ef62015-08-07 14:44:40 +02001728static void
1729lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001730{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001731 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001732
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001733 /* handle only specific parts for LY_NODE_CONTAINER */
1734 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001735
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001736 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001737 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001738 }
1739 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001740
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001741 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001742 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001743 }
1744 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001745
Radek Krejci1d82ef62015-08-07 14:44:40 +02001746 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001747}
1748
Radek Krejci1d82ef62015-08-07 14:44:40 +02001749static void
1750lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001751{
1752 lydict_remove(ctx, f->name);
1753 lydict_remove(ctx, f->dsc);
1754 lydict_remove(ctx, f->ref);
1755 free(f->features);
1756}
1757
Radek Krejci1d82ef62015-08-07 14:44:40 +02001758static void
1759lys_deviation_free(struct ly_ctx *ctx, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001760{
Radek Krejci581ce772015-11-10 17:22:40 +01001761 int i, j, k;
Radek Krejcieb00f512015-07-01 16:44:58 +02001762
1763 lydict_remove(ctx, dev->target_name);
1764 lydict_remove(ctx, dev->dsc);
1765 lydict_remove(ctx, dev->ref);
1766
1767 for (i = 0; i < dev->deviate_size; i++) {
1768 lydict_remove(ctx, dev->deviate[i].dflt);
1769 lydict_remove(ctx, dev->deviate[i].units);
1770
1771 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1772 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001773 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001774 }
1775 free(dev->deviate[i].must);
1776
1777 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001778 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1779 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1780 }
1781 free(dev->deviate[j].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001782 }
1783 free(dev->deviate[i].unique);
1784 }
1785 }
1786 free(dev->deviate);
1787}
1788
Radek Krejci1d82ef62015-08-07 14:44:40 +02001789static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001790lys_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 +02001791{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001792 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001793
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001794 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001795 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001796 lydict_remove(ctx, uses->refine[i].dsc);
1797 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001798
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001799 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001800 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001801 }
1802 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001803
Radek Krejci76512572015-08-04 09:47:08 +02001804 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001805 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001806 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001807 lydict_remove(ctx, uses->refine[i].mod.presence);
1808 }
1809 }
1810 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001811
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001812 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001813 lys_augment_free(ctx, uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001814 }
1815 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001816
Radek Krejci1d82ef62015-08-07 14:44:40 +02001817 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001818}
1819
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001820void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001821lys_node_free(struct lys_node *node, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02001822{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001823 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001824 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001825
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001826 if (!node) {
1827 return;
1828 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001829
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001830 assert(node->module);
1831 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001832
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001833 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001834
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001835 /* remove private object */
1836 if (node->private && private_destructor) {
1837 private_destructor(node, node->private);
1838 }
1839
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001840 /* common part */
Radek Krejcid12f57b2015-08-06 10:43:39 +02001841 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1842 free(node->features);
1843 lydict_remove(ctx, node->name);
1844 lydict_remove(ctx, node->dsc);
1845 lydict_remove(ctx, node->ref);
1846 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001847
Radek Krejci46c4cd72016-01-21 15:13:52 +01001848 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
1849 LY_TREE_FOR_SAFE(node->child, next, sub) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001850 lys_node_free(sub, private_destructor);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001851 }
1852 }
1853
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001854 /* specific part */
1855 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001856 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001857 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001858 break;
Radek Krejci76512572015-08-04 09:47:08 +02001859 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001860 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001861 break;
Radek Krejci76512572015-08-04 09:47:08 +02001862 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001863 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001864 break;
Radek Krejci76512572015-08-04 09:47:08 +02001865 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001866 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001867 break;
Radek Krejci76512572015-08-04 09:47:08 +02001868 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001869 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001870 break;
Radek Krejci76512572015-08-04 09:47:08 +02001871 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001872 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001873 break;
Radek Krejci76512572015-08-04 09:47:08 +02001874 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001875 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001876 break;
Radek Krejci76512572015-08-04 09:47:08 +02001877 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001878 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001879 break;
Radek Krejci76512572015-08-04 09:47:08 +02001880 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001881 /* do nothing */
1882 break;
Radek Krejci76512572015-08-04 09:47:08 +02001883 case LYS_GROUPING:
1884 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001885 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001886 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001887 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001888
1889 case LYS_INPUT:
1890 case LYS_OUTPUT:
1891 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1892 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001893 case LYS_UNKNOWN:
1894 LOGINT;
1895 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001896 }
Radek Krejci5a065542015-05-22 15:02:07 +02001897
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001898 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001899 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001900 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001901}
1902
Michal Vasko1e62a092015-12-01 12:27:20 +01001903const struct lys_module *
1904lys_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 +02001905{
Radek Krejcic071c542016-01-27 14:57:51 +01001906 const struct lys_module *main_module;
Michal Vasko3edeaf72016-02-11 13:17:43 +01001907 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02001908
Michal Vaskoa7789a82016-02-11 15:42:55 +01001909 assert(!prefix || !name);
1910
Michal Vaskob6729c62015-10-21 12:09:47 +02001911 if (prefix && !pref_len) {
1912 pref_len = strlen(prefix);
1913 }
1914 if (name && !name_len) {
1915 name_len = strlen(name);
1916 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02001917
Michal Vasko4f0dad02016-02-15 14:08:23 +01001918 main_module = lys_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01001919
1920 /* module own prefix, submodule own prefix, (sub)module own name */
1921 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
1922 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01001923 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01001924 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02001925 }
1926
Michal Vasko8ce24d72015-10-21 11:27:26 +02001927 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01001928 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
1929 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02001930 return module->imp[i].module;
1931 }
1932 }
1933
1934 return NULL;
1935}
1936
Michal Vasko13b15832015-08-19 11:04:48 +02001937/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001938static void
Michal Vaskob746fff2016-02-11 11:37:50 +01001939module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02001940{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001941 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01001942 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001943 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001944
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001945 assert(module->ctx);
1946 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001947
Michal Vaskob746fff2016-02-11 11:37:50 +01001948 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01001949 for (i = 0; i < module->imp_size; i++) {
1950 lydict_remove(ctx, module->imp[i].prefix);
1951 }
Radek Krejcidce51452015-06-16 15:20:08 +02001952 free(module->imp);
1953
Radek Krejcic071c542016-01-27 14:57:51 +01001954 /* submodules don't have data tree, the data nodes
1955 * are placed in the main module altogether */
1956 if (!module->type) {
1957 LY_TREE_FOR_SAFE(module->data, next, iter) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001958 lys_node_free(iter, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01001959 }
Radek Krejci21181962015-06-30 14:11:00 +02001960 }
Radek Krejci5a065542015-05-22 15:02:07 +02001961
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001962 lydict_remove(ctx, module->dsc);
1963 lydict_remove(ctx, module->ref);
1964 lydict_remove(ctx, module->org);
1965 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001966
Radek Krejcieb00f512015-07-01 16:44:58 +02001967 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001968 for (i = 0; i < module->rev_size; i++) {
1969 lydict_remove(ctx, module->rev[i].dsc);
1970 lydict_remove(ctx, module->rev[i].ref);
1971 }
1972 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001973
Radek Krejcieb00f512015-07-01 16:44:58 +02001974 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001975 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001976 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001977 }
1978 module->ident_size = 0;
1979 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001980
Radek Krejcieb00f512015-07-01 16:44:58 +02001981 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001982 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001983 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001984 }
1985 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001986
Radek Krejcieb00f512015-07-01 16:44:58 +02001987 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001988 for (i = 0; i < module->inc_size; i++) {
Radek Krejcic071c542016-01-27 14:57:51 +01001989 /* complete submodule free is done only from main module since
1990 * submodules propagate their includes to the main module */
1991 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01001992 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01001993 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001994 }
1995 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001996
Radek Krejcieb00f512015-07-01 16:44:58 +02001997 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02001998 for (i = 0; i < module->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001999 lys_augment_free(ctx, module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002000 }
2001 free(module->augment);
2002
Radek Krejcieb00f512015-07-01 16:44:58 +02002003 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002004 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002005 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002006 }
2007 free(module->features);
2008
Radek Krejcieb00f512015-07-01 16:44:58 +02002009 /* deviations */
2010 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002011 lys_deviation_free(ctx, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002012 }
2013 free(module->deviation);
2014
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002015 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02002016}
2017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002018void
Michal Vaskob746fff2016-02-11 11:37:50 +01002019lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002020{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002021 if (!submodule) {
2022 return;
2023 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002024
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002025 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002026 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002027
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002028 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002029
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002030 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002031}
2032
Radek Krejci76512572015-08-04 09:47:08 +02002033struct lys_node *
Radek Krejcic071c542016-01-27 14:57:51 +01002034lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node, uint8_t flags,
2035 uint8_t nacm, struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002036{
Radek Krejcic071c542016-01-27 14:57:51 +01002037 struct lys_node *retval = NULL, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002038 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002039 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002040
Michal Vaskoc07187d2015-08-13 15:20:57 +02002041 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002042 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002043 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002044 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002045 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002046 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002047 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002048 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002049 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002050 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002051 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002052 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002053 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002054 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002055 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002056 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002057 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002058 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002059 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002060 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002061 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002062 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002063 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002064 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002065
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002066 /* we cannot just duplicate memory since the strings are stored in
2067 * dictionary and we need to update dictionary counters.
2068 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002069
Radek Krejci1d82ef62015-08-07 14:44:40 +02002070 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002071 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002072 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002073 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002074 break;
2075
Radek Krejci76512572015-08-04 09:47:08 +02002076 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002077 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002078 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002079 break;
2080
Radek Krejci76512572015-08-04 09:47:08 +02002081 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002082 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002083 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002084 break;
2085
Radek Krejci76512572015-08-04 09:47:08 +02002086 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002087 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002088 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002089 break;
2090
Radek Krejci76512572015-08-04 09:47:08 +02002091 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002092 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002093 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002094 break;
2095
Radek Krejci76512572015-08-04 09:47:08 +02002096 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002097 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002098 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002099 break;
2100
Radek Krejci76512572015-08-04 09:47:08 +02002101 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002102 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002103 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002104 break;
2105
Radek Krejci76512572015-08-04 09:47:08 +02002106 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002107 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002108 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002109 break;
2110
Radek Krejci76512572015-08-04 09:47:08 +02002111 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002112 grp = calloc(1, sizeof *grp);
2113 retval = (struct lys_node *)grp;
2114 break;
2115
Radek Krejci76512572015-08-04 09:47:08 +02002116 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002117 rpc = calloc(1, sizeof *rpc);
2118 retval = (struct lys_node *)rpc;
2119 break;
2120
Radek Krejci76512572015-08-04 09:47:08 +02002121 case LYS_INPUT:
2122 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002123 io = calloc(1, sizeof *io);
2124 retval = (struct lys_node *)io;
2125 break;
2126
Radek Krejci76512572015-08-04 09:47:08 +02002127 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002128 ntf = calloc(1, sizeof *ntf);
2129 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002130 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002131
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002132 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002133 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002134 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002135 }
Radek Krejcib388c152015-06-04 17:03:03 +02002136
Michal Vasko253035f2015-12-17 16:58:13 +01002137 if (!retval) {
2138 LOGMEM;
2139 return NULL;
2140 }
2141
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002142 /*
2143 * duplicate generic part of the structure
2144 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002145 retval->name = lydict_insert(ctx, node->name, 0);
2146 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2147 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002148 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002149 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002150 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002151 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002152 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002153 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002154
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002155 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002156 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002157
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002158 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002159
Radek Krejci1d82ef62015-08-07 14:44:40 +02002160 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002161 retval->features = calloc(retval->features_size, sizeof *retval->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002162 if (!retval->features) {
2163 LOGMEM;
2164 goto error;
2165 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002166 for (i = 0; i < node->features_size; ++i) {
Radek Krejcicf509982015-12-15 09:22:44 +01002167 retval->features[i] = (struct lys_feature *)retval;
Michal Vasko0bd29d12015-08-19 11:45:49 +02002168 if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002169 retval->features[i] = node->features[i];
Michal Vaskod23ce592015-08-06 09:55:37 +02002170 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002171 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002172
Radek Krejcic071c542016-01-27 14:57:51 +01002173 /* connect it to the parent */
2174 if (lys_node_addchild(parent, retval->module, retval)) {
2175 goto error;
2176 }
2177
2178 /* go recursively */
2179 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002180 LY_TREE_FOR(node->child, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01002181 if (!lys_node_dup(module, retval, child, retval->flags, retval->nacm, unres)) {
Michal Vasko49168a22015-08-17 16:35:41 +02002182 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002183 }
2184 }
2185 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002186
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002187 /*
2188 * duplicate specific part of the structure
2189 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002190 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002191 case LYS_CONTAINER:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002192 if (cont_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002193 cont->when = lys_when_dup(ctx, cont_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002194 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002195 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002196
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002197 cont->must_size = cont_orig->must_size;
2198 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002199
Radek Krejci1d82ef62015-08-07 14:44:40 +02002200 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci1d82ef62015-08-07 14:44:40 +02002201 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002202 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002203
Radek Krejci76512572015-08-04 09:47:08 +02002204 case LYS_CHOICE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002205 if (choice_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002206 choice->when = lys_when_dup(ctx, choice_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002207 }
2208
2209 if (choice_orig->dflt) {
Michal Vasko4f0dad02016-02-15 14:08:23 +01002210 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0, LYS_ANYXML
Radek Krejci76512572015-08-04 09:47:08 +02002211 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
Michal Vasko1e62a092015-12-01 12:27:20 +01002212 | LYS_LIST, (const struct lys_node **)&choice->dflt);
Michal Vasko49168a22015-08-17 16:35:41 +02002213 if (rc) {
2214 if (rc == EXIT_FAILURE) {
2215 LOGINT;
2216 }
2217 goto error;
2218 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002219 } else {
Michal Vaskoc68a2a22015-08-06 09:57:24 +02002220 /* useless to check return value, we don't know whether
2221 * there really wasn't any default defined or it just hasn't
2222 * been resolved, we just hope for the best :)
2223 */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002224 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002225 }
2226 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002227
Radek Krejci76512572015-08-04 09:47:08 +02002228 case LYS_LEAF:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002229 if (lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres)) {
2230 goto error;
2231 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002232 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2233
2234 if (leaf_orig->dflt) {
2235 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002236 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002237 goto error;
2238 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002239 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002240
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002241 leaf->must_size = leaf_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002242 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002243
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002244 if (leaf_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002245 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002246 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002247 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002248
Radek Krejci76512572015-08-04 09:47:08 +02002249 case LYS_LEAFLIST:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002250 if (lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres)) {
2251 goto error;
2252 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002253 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002254
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002255 llist->min = llist_orig->min;
2256 llist->max = llist_orig->max;
2257
2258 llist->must_size = llist_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002259 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002260
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002261 if (llist_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002262 llist->when = lys_when_dup(ctx, llist_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002263 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002264 break;
2265
Radek Krejci76512572015-08-04 09:47:08 +02002266 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002267 list->min = list_orig->min;
2268 list->max = list_orig->max;
2269
2270 list->must_size = list_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002271 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002272
Radek Krejci581ce772015-11-10 17:22:40 +01002273 list->tpdf_size = list_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002274 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002275
Radek Krejci581ce772015-11-10 17:22:40 +01002276 list->keys_size = list_orig->keys_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002277 if (list->keys_size) {
2278 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01002279 if (!list->keys) {
2280 LOGMEM;
2281 goto error;
2282 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002283
2284 /* we managed to resolve it before, resolve it again manually */
2285 if (list_orig->keys[0]) {
2286 for (i = 0; i < list->keys_size; ++i) {
Michal Vasko4f0dad02016-02-15 14:08:23 +01002287 rc = lys_get_sibling(list->child, lys_node_module(retval)->name, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
Michal Vasko1e62a092015-12-01 12:27:20 +01002288 (const struct lys_node **)&list->keys[i]);
Michal Vasko49168a22015-08-17 16:35:41 +02002289 if (rc) {
2290 if (rc == EXIT_FAILURE) {
2291 LOGINT;
2292 }
2293 goto error;
2294 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002295 }
2296 /* it was not resolved yet, add unres copy */
2297 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002298 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02002299 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002300 goto error;
Michal Vaskod23ce592015-08-06 09:55:37 +02002301 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002302 }
2303 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002304
Radek Krejci581ce772015-11-10 17:22:40 +01002305 list->unique_size = list_orig->unique_size;
2306 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002307 if (!list->unique) {
2308 LOGMEM;
2309 goto error;
2310 }
Radek Krejci581ce772015-11-10 17:22:40 +01002311 for (i = 0; i < list->unique_size; ++i) {
2312 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2313 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002314 if (!list->unique[i].expr) {
2315 LOGMEM;
2316 goto error;
2317 }
Radek Krejci581ce772015-11-10 17:22:40 +01002318 for (j = 0; j < list->unique[i].expr_size; j++) {
2319 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2320
2321 /* if it stays in unres list, duplicate it also there */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002322 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002323 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002324 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002325
2326 if (list_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002327 list->when = lys_when_dup(ctx, list_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002328 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002329 break;
2330
Radek Krejci76512572015-08-04 09:47:08 +02002331 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002332 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002333 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002334
2335 if (anyxml_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002336 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002337 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002338 break;
2339
Radek Krejci76512572015-08-04 09:47:08 +02002340 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002341 uses->grp = uses_orig->grp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002342
2343 if (uses_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002344 uses->when = lys_when_dup(ctx, uses_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002345 }
2346
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002347 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002348 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002349 uses->augment_size = uses_orig->augment_size;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02002350 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Michal Vaskof8c128d2015-08-06 15:25:28 +02002351 if (!uses->child) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002352 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002353 goto error;
2354 }
Michal Vaskof8c128d2015-08-06 15:25:28 +02002355 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002356 break;
2357
Radek Krejci76512572015-08-04 09:47:08 +02002358 case LYS_CASE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002359 if (cs_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002360 cs->when = lys_when_dup(ctx, cs_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002361 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002362 break;
2363
Radek Krejci76512572015-08-04 09:47:08 +02002364 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002365 grp->tpdf_size = grp_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002366 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002367 break;
2368
Radek Krejci76512572015-08-04 09:47:08 +02002369 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002370 rpc->tpdf_size = rpc_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002371 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002372 break;
2373
Radek Krejci76512572015-08-04 09:47:08 +02002374 case LYS_INPUT:
2375 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002376 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002377 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002378 break;
2379
Radek Krejci76512572015-08-04 09:47:08 +02002380 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002381 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002382 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcia01e5432015-06-16 10:35:25 +02002383 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002384
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002385 default:
Radek Krejci00768f42015-06-18 17:04:04 +02002386 /* LY_NODE_AUGMENT */
Michal Vaskod23ce592015-08-06 09:55:37 +02002387 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002388 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002389 }
2390
2391 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002392
2393error:
2394
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002395 lys_node_free(retval, NULL);
Michal Vasko49168a22015-08-17 16:35:41 +02002396 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002397}
2398
Michal Vasko13b15832015-08-19 11:04:48 +02002399void
Michal Vasko627975a2016-02-11 11:39:03 +01002400lys_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 +02002401{
Radek Krejcidce51452015-06-16 15:20:08 +02002402 struct ly_ctx *ctx;
2403 int i;
2404
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002405 if (!module) {
2406 return;
2407 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002408
Radek Krejcidce51452015-06-16 15:20:08 +02002409 /* remove schema from the context */
2410 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01002411 if (remove_from_ctx && ctx->models.used) {
Radek Krejcidce51452015-06-16 15:20:08 +02002412 for (i = 0; i < ctx->models.used; i++) {
2413 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01002414 /* move all the models to not change the order in the list */
Radek Krejcidce51452015-06-16 15:20:08 +02002415 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01002416 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 +02002417 ctx->models.list[ctx->models.used] = NULL;
2418 /* we are done */
2419 break;
2420 }
2421 }
2422 }
2423
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002424 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01002425 module_free_common(module, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002426
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002427 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01002428 lydict_remove(ctx, module->ns);
2429 lydict_remove(ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02002430
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002431 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002432}
Radek Krejci7e97c352015-06-19 16:26:34 +02002433
2434/*
2435 * op: 1 - enable, 0 - disable
2436 */
2437static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002438lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002439{
2440 int all = 0;
2441 int i, j, k;
2442
2443 if (!module || !name || !strlen(name)) {
2444 return EXIT_FAILURE;
2445 }
2446
2447 if (!strcmp(name, "*")) {
2448 /* enable all */
2449 all = 1;
2450 }
2451
2452 /* module itself */
2453 for (i = 0; i < module->features_size; i++) {
2454 if (all || !strcmp(module->features[i].name, name)) {
2455 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002456 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002457 /* enable referenced features (recursion) */
2458 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002459 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002460 module->features[i].features[k]->name, op);
2461 }
2462 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002463 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002464 }
2465 if (!all) {
2466 return EXIT_SUCCESS;
2467 }
2468 }
2469 }
2470
2471 /* submodules */
2472 for (j = 0; j < module->inc_size; j++) {
2473 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2474 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2475 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002476 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002477 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002478 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002479 }
2480 if (!all) {
2481 return EXIT_SUCCESS;
2482 }
2483 }
2484 }
2485 }
2486
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002487 /* TODO submodules of submodules ... */
2488
Radek Krejci7e97c352015-06-19 16:26:34 +02002489 if (all) {
2490 return EXIT_SUCCESS;
2491 } else {
2492 return EXIT_FAILURE;
2493 }
2494}
2495
2496API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002497lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002498{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002499 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002500}
2501
2502API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002503lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002504{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002505 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002506}
2507
2508API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002509lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002510{
2511 int i, j;
2512
2513 if (!module || !feature) {
2514 return -1;
2515 }
2516
2517 /* search for the specified feature */
2518 /* module itself */
2519 for (i = 0; i < module->features_size; i++) {
2520 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002521 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002522 return 1;
2523 } else {
2524 return 0;
2525 }
2526 }
2527 }
2528
2529 /* submodules */
2530 for (j = 0; j < module->inc_size; j++) {
2531 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2532 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002533 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002534 return 1;
2535 } else {
2536 return 0;
2537 }
2538 }
2539 }
2540 }
2541
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002542 /* feature definition not found */
2543 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002544}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002545
Radek Krejci96a10da2015-07-30 11:00:14 +02002546API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01002547lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002548{
Radek Krejci96a10da2015-07-30 11:00:14 +02002549 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002550 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002551 unsigned int count;
2552
2553 if (!module) {
2554 return NULL;
2555 }
2556
2557 count = module->features_size;
2558 for (i = 0; i < module->inc_size; i++) {
2559 count += module->inc[i].submodule->features_size;
2560 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002561 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01002562 if (!result) {
2563 LOGMEM;
2564 return NULL;
2565 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002566 if (states) {
2567 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01002568 if (!(*states)) {
2569 LOGMEM;
2570 free(result);
2571 return NULL;
2572 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002573 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002574 count = 0;
2575
2576 /* module itself */
2577 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002578 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002579 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002580 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002581 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002582 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002583 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002584 }
2585 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002586 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002587 }
2588
2589 /* submodules */
2590 for (j = 0; j < module->inc_size; j++) {
2591 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002592 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002593 if (states) {
2594 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2595 (*states)[count] = 1;
2596 } else {
2597 (*states)[count] = 0;
2598 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002599 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002600 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002601 }
2602 }
2603
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002604 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002605 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002606
2607 return result;
2608}
Michal Vaskobaefb032015-09-24 14:52:10 +02002609
Radek Krejcic071c542016-01-27 14:57:51 +01002610struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01002611lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01002612{
2613 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
2614}
2615
Michal Vasko320e8532016-02-15 13:11:57 +01002616struct lys_module *
2617lys_module(const struct lys_module *module)
2618{
2619 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
2620}
2621
Michal Vaskobaefb032015-09-24 14:52:10 +02002622API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002623lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02002624{
2625 if (!node || !node->parent) {
2626 return NULL;
2627 }
2628
2629 if (node->parent->nodetype == LYS_AUGMENT) {
2630 return ((struct lys_node_augment *)node->parent)->target;
2631 }
2632
2633 return node->parent;
2634}
Michal Vasko1b229152016-01-13 11:28:38 +01002635
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002636API void *
Michal Vasko1b229152016-01-13 11:28:38 +01002637lys_set_private(const struct lys_node *node, void *priv)
2638{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002639 void *prev;
2640
Michal Vasko1b229152016-01-13 11:28:38 +01002641 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002642 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2643 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01002644 }
2645
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002646 prev = node->private;
Michal Vasko1b229152016-01-13 11:28:38 +01002647 ((struct lys_node *)node)->private = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002648
2649 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01002650}