blob: 44111f37da3f56002d38b4ab250d95d4b3bcdbaf [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 Vasko6c629ac2016-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 Vasko6c629ac2016-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 Vasko6c629ac2016-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 Vasko6c629ac2016-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 Vasko6c629ac2016-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 Vasko5a721fd2016-02-16 12:16:48 +01001015struct lys_submodule *
1016lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001017{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001018 struct lys_submodule *submod = NULL;
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 Vasko6c629ac2016-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 Vasko5a721fd2016-02-16 12:16:48 +01001028 submod = yin_read_submodule(module, data, unres);
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 Vaskoc3d9f8c2015-07-31 14:37:24 +02001033 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001034 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001035
Michal Vasko5a721fd2016-02-16 12:16:48 +01001036 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001037}
1038
Michal Vasko1e62a092015-12-01 12:27:20 +01001039API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +01001040lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1041{
1042 int fd;
1043 const struct lys_module *ret;
1044
1045 if (!ctx || !path) {
1046 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1047 return NULL;
1048 }
1049
1050 fd = open(path, O_RDONLY);
1051 if (fd == -1) {
1052 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
1053 return NULL;
1054 }
1055
1056 ret = lys_parse_fd(ctx, fd, format);
1057 close(fd);
1058 return ret;
1059}
1060
1061API const struct lys_module *
1062lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001063{
Michal Vasko1e62a092015-12-01 12:27:20 +01001064 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +02001065 struct stat sb;
1066 char *addr;
1067
1068 if (!ctx || fd < 0) {
1069 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1070 return NULL;
1071 }
1072
Radek Krejci10a833c2015-12-16 15:28:37 +01001073 if (fstat(fd, &sb) == -1) {
1074 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
1075 return NULL;
1076 }
Radek Krejci3006be02015-12-17 11:24:33 +01001077 addr = mmap(NULL, sb.st_size + 1, PROT_READ, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001078 if (addr == MAP_FAILED) {
Michal Vasko662610a2015-12-07 11:25:45 +01001079 LOGERR(LY_EMEM, "Map file into memory failed (%s()).",__func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001080 return NULL;
1081 }
Radek Krejci722b0072016-02-01 17:09:45 +01001082 module = lys_parse_mem(ctx, addr, format);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001083 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001084
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001085 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001086}
1087
Michal Vasko5a721fd2016-02-16 12:16:48 +01001088struct lys_submodule *
1089lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001090{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001091 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001092 struct stat sb;
1093 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001094
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001095 assert(module);
1096 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001097
Radek Krejci10a833c2015-12-16 15:28:37 +01001098 if (fstat(fd, &sb) == -1) {
1099 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
Michal Vasko5a721fd2016-02-16 12:16:48 +01001100 return NULL;
Radek Krejci10a833c2015-12-16 15:28:37 +01001101 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001102 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001103 if (addr == MAP_FAILED) {
1104 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001105 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001106 }
Michal Vasko5a721fd2016-02-16 12:16:48 +01001107 submodule = lys_submodule_parse(module, addr, format, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001108 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +02001109
Michal Vasko5a721fd2016-02-16 12:16:48 +01001110 return submodule;
1111
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 Vaskod51d6ad2016-02-16 13:24:31 +01001232 if (i > -1 && unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i], 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001233 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001234 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001235 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001236 break;
1237
Radek Krejciaf351422015-06-19 14:49:38 +02001238 case LY_TYPE_INST:
1239 new->info.inst.req = old->info.inst.req;
1240 break;
1241
Radek Krejcif2860132015-06-20 12:37:20 +02001242 case LY_TYPE_INT8:
1243 case LY_TYPE_INT16:
1244 case LY_TYPE_INT32:
1245 case LY_TYPE_INT64:
1246 case LY_TYPE_UINT8:
1247 case LY_TYPE_UINT16:
1248 case LY_TYPE_UINT32:
1249 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +02001250 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001251 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001252 }
Radek Krejcif2860132015-06-20 12:37:20 +02001253 break;
1254
Radek Krejcidc4c1412015-06-19 15:39:54 +02001255 case LY_TYPE_LEAFREF:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001256 if (old->info.lref.path) {
1257 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
1258 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0)) {
1259 return -1;
1260 }
Michal Vasko49168a22015-08-17 16:35:41 +02001261 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001262 break;
1263
Radek Krejci3733a802015-06-19 13:43:21 +02001264 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +02001265 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001266 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001267 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001268 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 +02001269 break;
1270
Radek Krejcie4c366b2015-07-02 10:11:31 +02001271 case LY_TYPE_UNION:
1272 new->info.uni.count = old->info.uni.count;
1273 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001274 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +01001275 if (!new->info.uni.types) {
1276 LOGMEM;
1277 return -1;
1278 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001279 for (i = 0; i < new->info.uni.count; i++) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001280 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres)) {
1281 return -1;
1282 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001283 }
1284 }
1285 break;
1286
Radek Krejci3733a802015-06-19 13:43:21 +02001287 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001288 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001289 break;
1290 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001291
1292 return EXIT_SUCCESS;
Radek Krejci3733a802015-06-19 13:43:21 +02001293}
1294
1295void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001296lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001297{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001298 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001299
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001300 assert(ctx);
1301 if (!type) {
1302 return;
1303 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001304
Michal Vasko1dca6882015-10-22 14:29:42 +02001305 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001306
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001307 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001308 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001309 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001310 free(type->info.binary.length);
1311 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001312 case LY_TYPE_BITS:
1313 for (i = 0; i < type->info.bits.count; i++) {
1314 lydict_remove(ctx, type->info.bits.bit[i].name);
1315 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1316 lydict_remove(ctx, type->info.bits.bit[i].ref);
1317 }
1318 free(type->info.bits.bit);
1319 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001320
1321 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001322 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001323 free(type->info.dec64.range);
1324 break;
1325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001326 case LY_TYPE_ENUM:
1327 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001328 lydict_remove(ctx, type->info.enums.enm[i].name);
1329 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1330 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001331 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001332 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001333 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001334
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001335 case LY_TYPE_INT8:
1336 case LY_TYPE_INT16:
1337 case LY_TYPE_INT32:
1338 case LY_TYPE_INT64:
1339 case LY_TYPE_UINT8:
1340 case LY_TYPE_UINT16:
1341 case LY_TYPE_UINT32:
1342 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001343 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001344 free(type->info.num.range);
1345 break;
1346
Radek Krejcidc4c1412015-06-19 15:39:54 +02001347 case LY_TYPE_LEAFREF:
1348 lydict_remove(ctx, type->info.lref.path);
1349 break;
1350
Radek Krejci3733a802015-06-19 13:43:21 +02001351 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001352 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001353 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001354 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001355 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001356 }
1357 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001358 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001359
Radek Krejcie4c366b2015-07-02 10:11:31 +02001360 case LY_TYPE_UNION:
1361 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001362 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001363 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001364 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001365 break;
1366
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001367 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001368 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001369 break;
1370 }
Radek Krejci5a065542015-05-22 15:02:07 +02001371}
1372
Radek Krejci1d82ef62015-08-07 14:44:40 +02001373static void
1374lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001375{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001376 assert(ctx);
1377 if (!tpdf) {
1378 return;
1379 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001380
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001381 lydict_remove(ctx, tpdf->name);
1382 lydict_remove(ctx, tpdf->dsc);
1383 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001384
Radek Krejci1d82ef62015-08-07 14:44:40 +02001385 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001386
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001387 lydict_remove(ctx, tpdf->units);
1388 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001389}
1390
Michal Vaskob84f88a2015-09-24 13:16:10 +02001391static struct lys_tpdf *
1392lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1393{
1394 struct lys_tpdf *result;
1395 int i, j;
1396
1397 if (!size) {
1398 return NULL;
1399 }
1400
1401 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001402 if (!result) {
1403 LOGMEM;
1404 return NULL;
1405 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001406 for (i = 0; i < size; i++) {
1407 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1408 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1409 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1410 result[i].flags = old[i].flags;
1411 result[i].module = old[i].module;
1412
1413 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres)) {
1414 for (j = 0; j <= i; ++j) {
1415 lys_tpdf_free(mod->ctx, &result[j]);
1416 }
1417 free(result);
1418 return NULL;
1419 }
1420
1421 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1422 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1423 }
1424
1425 return result;
1426}
1427
Radek Krejci1d82ef62015-08-07 14:44:40 +02001428static struct lys_when *
1429lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001430{
Radek Krejci76512572015-08-04 09:47:08 +02001431 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001432
1433 if (!old) {
1434 return NULL;
1435 }
1436
1437 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001438 if (!new) {
1439 LOGMEM;
1440 return NULL;
1441 }
Radek Krejci00768f42015-06-18 17:04:04 +02001442 new->cond = lydict_insert(ctx, old->cond, 0);
1443 new->dsc = lydict_insert(ctx, old->dsc, 0);
1444 new->ref = lydict_insert(ctx, old->ref, 0);
1445
1446 return new;
1447}
1448
Michal Vasko0308dd62015-10-07 09:14:40 +02001449void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001450lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001451{
1452 if (!w) {
1453 return;
1454 }
1455
1456 lydict_remove(ctx, w->cond);
1457 lydict_remove(ctx, w->dsc);
1458 lydict_remove(ctx, w->ref);
1459
1460 free(w);
1461}
1462
Radek Krejcib7f5e412015-08-13 10:15:51 +02001463static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001464lys_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 +02001465{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001466 struct lys_node *next, *sub;
1467
Radek Krejcic071c542016-01-27 14:57:51 +01001468 /* children from a resolved augment are freed under the target node */
1469 if (!aug.target) {
1470 LY_TREE_FOR_SAFE(aug.child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001471 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001472 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001473 }
1474
Radek Krejcib7f5e412015-08-13 10:15:51 +02001475 lydict_remove(ctx, aug.target_name);
1476 lydict_remove(ctx, aug.dsc);
1477 lydict_remove(ctx, aug.ref);
1478
1479 free(aug.features);
1480
1481 lys_when_free(ctx, aug.when);
1482
Michal Vasko7d356a52015-08-19 15:06:31 +02001483 /* Do not free the children, they were appended somewhere and their
1484 * new parent will take care of them.
1485 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001486}
1487
Radek Krejci76512572015-08-04 09:47:08 +02001488static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001489lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001490{
Radek Krejci76512572015-08-04 09:47:08 +02001491 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001492 struct lys_node *old_child, *new_child;
1493 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001494
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001495 if (!size) {
1496 return NULL;
1497 }
Radek Krejci106efc02015-06-10 14:36:27 +02001498
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001499 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001500 if (!new) {
1501 LOGMEM;
1502 return NULL;
1503 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001504 for (i = 0; i < size; i++) {
1505 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1506 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1507 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1508 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001509 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001510 new[i].nodetype = old[i].nodetype;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001511
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001512 /* this must succeed, it was already resolved once */
Michal Vasko3edeaf72016-02-11 13:17:43 +01001513 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL,
1514 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001515 LOGINT;
1516 free(new);
1517 return NULL;
1518 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001519 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001520
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001521 /* Correct the augment nodes.
1522 * This function can only be called from lys_node_dup() with uses
1523 * being the node duplicated, so we must have a case of grouping
1524 * with a uses with augments. The augmented nodes have already been
1525 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001526 * (it was set to their actual data parent, not an augment), and
1527 * the new augment does not have child pointer to its augment nodes,
1528 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001529 */
1530 LY_TREE_FOR(new[i].target->child, new_child) {
1531 if (new_child->name == old[i].child->name) {
1532 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001533 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001534 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001535 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001536 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001537 LY_TREE_FOR(old[i].child, old_child) {
1538 /* all augment nodes were connected as siblings, there can be no more after this */
1539 if (old_child->parent != (struct lys_node *)&old[i]) {
1540 break;
1541 }
1542
1543 assert(old_child->name == new_child->name);
1544
1545 new_child->parent = (struct lys_node *)&new[i];
1546 new_child = new_child->next;
1547 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001548 }
Radek Krejci106efc02015-06-10 14:36:27 +02001549
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001550 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001551}
1552
Radek Krejci76512572015-08-04 09:47:08 +02001553static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001554lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001555{
Radek Krejci76512572015-08-04 09:47:08 +02001556 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001557 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001558
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001559 if (!size) {
1560 return NULL;
1561 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001562
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001563 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001564 if (!result) {
1565 LOGMEM;
1566 return NULL;
1567 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001568 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001569 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001570 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1571 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001572 result[i].flags = old[i].flags;
1573 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001574
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001575 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001576 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001577
Radek Krejci76512572015-08-04 09:47:08 +02001578 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001579 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001580 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001581 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001582 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001583 result[i].mod.list = old[i].mod.list;
1584 }
1585 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001586
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001587 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001588}
1589
Radek Krejci1d82ef62015-08-07 14:44:40 +02001590static void
1591lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001592{
Radek Krejcia52656e2015-08-05 13:41:50 +02001593 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001594
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001595 assert(ctx);
1596 if (!ident) {
1597 return;
1598 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001599
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001600 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001601 * if caller free only a single data model which is used (its identity is
1602 * reference from identity in another module), this silly freeing can lead
1603 * to segmentation fault. But without noting if the module is used by some
1604 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001605 *
1606 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001607 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001608 */
1609 while (ident->der) {
1610 der = ident->der;
1611 ident->der = der->next;
1612 free(der);
1613 }
Radek Krejci6793db02015-05-22 17:49:54 +02001614
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001615 lydict_remove(ctx, ident->name);
1616 lydict_remove(ctx, ident->dsc);
1617 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001618
1619}
1620
Radek Krejci1d82ef62015-08-07 14:44:40 +02001621static void
1622lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001623{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001624 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001625
Radek Krejcid12f57b2015-08-06 10:43:39 +02001626 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001627 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001628 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001629 }
1630 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001631}
1632
Radek Krejci1d82ef62015-08-07 14:44:40 +02001633static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001634lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1635{
1636 int i;
1637
1638 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1639 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001640 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001641 }
1642 free(io->tpdf);
1643}
1644
Radek Krejci1d82ef62015-08-07 14:44:40 +02001645static void
1646lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001647{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001648 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001649
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001650 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001651 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001652 }
1653 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001654
Radek Krejci1d82ef62015-08-07 14:44:40 +02001655 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001656}
1657
Radek Krejci1d82ef62015-08-07 14:44:40 +02001658static void
1659lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001660{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001661 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001662
Radek Krejci46c4cd72016-01-21 15:13:52 +01001663 if (leaf->child) {
1664 /* leafref backlinks */
1665 ly_set_free((struct ly_set *)leaf->child);
1666 }
1667
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001668 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001669 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001670 }
1671 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001672
Radek Krejci1d82ef62015-08-07 14:44:40 +02001673 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001674
Radek Krejci1d82ef62015-08-07 14:44:40 +02001675 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001676 lydict_remove(ctx, leaf->units);
1677 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001678}
1679
Radek Krejci1d82ef62015-08-07 14:44:40 +02001680static void
1681lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001682{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001683 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001684
Radek Krejci46c4cd72016-01-21 15:13:52 +01001685 if (llist->child) {
1686 /* leafref backlinks */
1687 ly_set_free((struct ly_set *)llist->child);
1688 }
1689
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001690 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001691 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001692 }
1693 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001694
Radek Krejci1d82ef62015-08-07 14:44:40 +02001695 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001696
Radek Krejci1d82ef62015-08-07 14:44:40 +02001697 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001698 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001699}
1700
Radek Krejci1d82ef62015-08-07 14:44:40 +02001701static void
1702lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001703{
Radek Krejci581ce772015-11-10 17:22:40 +01001704 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001705
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001706 /* handle only specific parts for LY_NODE_LIST */
1707 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001708 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001709 }
1710 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001711
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001712 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001713 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001714 }
1715 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001716
Radek Krejci1d82ef62015-08-07 14:44:40 +02001717 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001718
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001719 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001720 for (j = 0; j > list->unique[i].expr_size; j++) {
1721 lydict_remove(ctx, list->unique[i].expr[j]);
1722 }
1723 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001724 }
1725 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001726
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001727 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001728}
1729
Radek Krejci1d82ef62015-08-07 14:44:40 +02001730static void
1731lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001732{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001733 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001734
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001735 /* handle only specific parts for LY_NODE_CONTAINER */
1736 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001737
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001738 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001739 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001740 }
1741 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001742
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001743 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001744 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001745 }
1746 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001747
Radek Krejci1d82ef62015-08-07 14:44:40 +02001748 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001749}
1750
Radek Krejci1d82ef62015-08-07 14:44:40 +02001751static void
1752lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001753{
1754 lydict_remove(ctx, f->name);
1755 lydict_remove(ctx, f->dsc);
1756 lydict_remove(ctx, f->ref);
1757 free(f->features);
1758}
1759
Radek Krejci1d82ef62015-08-07 14:44:40 +02001760static void
Michal Vaskoff006c12016-02-17 11:15:19 +01001761lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001762{
Radek Krejci581ce772015-11-10 17:22:40 +01001763 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01001764 struct ly_ctx *ctx;
1765 struct lys_node *next, *elem;
1766
1767 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02001768
1769 lydict_remove(ctx, dev->target_name);
1770 lydict_remove(ctx, dev->dsc);
1771 lydict_remove(ctx, dev->ref);
1772
Michal Vaskoff006c12016-02-17 11:15:19 +01001773 /* the module was freed, but we only need the context from orig_node, use ours */
1774 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
1775 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
1776 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
1777 elem->module = module;
1778
1779 LY_TREE_DFS_END(dev->orig_node, next, elem);
1780 }
1781 lys_node_free(dev->orig_node, NULL, 0);
1782 } else {
1783 /* it's just a shallow copy, freeing one node */
1784 dev->orig_node->module = module;
1785 lys_node_free(dev->orig_node, NULL, 1);
1786 }
1787
Radek Krejcieb00f512015-07-01 16:44:58 +02001788 for (i = 0; i < dev->deviate_size; i++) {
1789 lydict_remove(ctx, dev->deviate[i].dflt);
1790 lydict_remove(ctx, dev->deviate[i].units);
1791
1792 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1793 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001794 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001795 }
1796 free(dev->deviate[i].must);
1797
1798 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001799 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1800 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1801 }
1802 free(dev->deviate[j].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001803 }
1804 free(dev->deviate[i].unique);
1805 }
1806 }
1807 free(dev->deviate);
1808}
1809
Radek Krejci1d82ef62015-08-07 14:44:40 +02001810static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001811lys_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 +02001812{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001813 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001814
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001815 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001816 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001817 lydict_remove(ctx, uses->refine[i].dsc);
1818 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001819
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001820 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001821 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001822 }
1823 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001824
Radek Krejci76512572015-08-04 09:47:08 +02001825 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001826 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001827 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001828 lydict_remove(ctx, uses->refine[i].mod.presence);
1829 }
1830 }
1831 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001832
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001833 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001834 lys_augment_free(ctx, uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001835 }
1836 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001837
Radek Krejci1d82ef62015-08-07 14:44:40 +02001838 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001839}
1840
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001841void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001842lys_node_free(struct lys_node *node, void (*private_destructor)(const struct lys_node *node, void *priv), int shallow)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001843{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001844 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001845 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001846
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001847 if (!node) {
1848 return;
1849 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001850
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001851 assert(node->module);
1852 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001853
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001854 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001855
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001856 /* remove private object */
1857 if (node->private && private_destructor) {
1858 private_destructor(node, node->private);
1859 }
1860
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001861 /* common part */
Radek Krejcid12f57b2015-08-06 10:43:39 +02001862 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1863 free(node->features);
1864 lydict_remove(ctx, node->name);
1865 lydict_remove(ctx, node->dsc);
1866 lydict_remove(ctx, node->ref);
1867 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001868
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001869 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01001870 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001871 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001872 }
1873 }
1874
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001875 /* specific part */
1876 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001877 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001878 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001879 break;
Radek Krejci76512572015-08-04 09:47:08 +02001880 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001881 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001882 break;
Radek Krejci76512572015-08-04 09:47:08 +02001883 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001884 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001885 break;
Radek Krejci76512572015-08-04 09:47:08 +02001886 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001887 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001888 break;
Radek Krejci76512572015-08-04 09:47:08 +02001889 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001890 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001891 break;
Radek Krejci76512572015-08-04 09:47:08 +02001892 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001893 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001894 break;
Radek Krejci76512572015-08-04 09:47:08 +02001895 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001896 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001897 break;
Radek Krejci76512572015-08-04 09:47:08 +02001898 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001899 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001900 break;
Radek Krejci76512572015-08-04 09:47:08 +02001901 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001902 /* do nothing */
1903 break;
Radek Krejci76512572015-08-04 09:47:08 +02001904 case LYS_GROUPING:
1905 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001906 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001907 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001908 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001909
1910 case LYS_INPUT:
1911 case LYS_OUTPUT:
1912 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1913 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001914 case LYS_UNKNOWN:
1915 LOGINT;
1916 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001917 }
Radek Krejci5a065542015-05-22 15:02:07 +02001918
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001919 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001920 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001921 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001922}
1923
Michal Vasko1e62a092015-12-01 12:27:20 +01001924const struct lys_module *
1925lys_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 +02001926{
Radek Krejcic071c542016-01-27 14:57:51 +01001927 const struct lys_module *main_module;
Michal Vasko3edeaf72016-02-11 13:17:43 +01001928 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02001929
Michal Vaskoa7789a82016-02-11 15:42:55 +01001930 assert(!prefix || !name);
1931
Michal Vaskob6729c62015-10-21 12:09:47 +02001932 if (prefix && !pref_len) {
1933 pref_len = strlen(prefix);
1934 }
1935 if (name && !name_len) {
1936 name_len = strlen(name);
1937 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02001938
Michal Vasko6c629ac2016-02-15 14:08:23 +01001939 main_module = lys_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01001940
1941 /* module own prefix, submodule own prefix, (sub)module own name */
1942 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
1943 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01001944 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01001945 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02001946 }
1947
Michal Vasko8ce24d72015-10-21 11:27:26 +02001948 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01001949 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
1950 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02001951 return module->imp[i].module;
1952 }
1953 }
1954
1955 return NULL;
1956}
1957
Michal Vasko13b15832015-08-19 11:04:48 +02001958/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001959static void
Michal Vaskob746fff2016-02-11 11:37:50 +01001960module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02001961{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001962 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01001963 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001964 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001965
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001966 assert(module->ctx);
1967 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001968
Michal Vaskob746fff2016-02-11 11:37:50 +01001969 /* just free the import array, imported modules will stay in the context */
Radek Krejcidce51452015-06-16 15:20:08 +02001970 free(module->imp);
1971
Radek Krejcic071c542016-01-27 14:57:51 +01001972 /* submodules don't have data tree, the data nodes
1973 * are placed in the main module altogether */
1974 if (!module->type) {
1975 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001976 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001977 }
Radek Krejci21181962015-06-30 14:11:00 +02001978 }
Radek Krejci5a065542015-05-22 15:02:07 +02001979
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001980 lydict_remove(ctx, module->dsc);
1981 lydict_remove(ctx, module->ref);
1982 lydict_remove(ctx, module->org);
1983 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001984
Radek Krejcieb00f512015-07-01 16:44:58 +02001985 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001986 for (i = 0; i < module->rev_size; i++) {
1987 lydict_remove(ctx, module->rev[i].dsc);
1988 lydict_remove(ctx, module->rev[i].ref);
1989 }
1990 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001991
Radek Krejcieb00f512015-07-01 16:44:58 +02001992 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001993 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001994 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001995 }
1996 module->ident_size = 0;
1997 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001998
Radek Krejcieb00f512015-07-01 16:44:58 +02001999 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002000 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002001 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002002 }
2003 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002004
Radek Krejcieb00f512015-07-01 16:44:58 +02002005 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002006 for (i = 0; i < module->inc_size; i++) {
Radek Krejcic071c542016-01-27 14:57:51 +01002007 /* complete submodule free is done only from main module since
2008 * submodules propagate their includes to the main module */
2009 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002010 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002011 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002012 }
2013 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002014
Radek Krejcieb00f512015-07-01 16:44:58 +02002015 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002016 for (i = 0; i < module->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002017 lys_augment_free(ctx, module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002018 }
2019 free(module->augment);
2020
Radek Krejcieb00f512015-07-01 16:44:58 +02002021 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002022 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002023 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002024 }
2025 free(module->features);
2026
Radek Krejcieb00f512015-07-01 16:44:58 +02002027 /* deviations */
2028 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002029 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002030 }
2031 free(module->deviation);
2032
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002033 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02002034}
2035
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002036void
Michal Vaskob746fff2016-02-11 11:37:50 +01002037lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002038{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002039 if (!submodule) {
2040 return;
2041 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002042
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002043 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002044 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002045
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002046 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002047
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002048 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002049}
2050
Radek Krejci76512572015-08-04 09:47:08 +02002051struct lys_node *
Radek Krejcic071c542016-01-27 14:57:51 +01002052lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node, uint8_t flags,
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002053 uint8_t nacm, struct unres_schema *unres, int shallow)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002054{
Radek Krejcic071c542016-01-27 14:57:51 +01002055 struct lys_node *retval = NULL, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002056 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002057 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002058
Michal Vaskoc07187d2015-08-13 15:20:57 +02002059 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002060 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002061 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002062 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002063 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002064 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002065 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002066 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002067 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002068 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002069 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002070 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002071 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002072 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002073 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002074 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002075 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002076 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002077 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002078 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002079 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002080 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002081 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002082 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002083
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002084 /* we cannot just duplicate memory since the strings are stored in
2085 * dictionary and we need to update dictionary counters.
2086 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002087
Radek Krejci1d82ef62015-08-07 14:44:40 +02002088 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002089 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002090 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002091 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002092 break;
2093
Radek Krejci76512572015-08-04 09:47:08 +02002094 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002095 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002096 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002097 break;
2098
Radek Krejci76512572015-08-04 09:47:08 +02002099 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002100 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002101 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002102 break;
2103
Radek Krejci76512572015-08-04 09:47:08 +02002104 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002105 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002106 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002107 break;
2108
Radek Krejci76512572015-08-04 09:47:08 +02002109 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002110 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002111 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002112 break;
2113
Radek Krejci76512572015-08-04 09:47:08 +02002114 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002115 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002116 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002117 break;
2118
Radek Krejci76512572015-08-04 09:47:08 +02002119 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002120 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002121 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002122 break;
2123
Radek Krejci76512572015-08-04 09:47:08 +02002124 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002125 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002126 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002127 break;
2128
Radek Krejci76512572015-08-04 09:47:08 +02002129 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002130 grp = calloc(1, sizeof *grp);
2131 retval = (struct lys_node *)grp;
2132 break;
2133
Radek Krejci76512572015-08-04 09:47:08 +02002134 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002135 rpc = calloc(1, sizeof *rpc);
2136 retval = (struct lys_node *)rpc;
2137 break;
2138
Radek Krejci76512572015-08-04 09:47:08 +02002139 case LYS_INPUT:
2140 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002141 io = calloc(1, sizeof *io);
2142 retval = (struct lys_node *)io;
2143 break;
2144
Radek Krejci76512572015-08-04 09:47:08 +02002145 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002146 ntf = calloc(1, sizeof *ntf);
2147 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002148 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002150 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002151 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002152 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002153 }
Radek Krejcib388c152015-06-04 17:03:03 +02002154
Michal Vasko253035f2015-12-17 16:58:13 +01002155 if (!retval) {
2156 LOGMEM;
2157 return NULL;
2158 }
2159
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002160 /*
2161 * duplicate generic part of the structure
2162 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002163 retval->name = lydict_insert(ctx, node->name, 0);
2164 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2165 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002166 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002167 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002168 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002169 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002170 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002171 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002172
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002173 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002174 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002175
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002176 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002177
Radek Krejci1d82ef62015-08-07 14:44:40 +02002178 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002179 retval->features = calloc(retval->features_size, sizeof *retval->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002180 if (!retval->features) {
2181 LOGMEM;
2182 goto error;
2183 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002184
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002185 if (!shallow) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002186 for (i = 0; i < node->features_size; ++i) {
2187 retval->features[i] = (struct lys_feature *)retval;
2188 if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
2189 retval->features[i] = node->features[i];
2190 }
2191 }
2192
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002193 /* connect it to the parent */
2194 if (lys_node_addchild(parent, retval->module, retval)) {
2195 goto error;
2196 }
Radek Krejcic071c542016-01-27 14:57:51 +01002197
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002198 /* go recursively */
2199 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2200 LY_TREE_FOR(node->child, child) {
2201 if (!lys_node_dup(module, retval, child, retval->flags, retval->nacm, unres, 0)) {
2202 goto error;
2203 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002204 }
2205 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002206 } else {
2207 memcpy(retval->features, node->features, retval->features_size * sizeof *retval->features);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002208 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002209
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002210 /*
2211 * duplicate specific part of the structure
2212 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002213 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002214 case LYS_CONTAINER:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002215 if (cont_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002216 cont->when = lys_when_dup(ctx, cont_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002217 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002218 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002219
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002220 cont->must_size = cont_orig->must_size;
2221 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002222
Radek Krejci1d82ef62015-08-07 14:44:40 +02002223 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci1d82ef62015-08-07 14:44:40 +02002224 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002225 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002226
Radek Krejci76512572015-08-04 09:47:08 +02002227 case LYS_CHOICE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002228 if (choice_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002229 choice->when = lys_when_dup(ctx, choice_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002230 }
2231
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002232 if (!shallow) {
2233 if (choice_orig->dflt) {
2234 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0, LYS_ANYXML
2235 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
2236 | LYS_LIST, (const struct lys_node **)&choice->dflt);
2237 if (rc) {
2238 if (rc == EXIT_FAILURE) {
2239 LOGINT;
2240 }
2241 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002242 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002243 } else {
2244 /* useless to check return value, we don't know whether
2245 * there really wasn't any default defined or it just hasn't
2246 * been resolved, we just hope for the best :)
2247 */
2248 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002249 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002250 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002251 choice->dflt = choice_orig->dflt;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002252 }
2253 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002254
Radek Krejci76512572015-08-04 09:47:08 +02002255 case LYS_LEAF:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002256 if (lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres)) {
2257 goto error;
2258 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002259 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2260
2261 if (leaf_orig->dflt) {
2262 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002263 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002264 goto error;
2265 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002266 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002267
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002268 leaf->must_size = leaf_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002269 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002270
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002271 if (leaf_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002272 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002273 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002274 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002275
Radek Krejci76512572015-08-04 09:47:08 +02002276 case LYS_LEAFLIST:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002277 if (lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres)) {
2278 goto error;
2279 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002280 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002281
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002282 llist->min = llist_orig->min;
2283 llist->max = llist_orig->max;
2284
2285 llist->must_size = llist_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002286 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002287
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002288 if (llist_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002289 llist->when = lys_when_dup(ctx, llist_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002290 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002291 break;
2292
Radek Krejci76512572015-08-04 09:47:08 +02002293 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002294 list->min = list_orig->min;
2295 list->max = list_orig->max;
2296
2297 list->must_size = list_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002298 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002299
Radek Krejci581ce772015-11-10 17:22:40 +01002300 list->tpdf_size = list_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002301 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002302
Radek Krejci581ce772015-11-10 17:22:40 +01002303 list->keys_size = list_orig->keys_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002304 if (list->keys_size) {
2305 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01002306 if (!list->keys) {
2307 LOGMEM;
2308 goto error;
2309 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002310
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002311 if (!shallow) {
2312 /* we managed to resolve it before, resolve it again manually */
2313 if (list_orig->keys[0]) {
2314 for (i = 0; i < list->keys_size; ++i) {
2315 rc = lys_get_sibling(list->child, lys_node_module(retval)->name, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2316 (const struct lys_node **)&list->keys[i]);
2317 if (rc) {
2318 if (rc == EXIT_FAILURE) {
2319 LOGINT;
2320 }
2321 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002322 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002323 }
2324 /* it was not resolved yet, add unres copy */
2325 } else {
2326 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
2327 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002328 goto error;
2329 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002330 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002331 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002332 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002333 }
2334 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002335
Radek Krejci581ce772015-11-10 17:22:40 +01002336 list->unique_size = list_orig->unique_size;
2337 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002338 if (!list->unique) {
2339 LOGMEM;
2340 goto error;
2341 }
Radek Krejci581ce772015-11-10 17:22:40 +01002342 for (i = 0; i < list->unique_size; ++i) {
2343 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2344 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002345 if (!list->unique[i].expr) {
2346 LOGMEM;
2347 goto error;
2348 }
Radek Krejci581ce772015-11-10 17:22:40 +01002349 for (j = 0; j < list->unique[i].expr_size; j++) {
2350 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2351
2352 /* if it stays in unres list, duplicate it also there */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002353 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002354 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002355 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002356
2357 if (list_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002358 list->when = lys_when_dup(ctx, list_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002359 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002360 break;
2361
Radek Krejci76512572015-08-04 09:47:08 +02002362 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002363 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002364 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002365
2366 if (anyxml_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002367 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002368 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002369 break;
2370
Radek Krejci76512572015-08-04 09:47:08 +02002371 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002372 uses->grp = uses_orig->grp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002373
2374 if (uses_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002375 uses->when = lys_when_dup(ctx, uses_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002376 }
2377
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002378 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002379 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002380 uses->augment_size = uses_orig->augment_size;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002381 if (!shallow) {
2382 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
2383 if (!uses->child) {
2384 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, 0) == -1) {
2385 goto error;
2386 }
Michal Vasko49168a22015-08-17 16:35:41 +02002387 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002388 } else {
2389 memcpy(uses->augment, uses_orig->augment, uses->augment_size * sizeof *uses->augment);
Michal Vaskof8c128d2015-08-06 15:25:28 +02002390 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002391 break;
2392
Radek Krejci76512572015-08-04 09:47:08 +02002393 case LYS_CASE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002394 if (cs_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002395 cs->when = lys_when_dup(ctx, cs_orig->when);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002396 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002397 break;
2398
Radek Krejci76512572015-08-04 09:47:08 +02002399 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002400 grp->tpdf_size = grp_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002401 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002402 break;
2403
Radek Krejci76512572015-08-04 09:47:08 +02002404 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002405 rpc->tpdf_size = rpc_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002406 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002407 break;
2408
Radek Krejci76512572015-08-04 09:47:08 +02002409 case LYS_INPUT:
2410 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002411 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002412 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002413 break;
2414
Radek Krejci76512572015-08-04 09:47:08 +02002415 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002416 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002417 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcia01e5432015-06-16 10:35:25 +02002418 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002419
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002420 default:
Radek Krejci00768f42015-06-18 17:04:04 +02002421 /* LY_NODE_AUGMENT */
Michal Vaskod23ce592015-08-06 09:55:37 +02002422 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002423 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002424 }
2425
2426 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002427
2428error:
2429
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002430 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02002431 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002432}
2433
Michal Vasko13b15832015-08-19 11:04:48 +02002434void
Michal Vaskoff006c12016-02-17 11:15:19 +01002435lys_node_switch(struct lys_node *dst, struct lys_node *src)
2436{
2437 struct lys_node *child;
2438
2439 assert((dst->module == src->module) && (dst->name == src->name) && (dst->nodetype == src->nodetype));
2440
2441 /* sibling next */
2442 if (dst->prev != dst) {
2443 dst->prev->next = src;
2444 }
2445
2446 /* sibling prev */
2447 if (dst->next) {
2448 dst->next->prev = src;
2449 }
2450
2451 /* parent child prev */
2452 if (!dst->next && dst->parent) {
2453 dst->parent->child->prev = src;
2454 }
2455
2456 /* next */
2457 src->next = dst->next;
2458 dst->next = NULL;
2459
2460 /* prev */
2461 if (dst->prev != dst) {
2462 src->prev = dst->prev;
2463 }
2464 dst->prev = dst;
2465
2466 /* parent child */
2467 if (dst->parent && (dst->parent->child == dst)) {
2468 dst->parent->child = src;
2469 }
2470
2471 /* parent */
2472 src->parent = dst->parent;
2473 dst->parent = NULL;
2474
2475 /* child parent */
2476 LY_TREE_FOR(dst->child, child) {
2477 if (child->parent == dst) {
2478 child->parent = src;
2479 }
2480 }
2481
2482 /* child */
2483 src->child = dst->child;
2484 dst->child = NULL;
2485}
2486
2487void
Michal Vasko627975a2016-02-11 11:39:03 +01002488lys_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 +02002489{
Radek Krejcidce51452015-06-16 15:20:08 +02002490 struct ly_ctx *ctx;
2491 int i;
2492
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002493 if (!module) {
2494 return;
2495 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002496
Radek Krejcidce51452015-06-16 15:20:08 +02002497 /* remove schema from the context */
2498 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01002499 if (remove_from_ctx && ctx->models.used) {
Radek Krejcidce51452015-06-16 15:20:08 +02002500 for (i = 0; i < ctx->models.used; i++) {
2501 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01002502 /* move all the models to not change the order in the list */
Radek Krejcidce51452015-06-16 15:20:08 +02002503 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01002504 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 +02002505 ctx->models.list[ctx->models.used] = NULL;
2506 /* we are done */
2507 break;
2508 }
2509 }
2510 }
2511
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002512 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01002513 module_free_common(module, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002514
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002515 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01002516 lydict_remove(ctx, module->ns);
2517 lydict_remove(ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02002518
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002519 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002520}
Radek Krejci7e97c352015-06-19 16:26:34 +02002521
2522/*
2523 * op: 1 - enable, 0 - disable
2524 */
2525static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002526lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002527{
2528 int all = 0;
2529 int i, j, k;
2530
2531 if (!module || !name || !strlen(name)) {
2532 return EXIT_FAILURE;
2533 }
2534
2535 if (!strcmp(name, "*")) {
2536 /* enable all */
2537 all = 1;
2538 }
2539
2540 /* module itself */
2541 for (i = 0; i < module->features_size; i++) {
2542 if (all || !strcmp(module->features[i].name, name)) {
2543 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002544 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002545 /* enable referenced features (recursion) */
2546 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002547 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002548 module->features[i].features[k]->name, op);
2549 }
2550 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002551 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002552 }
2553 if (!all) {
2554 return EXIT_SUCCESS;
2555 }
2556 }
2557 }
2558
2559 /* submodules */
2560 for (j = 0; j < module->inc_size; j++) {
2561 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2562 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2563 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002564 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002565 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002566 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002567 }
2568 if (!all) {
2569 return EXIT_SUCCESS;
2570 }
2571 }
2572 }
2573 }
2574
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002575 /* TODO submodules of submodules ... */
2576
Radek Krejci7e97c352015-06-19 16:26:34 +02002577 if (all) {
2578 return EXIT_SUCCESS;
2579 } else {
2580 return EXIT_FAILURE;
2581 }
2582}
2583
2584API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002585lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002586{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002587 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002588}
2589
2590API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002591lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002592{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002593 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002594}
2595
2596API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002597lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002598{
2599 int i, j;
2600
2601 if (!module || !feature) {
2602 return -1;
2603 }
2604
2605 /* search for the specified feature */
2606 /* module itself */
2607 for (i = 0; i < module->features_size; i++) {
2608 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002609 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002610 return 1;
2611 } else {
2612 return 0;
2613 }
2614 }
2615 }
2616
2617 /* submodules */
2618 for (j = 0; j < module->inc_size; j++) {
2619 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2620 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002621 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002622 return 1;
2623 } else {
2624 return 0;
2625 }
2626 }
2627 }
2628 }
2629
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002630 /* feature definition not found */
2631 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002632}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002633
Radek Krejci96a10da2015-07-30 11:00:14 +02002634API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01002635lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002636{
Radek Krejci96a10da2015-07-30 11:00:14 +02002637 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002638 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002639 unsigned int count;
2640
2641 if (!module) {
2642 return NULL;
2643 }
2644
2645 count = module->features_size;
2646 for (i = 0; i < module->inc_size; i++) {
2647 count += module->inc[i].submodule->features_size;
2648 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002649 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01002650 if (!result) {
2651 LOGMEM;
2652 return NULL;
2653 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002654 if (states) {
2655 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01002656 if (!(*states)) {
2657 LOGMEM;
2658 free(result);
2659 return NULL;
2660 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002661 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002662 count = 0;
2663
2664 /* module itself */
2665 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002666 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002667 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002668 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002669 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002670 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002671 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002672 }
2673 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002674 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002675 }
2676
2677 /* submodules */
2678 for (j = 0; j < module->inc_size; j++) {
2679 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002680 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002681 if (states) {
2682 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2683 (*states)[count] = 1;
2684 } else {
2685 (*states)[count] = 0;
2686 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002687 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002688 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002689 }
2690 }
2691
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002692 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002693 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002694
2695 return result;
2696}
Michal Vaskobaefb032015-09-24 14:52:10 +02002697
Radek Krejcic071c542016-01-27 14:57:51 +01002698struct lys_module *
Michal Vasko0c5e9282016-02-15 13:11:57 +01002699lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01002700{
2701 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
2702}
2703
Michal Vasko0c5e9282016-02-15 13:11:57 +01002704struct lys_module *
2705lys_module(const struct lys_module *module)
2706{
2707 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
2708}
2709
Michal Vaskobaefb032015-09-24 14:52:10 +02002710API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002711lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02002712{
2713 if (!node || !node->parent) {
2714 return NULL;
2715 }
2716
2717 if (node->parent->nodetype == LYS_AUGMENT) {
2718 return ((struct lys_node_augment *)node->parent)->target;
2719 }
2720
2721 return node->parent;
2722}
Michal Vasko1b229152016-01-13 11:28:38 +01002723
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002724API void *
Michal Vasko1b229152016-01-13 11:28:38 +01002725lys_set_private(const struct lys_node *node, void *priv)
2726{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002727 void *prev;
2728
Michal Vasko1b229152016-01-13 11:28:38 +01002729 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002730 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2731 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01002732 }
2733
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002734 prev = node->private;
Michal Vasko1b229152016-01-13 11:28:38 +01002735 ((struct lys_node *)node)->private = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002736
2737 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01002738}