blob: ee344cab2a4993c3847c942c90e09d3d3b46d6f3 [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
Michal Vasko8de098c2016-02-26 10:00:25 +010011 *
Radek Krejci54f6fb32016-02-24 12:56:39 +010012 * 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);
Radek Krejci23f5de52016-02-25 15:53:17 +01001052
Radek Krejcia77904e2016-02-25 16:23:45 +01001053 if (ret && !ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +01001054 /* store URI */
Radek Krejcia77904e2016-02-25 16:23:45 +01001055 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
Radek Krejci23f5de52016-02-25 15:53:17 +01001056 }
1057
Michal Vasko662610a2015-12-07 11:25:45 +01001058 return ret;
1059}
1060
1061API const struct lys_module *
1062lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +02001063{
Michal Vasko1e62a092015-12-01 12:27:20 +01001064 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +02001065 struct stat sb;
1066 char *addr;
Radek Krejcib051f722016-02-25 15:12:21 +01001067 char buf[PATH_MAX];
1068 int len;
Radek Krejci63a91a92015-07-29 13:31:04 +02001069
1070 if (!ctx || fd < 0) {
1071 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1072 return NULL;
1073 }
1074
Radek Krejci10a833c2015-12-16 15:28:37 +01001075 if (fstat(fd, &sb) == -1) {
1076 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
1077 return NULL;
1078 }
Radek Krejcib051f722016-02-25 15:12:21 +01001079 if (!S_ISREG(sb.st_mode)) {
1080 LOGERR(LY_EINVAL, "Invalid parameter, input file is not a regular file");
1081 return NULL;
1082 }
1083
Radek Krejci3006be02015-12-17 11:24:33 +01001084 addr = mmap(NULL, sb.st_size + 1, PROT_READ, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001085 if (addr == MAP_FAILED) {
Michal Vasko662610a2015-12-07 11:25:45 +01001086 LOGERR(LY_EMEM, "Map file into memory failed (%s()).",__func__);
Pavol Vicane36ea262015-11-12 11:57:47 +01001087 return NULL;
1088 }
Radek Krejci722b0072016-02-01 17:09:45 +01001089 module = lys_parse_mem(ctx, addr, format);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001090 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001091
Radek Krejcia77904e2016-02-25 16:23:45 +01001092 if (module && !module->filepath) {
Radek Krejcib051f722016-02-25 15:12:21 +01001093 /* get URI if there is /proc */
1094 addr = NULL;
1095 asprintf(&addr, "/proc/self/fd/%d", fd);
1096 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
Radek Krejcia77904e2016-02-25 16:23:45 +01001097 ((struct lys_module *)module)->filepath = lydict_insert(ctx, buf, len);
Radek Krejcib051f722016-02-25 15:12:21 +01001098 }
1099 free(addr);
1100 }
1101
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001102 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001103}
1104
Michal Vasko5a721fd2016-02-16 12:16:48 +01001105struct lys_submodule *
1106lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001107{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001108 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001109 struct stat sb;
1110 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001111
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001112 assert(module);
1113 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001114
Radek Krejci10a833c2015-12-16 15:28:37 +01001115 if (fstat(fd, &sb) == -1) {
1116 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
Michal Vasko5a721fd2016-02-16 12:16:48 +01001117 return NULL;
Radek Krejci10a833c2015-12-16 15:28:37 +01001118 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001119 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001120 if (addr == MAP_FAILED) {
1121 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001122 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001123 }
Michal Vasko5a721fd2016-02-16 12:16:48 +01001124 submodule = lys_submodule_parse(module, addr, format, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001125 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +02001126
Michal Vasko5a721fd2016-02-16 12:16:48 +01001127 return submodule;
1128
Radek Krejciefaeba32015-05-27 14:30:57 +02001129}
1130
Radek Krejci1d82ef62015-08-07 14:44:40 +02001131static struct lys_restr *
1132lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001133{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001134 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001135 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001136
Radek Krejci3733a802015-06-19 13:43:21 +02001137 if (!size) {
1138 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001139 }
Radek Krejci3733a802015-06-19 13:43:21 +02001140
1141 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001142 if (!result) {
Radek Krejciaa2a8932016-02-17 15:03:14 +01001143 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +01001144 return NULL;
1145 }
Radek Krejci3733a802015-06-19 13:43:21 +02001146 for (i = 0; i < size; i++) {
1147 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1148 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1149 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1150 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1151 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1152 }
1153
1154 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001155}
1156
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001157void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001158lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001159{
1160 assert(ctx);
1161 if (!restr) {
1162 return;
1163 }
1164
1165 lydict_remove(ctx, restr->expr);
1166 lydict_remove(ctx, restr->dsc);
1167 lydict_remove(ctx, restr->ref);
1168 lydict_remove(ctx, restr->eapptag);
1169 lydict_remove(ctx, restr->emsg);
1170}
1171
Michal Vaskob84f88a2015-09-24 13:16:10 +02001172static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001173lys_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 +02001174 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001175{
1176 int i;
1177
Michal Vasko1dca6882015-10-22 14:29:42 +02001178 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001179 new->base = old->base;
1180 new->der = old->der;
1181
Michal Vasko0bd29d12015-08-19 11:45:49 +02001182 i = unres_schema_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001183 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001184 /* HACK (serious one) for unres */
1185 /* nothing else we can do but duplicate it immediately */
1186 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
Radek Krejcic071c542016-01-27 14:57:51 +01001187 new->parent = (struct lys_tpdf *)parent;
Michal Vaskob84f88a2015-09-24 13:16:10 +02001188 /* all these unres additions can fail even though they did not before */
Michal Vasko88c29542015-11-27 14:57:53 +01001189 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_DER, parent, 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001190 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001191 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001192 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001193 }
1194
Radek Krejci3733a802015-06-19 13:43:21 +02001195 switch (new->base) {
1196 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +02001197 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001198 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001199 }
Radek Krejci3733a802015-06-19 13:43:21 +02001200 break;
1201
1202 case LY_TYPE_BITS:
1203 new->info.bits.count = old->info.bits.count;
1204 if (new->info.bits.count) {
1205 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +01001206 if (!new->info.bits.bit) {
1207 LOGMEM;
1208 return -1;
1209 }
Radek Krejci3733a802015-06-19 13:43:21 +02001210 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001211 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1212 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1213 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Michal Vasko3f053ef2016-02-12 14:27:13 +01001214 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
Radek Krejci3733a802015-06-19 13:43:21 +02001215 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1216 }
1217 }
1218 break;
1219
Radek Krejcif9401c32015-06-26 16:47:36 +02001220 case LY_TYPE_DEC64:
1221 new->info.dec64.dig = old->info.dec64.dig;
1222 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001223 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +02001224 }
1225 break;
1226
Radek Krejci3733a802015-06-19 13:43:21 +02001227 case LY_TYPE_ENUM:
1228 new->info.enums.count = old->info.enums.count;
1229 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001230 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +01001231 if (!new->info.enums.enm) {
1232 LOGMEM;
1233 return -1;
1234 }
Radek Krejci3733a802015-06-19 13:43:21 +02001235 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001236 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1237 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1238 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
Michal Vasko3f053ef2016-02-12 14:27:13 +01001239 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001240 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +02001241 }
1242 }
1243 break;
1244
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001245 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001246 if (old->info.ident.ref) {
1247 new->info.ident.ref = old->info.ident.ref;
1248 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001249 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001250 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 +02001251 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001252 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001253 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001254 break;
1255
Radek Krejciaf351422015-06-19 14:49:38 +02001256 case LY_TYPE_INST:
1257 new->info.inst.req = old->info.inst.req;
1258 break;
1259
Radek Krejcif2860132015-06-20 12:37:20 +02001260 case LY_TYPE_INT8:
1261 case LY_TYPE_INT16:
1262 case LY_TYPE_INT32:
1263 case LY_TYPE_INT64:
1264 case LY_TYPE_UINT8:
1265 case LY_TYPE_UINT16:
1266 case LY_TYPE_UINT32:
1267 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +02001268 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001269 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001270 }
Radek Krejcif2860132015-06-20 12:37:20 +02001271 break;
1272
Radek Krejcidc4c1412015-06-19 15:39:54 +02001273 case LY_TYPE_LEAFREF:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001274 if (old->info.lref.path) {
1275 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
1276 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0)) {
1277 return -1;
1278 }
Michal Vasko49168a22015-08-17 16:35:41 +02001279 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001280 break;
1281
Radek Krejci3733a802015-06-19 13:43:21 +02001282 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +02001283 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001284 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001285 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001286 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 +01001287 new->info.str.pat_count = old->info.str.pat_count;
Radek Krejci3733a802015-06-19 13:43:21 +02001288 break;
1289
Radek Krejcie4c366b2015-07-02 10:11:31 +02001290 case LY_TYPE_UNION:
1291 new->info.uni.count = old->info.uni.count;
1292 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001293 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +01001294 if (!new->info.uni.types) {
1295 LOGMEM;
1296 return -1;
1297 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001298 for (i = 0; i < new->info.uni.count; i++) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001299 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres)) {
1300 return -1;
1301 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001302 }
1303 }
1304 break;
1305
Radek Krejci3733a802015-06-19 13:43:21 +02001306 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001307 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001308 break;
1309 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001310
1311 return EXIT_SUCCESS;
Radek Krejci3733a802015-06-19 13:43:21 +02001312}
1313
1314void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001315lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001316{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001317 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001318
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001319 assert(ctx);
1320 if (!type) {
1321 return;
1322 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001323
Michal Vasko1dca6882015-10-22 14:29:42 +02001324 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001326 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001327 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001328 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001329 free(type->info.binary.length);
1330 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001331 case LY_TYPE_BITS:
1332 for (i = 0; i < type->info.bits.count; i++) {
1333 lydict_remove(ctx, type->info.bits.bit[i].name);
1334 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1335 lydict_remove(ctx, type->info.bits.bit[i].ref);
1336 }
1337 free(type->info.bits.bit);
1338 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001339
1340 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001341 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001342 free(type->info.dec64.range);
1343 break;
1344
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001345 case LY_TYPE_ENUM:
1346 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001347 lydict_remove(ctx, type->info.enums.enm[i].name);
1348 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1349 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001350 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001351 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001352 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001353
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001354 case LY_TYPE_INT8:
1355 case LY_TYPE_INT16:
1356 case LY_TYPE_INT32:
1357 case LY_TYPE_INT64:
1358 case LY_TYPE_UINT8:
1359 case LY_TYPE_UINT16:
1360 case LY_TYPE_UINT32:
1361 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001362 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001363 free(type->info.num.range);
1364 break;
1365
Radek Krejcidc4c1412015-06-19 15:39:54 +02001366 case LY_TYPE_LEAFREF:
1367 lydict_remove(ctx, type->info.lref.path);
1368 break;
1369
Radek Krejci3733a802015-06-19 13:43:21 +02001370 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001371 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001372 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001373 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001374 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001375 }
1376 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001377 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001378
Radek Krejcie4c366b2015-07-02 10:11:31 +02001379 case LY_TYPE_UNION:
1380 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001381 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001382 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001383 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001384 break;
1385
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001386 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001387 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001388 break;
1389 }
Radek Krejci5a065542015-05-22 15:02:07 +02001390}
1391
Radek Krejci1d82ef62015-08-07 14:44:40 +02001392static void
1393lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001394{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001395 assert(ctx);
1396 if (!tpdf) {
1397 return;
1398 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001399
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001400 lydict_remove(ctx, tpdf->name);
1401 lydict_remove(ctx, tpdf->dsc);
1402 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001403
Radek Krejci1d82ef62015-08-07 14:44:40 +02001404 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001405
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001406 lydict_remove(ctx, tpdf->units);
1407 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001408}
1409
Michal Vaskob84f88a2015-09-24 13:16:10 +02001410static struct lys_tpdf *
1411lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1412{
1413 struct lys_tpdf *result;
1414 int i, j;
1415
1416 if (!size) {
1417 return NULL;
1418 }
1419
1420 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001421 if (!result) {
1422 LOGMEM;
1423 return NULL;
1424 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001425 for (i = 0; i < size; i++) {
1426 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1427 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1428 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1429 result[i].flags = old[i].flags;
1430 result[i].module = old[i].module;
1431
1432 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres)) {
1433 for (j = 0; j <= i; ++j) {
1434 lys_tpdf_free(mod->ctx, &result[j]);
1435 }
1436 free(result);
1437 return NULL;
1438 }
1439
1440 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1441 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1442 }
1443
1444 return result;
1445}
1446
Radek Krejci1d82ef62015-08-07 14:44:40 +02001447static struct lys_when *
1448lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001449{
Radek Krejci76512572015-08-04 09:47:08 +02001450 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001451
1452 if (!old) {
1453 return NULL;
1454 }
1455
1456 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001457 if (!new) {
1458 LOGMEM;
1459 return NULL;
1460 }
Radek Krejci00768f42015-06-18 17:04:04 +02001461 new->cond = lydict_insert(ctx, old->cond, 0);
1462 new->dsc = lydict_insert(ctx, old->dsc, 0);
1463 new->ref = lydict_insert(ctx, old->ref, 0);
1464
1465 return new;
1466}
1467
Michal Vasko0308dd62015-10-07 09:14:40 +02001468void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001469lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001470{
1471 if (!w) {
1472 return;
1473 }
1474
1475 lydict_remove(ctx, w->cond);
1476 lydict_remove(ctx, w->dsc);
1477 lydict_remove(ctx, w->ref);
1478
1479 free(w);
1480}
1481
Radek Krejcib7f5e412015-08-13 10:15:51 +02001482static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001483lys_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 +02001484{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001485 struct lys_node *next, *sub;
1486
Radek Krejcic071c542016-01-27 14:57:51 +01001487 /* children from a resolved augment are freed under the target node */
1488 if (!aug.target) {
1489 LY_TREE_FOR_SAFE(aug.child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001490 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001491 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001492 }
1493
Radek Krejcib7f5e412015-08-13 10:15:51 +02001494 lydict_remove(ctx, aug.target_name);
1495 lydict_remove(ctx, aug.dsc);
1496 lydict_remove(ctx, aug.ref);
1497
1498 free(aug.features);
1499
1500 lys_when_free(ctx, aug.when);
1501
Michal Vasko7d356a52015-08-19 15:06:31 +02001502 /* Do not free the children, they were appended somewhere and their
1503 * new parent will take care of them.
1504 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001505}
1506
Radek Krejci76512572015-08-04 09:47:08 +02001507static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001508lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001509{
Radek Krejci76512572015-08-04 09:47:08 +02001510 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001511 struct lys_node *old_child, *new_child;
1512 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001513
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001514 if (!size) {
1515 return NULL;
1516 }
Radek Krejci106efc02015-06-10 14:36:27 +02001517
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001518 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001519 if (!new) {
1520 LOGMEM;
1521 return NULL;
1522 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001523 for (i = 0; i < size; i++) {
1524 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1525 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1526 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1527 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001528 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001529 new[i].nodetype = old[i].nodetype;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001530
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001531 /* this must succeed, it was already resolved once */
Michal Vasko3edeaf72016-02-11 13:17:43 +01001532 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL,
1533 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001534 LOGINT;
1535 free(new);
1536 return NULL;
1537 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001538 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001539
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001540 /* Correct the augment nodes.
1541 * This function can only be called from lys_node_dup() with uses
1542 * being the node duplicated, so we must have a case of grouping
1543 * with a uses with augments. The augmented nodes have already been
1544 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001545 * (it was set to their actual data parent, not an augment), and
1546 * the new augment does not have child pointer to its augment nodes,
1547 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001548 */
1549 LY_TREE_FOR(new[i].target->child, new_child) {
Radek Krejci749190d2016-02-18 16:26:25 +01001550 if (ly_strequal(new_child->name, old[i].child->name, 1)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001551 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001552 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001553 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001554 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001555 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001556 LY_TREE_FOR(old[i].child, old_child) {
1557 /* all augment nodes were connected as siblings, there can be no more after this */
1558 if (old_child->parent != (struct lys_node *)&old[i]) {
1559 break;
1560 }
1561
Radek Krejci749190d2016-02-18 16:26:25 +01001562 assert(ly_strequal(old_child->name, new_child->name, 1));
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001563
1564 new_child->parent = (struct lys_node *)&new[i];
1565 new_child = new_child->next;
1566 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001567 }
Radek Krejci106efc02015-06-10 14:36:27 +02001568
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001569 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001570}
1571
Radek Krejci76512572015-08-04 09:47:08 +02001572static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001573lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001574{
Radek Krejci76512572015-08-04 09:47:08 +02001575 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001576 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001577
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001578 if (!size) {
1579 return NULL;
1580 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001581
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001582 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001583 if (!result) {
1584 LOGMEM;
1585 return NULL;
1586 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001587 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001588 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001589 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1590 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001591 result[i].flags = old[i].flags;
1592 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001593
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001594 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001595 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001596
Radek Krejci76512572015-08-04 09:47:08 +02001597 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001598 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001599 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001600 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001601 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001602 result[i].mod.list = old[i].mod.list;
1603 }
1604 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001605
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001606 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001607}
1608
Radek Krejci1d82ef62015-08-07 14:44:40 +02001609static void
1610lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001611{
Radek Krejcia52656e2015-08-05 13:41:50 +02001612 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001613
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001614 assert(ctx);
1615 if (!ident) {
1616 return;
1617 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001618
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001619 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001620 * if caller free only a single data model which is used (its identity is
1621 * reference from identity in another module), this silly freeing can lead
1622 * to segmentation fault. But without noting if the module is used by some
1623 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001624 *
1625 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001626 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001627 */
1628 while (ident->der) {
1629 der = ident->der;
1630 ident->der = der->next;
1631 free(der);
1632 }
Radek Krejci6793db02015-05-22 17:49:54 +02001633
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001634 lydict_remove(ctx, ident->name);
1635 lydict_remove(ctx, ident->dsc);
1636 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001637
1638}
1639
Radek Krejci1d82ef62015-08-07 14:44:40 +02001640static void
1641lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001642{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001643 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001644
Radek Krejcid12f57b2015-08-06 10:43:39 +02001645 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001646 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001647 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001648 }
1649 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001650}
1651
Radek Krejci1d82ef62015-08-07 14:44:40 +02001652static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001653lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1654{
1655 int i;
1656
1657 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1658 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001659 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001660 }
1661 free(io->tpdf);
1662}
1663
Radek Krejci1d82ef62015-08-07 14:44:40 +02001664static void
1665lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001666{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001667 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001668
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001669 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001670 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001671 }
1672 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001673
Radek Krejci1d82ef62015-08-07 14:44:40 +02001674 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001675}
1676
Radek Krejci1d82ef62015-08-07 14:44:40 +02001677static void
1678lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001679{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001680 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001681
Radek Krejci46c4cd72016-01-21 15:13:52 +01001682 if (leaf->child) {
1683 /* leafref backlinks */
1684 ly_set_free((struct ly_set *)leaf->child);
1685 }
1686
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001687 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001688 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001689 }
1690 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001691
Radek Krejci1d82ef62015-08-07 14:44:40 +02001692 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001693
Radek Krejci1d82ef62015-08-07 14:44:40 +02001694 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001695 lydict_remove(ctx, leaf->units);
1696 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001697}
1698
Radek Krejci1d82ef62015-08-07 14:44:40 +02001699static void
1700lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001701{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001702 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001703
Radek Krejci46c4cd72016-01-21 15:13:52 +01001704 if (llist->child) {
1705 /* leafref backlinks */
1706 ly_set_free((struct ly_set *)llist->child);
1707 }
1708
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001709 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001710 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001711 }
1712 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001713
Radek Krejci1d82ef62015-08-07 14:44:40 +02001714 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001715
Radek Krejci1d82ef62015-08-07 14:44:40 +02001716 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001717 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001718}
1719
Radek Krejci1d82ef62015-08-07 14:44:40 +02001720static void
1721lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001722{
Radek Krejci581ce772015-11-10 17:22:40 +01001723 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001724
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001725 /* handle only specific parts for LY_NODE_LIST */
1726 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001727 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001728 }
1729 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001730
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001731 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001732 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001733 }
1734 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001735
Radek Krejci1d82ef62015-08-07 14:44:40 +02001736 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001737
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001738 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001739 for (j = 0; j > list->unique[i].expr_size; j++) {
1740 lydict_remove(ctx, list->unique[i].expr[j]);
1741 }
1742 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001743 }
1744 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001746 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001747}
1748
Radek Krejci1d82ef62015-08-07 14:44:40 +02001749static void
1750lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001751{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001752 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001753
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001754 /* handle only specific parts for LY_NODE_CONTAINER */
1755 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001756
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001757 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001758 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001759 }
1760 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001761
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001762 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001763 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001764 }
1765 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001766
Radek Krejci1d82ef62015-08-07 14:44:40 +02001767 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001768}
1769
Radek Krejci1d82ef62015-08-07 14:44:40 +02001770static void
1771lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001772{
1773 lydict_remove(ctx, f->name);
1774 lydict_remove(ctx, f->dsc);
1775 lydict_remove(ctx, f->ref);
1776 free(f->features);
1777}
1778
Radek Krejci1d82ef62015-08-07 14:44:40 +02001779static void
Michal Vaskoff006c12016-02-17 11:15:19 +01001780lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001781{
Radek Krejci581ce772015-11-10 17:22:40 +01001782 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01001783 struct ly_ctx *ctx;
1784 struct lys_node *next, *elem;
1785
1786 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02001787
1788 lydict_remove(ctx, dev->target_name);
1789 lydict_remove(ctx, dev->dsc);
1790 lydict_remove(ctx, dev->ref);
1791
Michal Vaskoff006c12016-02-17 11:15:19 +01001792 /* the module was freed, but we only need the context from orig_node, use ours */
1793 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
1794 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
1795 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
1796 elem->module = module;
1797
1798 LY_TREE_DFS_END(dev->orig_node, next, elem);
1799 }
1800 lys_node_free(dev->orig_node, NULL, 0);
1801 } else {
1802 /* it's just a shallow copy, freeing one node */
1803 dev->orig_node->module = module;
1804 lys_node_free(dev->orig_node, NULL, 1);
1805 }
1806
Radek Krejcieb00f512015-07-01 16:44:58 +02001807 for (i = 0; i < dev->deviate_size; i++) {
1808 lydict_remove(ctx, dev->deviate[i].dflt);
1809 lydict_remove(ctx, dev->deviate[i].units);
1810
1811 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1812 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001813 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001814 }
1815 free(dev->deviate[i].must);
1816
1817 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001818 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1819 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1820 }
1821 free(dev->deviate[j].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001822 }
1823 free(dev->deviate[i].unique);
1824 }
1825 }
1826 free(dev->deviate);
1827}
1828
Radek Krejci1d82ef62015-08-07 14:44:40 +02001829static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001830lys_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 +02001831{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001832 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001833
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001834 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001835 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001836 lydict_remove(ctx, uses->refine[i].dsc);
1837 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001838
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001839 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001840 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001841 }
1842 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001843
Radek Krejci76512572015-08-04 09:47:08 +02001844 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001845 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001846 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001847 lydict_remove(ctx, uses->refine[i].mod.presence);
1848 }
1849 }
1850 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001851
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001852 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001853 lys_augment_free(ctx, uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001854 }
1855 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001856
Radek Krejci1d82ef62015-08-07 14:44:40 +02001857 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001858}
1859
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001860void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001861lys_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 +02001862{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001863 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001864 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001865
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001866 if (!node) {
1867 return;
1868 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001869
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001870 assert(node->module);
1871 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001872
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001873 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001874
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001875 /* remove private object */
1876 if (node->private && private_destructor) {
1877 private_destructor(node, node->private);
1878 }
1879
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001880 /* common part */
Radek Krejcid12f57b2015-08-06 10:43:39 +02001881 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1882 free(node->features);
1883 lydict_remove(ctx, node->name);
1884 lydict_remove(ctx, node->dsc);
1885 lydict_remove(ctx, node->ref);
1886 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001887
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001888 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01001889 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001890 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001891 }
1892 }
1893
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001894 /* specific part */
1895 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001896 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001897 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001898 break;
Radek Krejci76512572015-08-04 09:47:08 +02001899 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001900 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001901 break;
Radek Krejci76512572015-08-04 09:47:08 +02001902 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001903 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001904 break;
Radek Krejci76512572015-08-04 09:47:08 +02001905 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001906 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001907 break;
Radek Krejci76512572015-08-04 09:47:08 +02001908 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001909 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001910 break;
Radek Krejci76512572015-08-04 09:47:08 +02001911 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001912 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001913 break;
Radek Krejci76512572015-08-04 09:47:08 +02001914 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001915 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001916 break;
Radek Krejci76512572015-08-04 09:47:08 +02001917 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001918 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001919 break;
Radek Krejci76512572015-08-04 09:47:08 +02001920 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001921 /* do nothing */
1922 break;
Radek Krejci76512572015-08-04 09:47:08 +02001923 case LYS_GROUPING:
1924 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001925 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001926 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001927 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001928
1929 case LYS_INPUT:
1930 case LYS_OUTPUT:
1931 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1932 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001933 case LYS_UNKNOWN:
1934 LOGINT;
1935 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001936 }
Radek Krejci5a065542015-05-22 15:02:07 +02001937
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001938 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001939 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001940 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001941}
1942
Michal Vasko1e62a092015-12-01 12:27:20 +01001943const struct lys_module *
1944lys_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 +02001945{
Radek Krejcic071c542016-01-27 14:57:51 +01001946 const struct lys_module *main_module;
Michal Vasko3edeaf72016-02-11 13:17:43 +01001947 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02001948
Michal Vaskoa7789a82016-02-11 15:42:55 +01001949 assert(!prefix || !name);
1950
Michal Vaskob6729c62015-10-21 12:09:47 +02001951 if (prefix && !pref_len) {
1952 pref_len = strlen(prefix);
1953 }
1954 if (name && !name_len) {
1955 name_len = strlen(name);
1956 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02001957
Michal Vasko4f0dad02016-02-15 14:08:23 +01001958 main_module = lys_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01001959
1960 /* module own prefix, submodule own prefix, (sub)module own name */
1961 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
1962 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01001963 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01001964 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02001965 }
1966
Michal Vasko8ce24d72015-10-21 11:27:26 +02001967 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01001968 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
1969 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02001970 return module->imp[i].module;
1971 }
1972 }
1973
1974 return NULL;
1975}
1976
Michal Vasko13b15832015-08-19 11:04:48 +02001977/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001978static void
Michal Vaskob746fff2016-02-11 11:37:50 +01001979module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02001980{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001981 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01001982 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001983 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001984
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001985 assert(module->ctx);
1986 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001987
Michal Vaskob746fff2016-02-11 11:37:50 +01001988 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01001989 for (i = 0; i < module->imp_size; i++) {
Radek Krejci4f78b532016-02-17 13:43:00 +01001990 if (!module->imp[i].external) {
1991 lydict_remove(ctx, module->imp[i].prefix);
1992 }
Radek Krejci225376f2016-02-16 17:36:22 +01001993 }
Radek Krejcidce51452015-06-16 15:20:08 +02001994 free(module->imp);
1995
Radek Krejcic071c542016-01-27 14:57:51 +01001996 /* submodules don't have data tree, the data nodes
1997 * are placed in the main module altogether */
1998 if (!module->type) {
1999 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002000 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002001 }
Radek Krejci21181962015-06-30 14:11:00 +02002002 }
Radek Krejci5a065542015-05-22 15:02:07 +02002003
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002004 lydict_remove(ctx, module->dsc);
2005 lydict_remove(ctx, module->ref);
2006 lydict_remove(ctx, module->org);
2007 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002008 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002009
Radek Krejcieb00f512015-07-01 16:44:58 +02002010 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002011 for (i = 0; i < module->rev_size; i++) {
2012 lydict_remove(ctx, module->rev[i].dsc);
2013 lydict_remove(ctx, module->rev[i].ref);
2014 }
2015 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002016
Radek Krejcieb00f512015-07-01 16:44:58 +02002017 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002018 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002019 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002020 }
2021 module->ident_size = 0;
2022 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002023
Radek Krejcieb00f512015-07-01 16:44:58 +02002024 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002025 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002026 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002027 }
2028 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002029
Radek Krejcieb00f512015-07-01 16:44:58 +02002030 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002031 for (i = 0; i < module->inc_size; i++) {
Radek Krejcic071c542016-01-27 14:57:51 +01002032 /* complete submodule free is done only from main module since
2033 * submodules propagate their includes to the main module */
2034 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002035 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002036 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002037 }
2038 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002039
Radek Krejcieb00f512015-07-01 16:44:58 +02002040 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002041 for (i = 0; i < module->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002042 lys_augment_free(ctx, module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002043 }
2044 free(module->augment);
2045
Radek Krejcieb00f512015-07-01 16:44:58 +02002046 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002047 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002048 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002049 }
2050 free(module->features);
2051
Radek Krejcieb00f512015-07-01 16:44:58 +02002052 /* deviations */
2053 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002054 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002055 }
2056 free(module->deviation);
2057
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002058 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002059 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002060}
2061
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002062void
Michal Vaskob746fff2016-02-11 11:37:50 +01002063lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002064{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002065 if (!submodule) {
2066 return;
2067 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002068
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002069 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002070 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002071
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002072 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002073
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002074 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002075}
2076
Radek Krejci76512572015-08-04 09:47:08 +02002077struct lys_node *
Radek Krejcic071c542016-01-27 14:57:51 +01002078lys_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 +01002079 uint8_t nacm, struct unres_schema *unres, int shallow)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002080{
Radek Krejcic071c542016-01-27 14:57:51 +01002081 struct lys_node *retval = NULL, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002082 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002083 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002084
Michal Vaskoc07187d2015-08-13 15:20:57 +02002085 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002086 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002087 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002088 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002089 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002090 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002091 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002092 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002093 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002094 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002095 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002096 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002097 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002098 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002099 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002100 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002101 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002102 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002103 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002104 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002105 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002106 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002107 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002108 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002109
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002110 /* we cannot just duplicate memory since the strings are stored in
2111 * dictionary and we need to update dictionary counters.
2112 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002113
Radek Krejci1d82ef62015-08-07 14:44:40 +02002114 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002115 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002116 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002117 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002118 break;
2119
Radek Krejci76512572015-08-04 09:47:08 +02002120 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002121 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002122 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002123 break;
2124
Radek Krejci76512572015-08-04 09:47:08 +02002125 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002126 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002127 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002128 break;
2129
Radek Krejci76512572015-08-04 09:47:08 +02002130 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002131 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002132 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002133 break;
2134
Radek Krejci76512572015-08-04 09:47:08 +02002135 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002136 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002137 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002138 break;
2139
Radek Krejci76512572015-08-04 09:47:08 +02002140 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002141 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002142 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002143 break;
2144
Radek Krejci76512572015-08-04 09:47:08 +02002145 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002146 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002147 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002148 break;
2149
Radek Krejci76512572015-08-04 09:47:08 +02002150 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002151 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002152 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002153 break;
2154
Radek Krejci76512572015-08-04 09:47:08 +02002155 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002156 grp = calloc(1, sizeof *grp);
2157 retval = (struct lys_node *)grp;
2158 break;
2159
Radek Krejci76512572015-08-04 09:47:08 +02002160 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002161 rpc = calloc(1, sizeof *rpc);
2162 retval = (struct lys_node *)rpc;
2163 break;
2164
Radek Krejci76512572015-08-04 09:47:08 +02002165 case LYS_INPUT:
2166 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002167 io = calloc(1, sizeof *io);
2168 retval = (struct lys_node *)io;
2169 break;
2170
Radek Krejci76512572015-08-04 09:47:08 +02002171 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002172 ntf = calloc(1, sizeof *ntf);
2173 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002174 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002175
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002176 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002177 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002178 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002179 }
Radek Krejcib388c152015-06-04 17:03:03 +02002180
Michal Vasko253035f2015-12-17 16:58:13 +01002181 if (!retval) {
2182 LOGMEM;
2183 return NULL;
2184 }
2185
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002186 /*
2187 * duplicate generic part of the structure
2188 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002189 retval->name = lydict_insert(ctx, node->name, 0);
2190 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2191 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002192 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002193 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002194 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002195 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002196 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002197 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002198
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002199 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002200 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002201
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002202 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002203
Radek Krejci1d82ef62015-08-07 14:44:40 +02002204 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002205 retval->features = calloc(retval->features_size, sizeof *retval->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002206 if (!retval->features) {
2207 LOGMEM;
2208 goto error;
2209 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002210
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002211 if (!shallow) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002212 for (i = 0; i < node->features_size; ++i) {
2213 retval->features[i] = (struct lys_feature *)retval;
2214 if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
2215 retval->features[i] = node->features[i];
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002216 }
2217 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002218
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002219 /* connect it to the parent */
2220 if (lys_node_addchild(parent, retval->module, retval)) {
2221 goto error;
2222 }
Radek Krejcidce51452015-06-16 15:20:08 +02002223
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002224 /* go recursively */
2225 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2226 LY_TREE_FOR(node->child, child) {
2227 if (!lys_node_dup(module, retval, child, retval->flags, retval->nacm, unres, 0)) {
2228 goto error;
2229 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002230 }
2231 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002232 } else {
2233 memcpy(retval->features, node->features, retval->features_size * sizeof *retval->features);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002234 }
2235
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002236 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002237 * duplicate specific part of the structure
2238 */
2239 switch (node->nodetype) {
2240 case LYS_CONTAINER:
2241 if (cont_orig->when) {
2242 cont->when = lys_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002243 }
2244 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002245
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002246 cont->must_size = cont_orig->must_size;
2247 cont->tpdf_size = cont_orig->tpdf_size;
2248
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002249 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002250 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
2251 break;
2252
2253 case LYS_CHOICE:
2254 if (choice_orig->when) {
2255 choice->when = lys_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002256 }
2257
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002258 if (!shallow) {
2259 if (choice_orig->dflt) {
2260 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0, LYS_ANYXML
2261 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
2262 | LYS_LIST, (const struct lys_node **)&choice->dflt);
2263 if (rc) {
2264 if (rc == EXIT_FAILURE) {
2265 LOGINT;
2266 }
2267 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002268 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002269 } else {
2270 /* useless to check return value, we don't know whether
2271 * there really wasn't any default defined or it just hasn't
2272 * been resolved, we just hope for the best :)
2273 */
2274 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002275 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002276 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002277 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002278 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002279 break;
2280
2281 case LYS_LEAF:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002282 if (lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres)) {
2283 goto error;
2284 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002285 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2286
2287 if (leaf_orig->dflt) {
2288 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002289 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002290 goto error;
2291 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002292 }
2293
2294 leaf->must_size = leaf_orig->must_size;
2295 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002296
2297 if (leaf_orig->when) {
2298 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002299 }
2300 break;
2301
2302 case LYS_LEAFLIST:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002303 if (lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres)) {
2304 goto error;
2305 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002306 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
2307
2308 llist->min = llist_orig->min;
2309 llist->max = llist_orig->max;
2310
2311 llist->must_size = llist_orig->must_size;
2312 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002313
2314 if (llist_orig->when) {
2315 llist->when = lys_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002316 }
2317 break;
2318
2319 case LYS_LIST:
2320 list->min = list_orig->min;
2321 list->max = list_orig->max;
2322
2323 list->must_size = list_orig->must_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002324 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002325
Radek Krejci581ce772015-11-10 17:22:40 +01002326 list->tpdf_size = list_orig->tpdf_size;
Michal Vasko0ea41032015-06-16 08:53:55 +02002327 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02002328
Radek Krejci581ce772015-11-10 17:22:40 +01002329 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02002330 if (list->keys_size) {
2331 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01002332 if (!list->keys) {
2333 LOGMEM;
2334 goto error;
2335 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002336
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002337 if (!shallow) {
2338 /* we managed to resolve it before, resolve it again manually */
2339 if (list_orig->keys[0]) {
2340 for (i = 0; i < list->keys_size; ++i) {
2341 rc = lys_get_sibling(list->child, lys_node_module(retval)->name, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2342 (const struct lys_node **)&list->keys[i]);
2343 if (rc) {
2344 if (rc == EXIT_FAILURE) {
2345 LOGINT;
2346 }
2347 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002348 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002349 }
2350 /* it was not resolved yet, add unres copy */
2351 } else {
2352 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
2353 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002354 goto error;
2355 }
Michal Vasko38d01f72015-06-15 09:41:06 +02002356 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002357 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002358 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02002359 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002360 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002361
Radek Krejci581ce772015-11-10 17:22:40 +01002362 list->unique_size = list_orig->unique_size;
2363 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002364 if (!list->unique) {
2365 LOGMEM;
2366 goto error;
2367 }
Radek Krejci581ce772015-11-10 17:22:40 +01002368 for (i = 0; i < list->unique_size; ++i) {
2369 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2370 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002371 if (!list->unique[i].expr) {
2372 LOGMEM;
2373 goto error;
2374 }
Radek Krejci581ce772015-11-10 17:22:40 +01002375 for (j = 0; j < list->unique[i].expr_size; j++) {
2376 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2377
2378 /* if it stays in unres list, duplicate it also there */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002379 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002380 }
2381 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002382
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002383 if (list_orig->when) {
2384 list->when = lys_when_dup(ctx, list_orig->when);
Radek Krejciefaeba32015-05-27 14:30:57 +02002385 }
Radek Krejcidce51452015-06-16 15:20:08 +02002386 break;
2387
2388 case LYS_ANYXML:
2389 anyxml->must_size = anyxml_orig->must_size;
2390 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002391
2392 if (anyxml_orig->when) {
2393 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002394 }
2395 break;
2396
2397 case LYS_USES:
2398 uses->grp = uses_orig->grp;
2399
2400 if (uses_orig->when) {
2401 uses->when = lys_when_dup(ctx, uses_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002402 }
2403
2404 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002405 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002406 uses->augment_size = uses_orig->augment_size;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002407 if (!shallow) {
2408 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
2409 if (!uses->child) {
2410 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, 0) == -1) {
2411 goto error;
2412 }
Michal Vasko49168a22015-08-17 16:35:41 +02002413 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002414 } else {
2415 memcpy(uses->augment, uses_orig->augment, uses->augment_size * sizeof *uses->augment);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002416 }
2417 break;
2418
Radek Krejcidce51452015-06-16 15:20:08 +02002419 case LYS_CASE:
2420 if (cs_orig->when) {
2421 cs->when = lys_when_dup(ctx, cs_orig->when);
Radek Krejcidce51452015-06-16 15:20:08 +02002422 }
2423 break;
2424
2425 case LYS_GROUPING:
2426 grp->tpdf_size = grp_orig->tpdf_size;
2427 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
2428 break;
2429
2430 case LYS_RPC:
2431 rpc->tpdf_size = rpc_orig->tpdf_size;
2432 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
2433 break;
2434
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002435 case LYS_INPUT:
2436 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02002437 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002438 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
2439 break;
2440
Radek Krejcida04f4a2015-05-21 12:54:09 +02002441 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002442 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002443 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejci7e97c352015-06-19 16:26:34 +02002444 break;
2445
2446 default:
2447 /* LY_NODE_AUGMENT */
2448 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002449 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002450 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002451
2452 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002453
2454error:
2455
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002456 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02002457 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002458}
2459
Michal Vasko13b15832015-08-19 11:04:48 +02002460void
Michal Vaskoff006c12016-02-17 11:15:19 +01002461lys_node_switch(struct lys_node *dst, struct lys_node *src)
2462{
2463 struct lys_node *child;
2464
2465 assert((dst->module == src->module) && (dst->name == src->name) && (dst->nodetype == src->nodetype));
2466
2467 /* sibling next */
2468 if (dst->prev != dst) {
2469 dst->prev->next = src;
2470 }
2471
2472 /* sibling prev */
2473 if (dst->next) {
2474 dst->next->prev = src;
2475 }
2476
2477 /* parent child prev */
2478 if (!dst->next && dst->parent) {
2479 dst->parent->child->prev = src;
2480 }
2481
2482 /* next */
2483 src->next = dst->next;
2484 dst->next = NULL;
2485
2486 /* prev */
2487 if (dst->prev != dst) {
2488 src->prev = dst->prev;
2489 }
2490 dst->prev = dst;
2491
2492 /* parent child */
2493 if (dst->parent && (dst->parent->child == dst)) {
2494 dst->parent->child = src;
2495 }
2496
2497 /* parent */
2498 src->parent = dst->parent;
2499 dst->parent = NULL;
2500
2501 /* child parent */
2502 LY_TREE_FOR(dst->child, child) {
2503 if (child->parent == dst) {
2504 child->parent = src;
2505 }
2506 }
2507
2508 /* child */
2509 src->child = dst->child;
2510 dst->child = NULL;
2511}
2512
2513void
Michal Vasko627975a2016-02-11 11:39:03 +01002514lys_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 +02002515{
2516 struct ly_ctx *ctx;
2517 int i;
2518
2519 if (!module) {
2520 return;
2521 }
2522
2523 /* remove schema from the context */
2524 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01002525 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02002526 for (i = 0; i < ctx->models.used; i++) {
2527 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01002528 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02002529 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01002530 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 +02002531 ctx->models.list[ctx->models.used] = NULL;
2532 /* we are done */
2533 break;
2534 }
2535 }
2536 }
2537
2538 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01002539 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002540
2541 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01002542 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002543
2544 free(module);
2545}
Radek Krejci7e97c352015-06-19 16:26:34 +02002546
2547/*
2548 * op: 1 - enable, 0 - disable
2549 */
2550static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002551lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002552{
2553 int all = 0;
2554 int i, j, k;
2555
2556 if (!module || !name || !strlen(name)) {
2557 return EXIT_FAILURE;
2558 }
2559
2560 if (!strcmp(name, "*")) {
2561 /* enable all */
2562 all = 1;
2563 }
2564
2565 /* module itself */
2566 for (i = 0; i < module->features_size; i++) {
2567 if (all || !strcmp(module->features[i].name, name)) {
2568 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002569 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002570 /* enable referenced features (recursion) */
2571 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002572 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002573 module->features[i].features[k]->name, op);
2574 }
2575 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002576 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002577 }
2578 if (!all) {
2579 return EXIT_SUCCESS;
2580 }
2581 }
2582 }
2583
2584 /* submodules */
2585 for (j = 0; j < module->inc_size; j++) {
2586 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2587 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2588 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002589 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002590 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002591 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002592 }
2593 if (!all) {
2594 return EXIT_SUCCESS;
2595 }
2596 }
2597 }
2598 }
2599
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002600 /* TODO submodules of submodules ... */
2601
Radek Krejci7e97c352015-06-19 16:26:34 +02002602 if (all) {
2603 return EXIT_SUCCESS;
2604 } else {
2605 return EXIT_FAILURE;
2606 }
2607}
2608
2609API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002610lys_features_enable(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, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002613}
2614
2615API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002616lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002617{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002618 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002619}
2620
2621API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002622lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002623{
2624 int i, j;
2625
2626 if (!module || !feature) {
2627 return -1;
2628 }
2629
2630 /* search for the specified feature */
2631 /* module itself */
2632 for (i = 0; i < module->features_size; i++) {
2633 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002634 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002635 return 1;
2636 } else {
2637 return 0;
2638 }
2639 }
2640 }
2641
2642 /* submodules */
2643 for (j = 0; j < module->inc_size; j++) {
2644 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2645 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002646 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002647 return 1;
2648 } else {
2649 return 0;
2650 }
2651 }
2652 }
2653 }
2654
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002655 /* feature definition not found */
2656 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002657}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002658
Radek Krejci96a10da2015-07-30 11:00:14 +02002659API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01002660lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002661{
Radek Krejci96a10da2015-07-30 11:00:14 +02002662 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002663 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002664 unsigned int count;
2665
2666 if (!module) {
2667 return NULL;
2668 }
2669
2670 count = module->features_size;
2671 for (i = 0; i < module->inc_size; i++) {
2672 count += module->inc[i].submodule->features_size;
2673 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002674 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01002675 if (!result) {
2676 LOGMEM;
2677 return NULL;
2678 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002679 if (states) {
2680 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01002681 if (!(*states)) {
2682 LOGMEM;
2683 free(result);
2684 return NULL;
2685 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002686 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002687 count = 0;
2688
2689 /* module itself */
2690 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002691 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002692 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002693 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002694 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002695 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002696 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002697 }
2698 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002699 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002700 }
2701
2702 /* submodules */
2703 for (j = 0; j < module->inc_size; j++) {
2704 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002705 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002706 if (states) {
2707 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2708 (*states)[count] = 1;
2709 } else {
2710 (*states)[count] = 0;
2711 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002712 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002713 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002714 }
2715 }
2716
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002717 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002718 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002719
2720 return result;
2721}
Michal Vaskobaefb032015-09-24 14:52:10 +02002722
Radek Krejcic071c542016-01-27 14:57:51 +01002723struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01002724lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01002725{
2726 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
2727}
2728
Michal Vasko320e8532016-02-15 13:11:57 +01002729struct lys_module *
2730lys_module(const struct lys_module *module)
2731{
2732 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
2733}
2734
Michal Vaskobaefb032015-09-24 14:52:10 +02002735API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002736lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02002737{
2738 if (!node || !node->parent) {
2739 return NULL;
2740 }
2741
2742 if (node->parent->nodetype == LYS_AUGMENT) {
2743 return ((struct lys_node_augment *)node->parent)->target;
2744 }
2745
2746 return node->parent;
2747}
Michal Vasko1b229152016-01-13 11:28:38 +01002748
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002749API void *
Michal Vasko1b229152016-01-13 11:28:38 +01002750lys_set_private(const struct lys_node *node, void *priv)
2751{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002752 void *prev;
2753
Michal Vasko1b229152016-01-13 11:28:38 +01002754 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002755 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2756 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01002757 }
2758
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002759 prev = node->private;
Michal Vasko1b229152016-01-13 11:28:38 +01002760 ((struct lys_node *)node)->private = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002761
2762 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01002763}