blob: f3ea94c77b0467f4a1966e9ba257bea6f251c412 [file] [log] [blame]
Radek Krejcic6704c82015-10-06 11:12:45 +02001
Radek Krejcida04f4a2015-05-21 12:54:09 +02002/**
Michal Vasko2d162e12015-09-24 14:33:29 +02003 * @file tree_schema.c
Radek Krejcida04f4a2015-05-21 12:54:09 +02004 * @author Radek Krejci <rkrejci@cesnet.cz>
Michal Vasko2d162e12015-09-24 14:33:29 +02005 * @brief Manipulation with libyang schema data structures
Radek Krejcida04f4a2015-05-21 12:54:09 +02006 *
7 * Copyright (c) 2015 CESNET, z.s.p.o.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * 3. Neither the name of the Company nor the names of its contributors
19 * may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
21 */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020022#define _GNU_SOURCE
Radek Krejcida04f4a2015-05-21 12:54:09 +020023
Radek Krejci812b10a2015-05-28 16:48:25 +020024#include <assert.h>
Radek Krejci5a988152015-07-15 11:16:26 +020025#include <ctype.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020026#include <stdlib.h>
27#include <sys/mman.h>
Michal Vasko662610a2015-12-07 11:25:45 +010028#include <sys/types.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020029#include <sys/stat.h>
Michal Vasko662610a2015-12-07 11:25:45 +010030#include <fcntl.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020031#include <string.h>
Michal Vasko662610a2015-12-07 11:25:45 +010032#include <unistd.h>
33#include <errno.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020034
35#include "common.h"
36#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020037#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020038#include "resolve.h"
Michal Vasko88c29542015-11-27 14:57:53 +010039#include "xml.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020040#include "xml_internal.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020041#include "tree_internal.h"
Radek Krejcieab784a2015-08-27 09:56:53 +020042#include "validation.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020043
Michal Vasko1e62a092015-12-01 12:27:20 +010044API const struct lys_feature *
45lys_is_disabled(const struct lys_node *node, int recursive)
Radek Krejci48061fb2015-08-05 15:41:07 +020046{
47 int i;
48
49check:
50 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
51 /* input/output does not have if-feature, so skip them */
52
53 /* check local if-features */
54 for (i = 0; i < node->features_size; i++) {
55 if (!(node->features[i]->flags & LYS_FENABLED)) {
56 return node->features[i];
57 }
58 }
59 }
60
61 if (!recursive) {
62 return NULL;
63 }
64
65 /* go through parents */
66 if (node->nodetype == LYS_AUGMENT) {
67 /* go to parent actually means go to the target node */
68 node = ((struct lys_node_augment *)node)->target;
Radek Krejci48061fb2015-08-05 15:41:07 +020069 } else if (node->parent) {
70 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020071 } else {
72 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020073 }
74
Radek Krejci074bf852015-08-19 14:22:16 +020075 if (recursive == 2) {
76 /* continue only if the node cannot have a data instance */
77 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
78 return NULL;
79 }
80 }
81 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020082}
83
Michal Vasko1dca6882015-10-22 14:29:42 +020084int
Michal Vasko36cbaa42015-12-14 13:15:48 +010085lys_get_sibling(const struct lys_node *siblings, const char *mod_name, int mod_name_len, const char *name,
86 int nam_len, LYS_NODE type, const struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +020087{
Radek Krejcic071c542016-01-27 14:57:51 +010088 const struct lys_node *node, *parent = NULL;
89 const struct lys_module *mod = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +010090 const char *node_mod_name;
Michal Vasko1dca6882015-10-22 14:29:42 +020091
Michal Vasko36cbaa42015-12-14 13:15:48 +010092 assert(siblings && mod_name && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +020093 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +020094
Michal Vasko36cbaa42015-12-14 13:15:48 +010095 /* fill the lengths in case the caller is so indifferent */
96 if (!mod_name_len) {
97 mod_name_len = strlen(mod_name);
98 }
Michal Vasko1dca6882015-10-22 14:29:42 +020099 if (!nam_len) {
100 nam_len = strlen(name);
101 }
102
Michal Vasko36cbaa42015-12-14 13:15:48 +0100103 /* set mod correctly */
Radek Krejcic071c542016-01-27 14:57:51 +0100104 parent = lys_parent(siblings);
105 if (!parent) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100106 mod = lys_node_module(siblings);
Michal Vasko1dca6882015-10-22 14:29:42 +0200107 }
108
Radek Krejcic071c542016-01-27 14:57:51 +0100109 /* try to find the node */
110 node = NULL;
111 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
112 if (!type || (node->nodetype & type)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100113 /* module name comparison */
114 node_mod_name = lys_node_module(node)->name;
115 if ((node_mod_name != mod_name) && (strncmp(node_mod_name, mod_name, mod_name_len) || node_mod_name[mod_name_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100116 continue;
117 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200118
Radek Krejcic071c542016-01-27 14:57:51 +0100119 /* direct name check */
120 if ((node->name == name) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
121 if (ret) {
122 *ret = node;
Michal Vasko1dca6882015-10-22 14:29:42 +0200123 }
Radek Krejcic071c542016-01-27 14:57:51 +0100124 return EXIT_SUCCESS;
Michal Vasko1dca6882015-10-22 14:29:42 +0200125 }
126 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200127 }
128
129 return EXIT_FAILURE;
130}
131
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200132int
Michal Vasko1e62a092015-12-01 12:27:20 +0100133lys_get_data_sibling(const struct lys_module *mod, const struct lys_node *siblings, const char *name, LYS_NODE type,
134 const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200135{
Michal Vasko1e62a092015-12-01 12:27:20 +0100136 const struct lys_node *node;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200137
138 assert(siblings && name);
139 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
140
141 /* find the beginning */
142 while (siblings->prev->next) {
143 siblings = siblings->prev;
144 }
145
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200146 if (!mod) {
147 mod = siblings->module;
148 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200149
Michal Vasko4f0dad02016-02-15 14:08:23 +0100150 /* try to find the node */
151 node = NULL;
152 while ((node = lys_getnext(node, siblings->parent, mod, 0))) {
153 if (!type || (node->nodetype & type)) {
154 /* module check */
155 if (lys_node_module(node) != lys_module(mod)) {
Radek Krejcic071c542016-01-27 14:57:51 +0100156 continue;
157 }
158
Michal Vasko4f0dad02016-02-15 14:08:23 +0100159 /* direct name check */
Radek Krejci749190d2016-02-18 16:26:25 +0100160 if (ly_strequal(node->name, name, 0)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100161 if (ret) {
162 *ret = node;
163 }
164 return EXIT_SUCCESS;
165 }
Radek Krejcic071c542016-01-27 14:57:51 +0100166 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200167 }
168
169 return EXIT_FAILURE;
170}
171
Michal Vasko1e62a092015-12-01 12:27:20 +0100172API const struct lys_node *
173lys_getnext(const struct lys_node *last, const struct lys_node *parent, const struct lys_module *module, int options)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200174{
Michal Vasko1e62a092015-12-01 12:27:20 +0100175 const struct lys_node *next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200176
Radek Krejci8bc87f62015-09-02 16:19:05 +0200177 if (!last) {
178 /* first call */
179
180 /* get know where to start */
181 if (parent) {
182 /* schema subtree */
183 next = last = parent->child;
184 } else {
185 /* top level data */
186 assert(module);
187 next = last = module->data;
188 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200189 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200190 /* continue after the last returned value */
191 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200192 }
193
194repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200195 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200196 if (options & LYS_GETNEXT_WITHGROUPING) {
197 return next;
198 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200199 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200200 }
201
Radek Krejcic4ccbd92016-01-07 13:13:33 +0100202 if (!next) {
Radek Krejci63318e82016-02-12 09:43:12 +0100203 if (!last || lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200204 /* no next element */
205 return NULL;
206 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200207 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200208 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200209 goto repeat;
210 }
211
212 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200213 case LYS_INPUT:
214 case LYS_OUTPUT:
215 if (options & LYS_GETNEXT_WITHINOUT) {
216 return next;
217 } else {
218 next = next->child;
219 goto repeat;
220 }
221 break;
222
Michal Vaskoa5835e92015-10-20 15:07:39 +0200223 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200224 if (options & LYS_GETNEXT_WITHCASE) {
225 return next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200226 } else {
227 next = next->child;
228 goto repeat;
Michal Vasko1dca6882015-10-22 14:29:42 +0200229 }
Michal Vaskob6eedf02015-10-22 16:07:03 +0200230 break;
231
Michal Vasko1dca6882015-10-22 14:29:42 +0200232 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200233 /* go into */
234 next = next->child;
235 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200236
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200237 case LYS_RPC:
238 case LYS_NOTIF:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200239 case LYS_CONTAINER:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200240 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200241 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200242 case LYS_LIST:
243 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200244 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200245
246 case LYS_CHOICE:
247 if (options & LYS_GETNEXT_WITHCHOICE) {
248 return next;
249 } else {
250 /* go into */
251 next = next->child;
252 goto repeat;
253 }
254 break;
255
Radek Krejci7f40ce32015-08-12 20:38:46 +0200256 default:
257 /* we should not be here */
258 return NULL;
259 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200260
261
262}
263
Michal Vasko1e62a092015-12-01 12:27:20 +0100264static const struct lys_node *
Radek Krejci2342cf62016-01-29 16:48:23 +0100265check_mand_getnext(const struct lys_node *last, const struct lys_node *parent, const struct lys_module *module)
Radek Krejci8bc87f62015-09-02 16:19:05 +0200266{
Michal Vasko1e62a092015-12-01 12:27:20 +0100267 const struct lys_node *next;
268
Radek Krejci2342cf62016-01-29 16:48:23 +0100269 next = lys_getnext(last, parent, module, LYS_GETNEXT_WITHCHOICE);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200270
Radek Krejci4b6c2112015-10-06 12:48:34 +0200271repeat:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200272 if (next && next->nodetype == LYS_CONTAINER) {
273 if (((struct lys_node_container *)next)->presence) {
274 /* mandatory elements under the non-existing presence
275 * container are not mandatory - 7.6.5, rule 1 */
276 next = next->next;
277 } else {
278 /* go into */
279 next = next->child;
280 }
281 goto repeat;
282 }
283
284 return next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200285}
286
Michal Vasko1e62a092015-12-01 12:27:20 +0100287static const struct lys_node *
288check_mand_check(const struct lys_node *node, const struct lys_node *stop, const struct lyd_node *data)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200289{
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200290 struct lys_node *siter = NULL, *parent = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200291 struct lyd_node *diter = NULL;
Radek Krejcidc154432016-01-21 11:10:59 +0100292 struct ly_set *set = NULL;
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200293 unsigned int i;
Radek Krejci14a11a62015-08-17 17:27:38 +0200294 uint32_t minmax;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200295
296 if (node->flags & LYS_MAND_TRUE) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100297 if (!data) {
298 /* we have no data but a mandatory node */
299 return node;
300 }
301 switch (node->nodetype) {
302 case LYS_LEAF:
303 case LYS_ANYXML:
304 case LYS_CHOICE:
305 if (node->parent && node->parent->nodetype == LYS_CASE) {
306 /* 7.6.5, rule 2 */
307 /* 7.9.4, rule 1 */
308 if (node->parent->parent->parent == data->schema) {
309 /* the only case the node's siblings can exist is that the
310 * data node passed originally to ly_check_mandatory()
311 * had this choice as a child
312 */
313 /* try to find the node's siblings in data */
314 LY_TREE_FOR(data->child, diter) {
315 LY_TREE_FOR(node->parent->child, siter) {
316 if (siter == diter->schema) {
317 /* some sibling exists, rule applies */
318 break;
319 }
320 }
321 if (siter) {
322 break;
323 }
324 }
325 }
326 if (!siter) {
327 /* no sibling exists */
328 return NULL;
329 }
330 } else {
Radek Krejci7eb12132016-02-01 10:55:23 +0100331 for (parent = node->parent; parent && parent != stop; parent = parent->parent) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100332 if (parent->nodetype != LYS_CONTAINER) {
333 /* 7.6.5, rule 1, checking presence is not needed
334 * since it is done in check_mand_getnext()
335 */
336 ly_set_free(set);
337 return NULL;
338 }
339 /* add the parent to the list for searching in data tree */
340 if (!set) {
341 set = ly_set_new();
342 }
343 /* ignore return - memory error is logged and we will
344 * check at least the rest of nodes we have */
345 (void)ly_set_add(set, parent);
346 }
347 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200348
Radek Krejci2342cf62016-01-29 16:48:23 +0100349 /* search for instance */
350 if (set) {
351 for (i = 0; i < set->number; i++) {
352 LY_TREE_FOR(data->child, diter) {
353 if (diter->schema == set->sset[i]) {
354 break;
355 }
356 }
357 if (!diter) {
358 /* instance not found */
359 node = set->sset[i];
360 ly_set_free(set);
361 return node;
362 }
363 data = diter;
364 }
365 ly_set_free(set);
366 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200367
Radek Krejci2342cf62016-01-29 16:48:23 +0100368 LY_TREE_FOR(data->child, diter) {
369 if (diter->schema == node) {
370 return NULL;
371 }
372 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200373
Radek Krejci2342cf62016-01-29 16:48:23 +0100374 /* instance not found */
375 /* 7.6.5, rule 3 (or 2) */
376 /* 7.9.4, rule 2 */
377 return node;
378 default:
379 /* error */
380 break;
381 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200382 } else if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
383 /* search for number of instances */
384 minmax = 0;
Radek Krejci2342cf62016-01-29 16:48:23 +0100385 if (data) {
386 LY_TREE_FOR(data->child, diter) {
387 if (diter->schema == node) {
388 minmax++;
389 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200390 }
391 }
392
393 /* check the specified constraints */
394 if (node->nodetype == LYS_LIST) {
395 if (((struct lys_node_list *)node)->min && minmax < ((struct lys_node_list *)node)->min) {
396 return node;
397 }
398
399 if (((struct lys_node_list *)node)->max && minmax > ((struct lys_node_list *)node)->max) {
400 return node;
401 }
402 } else if (node->nodetype == LYS_LEAFLIST) {
403 if (((struct lys_node_leaflist *)node)->min && minmax < ((struct lys_node_leaflist *)node)->min) {
404 return node;
405 }
406
407 if (((struct lys_node_leaflist *)node)->max && minmax > ((struct lys_node_leaflist *)node)->max) {
408 return node;
409 }
410 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200411 }
412
413 return NULL;
414}
415
Michal Vasko1e62a092015-12-01 12:27:20 +0100416const struct lys_node *
Radek Krejci2342cf62016-01-29 16:48:23 +0100417ly_check_mandatory(const struct lyd_node *data, const struct lys_node *schema)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200418{
Michal Vasko1e62a092015-12-01 12:27:20 +0100419 const struct lys_node *siter, *saux, *saux2, *result, *parent = NULL, *parent2;
420 const struct lyd_node *diter;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200421 int found;
422
Radek Krejci2342cf62016-01-29 16:48:23 +0100423 assert(data || schema);
424
425 if (!data) { /* !data && schema */
426 siter = schema;
427 } else { /* data && !schema */
Radek Krejcie2f12212016-02-12 13:50:22 +0100428 schema = data->schema;
429 siter = data->schema->child;
Radek Krejci2342cf62016-01-29 16:48:23 +0100430 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200431
432repeat:
433 while (siter) {
Radek Krejci074bf852015-08-19 14:22:16 +0200434 if (lys_is_disabled(siter, 2)) {
435 siter = siter->next;
436 continue;
437 }
438
Radek Krejci7f40ce32015-08-12 20:38:46 +0200439 switch (siter->nodetype) {
440 case LYS_CONTAINER:
441 case LYS_LEAF:
442 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200443 case LYS_LIST:
444 case LYS_LEAFLIST:
445 /* check if there is some mandatory node; first test the siter itself ... */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200446 result = check_mand_check(siter, siter->parent, data);
447 if (result) {
448 return result;
449 }
450 /* ... and then the subtree */
Radek Krejci14a11a62015-08-17 17:27:38 +0200451 if (parent && siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
452 saux = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100453 while ((saux = check_mand_getnext(saux, siter, NULL))) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200454 result = check_mand_check(saux, siter, data);
455 if (result) {
456 return result;
457 }
458 }
459 }
460 siter = siter->next;
461 break;
462 case LYS_CHOICE:
Radek Krejci14a11a62015-08-17 17:27:38 +0200463 /* search for instance */
464 saux = siter;
465 siter = siter->child;
466 found = 0;
467 parent2 = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200468repeat_choice:
Radek Krejci2342cf62016-01-29 16:48:23 +0100469 while (siter && data) {
Radek Krejci074bf852015-08-19 14:22:16 +0200470 if (lys_is_disabled(siter, 2)) {
471 siter = siter->next;
472 continue;
473 }
474
Radek Krejci14a11a62015-08-17 17:27:38 +0200475 switch (siter->nodetype) {
476 case LYS_CONTAINER:
477 case LYS_LEAF:
478 case LYS_LEAFLIST:
479 case LYS_LIST:
480 case LYS_ANYXML:
481 LY_TREE_FOR(data->child, diter) {
482 if (diter->schema == siter) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200483 break;
484 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200485 }
486 if (diter) {
487 /* got instance */
488 /* check presence of mandatory siblings */
Radek Krejci65d0a652015-08-27 13:09:42 +0200489 if (parent2 && parent2->nodetype == LYS_CASE) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200490 saux2 = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100491 while ((saux2 = check_mand_getnext(saux2, parent2, NULL))) {
Radek Krejci37bda002015-08-27 11:23:56 +0200492 result = check_mand_check(saux2, parent2, data);
Radek Krejci14a11a62015-08-17 17:27:38 +0200493 if (result) {
494 return result;
495 }
496 }
497 }
498 siter = parent2 = NULL;
499 found = 1;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200500 break;
501 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200502 siter = siter->next;
503 break;
504 case LYS_CASE:
505 case LYS_CHOICE:
506 case LYS_USES:
507 /* go into */
Radek Krejci37bda002015-08-27 11:23:56 +0200508 if (!parent2) {
509 parent2 = siter;
510 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200511 siter = siter->child;
512 break;
513 case LYS_AUGMENT:
514 case LYS_GROUPING:
515 /* skip */
516 siter = siter->next;
517 break;
518 default:
519 /* error */
520 break;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200521 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200522 }
523
Radek Krejci14a11a62015-08-17 17:27:38 +0200524 if (parent2) {
525 siter = parent2->next;
526 if (parent2->parent == saux) {
527 parent2 = NULL;
528 } else {
529 parent2 = parent2->parent;
530 }
531 goto repeat_choice;
532 }
533
Radek Krejci074bf852015-08-19 14:22:16 +0200534 if (!found && (saux->flags & LYS_MAND_TRUE)) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200535 return saux;
536 }
537
538 /* go to next */
539 siter = saux->next;
540
Radek Krejci7f40ce32015-08-12 20:38:46 +0200541 break;
542 case LYS_USES:
543 case LYS_CASE:
544 /* go into */
545 parent = siter;
546 siter = siter->child;
547 break;
548 default:
549 /* can ignore, go to next */
550 siter = siter->next;
551 break;
552 }
553 }
554
555 if (parent) {
556 siter = parent->next;
Radek Krejci2342cf62016-01-29 16:48:23 +0100557 if (parent->parent == schema) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200558 parent = NULL;
559 } else {
560 parent = parent->parent;
561 }
562 goto repeat;
563 }
564
565 return NULL;
566}
567
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200568void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200569lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200570{
Radek Krejci76512572015-08-04 09:47:08 +0200571 struct lys_node *parent, *first;
Radek Krejcic071c542016-01-27 14:57:51 +0100572 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200573
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200574 if (!node) {
575 return;
576 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200577
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200578 /* unlink from data model if necessary */
579 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100580 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100581 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100582 if (main_module->data == node) {
583 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200584 }
585 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200586
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200587 /* store pointers to important nodes */
588 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200589 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200590 /* handle augments - first, unlink it from the augment parent ... */
591 if (parent->child == node) {
592 parent->child = node->next;
593 }
594 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200595 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200596 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200597
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200598 /* unlink from parent */
599 if (parent) {
600 if (parent->child == node) {
601 parent->child = node->next;
602 }
603 node->parent = NULL;
604 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200605
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200606 /* unlink from siblings */
607 if (node->prev == node) {
608 /* there are no more siblings */
609 return;
610 }
611 if (node->next) {
612 node->next->prev = node->prev;
613 } else {
614 /* unlinking the last element */
615 if (parent) {
616 first = parent->child;
617 } else {
618 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200619 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200620 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200621 }
622 }
623 first->prev = node->prev;
624 }
625 if (node->prev->next) {
626 node->prev->next = node->next;
627 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200628
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200629 /* clean up the unlinked element */
630 node->next = NULL;
631 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200632}
633
Michal Vasko563ef092015-09-04 13:17:23 +0200634struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100635lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200636{
637 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200638
639 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200640 /* top-level augment, look into module (uses augment is handled correctly below) */
641 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
642 par_iter = par_iter->parent->module->data;
643 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200644 break;
645 }
646 }
647
Michal Vasko6f929da2015-10-02 16:23:25 +0200648 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200649 continue;
650 }
651
652 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
653 if (!stop) {
654 stop = par_iter;
655 } else if (iter == stop) {
656 break;
657 }
658 if (iter->nodetype != LYS_GROUPING) {
659 continue;
660 }
661
Radek Krejcif8426a72015-10-31 23:14:03 +0100662 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200663 return (struct lys_node_grp *)iter;
664 }
665 }
666 }
667
Michal Vasko563ef092015-09-04 13:17:23 +0200668 return NULL;
669}
670
Radek Krejci10c760e2015-08-14 14:45:43 +0200671/*
672 * get next grouping in the root's subtree, in the
673 * first call, tha last is NULL
674 */
675static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200676lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200677{
Radek Krejci10c760e2015-08-14 14:45:43 +0200678 struct lys_node *last = (struct lys_node *)lastgrp;
679 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200680
Radek Krejci10c760e2015-08-14 14:45:43 +0200681 assert(root);
682
683 if (!last) {
684 last = root;
685 }
686
687 while (1) {
688 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
689 next = last->child;
690 } else {
691 next = NULL;
692 }
693 if (!next) {
694 if (last == root) {
695 /* we are done */
696 return NULL;
697 }
698
699 /* no children, go to siblings */
700 next = last->next;
701 }
702 while (!next) {
703 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100704 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200705 /* we are done */
706 return NULL;
707 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200708 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100709 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200710 }
711
712 if (next->nodetype == LYS_GROUPING) {
713 return (struct lys_node_grp *)next;
714 }
715
716 last = next;
717 }
718}
719
Michal Vasko0d343d12015-08-24 14:57:36 +0200720/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200721int
Radek Krejci07911992015-08-14 15:13:31 +0200722lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
723{
Michal Vasko563ef092015-09-04 13:17:23 +0200724 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200725 struct lys_node_grp *grp;
726 int down;
727
728 assert(node);
729
730 if (!parent) {
731 assert(module);
732 } else {
733 module = parent->module;
734 }
735
736 switch (node->nodetype) {
737 case LYS_GROUPING:
738 /* 6.2.1, rule 6 */
739 if (parent) {
740 if (parent->child) {
741 down = 1;
742 start = parent->child;
743 } else {
744 down = 0;
745 start = parent;
746 }
747 } else {
748 down = 1;
749 start = module->data;
750 }
751 /* go up */
Radek Krejcic071c542016-01-27 14:57:51 +0100752 if (lys_find_grouping_up(node->name, start)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100753 LOGVAL(LYE_DUPID, 0, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200754 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200755 }
756 /* go down, because grouping can be defined after e.g. container in which is collision */
757 if (down) {
758 for (iter = start, stop = NULL; iter; iter = iter->prev) {
759 if (!stop) {
760 stop = start;
761 } else if (iter == stop) {
762 break;
763 }
764 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
765 continue;
766 }
767
768 grp = NULL;
769 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100770 if (ly_strequal(node->name, grp->name, 1)) {
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)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100808 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
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
Radek Krejci749190d2016-02-18 16:26:25 +0100853 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
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 Vasko4f0dad02016-02-15 14:08:23 +01001024 module = lys_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001025
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001026 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001027 case LYS_IN_YIN:
Michal 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) {
Radek Krejciaa2a8932016-02-17 15:03:14 +01001126 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +01001127 return NULL;
1128 }
Radek Krejci3733a802015-06-19 13:43:21 +02001129 for (i = 0; i < size; i++) {
1130 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1131 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1132 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1133 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1134 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1135 }
1136
1137 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001138}
1139
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001140void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001141lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001142{
1143 assert(ctx);
1144 if (!restr) {
1145 return;
1146 }
1147
1148 lydict_remove(ctx, restr->expr);
1149 lydict_remove(ctx, restr->dsc);
1150 lydict_remove(ctx, restr->ref);
1151 lydict_remove(ctx, restr->eapptag);
1152 lydict_remove(ctx, restr->emsg);
1153}
1154
Michal Vaskob84f88a2015-09-24 13:16:10 +02001155static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001156lys_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 +02001157 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001158{
1159 int i;
1160
Michal Vasko1dca6882015-10-22 14:29:42 +02001161 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001162 new->base = old->base;
1163 new->der = old->der;
1164
Michal Vasko0bd29d12015-08-19 11:45:49 +02001165 i = unres_schema_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001166 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001167 /* HACK (serious one) for unres */
1168 /* nothing else we can do but duplicate it immediately */
1169 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
Radek Krejcic071c542016-01-27 14:57:51 +01001170 new->parent = (struct lys_tpdf *)parent;
Michal Vaskob84f88a2015-09-24 13:16:10 +02001171 /* all these unres additions can fail even though they did not before */
Michal Vasko88c29542015-11-27 14:57:53 +01001172 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_DER, parent, 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001173 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001174 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001175 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001176 }
1177
Radek Krejci3733a802015-06-19 13:43:21 +02001178 switch (new->base) {
1179 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +02001180 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001181 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001182 }
Radek Krejci3733a802015-06-19 13:43:21 +02001183 break;
1184
1185 case LY_TYPE_BITS:
1186 new->info.bits.count = old->info.bits.count;
1187 if (new->info.bits.count) {
1188 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +01001189 if (!new->info.bits.bit) {
1190 LOGMEM;
1191 return -1;
1192 }
Radek Krejci3733a802015-06-19 13:43:21 +02001193 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001194 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1195 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1196 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Michal Vasko3f053ef2016-02-12 14:27:13 +01001197 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
Radek Krejci3733a802015-06-19 13:43:21 +02001198 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1199 }
1200 }
1201 break;
1202
Radek Krejcif9401c32015-06-26 16:47:36 +02001203 case LY_TYPE_DEC64:
1204 new->info.dec64.dig = old->info.dec64.dig;
1205 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001206 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +02001207 }
1208 break;
1209
Radek Krejci3733a802015-06-19 13:43:21 +02001210 case LY_TYPE_ENUM:
1211 new->info.enums.count = old->info.enums.count;
1212 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001213 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +01001214 if (!new->info.enums.enm) {
1215 LOGMEM;
1216 return -1;
1217 }
Radek Krejci3733a802015-06-19 13:43:21 +02001218 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001219 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1220 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1221 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
Michal Vasko3f053ef2016-02-12 14:27:13 +01001222 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001223 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +02001224 }
1225 }
1226 break;
1227
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001228 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001229 if (old->info.ident.ref) {
1230 new->info.ident.ref = old->info.ident.ref;
1231 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001232 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001233 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 +02001234 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001235 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001236 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001237 break;
1238
Radek Krejciaf351422015-06-19 14:49:38 +02001239 case LY_TYPE_INST:
1240 new->info.inst.req = old->info.inst.req;
1241 break;
1242
Radek Krejcif2860132015-06-20 12:37:20 +02001243 case LY_TYPE_INT8:
1244 case LY_TYPE_INT16:
1245 case LY_TYPE_INT32:
1246 case LY_TYPE_INT64:
1247 case LY_TYPE_UINT8:
1248 case LY_TYPE_UINT16:
1249 case LY_TYPE_UINT32:
1250 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +02001251 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001252 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001253 }
Radek Krejcif2860132015-06-20 12:37:20 +02001254 break;
1255
Radek Krejcidc4c1412015-06-19 15:39:54 +02001256 case LY_TYPE_LEAFREF:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001257 if (old->info.lref.path) {
1258 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
1259 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0)) {
1260 return -1;
1261 }
Michal Vasko49168a22015-08-17 16:35:41 +02001262 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001263 break;
1264
Radek Krejci3733a802015-06-19 13:43:21 +02001265 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +02001266 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001267 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001268 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001269 new->info.str.patterns = lys_restr_dup(mod->ctx, old->info.str.patterns, old->info.str.pat_count);
Radek Krejciaa2a8932016-02-17 15:03:14 +01001270 new->info.str.pat_count = old->info.str.pat_count;
Radek Krejci3733a802015-06-19 13:43:21 +02001271 break;
1272
Radek Krejcie4c366b2015-07-02 10:11:31 +02001273 case LY_TYPE_UNION:
1274 new->info.uni.count = old->info.uni.count;
1275 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001276 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +01001277 if (!new->info.uni.types) {
1278 LOGMEM;
1279 return -1;
1280 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001281 for (i = 0; i < new->info.uni.count; i++) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001282 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres)) {
1283 return -1;
1284 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001285 }
1286 }
1287 break;
1288
Radek Krejci3733a802015-06-19 13:43:21 +02001289 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001290 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001291 break;
1292 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001293
1294 return EXIT_SUCCESS;
Radek Krejci3733a802015-06-19 13:43:21 +02001295}
1296
1297void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001298lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001299{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001300 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001302 assert(ctx);
1303 if (!type) {
1304 return;
1305 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001306
Michal Vasko1dca6882015-10-22 14:29:42 +02001307 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001308
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001309 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001310 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001311 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001312 free(type->info.binary.length);
1313 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001314 case LY_TYPE_BITS:
1315 for (i = 0; i < type->info.bits.count; i++) {
1316 lydict_remove(ctx, type->info.bits.bit[i].name);
1317 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1318 lydict_remove(ctx, type->info.bits.bit[i].ref);
1319 }
1320 free(type->info.bits.bit);
1321 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001322
1323 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001324 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001325 free(type->info.dec64.range);
1326 break;
1327
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001328 case LY_TYPE_ENUM:
1329 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001330 lydict_remove(ctx, type->info.enums.enm[i].name);
1331 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1332 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001333 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001334 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001335 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001336
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001337 case LY_TYPE_INT8:
1338 case LY_TYPE_INT16:
1339 case LY_TYPE_INT32:
1340 case LY_TYPE_INT64:
1341 case LY_TYPE_UINT8:
1342 case LY_TYPE_UINT16:
1343 case LY_TYPE_UINT32:
1344 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001345 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001346 free(type->info.num.range);
1347 break;
1348
Radek Krejcidc4c1412015-06-19 15:39:54 +02001349 case LY_TYPE_LEAFREF:
1350 lydict_remove(ctx, type->info.lref.path);
1351 break;
1352
Radek Krejci3733a802015-06-19 13:43:21 +02001353 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001354 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001355 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001356 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001357 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001358 }
1359 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001360 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001361
Radek Krejcie4c366b2015-07-02 10:11:31 +02001362 case LY_TYPE_UNION:
1363 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001364 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001365 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001366 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001367 break;
1368
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001369 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001370 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001371 break;
1372 }
Radek Krejci5a065542015-05-22 15:02:07 +02001373}
1374
Radek Krejci1d82ef62015-08-07 14:44:40 +02001375static void
1376lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001377{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001378 assert(ctx);
1379 if (!tpdf) {
1380 return;
1381 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001382
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001383 lydict_remove(ctx, tpdf->name);
1384 lydict_remove(ctx, tpdf->dsc);
1385 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001386
Radek Krejci1d82ef62015-08-07 14:44:40 +02001387 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001388
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001389 lydict_remove(ctx, tpdf->units);
1390 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001391}
1392
Michal Vaskob84f88a2015-09-24 13:16:10 +02001393static struct lys_tpdf *
1394lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1395{
1396 struct lys_tpdf *result;
1397 int i, j;
1398
1399 if (!size) {
1400 return NULL;
1401 }
1402
1403 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001404 if (!result) {
1405 LOGMEM;
1406 return NULL;
1407 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001408 for (i = 0; i < size; i++) {
1409 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1410 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1411 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1412 result[i].flags = old[i].flags;
1413 result[i].module = old[i].module;
1414
1415 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres)) {
1416 for (j = 0; j <= i; ++j) {
1417 lys_tpdf_free(mod->ctx, &result[j]);
1418 }
1419 free(result);
1420 return NULL;
1421 }
1422
1423 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1424 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1425 }
1426
1427 return result;
1428}
1429
Radek Krejci1d82ef62015-08-07 14:44:40 +02001430static struct lys_when *
1431lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001432{
Radek Krejci76512572015-08-04 09:47:08 +02001433 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001434
1435 if (!old) {
1436 return NULL;
1437 }
1438
1439 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001440 if (!new) {
1441 LOGMEM;
1442 return NULL;
1443 }
Radek Krejci00768f42015-06-18 17:04:04 +02001444 new->cond = lydict_insert(ctx, old->cond, 0);
1445 new->dsc = lydict_insert(ctx, old->dsc, 0);
1446 new->ref = lydict_insert(ctx, old->ref, 0);
1447
1448 return new;
1449}
1450
Michal Vasko0308dd62015-10-07 09:14:40 +02001451void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001452lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001453{
1454 if (!w) {
1455 return;
1456 }
1457
1458 lydict_remove(ctx, w->cond);
1459 lydict_remove(ctx, w->dsc);
1460 lydict_remove(ctx, w->ref);
1461
1462 free(w);
1463}
1464
Radek Krejcib7f5e412015-08-13 10:15:51 +02001465static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001466lys_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 +02001467{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001468 struct lys_node *next, *sub;
1469
Radek Krejcic071c542016-01-27 14:57:51 +01001470 /* children from a resolved augment are freed under the target node */
1471 if (!aug.target) {
1472 LY_TREE_FOR_SAFE(aug.child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001473 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001474 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001475 }
1476
Radek Krejcib7f5e412015-08-13 10:15:51 +02001477 lydict_remove(ctx, aug.target_name);
1478 lydict_remove(ctx, aug.dsc);
1479 lydict_remove(ctx, aug.ref);
1480
1481 free(aug.features);
1482
1483 lys_when_free(ctx, aug.when);
1484
Michal Vasko7d356a52015-08-19 15:06:31 +02001485 /* Do not free the children, they were appended somewhere and their
1486 * new parent will take care of them.
1487 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001488}
1489
Radek Krejci76512572015-08-04 09:47:08 +02001490static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001491lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001492{
Radek Krejci76512572015-08-04 09:47:08 +02001493 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001494 struct lys_node *old_child, *new_child;
1495 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001496
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001497 if (!size) {
1498 return NULL;
1499 }
Radek Krejci106efc02015-06-10 14:36:27 +02001500
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001501 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001502 if (!new) {
1503 LOGMEM;
1504 return NULL;
1505 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001506 for (i = 0; i < size; i++) {
1507 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1508 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1509 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1510 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001511 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001512 new[i].nodetype = old[i].nodetype;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001513
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001514 /* this must succeed, it was already resolved once */
Michal Vasko3edeaf72016-02-11 13:17:43 +01001515 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL,
1516 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001517 LOGINT;
1518 free(new);
1519 return NULL;
1520 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001521 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001522
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001523 /* Correct the augment nodes.
1524 * This function can only be called from lys_node_dup() with uses
1525 * being the node duplicated, so we must have a case of grouping
1526 * with a uses with augments. The augmented nodes have already been
1527 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001528 * (it was set to their actual data parent, not an augment), and
1529 * the new augment does not have child pointer to its augment nodes,
1530 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001531 */
1532 LY_TREE_FOR(new[i].target->child, new_child) {
Radek Krejci749190d2016-02-18 16:26:25 +01001533 if (ly_strequal(new_child->name, old[i].child->name, 1)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001534 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001535 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001536 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001537 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001538 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001539 LY_TREE_FOR(old[i].child, old_child) {
1540 /* all augment nodes were connected as siblings, there can be no more after this */
1541 if (old_child->parent != (struct lys_node *)&old[i]) {
1542 break;
1543 }
1544
Radek Krejci749190d2016-02-18 16:26:25 +01001545 assert(ly_strequal(old_child->name, new_child->name, 1));
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001546
1547 new_child->parent = (struct lys_node *)&new[i];
1548 new_child = new_child->next;
1549 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001550 }
Radek Krejci106efc02015-06-10 14:36:27 +02001551
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001552 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001553}
1554
Radek Krejci76512572015-08-04 09:47:08 +02001555static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001556lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001557{
Radek Krejci76512572015-08-04 09:47:08 +02001558 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001559 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001560
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001561 if (!size) {
1562 return NULL;
1563 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001564
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001565 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001566 if (!result) {
1567 LOGMEM;
1568 return NULL;
1569 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001570 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001571 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001572 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1573 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001574 result[i].flags = old[i].flags;
1575 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001576
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001577 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001578 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001579
Radek Krejci76512572015-08-04 09:47:08 +02001580 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001581 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001582 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001583 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001584 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001585 result[i].mod.list = old[i].mod.list;
1586 }
1587 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001588
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001589 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001590}
1591
Radek Krejci1d82ef62015-08-07 14:44:40 +02001592static void
1593lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001594{
Radek Krejcia52656e2015-08-05 13:41:50 +02001595 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001596
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001597 assert(ctx);
1598 if (!ident) {
1599 return;
1600 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001601
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001602 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001603 * if caller free only a single data model which is used (its identity is
1604 * reference from identity in another module), this silly freeing can lead
1605 * to segmentation fault. But without noting if the module is used by some
1606 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001607 *
1608 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001609 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001610 */
1611 while (ident->der) {
1612 der = ident->der;
1613 ident->der = der->next;
1614 free(der);
1615 }
Radek Krejci6793db02015-05-22 17:49:54 +02001616
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001617 lydict_remove(ctx, ident->name);
1618 lydict_remove(ctx, ident->dsc);
1619 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001620
1621}
1622
Radek Krejci1d82ef62015-08-07 14:44:40 +02001623static void
1624lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001625{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001626 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001627
Radek Krejcid12f57b2015-08-06 10:43:39 +02001628 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001629 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001630 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001631 }
1632 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001633}
1634
Radek Krejci1d82ef62015-08-07 14:44:40 +02001635static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001636lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1637{
1638 int i;
1639
1640 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1641 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001642 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001643 }
1644 free(io->tpdf);
1645}
1646
Radek Krejci1d82ef62015-08-07 14:44:40 +02001647static void
1648lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001649{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001650 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001651
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001652 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001653 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001654 }
1655 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001656
Radek Krejci1d82ef62015-08-07 14:44:40 +02001657 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001658}
1659
Radek Krejci1d82ef62015-08-07 14:44:40 +02001660static void
1661lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001662{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001663 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001664
Radek Krejci46c4cd72016-01-21 15:13:52 +01001665 if (leaf->child) {
1666 /* leafref backlinks */
1667 ly_set_free((struct ly_set *)leaf->child);
1668 }
1669
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001670 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001671 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001672 }
1673 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001674
Radek Krejci1d82ef62015-08-07 14:44:40 +02001675 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001676
Radek Krejci1d82ef62015-08-07 14:44:40 +02001677 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001678 lydict_remove(ctx, leaf->units);
1679 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001680}
1681
Radek Krejci1d82ef62015-08-07 14:44:40 +02001682static void
1683lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001684{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001685 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001686
Radek Krejci46c4cd72016-01-21 15:13:52 +01001687 if (llist->child) {
1688 /* leafref backlinks */
1689 ly_set_free((struct ly_set *)llist->child);
1690 }
1691
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001692 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001693 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001694 }
1695 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001696
Radek Krejci1d82ef62015-08-07 14:44:40 +02001697 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001698
Radek Krejci1d82ef62015-08-07 14:44:40 +02001699 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001700 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001701}
1702
Radek Krejci1d82ef62015-08-07 14:44:40 +02001703static void
1704lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001705{
Radek Krejci581ce772015-11-10 17:22:40 +01001706 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001707
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001708 /* handle only specific parts for LY_NODE_LIST */
1709 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001710 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001711 }
1712 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001713
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001714 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001715 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001716 }
1717 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001718
Radek Krejci1d82ef62015-08-07 14:44:40 +02001719 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001720
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001721 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001722 for (j = 0; j > list->unique[i].expr_size; j++) {
1723 lydict_remove(ctx, list->unique[i].expr[j]);
1724 }
1725 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001726 }
1727 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001728
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001729 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001730}
1731
Radek Krejci1d82ef62015-08-07 14:44:40 +02001732static void
1733lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001734{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001735 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001736
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001737 /* handle only specific parts for LY_NODE_CONTAINER */
1738 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001739
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001740 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001741 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001742 }
1743 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001744
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001745 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001746 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001747 }
1748 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001749
Radek Krejci1d82ef62015-08-07 14:44:40 +02001750 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001751}
1752
Radek Krejci1d82ef62015-08-07 14:44:40 +02001753static void
1754lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001755{
1756 lydict_remove(ctx, f->name);
1757 lydict_remove(ctx, f->dsc);
1758 lydict_remove(ctx, f->ref);
1759 free(f->features);
1760}
1761
Radek Krejci1d82ef62015-08-07 14:44:40 +02001762static void
Michal Vaskoff006c12016-02-17 11:15:19 +01001763lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001764{
Radek Krejci581ce772015-11-10 17:22:40 +01001765 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01001766 struct ly_ctx *ctx;
1767 struct lys_node *next, *elem;
1768
1769 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02001770
1771 lydict_remove(ctx, dev->target_name);
1772 lydict_remove(ctx, dev->dsc);
1773 lydict_remove(ctx, dev->ref);
1774
Michal Vaskoff006c12016-02-17 11:15:19 +01001775 /* the module was freed, but we only need the context from orig_node, use ours */
1776 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
1777 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
1778 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
1779 elem->module = module;
1780
1781 LY_TREE_DFS_END(dev->orig_node, next, elem);
1782 }
1783 lys_node_free(dev->orig_node, NULL, 0);
1784 } else {
1785 /* it's just a shallow copy, freeing one node */
1786 dev->orig_node->module = module;
1787 lys_node_free(dev->orig_node, NULL, 1);
1788 }
1789
Radek Krejcieb00f512015-07-01 16:44:58 +02001790 for (i = 0; i < dev->deviate_size; i++) {
1791 lydict_remove(ctx, dev->deviate[i].dflt);
1792 lydict_remove(ctx, dev->deviate[i].units);
1793
1794 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1795 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001796 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001797 }
1798 free(dev->deviate[i].must);
1799
1800 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001801 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1802 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1803 }
1804 free(dev->deviate[j].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001805 }
1806 free(dev->deviate[i].unique);
1807 }
1808 }
1809 free(dev->deviate);
1810}
1811
Radek Krejci1d82ef62015-08-07 14:44:40 +02001812static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001813lys_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 +02001814{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001815 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001816
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001817 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001818 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001819 lydict_remove(ctx, uses->refine[i].dsc);
1820 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001821
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001822 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001823 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001824 }
1825 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001826
Radek Krejci76512572015-08-04 09:47:08 +02001827 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001828 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001829 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001830 lydict_remove(ctx, uses->refine[i].mod.presence);
1831 }
1832 }
1833 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001834
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001835 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001836 lys_augment_free(ctx, uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001837 }
1838 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001839
Radek Krejci1d82ef62015-08-07 14:44:40 +02001840 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001841}
1842
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001843void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001844lys_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 +02001845{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001846 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001847 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001848
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001849 if (!node) {
1850 return;
1851 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001852
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001853 assert(node->module);
1854 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001855
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001856 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001857
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001858 /* remove private object */
1859 if (node->private && private_destructor) {
1860 private_destructor(node, node->private);
1861 }
1862
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001863 /* common part */
Radek Krejcid12f57b2015-08-06 10:43:39 +02001864 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1865 free(node->features);
1866 lydict_remove(ctx, node->name);
1867 lydict_remove(ctx, node->dsc);
1868 lydict_remove(ctx, node->ref);
1869 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001870
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001871 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01001872 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001873 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001874 }
1875 }
1876
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001877 /* specific part */
1878 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001879 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001880 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001881 break;
Radek Krejci76512572015-08-04 09:47:08 +02001882 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001883 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001884 break;
Radek Krejci76512572015-08-04 09:47:08 +02001885 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001886 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001887 break;
Radek Krejci76512572015-08-04 09:47:08 +02001888 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001889 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001890 break;
Radek Krejci76512572015-08-04 09:47:08 +02001891 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001892 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001893 break;
Radek Krejci76512572015-08-04 09:47:08 +02001894 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001895 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001896 break;
Radek Krejci76512572015-08-04 09:47:08 +02001897 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001898 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001899 break;
Radek Krejci76512572015-08-04 09:47:08 +02001900 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001901 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001902 break;
Radek Krejci76512572015-08-04 09:47:08 +02001903 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001904 /* do nothing */
1905 break;
Radek Krejci76512572015-08-04 09:47:08 +02001906 case LYS_GROUPING:
1907 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001908 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001909 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001910 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001911
1912 case LYS_INPUT:
1913 case LYS_OUTPUT:
1914 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1915 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001916 case LYS_UNKNOWN:
1917 LOGINT;
1918 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001919 }
Radek Krejci5a065542015-05-22 15:02:07 +02001920
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001921 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001922 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001923 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001924}
1925
Michal Vasko1e62a092015-12-01 12:27:20 +01001926const struct lys_module *
1927lys_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 +02001928{
Radek Krejcic071c542016-01-27 14:57:51 +01001929 const struct lys_module *main_module;
Michal Vasko3edeaf72016-02-11 13:17:43 +01001930 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02001931
Michal Vaskoa7789a82016-02-11 15:42:55 +01001932 assert(!prefix || !name);
1933
Michal Vaskob6729c62015-10-21 12:09:47 +02001934 if (prefix && !pref_len) {
1935 pref_len = strlen(prefix);
1936 }
1937 if (name && !name_len) {
1938 name_len = strlen(name);
1939 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02001940
Michal Vasko4f0dad02016-02-15 14:08:23 +01001941 main_module = lys_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01001942
1943 /* module own prefix, submodule own prefix, (sub)module own name */
1944 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
1945 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01001946 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01001947 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02001948 }
1949
Michal Vasko8ce24d72015-10-21 11:27:26 +02001950 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01001951 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
1952 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02001953 return module->imp[i].module;
1954 }
1955 }
1956
1957 return NULL;
1958}
1959
Michal Vasko13b15832015-08-19 11:04:48 +02001960/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001961static void
Michal Vaskob746fff2016-02-11 11:37:50 +01001962module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02001963{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001964 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01001965 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001966 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001967
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001968 assert(module->ctx);
1969 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001970
Michal Vaskob746fff2016-02-11 11:37:50 +01001971 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01001972 for (i = 0; i < module->imp_size; i++) {
Radek Krejci4f78b532016-02-17 13:43:00 +01001973 if (!module->imp[i].external) {
1974 lydict_remove(ctx, module->imp[i].prefix);
1975 }
Radek Krejci225376f2016-02-16 17:36:22 +01001976 }
Radek Krejcidce51452015-06-16 15:20:08 +02001977 free(module->imp);
1978
Radek Krejcic071c542016-01-27 14:57:51 +01001979 /* submodules don't have data tree, the data nodes
1980 * are placed in the main module altogether */
1981 if (!module->type) {
1982 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001983 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001984 }
Radek Krejci21181962015-06-30 14:11:00 +02001985 }
Radek Krejci5a065542015-05-22 15:02:07 +02001986
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001987 lydict_remove(ctx, module->dsc);
1988 lydict_remove(ctx, module->ref);
1989 lydict_remove(ctx, module->org);
1990 lydict_remove(ctx, module->contact);
Radek Krejcic5989d42016-02-17 11:16:38 +01001991 lydict_remove(ctx, module->uri);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001992
Radek Krejcieb00f512015-07-01 16:44:58 +02001993 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001994 for (i = 0; i < module->rev_size; i++) {
1995 lydict_remove(ctx, module->rev[i].dsc);
1996 lydict_remove(ctx, module->rev[i].ref);
1997 }
1998 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001999
Radek Krejcieb00f512015-07-01 16:44:58 +02002000 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002001 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002002 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002003 }
2004 module->ident_size = 0;
2005 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002006
Radek Krejcieb00f512015-07-01 16:44:58 +02002007 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002008 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002009 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002010 }
2011 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002012
Radek Krejcieb00f512015-07-01 16:44:58 +02002013 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002014 for (i = 0; i < module->inc_size; i++) {
Radek Krejcic071c542016-01-27 14:57:51 +01002015 /* complete submodule free is done only from main module since
2016 * submodules propagate their includes to the main module */
2017 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002018 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002019 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002020 }
2021 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002022
Radek Krejcieb00f512015-07-01 16:44:58 +02002023 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002024 for (i = 0; i < module->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002025 lys_augment_free(ctx, module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002026 }
2027 free(module->augment);
2028
Radek Krejcieb00f512015-07-01 16:44:58 +02002029 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002030 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002031 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002032 }
2033 free(module->features);
2034
Radek Krejcieb00f512015-07-01 16:44:58 +02002035 /* deviations */
2036 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002037 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002038 }
2039 free(module->deviation);
2040
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002041 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002042 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002043}
2044
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002045void
Michal Vaskob746fff2016-02-11 11:37:50 +01002046lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002047{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002048 if (!submodule) {
2049 return;
2050 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002051
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002052 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002053 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002054
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002055 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002056
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002057 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002058}
2059
Radek Krejci76512572015-08-04 09:47:08 +02002060struct lys_node *
Radek Krejcic071c542016-01-27 14:57:51 +01002061lys_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 +01002062 uint8_t nacm, struct unres_schema *unres, int shallow)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002063{
Radek Krejcic071c542016-01-27 14:57:51 +01002064 struct lys_node *retval = NULL, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002065 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002066 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002067
Michal Vaskoc07187d2015-08-13 15:20:57 +02002068 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002069 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002070 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002071 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002072 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002073 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002074 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002075 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002076 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002077 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002078 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002079 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002080 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002081 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002082 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002083 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002084 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002085 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002086 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002087 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002088 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002089 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002090 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002091 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002092
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002093 /* we cannot just duplicate memory since the strings are stored in
2094 * dictionary and we need to update dictionary counters.
2095 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002096
Radek Krejci1d82ef62015-08-07 14:44:40 +02002097 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002098 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002099 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002100 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002101 break;
2102
Radek Krejci76512572015-08-04 09:47:08 +02002103 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002104 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002105 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002106 break;
2107
Radek Krejci76512572015-08-04 09:47:08 +02002108 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002109 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002110 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002111 break;
2112
Radek Krejci76512572015-08-04 09:47:08 +02002113 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002114 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002115 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002116 break;
2117
Radek Krejci76512572015-08-04 09:47:08 +02002118 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002119 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002120 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002121 break;
2122
Radek Krejci76512572015-08-04 09:47:08 +02002123 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002124 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002125 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002126 break;
2127
Radek Krejci76512572015-08-04 09:47:08 +02002128 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002129 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002130 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002131 break;
2132
Radek Krejci76512572015-08-04 09:47:08 +02002133 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002134 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002135 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002136 break;
2137
Radek Krejci76512572015-08-04 09:47:08 +02002138 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002139 grp = calloc(1, sizeof *grp);
2140 retval = (struct lys_node *)grp;
2141 break;
2142
Radek Krejci76512572015-08-04 09:47:08 +02002143 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002144 rpc = calloc(1, sizeof *rpc);
2145 retval = (struct lys_node *)rpc;
2146 break;
2147
Radek Krejci76512572015-08-04 09:47:08 +02002148 case LYS_INPUT:
2149 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002150 io = calloc(1, sizeof *io);
2151 retval = (struct lys_node *)io;
2152 break;
2153
Radek Krejci76512572015-08-04 09:47:08 +02002154 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002155 ntf = calloc(1, sizeof *ntf);
2156 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002157 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002158
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002159 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002160 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002161 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002162 }
Radek Krejcib388c152015-06-04 17:03:03 +02002163
Michal Vasko253035f2015-12-17 16:58:13 +01002164 if (!retval) {
2165 LOGMEM;
2166 return NULL;
2167 }
2168
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002169 /*
2170 * duplicate generic part of the structure
2171 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002172 retval->name = lydict_insert(ctx, node->name, 0);
2173 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2174 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002175 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002176 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002177 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002178 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002179 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002180 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002181
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002182 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002183 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002184
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002185 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002186
Radek Krejci1d82ef62015-08-07 14:44:40 +02002187 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002188 retval->features = calloc(retval->features_size, sizeof *retval->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002189 if (!retval->features) {
2190 LOGMEM;
2191 goto error;
2192 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002193
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002194 if (!shallow) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002195 for (i = 0; i < node->features_size; ++i) {
2196 retval->features[i] = (struct lys_feature *)retval;
2197 if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
2198 retval->features[i] = node->features[i];
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002199 }
2200 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002201
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002202 /* connect it to the parent */
2203 if (lys_node_addchild(parent, retval->module, retval)) {
2204 goto error;
2205 }
Radek Krejcidce51452015-06-16 15:20:08 +02002206
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002207 /* go recursively */
2208 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2209 LY_TREE_FOR(node->child, child) {
2210 if (!lys_node_dup(module, retval, child, retval->flags, retval->nacm, unres, 0)) {
2211 goto error;
2212 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002213 }
2214 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002215 } else {
2216 memcpy(retval->features, node->features, retval->features_size * sizeof *retval->features);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002217 }
2218
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002219 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002220 * duplicate specific part of the structure
2221 */
2222 switch (node->nodetype) {
2223 case LYS_CONTAINER:
2224 if (cont_orig->when) {
2225 cont->when = lys_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002226 }
2227 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002228
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002229 cont->must_size = cont_orig->must_size;
2230 cont->tpdf_size = cont_orig->tpdf_size;
2231
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002232 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002233 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
2234 break;
2235
2236 case LYS_CHOICE:
2237 if (choice_orig->when) {
2238 choice->when = lys_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002239 }
2240
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002241 if (!shallow) {
2242 if (choice_orig->dflt) {
2243 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0, LYS_ANYXML
2244 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
2245 | LYS_LIST, (const struct lys_node **)&choice->dflt);
2246 if (rc) {
2247 if (rc == EXIT_FAILURE) {
2248 LOGINT;
2249 }
2250 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002251 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002252 } else {
2253 /* useless to check return value, we don't know whether
2254 * there really wasn't any default defined or it just hasn't
2255 * been resolved, we just hope for the best :)
2256 */
2257 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002258 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002259 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002260 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002261 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002262 break;
2263
2264 case LYS_LEAF:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002265 if (lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres)) {
2266 goto error;
2267 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002268 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2269
2270 if (leaf_orig->dflt) {
2271 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002272 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002273 goto error;
2274 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002275 }
2276
2277 leaf->must_size = leaf_orig->must_size;
2278 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002279
2280 if (leaf_orig->when) {
2281 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002282 }
2283 break;
2284
2285 case LYS_LEAFLIST:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002286 if (lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres)) {
2287 goto error;
2288 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002289 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
2290
2291 llist->min = llist_orig->min;
2292 llist->max = llist_orig->max;
2293
2294 llist->must_size = llist_orig->must_size;
2295 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002296
2297 if (llist_orig->when) {
2298 llist->when = lys_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002299 }
2300 break;
2301
2302 case LYS_LIST:
2303 list->min = list_orig->min;
2304 list->max = list_orig->max;
2305
2306 list->must_size = list_orig->must_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002307 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002308
Radek Krejci581ce772015-11-10 17:22:40 +01002309 list->tpdf_size = list_orig->tpdf_size;
Michal Vasko0ea41032015-06-16 08:53:55 +02002310 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02002311
Radek Krejci581ce772015-11-10 17:22:40 +01002312 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02002313 if (list->keys_size) {
2314 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01002315 if (!list->keys) {
2316 LOGMEM;
2317 goto error;
2318 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002319
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002320 if (!shallow) {
2321 /* we managed to resolve it before, resolve it again manually */
2322 if (list_orig->keys[0]) {
2323 for (i = 0; i < list->keys_size; ++i) {
2324 rc = lys_get_sibling(list->child, lys_node_module(retval)->name, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2325 (const struct lys_node **)&list->keys[i]);
2326 if (rc) {
2327 if (rc == EXIT_FAILURE) {
2328 LOGINT;
2329 }
2330 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002331 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002332 }
2333 /* it was not resolved yet, add unres copy */
2334 } else {
2335 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
2336 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002337 goto error;
2338 }
Michal Vasko38d01f72015-06-15 09:41:06 +02002339 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002340 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002341 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02002342 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002343 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002344
Radek Krejci581ce772015-11-10 17:22:40 +01002345 list->unique_size = list_orig->unique_size;
2346 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002347 if (!list->unique) {
2348 LOGMEM;
2349 goto error;
2350 }
Radek Krejci581ce772015-11-10 17:22:40 +01002351 for (i = 0; i < list->unique_size; ++i) {
2352 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2353 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002354 if (!list->unique[i].expr) {
2355 LOGMEM;
2356 goto error;
2357 }
Radek Krejci581ce772015-11-10 17:22:40 +01002358 for (j = 0; j < list->unique[i].expr_size; j++) {
2359 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2360
2361 /* if it stays in unres list, duplicate it also there */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002362 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002363 }
2364 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002365
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002366 if (list_orig->when) {
2367 list->when = lys_when_dup(ctx, list_orig->when);
Radek Krejciefaeba32015-05-27 14:30:57 +02002368 }
Radek Krejcidce51452015-06-16 15:20:08 +02002369 break;
2370
2371 case LYS_ANYXML:
2372 anyxml->must_size = anyxml_orig->must_size;
2373 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002374
2375 if (anyxml_orig->when) {
2376 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002377 }
2378 break;
2379
2380 case LYS_USES:
2381 uses->grp = uses_orig->grp;
2382
2383 if (uses_orig->when) {
2384 uses->when = lys_when_dup(ctx, uses_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002385 }
2386
2387 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002388 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002389 uses->augment_size = uses_orig->augment_size;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002390 if (!shallow) {
2391 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
2392 if (!uses->child) {
2393 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, 0) == -1) {
2394 goto error;
2395 }
Michal Vasko49168a22015-08-17 16:35:41 +02002396 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002397 } else {
2398 memcpy(uses->augment, uses_orig->augment, uses->augment_size * sizeof *uses->augment);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002399 }
2400 break;
2401
Radek Krejcidce51452015-06-16 15:20:08 +02002402 case LYS_CASE:
2403 if (cs_orig->when) {
2404 cs->when = lys_when_dup(ctx, cs_orig->when);
Radek Krejcidce51452015-06-16 15:20:08 +02002405 }
2406 break;
2407
2408 case LYS_GROUPING:
2409 grp->tpdf_size = grp_orig->tpdf_size;
2410 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
2411 break;
2412
2413 case LYS_RPC:
2414 rpc->tpdf_size = rpc_orig->tpdf_size;
2415 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
2416 break;
2417
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002418 case LYS_INPUT:
2419 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02002420 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002421 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
2422 break;
2423
Radek Krejcida04f4a2015-05-21 12:54:09 +02002424 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002425 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002426 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejci7e97c352015-06-19 16:26:34 +02002427 break;
2428
2429 default:
2430 /* LY_NODE_AUGMENT */
2431 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002432 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002433 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002434
2435 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002436
2437error:
2438
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002439 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02002440 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002441}
2442
Michal Vasko13b15832015-08-19 11:04:48 +02002443void
Michal Vaskoff006c12016-02-17 11:15:19 +01002444lys_node_switch(struct lys_node *dst, struct lys_node *src)
2445{
2446 struct lys_node *child;
2447
2448 assert((dst->module == src->module) && (dst->name == src->name) && (dst->nodetype == src->nodetype));
2449
2450 /* sibling next */
2451 if (dst->prev != dst) {
2452 dst->prev->next = src;
2453 }
2454
2455 /* sibling prev */
2456 if (dst->next) {
2457 dst->next->prev = src;
2458 }
2459
2460 /* parent child prev */
2461 if (!dst->next && dst->parent) {
2462 dst->parent->child->prev = src;
2463 }
2464
2465 /* next */
2466 src->next = dst->next;
2467 dst->next = NULL;
2468
2469 /* prev */
2470 if (dst->prev != dst) {
2471 src->prev = dst->prev;
2472 }
2473 dst->prev = dst;
2474
2475 /* parent child */
2476 if (dst->parent && (dst->parent->child == dst)) {
2477 dst->parent->child = src;
2478 }
2479
2480 /* parent */
2481 src->parent = dst->parent;
2482 dst->parent = NULL;
2483
2484 /* child parent */
2485 LY_TREE_FOR(dst->child, child) {
2486 if (child->parent == dst) {
2487 child->parent = src;
2488 }
2489 }
2490
2491 /* child */
2492 src->child = dst->child;
2493 dst->child = NULL;
2494}
2495
2496void
Michal Vasko627975a2016-02-11 11:39:03 +01002497lys_free(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv), int remove_from_ctx)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002498{
2499 struct ly_ctx *ctx;
2500 int i;
2501
2502 if (!module) {
2503 return;
2504 }
2505
2506 /* remove schema from the context */
2507 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01002508 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02002509 for (i = 0; i < ctx->models.used; i++) {
2510 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01002511 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02002512 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01002513 memmove(&ctx->models.list[i], ctx->models.list[i + 1], (ctx->models.used - i) * sizeof *ctx->models.list);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002514 ctx->models.list[ctx->models.used] = NULL;
2515 /* we are done */
2516 break;
2517 }
2518 }
2519 }
2520
2521 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01002522 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002523
2524 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01002525 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002526
2527 free(module);
2528}
Radek Krejci7e97c352015-06-19 16:26:34 +02002529
2530/*
2531 * op: 1 - enable, 0 - disable
2532 */
2533static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002534lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002535{
2536 int all = 0;
2537 int i, j, k;
2538
2539 if (!module || !name || !strlen(name)) {
2540 return EXIT_FAILURE;
2541 }
2542
2543 if (!strcmp(name, "*")) {
2544 /* enable all */
2545 all = 1;
2546 }
2547
2548 /* module itself */
2549 for (i = 0; i < module->features_size; i++) {
2550 if (all || !strcmp(module->features[i].name, name)) {
2551 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002552 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002553 /* enable referenced features (recursion) */
2554 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002555 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002556 module->features[i].features[k]->name, op);
2557 }
2558 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002559 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002560 }
2561 if (!all) {
2562 return EXIT_SUCCESS;
2563 }
2564 }
2565 }
2566
2567 /* submodules */
2568 for (j = 0; j < module->inc_size; j++) {
2569 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2570 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2571 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002572 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002573 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002574 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002575 }
2576 if (!all) {
2577 return EXIT_SUCCESS;
2578 }
2579 }
2580 }
2581 }
2582
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002583 /* TODO submodules of submodules ... */
2584
Radek Krejci7e97c352015-06-19 16:26:34 +02002585 if (all) {
2586 return EXIT_SUCCESS;
2587 } else {
2588 return EXIT_FAILURE;
2589 }
2590}
2591
2592API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002593lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002594{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002595 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002596}
2597
2598API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002599lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002600{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002601 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002602}
2603
2604API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002605lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002606{
2607 int i, j;
2608
2609 if (!module || !feature) {
2610 return -1;
2611 }
2612
2613 /* search for the specified feature */
2614 /* module itself */
2615 for (i = 0; i < module->features_size; i++) {
2616 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002617 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002618 return 1;
2619 } else {
2620 return 0;
2621 }
2622 }
2623 }
2624
2625 /* submodules */
2626 for (j = 0; j < module->inc_size; j++) {
2627 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2628 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002629 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002630 return 1;
2631 } else {
2632 return 0;
2633 }
2634 }
2635 }
2636 }
2637
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002638 /* feature definition not found */
2639 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002640}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002641
Radek Krejci96a10da2015-07-30 11:00:14 +02002642API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01002643lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002644{
Radek Krejci96a10da2015-07-30 11:00:14 +02002645 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002646 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002647 unsigned int count;
2648
2649 if (!module) {
2650 return NULL;
2651 }
2652
2653 count = module->features_size;
2654 for (i = 0; i < module->inc_size; i++) {
2655 count += module->inc[i].submodule->features_size;
2656 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002657 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01002658 if (!result) {
2659 LOGMEM;
2660 return NULL;
2661 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002662 if (states) {
2663 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01002664 if (!(*states)) {
2665 LOGMEM;
2666 free(result);
2667 return NULL;
2668 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002669 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002670 count = 0;
2671
2672 /* module itself */
2673 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002674 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002675 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002676 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002677 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002678 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002679 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002680 }
2681 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002682 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002683 }
2684
2685 /* submodules */
2686 for (j = 0; j < module->inc_size; j++) {
2687 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002688 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002689 if (states) {
2690 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2691 (*states)[count] = 1;
2692 } else {
2693 (*states)[count] = 0;
2694 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002695 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002696 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002697 }
2698 }
2699
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002700 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002701 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002702
2703 return result;
2704}
Michal Vaskobaefb032015-09-24 14:52:10 +02002705
Radek Krejcic071c542016-01-27 14:57:51 +01002706struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01002707lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01002708{
2709 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
2710}
2711
Michal Vasko320e8532016-02-15 13:11:57 +01002712struct lys_module *
2713lys_module(const struct lys_module *module)
2714{
2715 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
2716}
2717
Michal Vaskobaefb032015-09-24 14:52:10 +02002718API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002719lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02002720{
2721 if (!node || !node->parent) {
2722 return NULL;
2723 }
2724
2725 if (node->parent->nodetype == LYS_AUGMENT) {
2726 return ((struct lys_node_augment *)node->parent)->target;
2727 }
2728
2729 return node->parent;
2730}
Michal Vasko1b229152016-01-13 11:28:38 +01002731
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002732API void *
Michal Vasko1b229152016-01-13 11:28:38 +01002733lys_set_private(const struct lys_node *node, void *priv)
2734{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002735 void *prev;
2736
Michal Vasko1b229152016-01-13 11:28:38 +01002737 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002738 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2739 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01002740 }
2741
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002742 prev = node->private;
Michal Vasko1b229152016-01-13 11:28:38 +01002743 ((struct lys_node *)node)->private = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002744
2745 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01002746}