blob: 9d87a5cf39d360b8ffee63bf13428c2523365893 [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
Michal Vasko2d162e12015-09-24 14:33:29 +02002 * @file tree_schema.c
Radek Krejcida04f4a2015-05-21 12:54:09 +02003 * @author Radek Krejci <rkrejci@cesnet.cz>
Michal Vasko2d162e12015-09-24 14:33:29 +02004 * @brief Manipulation with libyang schema data structures
Radek Krejcida04f4a2015-05-21 12:54:09 +02005 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Radek Krejci54f6fb32016-02-24 12:56:39 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
Radek Krejcida04f4a2015-05-21 12:54:09 +020013 */
Radek Krejci54f6fb32016-02-24 12:56:39 +010014
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020015#define _GNU_SOURCE
Radek Krejcida04f4a2015-05-21 12:54:09 +020016
Radek Krejci812b10a2015-05-28 16:48:25 +020017#include <assert.h>
Radek Krejci5a988152015-07-15 11:16:26 +020018#include <ctype.h>
Radek Krejcib051f722016-02-25 15:12:21 +010019#include <limits.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020020#include <stdlib.h>
21#include <sys/mman.h>
Michal Vasko662610a2015-12-07 11:25:45 +010022#include <sys/types.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020023#include <sys/stat.h>
Michal Vasko662610a2015-12-07 11:25:45 +010024#include <fcntl.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020025#include <string.h>
Michal Vasko662610a2015-12-07 11:25:45 +010026#include <unistd.h>
27#include <errno.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020028
29#include "common.h"
30#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020031#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020032#include "resolve.h"
Michal Vasko88c29542015-11-27 14:57:53 +010033#include "xml.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020034#include "xml_internal.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020035#include "tree_internal.h"
Radek Krejcieab784a2015-08-27 09:56:53 +020036#include "validation.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020037
Michal Vasko1e62a092015-12-01 12:27:20 +010038API const struct lys_feature *
39lys_is_disabled(const struct lys_node *node, int recursive)
Radek Krejci48061fb2015-08-05 15:41:07 +020040{
41 int i;
42
43check:
44 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
45 /* input/output does not have if-feature, so skip them */
46
47 /* check local if-features */
48 for (i = 0; i < node->features_size; i++) {
49 if (!(node->features[i]->flags & LYS_FENABLED)) {
50 return node->features[i];
51 }
52 }
53 }
54
55 if (!recursive) {
56 return NULL;
57 }
58
59 /* go through parents */
60 if (node->nodetype == LYS_AUGMENT) {
61 /* go to parent actually means go to the target node */
62 node = ((struct lys_node_augment *)node)->target;
Radek Krejci48061fb2015-08-05 15:41:07 +020063 } else if (node->parent) {
64 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020065 } else {
66 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020067 }
68
Radek Krejci074bf852015-08-19 14:22:16 +020069 if (recursive == 2) {
70 /* continue only if the node cannot have a data instance */
71 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
72 return NULL;
73 }
74 }
75 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020076}
77
Michal Vasko1dca6882015-10-22 14:29:42 +020078int
Michal Vasko36cbaa42015-12-14 13:15:48 +010079lys_get_sibling(const struct lys_node *siblings, const char *mod_name, int mod_name_len, const char *name,
80 int nam_len, LYS_NODE type, const struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +020081{
Radek Krejcic071c542016-01-27 14:57:51 +010082 const struct lys_node *node, *parent = NULL;
83 const struct lys_module *mod = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +010084 const char *node_mod_name;
Michal Vasko1dca6882015-10-22 14:29:42 +020085
Michal Vasko36cbaa42015-12-14 13:15:48 +010086 assert(siblings && mod_name && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +020087 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +020088
Michal Vasko36cbaa42015-12-14 13:15:48 +010089 /* fill the lengths in case the caller is so indifferent */
90 if (!mod_name_len) {
91 mod_name_len = strlen(mod_name);
92 }
Michal Vasko1dca6882015-10-22 14:29:42 +020093 if (!nam_len) {
94 nam_len = strlen(name);
95 }
96
Michal Vasko36cbaa42015-12-14 13:15:48 +010097 /* set mod correctly */
Radek Krejcic071c542016-01-27 14:57:51 +010098 parent = lys_parent(siblings);
99 if (!parent) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100100 mod = lys_node_module(siblings);
Michal Vasko1dca6882015-10-22 14:29:42 +0200101 }
102
Radek Krejcic071c542016-01-27 14:57:51 +0100103 /* try to find the node */
104 node = NULL;
105 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
106 if (!type || (node->nodetype & type)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100107 /* module name comparison */
108 node_mod_name = lys_node_module(node)->name;
109 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 +0100110 continue;
111 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200112
Radek Krejcic071c542016-01-27 14:57:51 +0100113 /* direct name check */
114 if ((node->name == name) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
115 if (ret) {
116 *ret = node;
Michal Vasko1dca6882015-10-22 14:29:42 +0200117 }
Radek Krejcic071c542016-01-27 14:57:51 +0100118 return EXIT_SUCCESS;
Michal Vasko1dca6882015-10-22 14:29:42 +0200119 }
120 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200121 }
122
123 return EXIT_FAILURE;
124}
125
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200126int
Michal Vasko1e62a092015-12-01 12:27:20 +0100127lys_get_data_sibling(const struct lys_module *mod, const struct lys_node *siblings, const char *name, LYS_NODE type,
128 const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200129{
Michal Vasko1e62a092015-12-01 12:27:20 +0100130 const struct lys_node *node;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200131
132 assert(siblings && name);
133 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
134
135 /* find the beginning */
136 while (siblings->prev->next) {
137 siblings = siblings->prev;
138 }
139
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200140 if (!mod) {
141 mod = siblings->module;
142 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200143
Michal Vasko4f0dad02016-02-15 14:08:23 +0100144 /* try to find the node */
145 node = NULL;
146 while ((node = lys_getnext(node, siblings->parent, mod, 0))) {
147 if (!type || (node->nodetype & type)) {
148 /* module check */
149 if (lys_node_module(node) != lys_module(mod)) {
Radek Krejcic071c542016-01-27 14:57:51 +0100150 continue;
151 }
152
Michal Vasko4f0dad02016-02-15 14:08:23 +0100153 /* direct name check */
Radek Krejci749190d2016-02-18 16:26:25 +0100154 if (ly_strequal(node->name, name, 0)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100155 if (ret) {
156 *ret = node;
157 }
158 return EXIT_SUCCESS;
159 }
Radek Krejcic071c542016-01-27 14:57:51 +0100160 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200161 }
162
163 return EXIT_FAILURE;
164}
165
Michal Vasko1e62a092015-12-01 12:27:20 +0100166API const struct lys_node *
167lys_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 +0200168{
Michal Vasko1e62a092015-12-01 12:27:20 +0100169 const struct lys_node *next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200170
Radek Krejci8bc87f62015-09-02 16:19:05 +0200171 if (!last) {
172 /* first call */
173
174 /* get know where to start */
175 if (parent) {
176 /* schema subtree */
177 next = last = parent->child;
178 } else {
179 /* top level data */
180 assert(module);
181 next = last = module->data;
182 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200183 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200184 /* continue after the last returned value */
185 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200186 }
187
188repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200189 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200190 if (options & LYS_GETNEXT_WITHGROUPING) {
191 return next;
192 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200193 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200194 }
195
Radek Krejcic4ccbd92016-01-07 13:13:33 +0100196 if (!next) {
Radek Krejci63318e82016-02-12 09:43:12 +0100197 if (!last || lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200198 /* no next element */
199 return NULL;
200 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200201 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200202 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200203 goto repeat;
204 }
205
206 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200207 case LYS_INPUT:
208 case LYS_OUTPUT:
209 if (options & LYS_GETNEXT_WITHINOUT) {
210 return next;
211 } else {
212 next = next->child;
213 goto repeat;
214 }
215 break;
216
Michal Vaskoa5835e92015-10-20 15:07:39 +0200217 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200218 if (options & LYS_GETNEXT_WITHCASE) {
219 return next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200220 } else {
221 next = next->child;
222 goto repeat;
Michal Vasko1dca6882015-10-22 14:29:42 +0200223 }
Michal Vaskob6eedf02015-10-22 16:07:03 +0200224 break;
225
Michal Vasko1dca6882015-10-22 14:29:42 +0200226 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200227 /* go into */
228 next = next->child;
229 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200230
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200231 case LYS_RPC:
232 case LYS_NOTIF:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200233 case LYS_CONTAINER:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200234 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200235 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200236 case LYS_LIST:
237 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200238 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200239
240 case LYS_CHOICE:
241 if (options & LYS_GETNEXT_WITHCHOICE) {
242 return next;
243 } else {
244 /* go into */
245 next = next->child;
246 goto repeat;
247 }
248 break;
249
Radek Krejci7f40ce32015-08-12 20:38:46 +0200250 default:
251 /* we should not be here */
252 return NULL;
253 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200254
255
256}
257
Michal Vasko1e62a092015-12-01 12:27:20 +0100258static const struct lys_node *
Radek Krejci2342cf62016-01-29 16:48:23 +0100259check_mand_getnext(const struct lys_node *last, const struct lys_node *parent, const struct lys_module *module)
Radek Krejci8bc87f62015-09-02 16:19:05 +0200260{
Michal Vasko1e62a092015-12-01 12:27:20 +0100261 const struct lys_node *next;
262
Radek Krejci2342cf62016-01-29 16:48:23 +0100263 next = lys_getnext(last, parent, module, LYS_GETNEXT_WITHCHOICE);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200264
Radek Krejci4b6c2112015-10-06 12:48:34 +0200265repeat:
Radek Krejci8bc87f62015-09-02 16:19:05 +0200266 if (next && next->nodetype == LYS_CONTAINER) {
267 if (((struct lys_node_container *)next)->presence) {
268 /* mandatory elements under the non-existing presence
269 * container are not mandatory - 7.6.5, rule 1 */
270 next = next->next;
271 } else {
272 /* go into */
273 next = next->child;
274 }
275 goto repeat;
276 }
277
278 return next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200279}
280
Michal Vasko1e62a092015-12-01 12:27:20 +0100281static const struct lys_node *
282check_mand_check(const struct lys_node *node, const struct lys_node *stop, const struct lyd_node *data)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200283{
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200284 struct lys_node *siter = NULL, *parent = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200285 struct lyd_node *diter = NULL;
Radek Krejcidc154432016-01-21 11:10:59 +0100286 struct ly_set *set = NULL;
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200287 unsigned int i;
Radek Krejci14a11a62015-08-17 17:27:38 +0200288 uint32_t minmax;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200289
290 if (node->flags & LYS_MAND_TRUE) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100291 if (!data) {
292 /* we have no data but a mandatory node */
293 return node;
294 }
295 switch (node->nodetype) {
296 case LYS_LEAF:
297 case LYS_ANYXML:
298 case LYS_CHOICE:
299 if (node->parent && node->parent->nodetype == LYS_CASE) {
300 /* 7.6.5, rule 2 */
301 /* 7.9.4, rule 1 */
302 if (node->parent->parent->parent == data->schema) {
303 /* the only case the node's siblings can exist is that the
304 * data node passed originally to ly_check_mandatory()
305 * had this choice as a child
306 */
307 /* try to find the node's siblings in data */
308 LY_TREE_FOR(data->child, diter) {
309 LY_TREE_FOR(node->parent->child, siter) {
310 if (siter == diter->schema) {
311 /* some sibling exists, rule applies */
312 break;
313 }
314 }
315 if (siter) {
316 break;
317 }
318 }
319 }
320 if (!siter) {
321 /* no sibling exists */
322 return NULL;
323 }
324 } else {
Radek Krejci7eb12132016-02-01 10:55:23 +0100325 for (parent = node->parent; parent && parent != stop; parent = parent->parent) {
Radek Krejci2342cf62016-01-29 16:48:23 +0100326 if (parent->nodetype != LYS_CONTAINER) {
327 /* 7.6.5, rule 1, checking presence is not needed
328 * since it is done in check_mand_getnext()
329 */
330 ly_set_free(set);
331 return NULL;
332 }
333 /* add the parent to the list for searching in data tree */
334 if (!set) {
335 set = ly_set_new();
336 }
337 /* ignore return - memory error is logged and we will
338 * check at least the rest of nodes we have */
339 (void)ly_set_add(set, parent);
340 }
341 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200342
Radek Krejci2342cf62016-01-29 16:48:23 +0100343 /* search for instance */
344 if (set) {
345 for (i = 0; i < set->number; i++) {
346 LY_TREE_FOR(data->child, diter) {
347 if (diter->schema == set->sset[i]) {
348 break;
349 }
350 }
351 if (!diter) {
352 /* instance not found */
353 node = set->sset[i];
354 ly_set_free(set);
355 return node;
356 }
357 data = diter;
358 }
359 ly_set_free(set);
360 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200361
Radek Krejci2342cf62016-01-29 16:48:23 +0100362 LY_TREE_FOR(data->child, diter) {
363 if (diter->schema == node) {
364 return NULL;
365 }
366 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200367
Radek Krejci2342cf62016-01-29 16:48:23 +0100368 /* instance not found */
369 /* 7.6.5, rule 3 (or 2) */
370 /* 7.9.4, rule 2 */
371 return node;
372 default:
373 /* error */
374 break;
375 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200376 } else if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
377 /* search for number of instances */
378 minmax = 0;
Radek Krejci2342cf62016-01-29 16:48:23 +0100379 if (data) {
380 LY_TREE_FOR(data->child, diter) {
381 if (diter->schema == node) {
382 minmax++;
383 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200384 }
385 }
386
387 /* check the specified constraints */
388 if (node->nodetype == LYS_LIST) {
389 if (((struct lys_node_list *)node)->min && minmax < ((struct lys_node_list *)node)->min) {
390 return node;
391 }
392
393 if (((struct lys_node_list *)node)->max && minmax > ((struct lys_node_list *)node)->max) {
394 return node;
395 }
396 } else if (node->nodetype == LYS_LEAFLIST) {
397 if (((struct lys_node_leaflist *)node)->min && minmax < ((struct lys_node_leaflist *)node)->min) {
398 return node;
399 }
400
401 if (((struct lys_node_leaflist *)node)->max && minmax > ((struct lys_node_leaflist *)node)->max) {
402 return node;
403 }
404 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200405 }
406
407 return NULL;
408}
409
Michal Vasko1e62a092015-12-01 12:27:20 +0100410const struct lys_node *
Radek Krejci2342cf62016-01-29 16:48:23 +0100411ly_check_mandatory(const struct lyd_node *data, const struct lys_node *schema)
Radek Krejci7f40ce32015-08-12 20:38:46 +0200412{
Michal Vasko1e62a092015-12-01 12:27:20 +0100413 const struct lys_node *siter, *saux, *saux2, *result, *parent = NULL, *parent2;
414 const struct lyd_node *diter;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200415 int found;
416
Radek Krejci2342cf62016-01-29 16:48:23 +0100417 assert(data || schema);
418
419 if (!data) { /* !data && schema */
420 siter = schema;
421 } else { /* data && !schema */
Radek Krejcie2f12212016-02-12 13:50:22 +0100422 schema = data->schema;
423 siter = data->schema->child;
Radek Krejci2342cf62016-01-29 16:48:23 +0100424 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200425
426repeat:
427 while (siter) {
Radek Krejci074bf852015-08-19 14:22:16 +0200428 if (lys_is_disabled(siter, 2)) {
429 siter = siter->next;
430 continue;
431 }
432
Radek Krejci7f40ce32015-08-12 20:38:46 +0200433 switch (siter->nodetype) {
434 case LYS_CONTAINER:
435 case LYS_LEAF:
436 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200437 case LYS_LIST:
438 case LYS_LEAFLIST:
439 /* check if there is some mandatory node; first test the siter itself ... */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200440 result = check_mand_check(siter, siter->parent, data);
441 if (result) {
442 return result;
443 }
444 /* ... and then the subtree */
Radek Krejci14a11a62015-08-17 17:27:38 +0200445 if (parent && siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
446 saux = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100447 while ((saux = check_mand_getnext(saux, siter, NULL))) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200448 result = check_mand_check(saux, siter, data);
449 if (result) {
450 return result;
451 }
452 }
453 }
454 siter = siter->next;
455 break;
456 case LYS_CHOICE:
Radek Krejci14a11a62015-08-17 17:27:38 +0200457 /* search for instance */
458 saux = siter;
459 siter = siter->child;
460 found = 0;
461 parent2 = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200462repeat_choice:
Radek Krejci2342cf62016-01-29 16:48:23 +0100463 while (siter && data) {
Radek Krejci074bf852015-08-19 14:22:16 +0200464 if (lys_is_disabled(siter, 2)) {
465 siter = siter->next;
466 continue;
467 }
468
Radek Krejci14a11a62015-08-17 17:27:38 +0200469 switch (siter->nodetype) {
470 case LYS_CONTAINER:
471 case LYS_LEAF:
472 case LYS_LEAFLIST:
473 case LYS_LIST:
474 case LYS_ANYXML:
475 LY_TREE_FOR(data->child, diter) {
476 if (diter->schema == siter) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200477 break;
478 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200479 }
480 if (diter) {
481 /* got instance */
482 /* check presence of mandatory siblings */
Radek Krejci65d0a652015-08-27 13:09:42 +0200483 if (parent2 && parent2->nodetype == LYS_CASE) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200484 saux2 = NULL;
Radek Krejci2342cf62016-01-29 16:48:23 +0100485 while ((saux2 = check_mand_getnext(saux2, parent2, NULL))) {
Radek Krejci37bda002015-08-27 11:23:56 +0200486 result = check_mand_check(saux2, parent2, data);
Radek Krejci14a11a62015-08-17 17:27:38 +0200487 if (result) {
488 return result;
489 }
490 }
491 }
492 siter = parent2 = NULL;
493 found = 1;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200494 break;
495 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200496 siter = siter->next;
497 break;
498 case LYS_CASE:
499 case LYS_CHOICE:
500 case LYS_USES:
501 /* go into */
Radek Krejci37bda002015-08-27 11:23:56 +0200502 if (!parent2) {
503 parent2 = siter;
504 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200505 siter = siter->child;
506 break;
507 case LYS_AUGMENT:
508 case LYS_GROUPING:
509 /* skip */
510 siter = siter->next;
511 break;
512 default:
513 /* error */
514 break;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200515 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200516 }
517
Radek Krejci14a11a62015-08-17 17:27:38 +0200518 if (parent2) {
519 siter = parent2->next;
520 if (parent2->parent == saux) {
521 parent2 = NULL;
522 } else {
523 parent2 = parent2->parent;
524 }
525 goto repeat_choice;
526 }
527
Radek Krejci074bf852015-08-19 14:22:16 +0200528 if (!found && (saux->flags & LYS_MAND_TRUE)) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200529 return saux;
530 }
531
532 /* go to next */
533 siter = saux->next;
534
Radek Krejci7f40ce32015-08-12 20:38:46 +0200535 break;
536 case LYS_USES:
537 case LYS_CASE:
538 /* go into */
539 parent = siter;
540 siter = siter->child;
541 break;
542 default:
543 /* can ignore, go to next */
544 siter = siter->next;
545 break;
546 }
547 }
548
549 if (parent) {
550 siter = parent->next;
Radek Krejci2342cf62016-01-29 16:48:23 +0100551 if (parent->parent == schema) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200552 parent = NULL;
553 } else {
554 parent = parent->parent;
555 }
556 goto repeat;
557 }
558
559 return NULL;
560}
561
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200562void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200563lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200564{
Radek Krejci76512572015-08-04 09:47:08 +0200565 struct lys_node *parent, *first;
Radek Krejcic071c542016-01-27 14:57:51 +0100566 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200567
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200568 if (!node) {
569 return;
570 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200571
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200572 /* unlink from data model if necessary */
573 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100574 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100575 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100576 if (main_module->data == node) {
577 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200578 }
579 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200580
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200581 /* store pointers to important nodes */
582 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200583 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200584 /* handle augments - first, unlink it from the augment parent ... */
585 if (parent->child == node) {
586 parent->child = node->next;
587 }
588 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200589 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200590 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200591
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200592 /* unlink from parent */
593 if (parent) {
594 if (parent->child == node) {
595 parent->child = node->next;
596 }
597 node->parent = NULL;
598 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200599
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200600 /* unlink from siblings */
601 if (node->prev == node) {
602 /* there are no more siblings */
603 return;
604 }
605 if (node->next) {
606 node->next->prev = node->prev;
607 } else {
608 /* unlinking the last element */
609 if (parent) {
610 first = parent->child;
611 } else {
612 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200613 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200614 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200615 }
616 }
617 first->prev = node->prev;
618 }
619 if (node->prev->next) {
620 node->prev->next = node->next;
621 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200622
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200623 /* clean up the unlinked element */
624 node->next = NULL;
625 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200626}
627
Michal Vasko563ef092015-09-04 13:17:23 +0200628struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100629lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200630{
631 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200632
633 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200634 /* top-level augment, look into module (uses augment is handled correctly below) */
635 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
636 par_iter = par_iter->parent->module->data;
637 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200638 break;
639 }
640 }
641
Michal Vasko6f929da2015-10-02 16:23:25 +0200642 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200643 continue;
644 }
645
646 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
647 if (!stop) {
648 stop = par_iter;
649 } else if (iter == stop) {
650 break;
651 }
652 if (iter->nodetype != LYS_GROUPING) {
653 continue;
654 }
655
Radek Krejcif8426a72015-10-31 23:14:03 +0100656 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200657 return (struct lys_node_grp *)iter;
658 }
659 }
660 }
661
Michal Vasko563ef092015-09-04 13:17:23 +0200662 return NULL;
663}
664
Radek Krejci10c760e2015-08-14 14:45:43 +0200665/*
666 * get next grouping in the root's subtree, in the
667 * first call, tha last is NULL
668 */
669static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200670lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200671{
Radek Krejci10c760e2015-08-14 14:45:43 +0200672 struct lys_node *last = (struct lys_node *)lastgrp;
673 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200674
Radek Krejci10c760e2015-08-14 14:45:43 +0200675 assert(root);
676
677 if (!last) {
678 last = root;
679 }
680
681 while (1) {
682 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
683 next = last->child;
684 } else {
685 next = NULL;
686 }
687 if (!next) {
688 if (last == root) {
689 /* we are done */
690 return NULL;
691 }
692
693 /* no children, go to siblings */
694 next = last->next;
695 }
696 while (!next) {
697 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100698 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200699 /* we are done */
700 return NULL;
701 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200702 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100703 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200704 }
705
706 if (next->nodetype == LYS_GROUPING) {
707 return (struct lys_node_grp *)next;
708 }
709
710 last = next;
711 }
712}
713
Michal Vasko0d343d12015-08-24 14:57:36 +0200714/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200715int
Radek Krejci07911992015-08-14 15:13:31 +0200716lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
717{
Michal Vasko563ef092015-09-04 13:17:23 +0200718 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200719 struct lys_node_grp *grp;
720 int down;
721
722 assert(node);
723
724 if (!parent) {
725 assert(module);
726 } else {
727 module = parent->module;
728 }
729
730 switch (node->nodetype) {
731 case LYS_GROUPING:
732 /* 6.2.1, rule 6 */
733 if (parent) {
734 if (parent->child) {
735 down = 1;
736 start = parent->child;
737 } else {
738 down = 0;
739 start = parent;
740 }
741 } else {
742 down = 1;
743 start = module->data;
744 }
745 /* go up */
Radek Krejcic071c542016-01-27 14:57:51 +0100746 if (lys_find_grouping_up(node->name, start)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100747 LOGVAL(LYE_DUPID, 0, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200748 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200749 }
750 /* go down, because grouping can be defined after e.g. container in which is collision */
751 if (down) {
752 for (iter = start, stop = NULL; iter; iter = iter->prev) {
753 if (!stop) {
754 stop = start;
755 } else if (iter == stop) {
756 break;
757 }
758 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
759 continue;
760 }
761
762 grp = NULL;
763 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100764 if (ly_strequal(node->name, grp->name, 1)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100765 LOGVAL(LYE_DUPID, 0, LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200766 return EXIT_FAILURE;
767 }
768 }
769 }
770 }
771 break;
772 case LYS_LEAF:
773 case LYS_LEAFLIST:
774 case LYS_LIST:
775 case LYS_CONTAINER:
776 case LYS_CHOICE:
777 case LYS_ANYXML:
778 /* 6.2.1, rule 7 */
779 if (parent) {
780 iter = parent;
781 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE))) {
782 iter = iter->parent;
783 }
784 if (!iter) {
785 stop = NULL;
786 iter = module->data;
787 } else {
788 stop = iter;
789 iter = iter->child;
790 }
791 } else {
792 stop = NULL;
793 iter = module->data;
794 }
795 while (iter) {
796 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
797 iter = iter->child;
798 continue;
799 }
800
801 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100802 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100803 LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, node, "Duplicated child identifier \"%s\" in \"%s\".", node->name,
Radek Krejci07911992015-08-14 15:13:31 +0200804 stop ? stop->name : "(sub)module");
805 return EXIT_FAILURE;
806 }
807 }
808
809 /* special case for choice - we must check the choice's name as
810 * well as the names of nodes under the choice
811 */
812 if (iter->nodetype == LYS_CHOICE) {
813 iter = iter->child;
814 continue;
815 }
816
817 /* go to siblings */
818 if (!iter->next) {
819 /* no sibling, go to parent's sibling */
820 do {
821 iter = iter->parent;
822 if (iter && iter->next) {
823 break;
824 }
825 } while (iter != stop);
826
827 if (iter == stop) {
828 break;
829 }
830 }
831 iter = iter->next;
832 }
833 break;
834 case LYS_CASE:
835 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100836 if (parent) {
837 start = parent->child;
838 } else {
839 start = module->data;
840 }
841
842 LY_TREE_FOR(start, iter) {
Radek Krejci07911992015-08-14 15:13:31 +0200843 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
844 continue;
845 }
846
Radek Krejci749190d2016-02-18 16:26:25 +0100847 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejciadb57612016-02-16 13:34:34 +0100848 LOGVAL(LYE_DUPID, 0, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200849 return EXIT_FAILURE;
850 }
851 }
852 break;
853 default:
854 /* no check needed */
855 break;
856 }
857
858 return EXIT_SUCCESS;
859}
860
Michal Vasko0d343d12015-08-24 14:57:36 +0200861/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200862int
Radek Krejci10c760e2015-08-14 14:45:43 +0200863lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
864{
Radek Krejci92720552015-10-05 15:28:27 +0200865 struct lys_node *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200866 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200867
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200868 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200869
Radek Krejci10c760e2015-08-14 14:45:43 +0200870 if (parent) {
871 type = parent->nodetype;
872 module = parent->module;
873 } else {
874 assert(module);
875 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200876 }
877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200878 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200879 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200880 case LYS_CONTAINER:
881 case LYS_LIST:
882 case LYS_GROUPING:
883 case LYS_USES:
884 case LYS_INPUT:
885 case LYS_OUTPUT:
886 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200887 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200888 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
889 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejciadb57612016-02-16 13:34:34 +0100890 LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200891 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
892 return EXIT_FAILURE;
893 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200894
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200895 break;
Radek Krejci76512572015-08-04 09:47:08 +0200896 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200897 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200898 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejciadb57612016-02-16 13:34:34 +0100899 LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "Unexpected substatement \"%s\" in \"choice\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200900 strnodetype(child->nodetype), parent->name);
901 return EXIT_FAILURE;
902 }
903 break;
Radek Krejci76512572015-08-04 09:47:08 +0200904 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200905 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200906 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejciadb57612016-02-16 13:34:34 +0100907 LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "Unexpected substatement \"%s\" in \"case\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200908 strnodetype(child->nodetype), parent->name);
909 return EXIT_FAILURE;
910 }
911 break;
Radek Krejci76512572015-08-04 09:47:08 +0200912 case LYS_RPC:
913 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Radek Krejciadb57612016-02-16 13:34:34 +0100914 LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "Unexpected substatement \"%s\" in \"rpc\" %s.",
Michal Vasko38d01f72015-06-15 09:41:06 +0200915 strnodetype(child->nodetype), parent->name);
916 return EXIT_FAILURE;
917 }
918 break;
Radek Krejci76512572015-08-04 09:47:08 +0200919 case LYS_LEAF:
920 case LYS_LEAFLIST:
921 case LYS_ANYXML:
Radek Krejciadb57612016-02-16 13:34:34 +0100922 LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "The \"%s\" statement (%s) cannot have any data substatement.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200923 strnodetype(parent->nodetype), parent->name);
924 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200925 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200926 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200927 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
928 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejciadb57612016-02-16 13:34:34 +0100929 LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200930 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
931 return EXIT_FAILURE;
932 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200933 break;
934 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200935 /* top level */
936 if (!(child->nodetype &
937 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
938 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejciadb57612016-02-16 13:34:34 +0100939 LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "Unexpected substatement \"%s\" in (sub)module \"%s\"",
Radek Krejci2c0ca272015-08-14 15:31:01 +0200940 strnodetype(child->nodetype), module->name);
Radek Krejci10c760e2015-08-14 14:45:43 +0200941 return EXIT_FAILURE;
942 }
943
Radek Krejcic071c542016-01-27 14:57:51 +0100944 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200945 }
946
947 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200948 if (lys_check_id(child, parent, module)) {
949 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200950 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200951
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200952 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200953 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200954 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200955
Radek Krejci10c760e2015-08-14 14:45:43 +0200956 if (!parent) {
Radek Krejci92720552015-10-05 15:28:27 +0200957 if (module->data) {
958 module->data->prev->next = child;
959 child->prev = module->data->prev;
960 module->data->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200961 } else {
Radek Krejci92720552015-10-05 15:28:27 +0200962 module->data = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200963 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200964 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +0200965 if (!parent->child) {
966 /* the only/first child of the parent */
967 parent->child = child;
968 child->parent = parent;
969 iter = child;
970 } else {
971 /* add a new child at the end of parent's child list */
972 iter = parent->child->prev;
973 iter->next = child;
974 child->prev = iter;
975 }
976 while (iter->next) {
977 iter = iter->next;
978 iter->parent = parent;
979 }
980 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200981 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200982
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200983 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200984}
985
Michal Vasko1e62a092015-12-01 12:27:20 +0100986API const struct lys_module *
Radek Krejci722b0072016-02-01 17:09:45 +0100987lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200988{
Radek Krejci0b5805d2015-08-13 09:38:02 +0200989 struct lys_module *mod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200990
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200991 if (!ctx || !data) {
992 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
993 return NULL;
994 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200995
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200996 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200997 case LYS_IN_YIN:
Radek Krejcic071c542016-01-27 14:57:51 +0100998 mod = yin_read_module(ctx, data, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200999 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001000 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001001 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001002 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001003 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001004 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001005
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001006 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001007}
1008
Michal Vasko5a721fd2016-02-16 12:16:48 +01001009struct lys_submodule *
1010lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001011{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001012 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001013
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001014 assert(module);
1015 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001016
Radek Krejcic071c542016-01-27 14:57:51 +01001017 /* get the main module */
Michal Vasko4f0dad02016-02-15 14:08:23 +01001018 module = lys_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001019
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001020 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02001021 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +01001022 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001023 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +02001024 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001025 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +02001026 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001027 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001028 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001029
Michal Vasko5a721fd2016-02-16 12:16:48 +01001030 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +02001031}
1032
Michal Vasko1e62a092015-12-01 12:27:20 +01001033API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +01001034lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
1035{
1036 int fd;
1037 const struct lys_module *ret;
1038
1039 if (!ctx || !path) {
1040 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1041 return NULL;
1042 }
1043
1044 fd = open(path, O_RDONLY);
1045 if (fd == -1) {
1046 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
1047 return NULL;
1048 }
1049
1050 ret = lys_parse_fd(ctx, fd, format);
1051 close(fd);
1052 return ret;
1053}
1054
1055API const struct lys_module *
1056lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001057{
Michal Vasko1e62a092015-12-01 12:27:20 +01001058 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +02001059 struct stat sb;
1060 char *addr;
Radek Krejcib051f722016-02-25 15:12:21 +01001061 char buf[PATH_MAX];
1062 int len;
Radek Krejci63a91a92015-07-29 13:31:04 +02001063
1064 if (!ctx || fd < 0) {
1065 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1066 return NULL;
1067 }
1068
Radek Krejci10a833c2015-12-16 15:28:37 +01001069 if (fstat(fd, &sb) == -1) {
1070 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
1071 return NULL;
1072 }
Radek Krejcib051f722016-02-25 15:12:21 +01001073 if (!S_ISREG(sb.st_mode)) {
1074 LOGERR(LY_EINVAL, "Invalid parameter, input file is not a regular file");
1075 return NULL;
1076 }
1077
Radek Krejci3006be02015-12-17 11:24:33 +01001078 addr = mmap(NULL, sb.st_size + 1, PROT_READ, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001079 if (addr == MAP_FAILED) {
Michal Vasko662610a2015-12-07 11:25:45 +01001080 LOGERR(LY_EMEM, "Map file into memory failed (%s()).",__func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001081 return NULL;
1082 }
Radek Krejci722b0072016-02-01 17:09:45 +01001083 module = lys_parse_mem(ctx, addr, format);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001084 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001085
Radek Krejcib051f722016-02-25 15:12:21 +01001086 if (module && ! module->uri) {
1087 /* get URI if there is /proc */
1088 addr = NULL;
1089 asprintf(&addr, "/proc/self/fd/%d", fd);
1090 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
1091 ((struct lys_module *)module)->uri = lydict_insert(ctx, buf, len);
1092 }
1093 free(addr);
1094 }
1095
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001096 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001097}
1098
Michal Vasko5a721fd2016-02-16 12:16:48 +01001099struct lys_submodule *
1100lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001101{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001102 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001103 struct stat sb;
1104 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001105
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001106 assert(module);
1107 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001108
Radek Krejci10a833c2015-12-16 15:28:37 +01001109 if (fstat(fd, &sb) == -1) {
1110 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
Michal Vasko5a721fd2016-02-16 12:16:48 +01001111 return NULL;
Radek Krejci10a833c2015-12-16 15:28:37 +01001112 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001113 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001114 if (addr == MAP_FAILED) {
1115 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001116 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001117 }
Michal Vasko5a721fd2016-02-16 12:16:48 +01001118 submodule = lys_submodule_parse(module, addr, format, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001119 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +02001120
Michal Vasko5a721fd2016-02-16 12:16:48 +01001121 return submodule;
1122
Radek Krejciefaeba32015-05-27 14:30:57 +02001123}
1124
Radek Krejci1d82ef62015-08-07 14:44:40 +02001125static struct lys_restr *
1126lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001127{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001128 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001129 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001130
Radek Krejci3733a802015-06-19 13:43:21 +02001131 if (!size) {
1132 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001133 }
Radek Krejci3733a802015-06-19 13:43:21 +02001134
1135 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001136 if (!result) {
Radek Krejciaa2a8932016-02-17 15:03:14 +01001137 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +01001138 return NULL;
1139 }
Radek Krejci3733a802015-06-19 13:43:21 +02001140 for (i = 0; i < size; i++) {
1141 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1142 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1143 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1144 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1145 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1146 }
1147
1148 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001149}
1150
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001151void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001152lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001153{
1154 assert(ctx);
1155 if (!restr) {
1156 return;
1157 }
1158
1159 lydict_remove(ctx, restr->expr);
1160 lydict_remove(ctx, restr->dsc);
1161 lydict_remove(ctx, restr->ref);
1162 lydict_remove(ctx, restr->eapptag);
1163 lydict_remove(ctx, restr->emsg);
1164}
1165
Michal Vaskob84f88a2015-09-24 13:16:10 +02001166static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001167lys_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 +02001168 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001169{
1170 int i;
1171
Michal Vasko1dca6882015-10-22 14:29:42 +02001172 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001173 new->base = old->base;
1174 new->der = old->der;
1175
Michal Vasko0bd29d12015-08-19 11:45:49 +02001176 i = unres_schema_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001177 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001178 /* HACK (serious one) for unres */
1179 /* nothing else we can do but duplicate it immediately */
1180 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
Radek Krejcic071c542016-01-27 14:57:51 +01001181 new->parent = (struct lys_tpdf *)parent;
Michal Vaskob84f88a2015-09-24 13:16:10 +02001182 /* all these unres additions can fail even though they did not before */
Michal Vasko88c29542015-11-27 14:57:53 +01001183 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_DER, parent, 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001184 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001185 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001186 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001187 }
1188
Radek Krejci3733a802015-06-19 13:43:21 +02001189 switch (new->base) {
1190 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +02001191 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001192 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001193 }
Radek Krejci3733a802015-06-19 13:43:21 +02001194 break;
1195
1196 case LY_TYPE_BITS:
1197 new->info.bits.count = old->info.bits.count;
1198 if (new->info.bits.count) {
1199 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +01001200 if (!new->info.bits.bit) {
1201 LOGMEM;
1202 return -1;
1203 }
Radek Krejci3733a802015-06-19 13:43:21 +02001204 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001205 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1206 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1207 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Michal Vasko3f053ef2016-02-12 14:27:13 +01001208 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
Radek Krejci3733a802015-06-19 13:43:21 +02001209 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1210 }
1211 }
1212 break;
1213
Radek Krejcif9401c32015-06-26 16:47:36 +02001214 case LY_TYPE_DEC64:
1215 new->info.dec64.dig = old->info.dec64.dig;
1216 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001217 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +02001218 }
1219 break;
1220
Radek Krejci3733a802015-06-19 13:43:21 +02001221 case LY_TYPE_ENUM:
1222 new->info.enums.count = old->info.enums.count;
1223 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001224 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +01001225 if (!new->info.enums.enm) {
1226 LOGMEM;
1227 return -1;
1228 }
Radek Krejci3733a802015-06-19 13:43:21 +02001229 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001230 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1231 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1232 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
Michal Vasko3f053ef2016-02-12 14:27:13 +01001233 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001234 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +02001235 }
1236 }
1237 break;
1238
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001239 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001240 if (old->info.ident.ref) {
1241 new->info.ident.ref = old->info.ident.ref;
1242 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001243 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001244 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 +02001245 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001246 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001247 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001248 break;
1249
Radek Krejciaf351422015-06-19 14:49:38 +02001250 case LY_TYPE_INST:
1251 new->info.inst.req = old->info.inst.req;
1252 break;
1253
Radek Krejcif2860132015-06-20 12:37:20 +02001254 case LY_TYPE_INT8:
1255 case LY_TYPE_INT16:
1256 case LY_TYPE_INT32:
1257 case LY_TYPE_INT64:
1258 case LY_TYPE_UINT8:
1259 case LY_TYPE_UINT16:
1260 case LY_TYPE_UINT32:
1261 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +02001262 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001263 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001264 }
Radek Krejcif2860132015-06-20 12:37:20 +02001265 break;
1266
Radek Krejcidc4c1412015-06-19 15:39:54 +02001267 case LY_TYPE_LEAFREF:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001268 if (old->info.lref.path) {
1269 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
1270 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0)) {
1271 return -1;
1272 }
Michal Vasko49168a22015-08-17 16:35:41 +02001273 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001274 break;
1275
Radek Krejci3733a802015-06-19 13:43:21 +02001276 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +02001277 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001278 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001279 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001280 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 +01001281 new->info.str.pat_count = old->info.str.pat_count;
Radek Krejci3733a802015-06-19 13:43:21 +02001282 break;
1283
Radek Krejcie4c366b2015-07-02 10:11:31 +02001284 case LY_TYPE_UNION:
1285 new->info.uni.count = old->info.uni.count;
1286 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001287 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +01001288 if (!new->info.uni.types) {
1289 LOGMEM;
1290 return -1;
1291 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001292 for (i = 0; i < new->info.uni.count; i++) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001293 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres)) {
1294 return -1;
1295 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001296 }
1297 }
1298 break;
1299
Radek Krejci3733a802015-06-19 13:43:21 +02001300 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001301 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001302 break;
1303 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001304
1305 return EXIT_SUCCESS;
Radek Krejci3733a802015-06-19 13:43:21 +02001306}
1307
1308void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001309lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001310{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001311 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001312
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001313 assert(ctx);
1314 if (!type) {
1315 return;
1316 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001317
Michal Vasko1dca6882015-10-22 14:29:42 +02001318 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001319
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001320 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001321 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001322 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001323 free(type->info.binary.length);
1324 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001325 case LY_TYPE_BITS:
1326 for (i = 0; i < type->info.bits.count; i++) {
1327 lydict_remove(ctx, type->info.bits.bit[i].name);
1328 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1329 lydict_remove(ctx, type->info.bits.bit[i].ref);
1330 }
1331 free(type->info.bits.bit);
1332 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001333
1334 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001335 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001336 free(type->info.dec64.range);
1337 break;
1338
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001339 case LY_TYPE_ENUM:
1340 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001341 lydict_remove(ctx, type->info.enums.enm[i].name);
1342 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1343 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001344 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001345 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001346 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001347
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001348 case LY_TYPE_INT8:
1349 case LY_TYPE_INT16:
1350 case LY_TYPE_INT32:
1351 case LY_TYPE_INT64:
1352 case LY_TYPE_UINT8:
1353 case LY_TYPE_UINT16:
1354 case LY_TYPE_UINT32:
1355 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001356 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001357 free(type->info.num.range);
1358 break;
1359
Radek Krejcidc4c1412015-06-19 15:39:54 +02001360 case LY_TYPE_LEAFREF:
1361 lydict_remove(ctx, type->info.lref.path);
1362 break;
1363
Radek Krejci3733a802015-06-19 13:43:21 +02001364 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001365 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001366 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001367 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001368 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001369 }
1370 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001371 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001372
Radek Krejcie4c366b2015-07-02 10:11:31 +02001373 case LY_TYPE_UNION:
1374 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001375 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001376 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001377 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001378 break;
1379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001380 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001381 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001382 break;
1383 }
Radek Krejci5a065542015-05-22 15:02:07 +02001384}
1385
Radek Krejci1d82ef62015-08-07 14:44:40 +02001386static void
1387lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001388{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001389 assert(ctx);
1390 if (!tpdf) {
1391 return;
1392 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001393
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001394 lydict_remove(ctx, tpdf->name);
1395 lydict_remove(ctx, tpdf->dsc);
1396 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001397
Radek Krejci1d82ef62015-08-07 14:44:40 +02001398 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001399
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001400 lydict_remove(ctx, tpdf->units);
1401 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001402}
1403
Michal Vaskob84f88a2015-09-24 13:16:10 +02001404static struct lys_tpdf *
1405lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1406{
1407 struct lys_tpdf *result;
1408 int i, j;
1409
1410 if (!size) {
1411 return NULL;
1412 }
1413
1414 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001415 if (!result) {
1416 LOGMEM;
1417 return NULL;
1418 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001419 for (i = 0; i < size; i++) {
1420 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1421 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1422 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1423 result[i].flags = old[i].flags;
1424 result[i].module = old[i].module;
1425
1426 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres)) {
1427 for (j = 0; j <= i; ++j) {
1428 lys_tpdf_free(mod->ctx, &result[j]);
1429 }
1430 free(result);
1431 return NULL;
1432 }
1433
1434 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1435 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1436 }
1437
1438 return result;
1439}
1440
Radek Krejci1d82ef62015-08-07 14:44:40 +02001441static struct lys_when *
1442lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001443{
Radek Krejci76512572015-08-04 09:47:08 +02001444 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001445
1446 if (!old) {
1447 return NULL;
1448 }
1449
1450 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001451 if (!new) {
1452 LOGMEM;
1453 return NULL;
1454 }
Radek Krejci00768f42015-06-18 17:04:04 +02001455 new->cond = lydict_insert(ctx, old->cond, 0);
1456 new->dsc = lydict_insert(ctx, old->dsc, 0);
1457 new->ref = lydict_insert(ctx, old->ref, 0);
1458
1459 return new;
1460}
1461
Michal Vasko0308dd62015-10-07 09:14:40 +02001462void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001463lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001464{
1465 if (!w) {
1466 return;
1467 }
1468
1469 lydict_remove(ctx, w->cond);
1470 lydict_remove(ctx, w->dsc);
1471 lydict_remove(ctx, w->ref);
1472
1473 free(w);
1474}
1475
Radek Krejcib7f5e412015-08-13 10:15:51 +02001476static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001477lys_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 +02001478{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001479 struct lys_node *next, *sub;
1480
Radek Krejcic071c542016-01-27 14:57:51 +01001481 /* children from a resolved augment are freed under the target node */
1482 if (!aug.target) {
1483 LY_TREE_FOR_SAFE(aug.child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001484 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001485 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001486 }
1487
Radek Krejcib7f5e412015-08-13 10:15:51 +02001488 lydict_remove(ctx, aug.target_name);
1489 lydict_remove(ctx, aug.dsc);
1490 lydict_remove(ctx, aug.ref);
1491
1492 free(aug.features);
1493
1494 lys_when_free(ctx, aug.when);
1495
Michal Vasko7d356a52015-08-19 15:06:31 +02001496 /* Do not free the children, they were appended somewhere and their
1497 * new parent will take care of them.
1498 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001499}
1500
Radek Krejci76512572015-08-04 09:47:08 +02001501static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001502lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001503{
Radek Krejci76512572015-08-04 09:47:08 +02001504 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001505 struct lys_node *old_child, *new_child;
1506 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001507
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001508 if (!size) {
1509 return NULL;
1510 }
Radek Krejci106efc02015-06-10 14:36:27 +02001511
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001512 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001513 if (!new) {
1514 LOGMEM;
1515 return NULL;
1516 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001517 for (i = 0; i < size; i++) {
1518 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1519 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1520 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1521 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001522 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001523 new[i].nodetype = old[i].nodetype;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001524
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001525 /* this must succeed, it was already resolved once */
Michal Vasko3edeaf72016-02-11 13:17:43 +01001526 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL,
1527 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001528 LOGINT;
1529 free(new);
1530 return NULL;
1531 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001532 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001533
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001534 /* Correct the augment nodes.
1535 * This function can only be called from lys_node_dup() with uses
1536 * being the node duplicated, so we must have a case of grouping
1537 * with a uses with augments. The augmented nodes have already been
1538 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001539 * (it was set to their actual data parent, not an augment), and
1540 * the new augment does not have child pointer to its augment nodes,
1541 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001542 */
1543 LY_TREE_FOR(new[i].target->child, new_child) {
Radek Krejci749190d2016-02-18 16:26:25 +01001544 if (ly_strequal(new_child->name, old[i].child->name, 1)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001545 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001546 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001547 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001548 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001549 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001550 LY_TREE_FOR(old[i].child, old_child) {
1551 /* all augment nodes were connected as siblings, there can be no more after this */
1552 if (old_child->parent != (struct lys_node *)&old[i]) {
1553 break;
1554 }
1555
Radek Krejci749190d2016-02-18 16:26:25 +01001556 assert(ly_strequal(old_child->name, new_child->name, 1));
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001557
1558 new_child->parent = (struct lys_node *)&new[i];
1559 new_child = new_child->next;
1560 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001561 }
Radek Krejci106efc02015-06-10 14:36:27 +02001562
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001563 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001564}
1565
Radek Krejci76512572015-08-04 09:47:08 +02001566static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001567lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001568{
Radek Krejci76512572015-08-04 09:47:08 +02001569 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001570 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001571
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001572 if (!size) {
1573 return NULL;
1574 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001575
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001576 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001577 if (!result) {
1578 LOGMEM;
1579 return NULL;
1580 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001581 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001582 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001583 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1584 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001585 result[i].flags = old[i].flags;
1586 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001587
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001588 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001589 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001590
Radek Krejci76512572015-08-04 09:47:08 +02001591 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001592 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001593 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001594 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001595 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001596 result[i].mod.list = old[i].mod.list;
1597 }
1598 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001599
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001600 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001601}
1602
Radek Krejci1d82ef62015-08-07 14:44:40 +02001603static void
1604lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001605{
Radek Krejcia52656e2015-08-05 13:41:50 +02001606 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001607
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001608 assert(ctx);
1609 if (!ident) {
1610 return;
1611 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001612
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001613 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001614 * if caller free only a single data model which is used (its identity is
1615 * reference from identity in another module), this silly freeing can lead
1616 * to segmentation fault. But without noting if the module is used by some
1617 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001618 *
1619 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001620 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001621 */
1622 while (ident->der) {
1623 der = ident->der;
1624 ident->der = der->next;
1625 free(der);
1626 }
Radek Krejci6793db02015-05-22 17:49:54 +02001627
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001628 lydict_remove(ctx, ident->name);
1629 lydict_remove(ctx, ident->dsc);
1630 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001631
1632}
1633
Radek Krejci1d82ef62015-08-07 14:44:40 +02001634static void
1635lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001636{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001637 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001638
Radek Krejcid12f57b2015-08-06 10:43:39 +02001639 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001640 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001641 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001642 }
1643 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001644}
1645
Radek Krejci1d82ef62015-08-07 14:44:40 +02001646static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001647lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1648{
1649 int i;
1650
1651 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1652 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001653 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001654 }
1655 free(io->tpdf);
1656}
1657
Radek Krejci1d82ef62015-08-07 14:44:40 +02001658static void
1659lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001660{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001661 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001662
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001663 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001664 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001665 }
1666 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001667
Radek Krejci1d82ef62015-08-07 14:44:40 +02001668 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001669}
1670
Radek Krejci1d82ef62015-08-07 14:44:40 +02001671static void
1672lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001673{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001674 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001675
Radek Krejci46c4cd72016-01-21 15:13:52 +01001676 if (leaf->child) {
1677 /* leafref backlinks */
1678 ly_set_free((struct ly_set *)leaf->child);
1679 }
1680
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001681 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001682 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001683 }
1684 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001685
Radek Krejci1d82ef62015-08-07 14:44:40 +02001686 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001687
Radek Krejci1d82ef62015-08-07 14:44:40 +02001688 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001689 lydict_remove(ctx, leaf->units);
1690 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001691}
1692
Radek Krejci1d82ef62015-08-07 14:44:40 +02001693static void
1694lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001695{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001696 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001697
Radek Krejci46c4cd72016-01-21 15:13:52 +01001698 if (llist->child) {
1699 /* leafref backlinks */
1700 ly_set_free((struct ly_set *)llist->child);
1701 }
1702
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001703 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001704 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001705 }
1706 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001707
Radek Krejci1d82ef62015-08-07 14:44:40 +02001708 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001709
Radek Krejci1d82ef62015-08-07 14:44:40 +02001710 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001711 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001712}
1713
Radek Krejci1d82ef62015-08-07 14:44:40 +02001714static void
1715lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001716{
Radek Krejci581ce772015-11-10 17:22:40 +01001717 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001718
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001719 /* handle only specific parts for LY_NODE_LIST */
1720 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001721 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001722 }
1723 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001724
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001725 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001726 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001727 }
1728 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001729
Radek Krejci1d82ef62015-08-07 14:44:40 +02001730 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001731
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001732 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001733 for (j = 0; j > list->unique[i].expr_size; j++) {
1734 lydict_remove(ctx, list->unique[i].expr[j]);
1735 }
1736 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001737 }
1738 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001739
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001740 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001741}
1742
Radek Krejci1d82ef62015-08-07 14:44:40 +02001743static void
1744lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001745{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001746 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001747
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001748 /* handle only specific parts for LY_NODE_CONTAINER */
1749 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001750
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001751 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001752 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001753 }
1754 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001755
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001756 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001757 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001758 }
1759 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001760
Radek Krejci1d82ef62015-08-07 14:44:40 +02001761 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001762}
1763
Radek Krejci1d82ef62015-08-07 14:44:40 +02001764static void
1765lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001766{
1767 lydict_remove(ctx, f->name);
1768 lydict_remove(ctx, f->dsc);
1769 lydict_remove(ctx, f->ref);
1770 free(f->features);
1771}
1772
Radek Krejci1d82ef62015-08-07 14:44:40 +02001773static void
Michal Vaskoff006c12016-02-17 11:15:19 +01001774lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001775{
Radek Krejci581ce772015-11-10 17:22:40 +01001776 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01001777 struct ly_ctx *ctx;
1778 struct lys_node *next, *elem;
1779
1780 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02001781
1782 lydict_remove(ctx, dev->target_name);
1783 lydict_remove(ctx, dev->dsc);
1784 lydict_remove(ctx, dev->ref);
1785
Michal Vaskoff006c12016-02-17 11:15:19 +01001786 /* the module was freed, but we only need the context from orig_node, use ours */
1787 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
1788 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
1789 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
1790 elem->module = module;
1791
1792 LY_TREE_DFS_END(dev->orig_node, next, elem);
1793 }
1794 lys_node_free(dev->orig_node, NULL, 0);
1795 } else {
1796 /* it's just a shallow copy, freeing one node */
1797 dev->orig_node->module = module;
1798 lys_node_free(dev->orig_node, NULL, 1);
1799 }
1800
Radek Krejcieb00f512015-07-01 16:44:58 +02001801 for (i = 0; i < dev->deviate_size; i++) {
1802 lydict_remove(ctx, dev->deviate[i].dflt);
1803 lydict_remove(ctx, dev->deviate[i].units);
1804
1805 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1806 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001807 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001808 }
1809 free(dev->deviate[i].must);
1810
1811 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001812 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1813 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1814 }
1815 free(dev->deviate[j].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001816 }
1817 free(dev->deviate[i].unique);
1818 }
1819 }
1820 free(dev->deviate);
1821}
1822
Radek Krejci1d82ef62015-08-07 14:44:40 +02001823static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001824lys_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 +02001825{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001826 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001827
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001828 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001829 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001830 lydict_remove(ctx, uses->refine[i].dsc);
1831 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001832
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001833 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001834 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001835 }
1836 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001837
Radek Krejci76512572015-08-04 09:47:08 +02001838 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001839 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001840 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001841 lydict_remove(ctx, uses->refine[i].mod.presence);
1842 }
1843 }
1844 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001845
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001846 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001847 lys_augment_free(ctx, uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001848 }
1849 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001850
Radek Krejci1d82ef62015-08-07 14:44:40 +02001851 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001852}
1853
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001854void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001855lys_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 +02001856{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001857 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001858 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001859
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001860 if (!node) {
1861 return;
1862 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001863
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001864 assert(node->module);
1865 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001866
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001867 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001868
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001869 /* remove private object */
1870 if (node->private && private_destructor) {
1871 private_destructor(node, node->private);
1872 }
1873
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001874 /* common part */
Radek Krejcid12f57b2015-08-06 10:43:39 +02001875 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1876 free(node->features);
1877 lydict_remove(ctx, node->name);
1878 lydict_remove(ctx, node->dsc);
1879 lydict_remove(ctx, node->ref);
1880 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001881
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001882 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01001883 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001884 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001885 }
1886 }
1887
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001888 /* specific part */
1889 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001890 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001891 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001892 break;
Radek Krejci76512572015-08-04 09:47:08 +02001893 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001894 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001895 break;
Radek Krejci76512572015-08-04 09:47:08 +02001896 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001897 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001898 break;
Radek Krejci76512572015-08-04 09:47:08 +02001899 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001900 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001901 break;
Radek Krejci76512572015-08-04 09:47:08 +02001902 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001903 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001904 break;
Radek Krejci76512572015-08-04 09:47:08 +02001905 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001906 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001907 break;
Radek Krejci76512572015-08-04 09:47:08 +02001908 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001909 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001910 break;
Radek Krejci76512572015-08-04 09:47:08 +02001911 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001912 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001913 break;
Radek Krejci76512572015-08-04 09:47:08 +02001914 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001915 /* do nothing */
1916 break;
Radek Krejci76512572015-08-04 09:47:08 +02001917 case LYS_GROUPING:
1918 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001919 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001920 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001921 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001922
1923 case LYS_INPUT:
1924 case LYS_OUTPUT:
1925 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1926 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001927 case LYS_UNKNOWN:
1928 LOGINT;
1929 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001930 }
Radek Krejci5a065542015-05-22 15:02:07 +02001931
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001932 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001933 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001934 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001935}
1936
Michal Vasko1e62a092015-12-01 12:27:20 +01001937const struct lys_module *
1938lys_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 +02001939{
Radek Krejcic071c542016-01-27 14:57:51 +01001940 const struct lys_module *main_module;
Michal Vasko3edeaf72016-02-11 13:17:43 +01001941 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02001942
Michal Vaskoa7789a82016-02-11 15:42:55 +01001943 assert(!prefix || !name);
1944
Michal Vaskob6729c62015-10-21 12:09:47 +02001945 if (prefix && !pref_len) {
1946 pref_len = strlen(prefix);
1947 }
1948 if (name && !name_len) {
1949 name_len = strlen(name);
1950 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02001951
Michal Vasko4f0dad02016-02-15 14:08:23 +01001952 main_module = lys_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01001953
1954 /* module own prefix, submodule own prefix, (sub)module own name */
1955 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
1956 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01001957 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01001958 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02001959 }
1960
Michal Vasko8ce24d72015-10-21 11:27:26 +02001961 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01001962 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
1963 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02001964 return module->imp[i].module;
1965 }
1966 }
1967
1968 return NULL;
1969}
1970
Michal Vasko13b15832015-08-19 11:04:48 +02001971/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001972static void
Michal Vaskob746fff2016-02-11 11:37:50 +01001973module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02001974{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001975 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01001976 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001977 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001978
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001979 assert(module->ctx);
1980 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001981
Michal Vaskob746fff2016-02-11 11:37:50 +01001982 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01001983 for (i = 0; i < module->imp_size; i++) {
Radek Krejci4f78b532016-02-17 13:43:00 +01001984 if (!module->imp[i].external) {
1985 lydict_remove(ctx, module->imp[i].prefix);
1986 }
Radek Krejci225376f2016-02-16 17:36:22 +01001987 }
Radek Krejcidce51452015-06-16 15:20:08 +02001988 free(module->imp);
1989
Radek Krejcic071c542016-01-27 14:57:51 +01001990 /* submodules don't have data tree, the data nodes
1991 * are placed in the main module altogether */
1992 if (!module->type) {
1993 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001994 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001995 }
Radek Krejci21181962015-06-30 14:11:00 +02001996 }
Radek Krejci5a065542015-05-22 15:02:07 +02001997
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001998 lydict_remove(ctx, module->dsc);
1999 lydict_remove(ctx, module->ref);
2000 lydict_remove(ctx, module->org);
2001 lydict_remove(ctx, module->contact);
Radek Krejcic5989d42016-02-17 11:16:38 +01002002 lydict_remove(ctx, module->uri);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002003
Radek Krejcieb00f512015-07-01 16:44:58 +02002004 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002005 for (i = 0; i < module->rev_size; i++) {
2006 lydict_remove(ctx, module->rev[i].dsc);
2007 lydict_remove(ctx, module->rev[i].ref);
2008 }
2009 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002010
Radek Krejcieb00f512015-07-01 16:44:58 +02002011 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002012 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002013 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002014 }
2015 module->ident_size = 0;
2016 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002017
Radek Krejcieb00f512015-07-01 16:44:58 +02002018 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002019 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002020 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002021 }
2022 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002023
Radek Krejcieb00f512015-07-01 16:44:58 +02002024 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002025 for (i = 0; i < module->inc_size; i++) {
Radek Krejcic071c542016-01-27 14:57:51 +01002026 /* complete submodule free is done only from main module since
2027 * submodules propagate their includes to the main module */
2028 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002029 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002030 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002031 }
2032 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002033
Radek Krejcieb00f512015-07-01 16:44:58 +02002034 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002035 for (i = 0; i < module->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002036 lys_augment_free(ctx, module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002037 }
2038 free(module->augment);
2039
Radek Krejcieb00f512015-07-01 16:44:58 +02002040 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002041 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002042 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002043 }
2044 free(module->features);
2045
Radek Krejcieb00f512015-07-01 16:44:58 +02002046 /* deviations */
2047 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002048 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002049 }
2050 free(module->deviation);
2051
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002052 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002053 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002054}
2055
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002056void
Michal Vaskob746fff2016-02-11 11:37:50 +01002057lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002058{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002059 if (!submodule) {
2060 return;
2061 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002062
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002063 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002064 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002065
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002066 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002067
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002068 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002069}
2070
Radek Krejci76512572015-08-04 09:47:08 +02002071struct lys_node *
Radek Krejcic071c542016-01-27 14:57:51 +01002072lys_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 +01002073 uint8_t nacm, struct unres_schema *unres, int shallow)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002074{
Radek Krejcic071c542016-01-27 14:57:51 +01002075 struct lys_node *retval = NULL, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002076 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002077 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002078
Michal Vaskoc07187d2015-08-13 15:20:57 +02002079 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002080 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002081 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002082 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002083 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002084 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002085 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002086 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002087 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002088 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002089 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002090 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002091 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002092 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002093 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002094 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002095 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002096 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002097 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002098 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002099 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002100 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002101 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002102 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002104 /* we cannot just duplicate memory since the strings are stored in
2105 * dictionary and we need to update dictionary counters.
2106 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002107
Radek Krejci1d82ef62015-08-07 14:44:40 +02002108 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002109 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002110 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002111 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002112 break;
2113
Radek Krejci76512572015-08-04 09:47:08 +02002114 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002115 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002116 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002117 break;
2118
Radek Krejci76512572015-08-04 09:47:08 +02002119 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002120 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002121 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002122 break;
2123
Radek Krejci76512572015-08-04 09:47:08 +02002124 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002125 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002126 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002127 break;
2128
Radek Krejci76512572015-08-04 09:47:08 +02002129 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002130 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002131 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002132 break;
2133
Radek Krejci76512572015-08-04 09:47:08 +02002134 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002135 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002136 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002137 break;
2138
Radek Krejci76512572015-08-04 09:47:08 +02002139 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002140 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002141 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002142 break;
2143
Radek Krejci76512572015-08-04 09:47:08 +02002144 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002145 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002146 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002147 break;
2148
Radek Krejci76512572015-08-04 09:47:08 +02002149 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002150 grp = calloc(1, sizeof *grp);
2151 retval = (struct lys_node *)grp;
2152 break;
2153
Radek Krejci76512572015-08-04 09:47:08 +02002154 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002155 rpc = calloc(1, sizeof *rpc);
2156 retval = (struct lys_node *)rpc;
2157 break;
2158
Radek Krejci76512572015-08-04 09:47:08 +02002159 case LYS_INPUT:
2160 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002161 io = calloc(1, sizeof *io);
2162 retval = (struct lys_node *)io;
2163 break;
2164
Radek Krejci76512572015-08-04 09:47:08 +02002165 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002166 ntf = calloc(1, sizeof *ntf);
2167 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002168 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002169
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002170 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002171 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002172 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002173 }
Radek Krejcib388c152015-06-04 17:03:03 +02002174
Michal Vasko253035f2015-12-17 16:58:13 +01002175 if (!retval) {
2176 LOGMEM;
2177 return NULL;
2178 }
2179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002180 /*
2181 * duplicate generic part of the structure
2182 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002183 retval->name = lydict_insert(ctx, node->name, 0);
2184 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2185 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002186 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002187 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002188 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002189 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002190 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002191 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002192
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002193 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002194 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002195
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002196 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002197
Radek Krejci1d82ef62015-08-07 14:44:40 +02002198 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002199 retval->features = calloc(retval->features_size, sizeof *retval->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002200 if (!retval->features) {
2201 LOGMEM;
2202 goto error;
2203 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002204
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002205 if (!shallow) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002206 for (i = 0; i < node->features_size; ++i) {
2207 retval->features[i] = (struct lys_feature *)retval;
2208 if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
2209 retval->features[i] = node->features[i];
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002210 }
2211 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002212
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002213 /* connect it to the parent */
2214 if (lys_node_addchild(parent, retval->module, retval)) {
2215 goto error;
2216 }
Radek Krejcidce51452015-06-16 15:20:08 +02002217
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002218 /* go recursively */
2219 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2220 LY_TREE_FOR(node->child, child) {
2221 if (!lys_node_dup(module, retval, child, retval->flags, retval->nacm, unres, 0)) {
2222 goto error;
2223 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002224 }
2225 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002226 } else {
2227 memcpy(retval->features, node->features, retval->features_size * sizeof *retval->features);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002228 }
2229
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002230 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002231 * duplicate specific part of the structure
2232 */
2233 switch (node->nodetype) {
2234 case LYS_CONTAINER:
2235 if (cont_orig->when) {
2236 cont->when = lys_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002237 }
2238 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002239
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002240 cont->must_size = cont_orig->must_size;
2241 cont->tpdf_size = cont_orig->tpdf_size;
2242
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002243 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002244 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
2245 break;
2246
2247 case LYS_CHOICE:
2248 if (choice_orig->when) {
2249 choice->when = lys_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002250 }
2251
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002252 if (!shallow) {
2253 if (choice_orig->dflt) {
2254 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0, LYS_ANYXML
2255 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
2256 | LYS_LIST, (const struct lys_node **)&choice->dflt);
2257 if (rc) {
2258 if (rc == EXIT_FAILURE) {
2259 LOGINT;
2260 }
2261 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002262 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002263 } else {
2264 /* useless to check return value, we don't know whether
2265 * there really wasn't any default defined or it just hasn't
2266 * been resolved, we just hope for the best :)
2267 */
2268 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002269 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002270 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002271 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002272 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002273 break;
2274
2275 case LYS_LEAF:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002276 if (lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres)) {
2277 goto error;
2278 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002279 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2280
2281 if (leaf_orig->dflt) {
2282 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002283 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002284 goto error;
2285 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002286 }
2287
2288 leaf->must_size = leaf_orig->must_size;
2289 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002290
2291 if (leaf_orig->when) {
2292 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002293 }
2294 break;
2295
2296 case LYS_LEAFLIST:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002297 if (lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres)) {
2298 goto error;
2299 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002300 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
2301
2302 llist->min = llist_orig->min;
2303 llist->max = llist_orig->max;
2304
2305 llist->must_size = llist_orig->must_size;
2306 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002307
2308 if (llist_orig->when) {
2309 llist->when = lys_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002310 }
2311 break;
2312
2313 case LYS_LIST:
2314 list->min = list_orig->min;
2315 list->max = list_orig->max;
2316
2317 list->must_size = list_orig->must_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002318 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002319
Radek Krejci581ce772015-11-10 17:22:40 +01002320 list->tpdf_size = list_orig->tpdf_size;
Michal Vasko0ea41032015-06-16 08:53:55 +02002321 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02002322
Radek Krejci581ce772015-11-10 17:22:40 +01002323 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02002324 if (list->keys_size) {
2325 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01002326 if (!list->keys) {
2327 LOGMEM;
2328 goto error;
2329 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002330
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002331 if (!shallow) {
2332 /* we managed to resolve it before, resolve it again manually */
2333 if (list_orig->keys[0]) {
2334 for (i = 0; i < list->keys_size; ++i) {
2335 rc = lys_get_sibling(list->child, lys_node_module(retval)->name, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2336 (const struct lys_node **)&list->keys[i]);
2337 if (rc) {
2338 if (rc == EXIT_FAILURE) {
2339 LOGINT;
2340 }
2341 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002342 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002343 }
2344 /* it was not resolved yet, add unres copy */
2345 } else {
2346 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
2347 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002348 goto error;
2349 }
Michal Vasko38d01f72015-06-15 09:41:06 +02002350 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002351 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002352 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02002353 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002354 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002355
Radek Krejci581ce772015-11-10 17:22:40 +01002356 list->unique_size = list_orig->unique_size;
2357 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002358 if (!list->unique) {
2359 LOGMEM;
2360 goto error;
2361 }
Radek Krejci581ce772015-11-10 17:22:40 +01002362 for (i = 0; i < list->unique_size; ++i) {
2363 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2364 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002365 if (!list->unique[i].expr) {
2366 LOGMEM;
2367 goto error;
2368 }
Radek Krejci581ce772015-11-10 17:22:40 +01002369 for (j = 0; j < list->unique[i].expr_size; j++) {
2370 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2371
2372 /* if it stays in unres list, duplicate it also there */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002373 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002374 }
2375 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002376
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002377 if (list_orig->when) {
2378 list->when = lys_when_dup(ctx, list_orig->when);
Radek Krejciefaeba32015-05-27 14:30:57 +02002379 }
Radek Krejcidce51452015-06-16 15:20:08 +02002380 break;
2381
2382 case LYS_ANYXML:
2383 anyxml->must_size = anyxml_orig->must_size;
2384 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002385
2386 if (anyxml_orig->when) {
2387 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002388 }
2389 break;
2390
2391 case LYS_USES:
2392 uses->grp = uses_orig->grp;
2393
2394 if (uses_orig->when) {
2395 uses->when = lys_when_dup(ctx, uses_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002396 }
2397
2398 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002399 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002400 uses->augment_size = uses_orig->augment_size;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002401 if (!shallow) {
2402 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
2403 if (!uses->child) {
2404 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, 0) == -1) {
2405 goto error;
2406 }
Michal Vasko49168a22015-08-17 16:35:41 +02002407 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002408 } else {
2409 memcpy(uses->augment, uses_orig->augment, uses->augment_size * sizeof *uses->augment);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002410 }
2411 break;
2412
Radek Krejcidce51452015-06-16 15:20:08 +02002413 case LYS_CASE:
2414 if (cs_orig->when) {
2415 cs->when = lys_when_dup(ctx, cs_orig->when);
Radek Krejcidce51452015-06-16 15:20:08 +02002416 }
2417 break;
2418
2419 case LYS_GROUPING:
2420 grp->tpdf_size = grp_orig->tpdf_size;
2421 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
2422 break;
2423
2424 case LYS_RPC:
2425 rpc->tpdf_size = rpc_orig->tpdf_size;
2426 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
2427 break;
2428
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002429 case LYS_INPUT:
2430 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02002431 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002432 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
2433 break;
2434
Radek Krejcida04f4a2015-05-21 12:54:09 +02002435 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002436 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002437 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejci7e97c352015-06-19 16:26:34 +02002438 break;
2439
2440 default:
2441 /* LY_NODE_AUGMENT */
2442 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002443 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002444 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002445
2446 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002447
2448error:
2449
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002450 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02002451 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002452}
2453
Michal Vasko13b15832015-08-19 11:04:48 +02002454void
Michal Vaskoff006c12016-02-17 11:15:19 +01002455lys_node_switch(struct lys_node *dst, struct lys_node *src)
2456{
2457 struct lys_node *child;
2458
2459 assert((dst->module == src->module) && (dst->name == src->name) && (dst->nodetype == src->nodetype));
2460
2461 /* sibling next */
2462 if (dst->prev != dst) {
2463 dst->prev->next = src;
2464 }
2465
2466 /* sibling prev */
2467 if (dst->next) {
2468 dst->next->prev = src;
2469 }
2470
2471 /* parent child prev */
2472 if (!dst->next && dst->parent) {
2473 dst->parent->child->prev = src;
2474 }
2475
2476 /* next */
2477 src->next = dst->next;
2478 dst->next = NULL;
2479
2480 /* prev */
2481 if (dst->prev != dst) {
2482 src->prev = dst->prev;
2483 }
2484 dst->prev = dst;
2485
2486 /* parent child */
2487 if (dst->parent && (dst->parent->child == dst)) {
2488 dst->parent->child = src;
2489 }
2490
2491 /* parent */
2492 src->parent = dst->parent;
2493 dst->parent = NULL;
2494
2495 /* child parent */
2496 LY_TREE_FOR(dst->child, child) {
2497 if (child->parent == dst) {
2498 child->parent = src;
2499 }
2500 }
2501
2502 /* child */
2503 src->child = dst->child;
2504 dst->child = NULL;
2505}
2506
2507void
Michal Vasko627975a2016-02-11 11:39:03 +01002508lys_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 +02002509{
2510 struct ly_ctx *ctx;
2511 int i;
2512
2513 if (!module) {
2514 return;
2515 }
2516
2517 /* remove schema from the context */
2518 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01002519 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02002520 for (i = 0; i < ctx->models.used; i++) {
2521 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01002522 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02002523 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01002524 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 +02002525 ctx->models.list[ctx->models.used] = NULL;
2526 /* we are done */
2527 break;
2528 }
2529 }
2530 }
2531
2532 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01002533 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002534
2535 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01002536 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002537
2538 free(module);
2539}
Radek Krejci7e97c352015-06-19 16:26:34 +02002540
2541/*
2542 * op: 1 - enable, 0 - disable
2543 */
2544static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002545lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002546{
2547 int all = 0;
2548 int i, j, k;
2549
2550 if (!module || !name || !strlen(name)) {
2551 return EXIT_FAILURE;
2552 }
2553
2554 if (!strcmp(name, "*")) {
2555 /* enable all */
2556 all = 1;
2557 }
2558
2559 /* module itself */
2560 for (i = 0; i < module->features_size; i++) {
2561 if (all || !strcmp(module->features[i].name, name)) {
2562 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002563 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002564 /* enable referenced features (recursion) */
2565 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002566 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002567 module->features[i].features[k]->name, op);
2568 }
2569 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002570 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002571 }
2572 if (!all) {
2573 return EXIT_SUCCESS;
2574 }
2575 }
2576 }
2577
2578 /* submodules */
2579 for (j = 0; j < module->inc_size; j++) {
2580 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2581 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2582 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002583 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002584 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002585 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002586 }
2587 if (!all) {
2588 return EXIT_SUCCESS;
2589 }
2590 }
2591 }
2592 }
2593
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002594 /* TODO submodules of submodules ... */
2595
Radek Krejci7e97c352015-06-19 16:26:34 +02002596 if (all) {
2597 return EXIT_SUCCESS;
2598 } else {
2599 return EXIT_FAILURE;
2600 }
2601}
2602
2603API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002604lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002605{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002606 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002607}
2608
2609API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002610lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002611{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002612 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002613}
2614
2615API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002616lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002617{
2618 int i, j;
2619
2620 if (!module || !feature) {
2621 return -1;
2622 }
2623
2624 /* search for the specified feature */
2625 /* module itself */
2626 for (i = 0; i < module->features_size; i++) {
2627 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002628 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002629 return 1;
2630 } else {
2631 return 0;
2632 }
2633 }
2634 }
2635
2636 /* submodules */
2637 for (j = 0; j < module->inc_size; j++) {
2638 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2639 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002640 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002641 return 1;
2642 } else {
2643 return 0;
2644 }
2645 }
2646 }
2647 }
2648
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002649 /* feature definition not found */
2650 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002651}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002652
Radek Krejci96a10da2015-07-30 11:00:14 +02002653API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01002654lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002655{
Radek Krejci96a10da2015-07-30 11:00:14 +02002656 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002657 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002658 unsigned int count;
2659
2660 if (!module) {
2661 return NULL;
2662 }
2663
2664 count = module->features_size;
2665 for (i = 0; i < module->inc_size; i++) {
2666 count += module->inc[i].submodule->features_size;
2667 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002668 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01002669 if (!result) {
2670 LOGMEM;
2671 return NULL;
2672 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002673 if (states) {
2674 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01002675 if (!(*states)) {
2676 LOGMEM;
2677 free(result);
2678 return NULL;
2679 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002680 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002681 count = 0;
2682
2683 /* module itself */
2684 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002685 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002686 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002687 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002688 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002689 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002690 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002691 }
2692 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002693 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002694 }
2695
2696 /* submodules */
2697 for (j = 0; j < module->inc_size; j++) {
2698 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002699 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002700 if (states) {
2701 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2702 (*states)[count] = 1;
2703 } else {
2704 (*states)[count] = 0;
2705 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002706 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002707 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002708 }
2709 }
2710
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002711 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002712 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002713
2714 return result;
2715}
Michal Vaskobaefb032015-09-24 14:52:10 +02002716
Radek Krejcic071c542016-01-27 14:57:51 +01002717struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01002718lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01002719{
2720 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
2721}
2722
Michal Vasko320e8532016-02-15 13:11:57 +01002723struct lys_module *
2724lys_module(const struct lys_module *module)
2725{
2726 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
2727}
2728
Michal Vaskobaefb032015-09-24 14:52:10 +02002729API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002730lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02002731{
2732 if (!node || !node->parent) {
2733 return NULL;
2734 }
2735
2736 if (node->parent->nodetype == LYS_AUGMENT) {
2737 return ((struct lys_node_augment *)node->parent)->target;
2738 }
2739
2740 return node->parent;
2741}
Michal Vasko1b229152016-01-13 11:28:38 +01002742
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002743API void *
Michal Vasko1b229152016-01-13 11:28:38 +01002744lys_set_private(const struct lys_node *node, void *priv)
2745{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002746 void *prev;
2747
Michal Vasko1b229152016-01-13 11:28:38 +01002748 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002749 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2750 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01002751 }
2752
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002753 prev = node->private;
Michal Vasko1b229152016-01-13 11:28:38 +01002754 ((struct lys_node *)node)->private = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002755
2756 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01002757}