blob: f68d16bb4312fefa9dbfd5fa09a4cfba4d3f900b [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 Krejciff4874d2016-03-07 12:30:50 +0100998 mod = yin_read_module(ctx, data, NULL, 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;
Radek Krejci15412ca2016-03-03 11:16:52 +01001095 if (asprintf(&addr, "/proc/self/fd/%d", fd) != -1) {
1096 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
1097 ((struct lys_module *)module)->filepath = lydict_insert(ctx, buf, len);
1098 }
1099 free(addr);
Radek Krejcib051f722016-02-25 15:12:21 +01001100 }
Radek Krejcib051f722016-02-25 15:12:21 +01001101 }
1102
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001103 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001104}
1105
Michal Vasko5a721fd2016-02-16 12:16:48 +01001106struct lys_submodule *
1107lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02001108{
Michal Vasko5a721fd2016-02-16 12:16:48 +01001109 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001110 struct stat sb;
1111 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001112
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001113 assert(module);
1114 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001115
Radek Krejci10a833c2015-12-16 15:28:37 +01001116 if (fstat(fd, &sb) == -1) {
1117 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
Michal Vasko5a721fd2016-02-16 12:16:48 +01001118 return NULL;
Radek Krejci10a833c2015-12-16 15:28:37 +01001119 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001120 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +01001121 if (addr == MAP_FAILED) {
1122 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +01001123 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +01001124 }
Michal Vasko5a721fd2016-02-16 12:16:48 +01001125 submodule = lys_submodule_parse(module, addr, format, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001126 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +02001127
Michal Vasko5a721fd2016-02-16 12:16:48 +01001128 return submodule;
1129
Radek Krejciefaeba32015-05-27 14:30:57 +02001130}
1131
Radek Krejci1d82ef62015-08-07 14:44:40 +02001132static struct lys_restr *
1133lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001134{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001135 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001136 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001137
Radek Krejci3733a802015-06-19 13:43:21 +02001138 if (!size) {
1139 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001140 }
Radek Krejci3733a802015-06-19 13:43:21 +02001141
1142 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001143 if (!result) {
Radek Krejciaa2a8932016-02-17 15:03:14 +01001144 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +01001145 return NULL;
1146 }
Radek Krejci3733a802015-06-19 13:43:21 +02001147 for (i = 0; i < size; i++) {
1148 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1149 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1150 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1151 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1152 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1153 }
1154
1155 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001156}
1157
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001158void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001159lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001160{
1161 assert(ctx);
1162 if (!restr) {
1163 return;
1164 }
1165
1166 lydict_remove(ctx, restr->expr);
1167 lydict_remove(ctx, restr->dsc);
1168 lydict_remove(ctx, restr->ref);
1169 lydict_remove(ctx, restr->eapptag);
1170 lydict_remove(ctx, restr->emsg);
1171}
1172
Michal Vaskob84f88a2015-09-24 13:16:10 +02001173static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001174lys_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 +02001175 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001176{
1177 int i;
1178
Michal Vasko1dca6882015-10-22 14:29:42 +02001179 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001180 new->base = old->base;
1181 new->der = old->der;
1182
Michal Vasko0bd29d12015-08-19 11:45:49 +02001183 i = unres_schema_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001184 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001185 /* HACK (serious one) for unres */
1186 /* nothing else we can do but duplicate it immediately */
1187 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
Radek Krejcic071c542016-01-27 14:57:51 +01001188 new->parent = (struct lys_tpdf *)parent;
Michal Vaskob84f88a2015-09-24 13:16:10 +02001189 /* all these unres additions can fail even though they did not before */
Michal Vasko88c29542015-11-27 14:57:53 +01001190 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_DER, parent, 0)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001191 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001192 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001193 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001194 }
1195
Radek Krejci3733a802015-06-19 13:43:21 +02001196 switch (new->base) {
1197 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +02001198 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001199 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001200 }
Radek Krejci3733a802015-06-19 13:43:21 +02001201 break;
1202
1203 case LY_TYPE_BITS:
1204 new->info.bits.count = old->info.bits.count;
1205 if (new->info.bits.count) {
1206 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +01001207 if (!new->info.bits.bit) {
1208 LOGMEM;
1209 return -1;
1210 }
Radek Krejci3733a802015-06-19 13:43:21 +02001211 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001212 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1213 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1214 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Michal Vasko3f053ef2016-02-12 14:27:13 +01001215 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
Radek Krejci3733a802015-06-19 13:43:21 +02001216 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1217 }
1218 }
1219 break;
1220
Radek Krejcif9401c32015-06-26 16:47:36 +02001221 case LY_TYPE_DEC64:
1222 new->info.dec64.dig = old->info.dec64.dig;
1223 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001224 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +02001225 }
1226 break;
1227
Radek Krejci3733a802015-06-19 13:43:21 +02001228 case LY_TYPE_ENUM:
1229 new->info.enums.count = old->info.enums.count;
1230 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001231 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +01001232 if (!new->info.enums.enm) {
1233 LOGMEM;
1234 return -1;
1235 }
Radek Krejci3733a802015-06-19 13:43:21 +02001236 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001237 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1238 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1239 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
Michal Vasko3f053ef2016-02-12 14:27:13 +01001240 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001241 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +02001242 }
1243 }
1244 break;
1245
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001246 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001247 if (old->info.ident.ref) {
1248 new->info.ident.ref = old->info.ident.ref;
1249 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001250 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001251 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 +02001252 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001253 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001254 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001255 break;
1256
Radek Krejciaf351422015-06-19 14:49:38 +02001257 case LY_TYPE_INST:
1258 new->info.inst.req = old->info.inst.req;
1259 break;
1260
Radek Krejcif2860132015-06-20 12:37:20 +02001261 case LY_TYPE_INT8:
1262 case LY_TYPE_INT16:
1263 case LY_TYPE_INT32:
1264 case LY_TYPE_INT64:
1265 case LY_TYPE_UINT8:
1266 case LY_TYPE_UINT16:
1267 case LY_TYPE_UINT32:
1268 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +02001269 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001270 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001271 }
Radek Krejcif2860132015-06-20 12:37:20 +02001272 break;
1273
Radek Krejcidc4c1412015-06-19 15:39:54 +02001274 case LY_TYPE_LEAFREF:
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001275 if (old->info.lref.path) {
1276 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
1277 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0)) {
1278 return -1;
1279 }
Michal Vasko49168a22015-08-17 16:35:41 +02001280 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001281 break;
1282
Radek Krejci3733a802015-06-19 13:43:21 +02001283 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +02001284 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001285 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001286 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001287 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 +01001288 new->info.str.pat_count = old->info.str.pat_count;
Radek Krejci3733a802015-06-19 13:43:21 +02001289 break;
1290
Radek Krejcie4c366b2015-07-02 10:11:31 +02001291 case LY_TYPE_UNION:
1292 new->info.uni.count = old->info.uni.count;
1293 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001294 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +01001295 if (!new->info.uni.types) {
1296 LOGMEM;
1297 return -1;
1298 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001299 for (i = 0; i < new->info.uni.count; i++) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001300 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres)) {
1301 return -1;
1302 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001303 }
1304 }
1305 break;
1306
Radek Krejci3733a802015-06-19 13:43:21 +02001307 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001308 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001309 break;
1310 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001311
1312 return EXIT_SUCCESS;
Radek Krejci3733a802015-06-19 13:43:21 +02001313}
1314
1315void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001316lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001317{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001318 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001319
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001320 assert(ctx);
1321 if (!type) {
1322 return;
1323 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001324
Michal Vasko1dca6882015-10-22 14:29:42 +02001325 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001326
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001327 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001328 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001329 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001330 free(type->info.binary.length);
1331 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001332 case LY_TYPE_BITS:
1333 for (i = 0; i < type->info.bits.count; i++) {
1334 lydict_remove(ctx, type->info.bits.bit[i].name);
1335 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1336 lydict_remove(ctx, type->info.bits.bit[i].ref);
1337 }
1338 free(type->info.bits.bit);
1339 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001340
1341 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001342 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001343 free(type->info.dec64.range);
1344 break;
1345
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001346 case LY_TYPE_ENUM:
1347 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001348 lydict_remove(ctx, type->info.enums.enm[i].name);
1349 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1350 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001351 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001352 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001353 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001354
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001355 case LY_TYPE_INT8:
1356 case LY_TYPE_INT16:
1357 case LY_TYPE_INT32:
1358 case LY_TYPE_INT64:
1359 case LY_TYPE_UINT8:
1360 case LY_TYPE_UINT16:
1361 case LY_TYPE_UINT32:
1362 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001363 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001364 free(type->info.num.range);
1365 break;
1366
Radek Krejcidc4c1412015-06-19 15:39:54 +02001367 case LY_TYPE_LEAFREF:
1368 lydict_remove(ctx, type->info.lref.path);
1369 break;
1370
Radek Krejci3733a802015-06-19 13:43:21 +02001371 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001372 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001373 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001374 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001375 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001376 }
1377 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001378 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001379
Radek Krejcie4c366b2015-07-02 10:11:31 +02001380 case LY_TYPE_UNION:
1381 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001382 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001383 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001384 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001385 break;
1386
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001387 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001388 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001389 break;
1390 }
Radek Krejci5a065542015-05-22 15:02:07 +02001391}
1392
Radek Krejci1d82ef62015-08-07 14:44:40 +02001393static void
1394lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001395{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001396 assert(ctx);
1397 if (!tpdf) {
1398 return;
1399 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001401 lydict_remove(ctx, tpdf->name);
1402 lydict_remove(ctx, tpdf->dsc);
1403 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001404
Radek Krejci1d82ef62015-08-07 14:44:40 +02001405 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001406
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001407 lydict_remove(ctx, tpdf->units);
1408 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001409}
1410
Michal Vaskob84f88a2015-09-24 13:16:10 +02001411static struct lys_tpdf *
1412lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1413{
1414 struct lys_tpdf *result;
1415 int i, j;
1416
1417 if (!size) {
1418 return NULL;
1419 }
1420
1421 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001422 if (!result) {
1423 LOGMEM;
1424 return NULL;
1425 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001426 for (i = 0; i < size; i++) {
1427 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1428 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1429 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1430 result[i].flags = old[i].flags;
1431 result[i].module = old[i].module;
1432
1433 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres)) {
1434 for (j = 0; j <= i; ++j) {
1435 lys_tpdf_free(mod->ctx, &result[j]);
1436 }
1437 free(result);
1438 return NULL;
1439 }
1440
1441 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1442 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1443 }
1444
1445 return result;
1446}
1447
Radek Krejci1d82ef62015-08-07 14:44:40 +02001448static struct lys_when *
1449lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001450{
Radek Krejci76512572015-08-04 09:47:08 +02001451 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001452
1453 if (!old) {
1454 return NULL;
1455 }
1456
1457 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001458 if (!new) {
1459 LOGMEM;
1460 return NULL;
1461 }
Radek Krejci00768f42015-06-18 17:04:04 +02001462 new->cond = lydict_insert(ctx, old->cond, 0);
1463 new->dsc = lydict_insert(ctx, old->dsc, 0);
1464 new->ref = lydict_insert(ctx, old->ref, 0);
1465
1466 return new;
1467}
1468
Michal Vasko0308dd62015-10-07 09:14:40 +02001469void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001470lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001471{
1472 if (!w) {
1473 return;
1474 }
1475
1476 lydict_remove(ctx, w->cond);
1477 lydict_remove(ctx, w->dsc);
1478 lydict_remove(ctx, w->ref);
1479
1480 free(w);
1481}
1482
Radek Krejcib7f5e412015-08-13 10:15:51 +02001483static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001484lys_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 +02001485{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001486 struct lys_node *next, *sub;
1487
Radek Krejcic071c542016-01-27 14:57:51 +01001488 /* children from a resolved augment are freed under the target node */
1489 if (!aug.target) {
1490 LY_TREE_FOR_SAFE(aug.child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001491 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001492 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001493 }
1494
Radek Krejcib7f5e412015-08-13 10:15:51 +02001495 lydict_remove(ctx, aug.target_name);
1496 lydict_remove(ctx, aug.dsc);
1497 lydict_remove(ctx, aug.ref);
1498
1499 free(aug.features);
1500
1501 lys_when_free(ctx, aug.when);
1502
Michal Vasko7d356a52015-08-19 15:06:31 +02001503 /* Do not free the children, they were appended somewhere and their
1504 * new parent will take care of them.
1505 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001506}
1507
Radek Krejci76512572015-08-04 09:47:08 +02001508static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001509lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001510{
Radek Krejci76512572015-08-04 09:47:08 +02001511 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001512 struct lys_node *old_child, *new_child;
1513 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001514
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001515 if (!size) {
1516 return NULL;
1517 }
Radek Krejci106efc02015-06-10 14:36:27 +02001518
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001519 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001520 if (!new) {
1521 LOGMEM;
1522 return NULL;
1523 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001524 for (i = 0; i < size; i++) {
1525 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1526 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1527 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1528 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001529 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001530 new[i].nodetype = old[i].nodetype;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001531
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001532 /* this must succeed, it was already resolved once */
Michal Vasko3edeaf72016-02-11 13:17:43 +01001533 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL,
1534 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001535 LOGINT;
1536 free(new);
1537 return NULL;
1538 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001539 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001540
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001541 /* Correct the augment nodes.
1542 * This function can only be called from lys_node_dup() with uses
1543 * being the node duplicated, so we must have a case of grouping
1544 * with a uses with augments. The augmented nodes have already been
1545 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001546 * (it was set to their actual data parent, not an augment), and
1547 * the new augment does not have child pointer to its augment nodes,
1548 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001549 */
1550 LY_TREE_FOR(new[i].target->child, new_child) {
Radek Krejci749190d2016-02-18 16:26:25 +01001551 if (ly_strequal(new_child->name, old[i].child->name, 1)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001552 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001553 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001554 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001555 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001556 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001557 LY_TREE_FOR(old[i].child, old_child) {
1558 /* all augment nodes were connected as siblings, there can be no more after this */
1559 if (old_child->parent != (struct lys_node *)&old[i]) {
1560 break;
1561 }
1562
Radek Krejci749190d2016-02-18 16:26:25 +01001563 assert(ly_strequal(old_child->name, new_child->name, 1));
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001564
1565 new_child->parent = (struct lys_node *)&new[i];
1566 new_child = new_child->next;
1567 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001568 }
Radek Krejci106efc02015-06-10 14:36:27 +02001569
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001570 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001571}
1572
Radek Krejci76512572015-08-04 09:47:08 +02001573static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001574lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001575{
Radek Krejci76512572015-08-04 09:47:08 +02001576 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001577 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001578
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001579 if (!size) {
1580 return NULL;
1581 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001582
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001583 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001584 if (!result) {
1585 LOGMEM;
1586 return NULL;
1587 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001588 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001589 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001590 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1591 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001592 result[i].flags = old[i].flags;
1593 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001594
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001595 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001596 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001597
Radek Krejci76512572015-08-04 09:47:08 +02001598 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001599 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001600 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001601 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001602 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001603 result[i].mod.list = old[i].mod.list;
1604 }
1605 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001606
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001607 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001608}
1609
Radek Krejci1d82ef62015-08-07 14:44:40 +02001610static void
1611lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001612{
Radek Krejcia52656e2015-08-05 13:41:50 +02001613 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001614
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001615 assert(ctx);
1616 if (!ident) {
1617 return;
1618 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001619
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001620 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001621 * if caller free only a single data model which is used (its identity is
1622 * reference from identity in another module), this silly freeing can lead
1623 * to segmentation fault. But without noting if the module is used by some
1624 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001625 *
1626 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001627 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001628 */
1629 while (ident->der) {
1630 der = ident->der;
1631 ident->der = der->next;
1632 free(der);
1633 }
Radek Krejci6793db02015-05-22 17:49:54 +02001634
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001635 lydict_remove(ctx, ident->name);
1636 lydict_remove(ctx, ident->dsc);
1637 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001638
1639}
1640
Radek Krejci1d82ef62015-08-07 14:44:40 +02001641static void
1642lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001643{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001644 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001645
Radek Krejcid12f57b2015-08-06 10:43:39 +02001646 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001647 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001648 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001649 }
1650 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001651}
1652
Radek Krejci1d82ef62015-08-07 14:44:40 +02001653static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001654lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1655{
1656 int i;
1657
1658 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1659 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001660 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001661 }
1662 free(io->tpdf);
1663}
1664
Radek Krejci1d82ef62015-08-07 14:44:40 +02001665static void
1666lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001667{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001668 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001669
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001670 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001671 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001672 }
1673 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001674
Radek Krejci1d82ef62015-08-07 14:44:40 +02001675 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001676}
1677
Radek Krejci1d82ef62015-08-07 14:44:40 +02001678static void
1679lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001680{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001681 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001682
Radek Krejci46c4cd72016-01-21 15:13:52 +01001683 if (leaf->child) {
1684 /* leafref backlinks */
1685 ly_set_free((struct ly_set *)leaf->child);
1686 }
1687
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001688 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001689 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001690 }
1691 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001692
Radek Krejci1d82ef62015-08-07 14:44:40 +02001693 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001694
Radek Krejci1d82ef62015-08-07 14:44:40 +02001695 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001696 lydict_remove(ctx, leaf->units);
1697 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001698}
1699
Radek Krejci1d82ef62015-08-07 14:44:40 +02001700static void
1701lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001702{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001703 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001704
Radek Krejci46c4cd72016-01-21 15:13:52 +01001705 if (llist->child) {
1706 /* leafref backlinks */
1707 ly_set_free((struct ly_set *)llist->child);
1708 }
1709
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001710 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001711 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001712 }
1713 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001714
Radek Krejci1d82ef62015-08-07 14:44:40 +02001715 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001716
Radek Krejci1d82ef62015-08-07 14:44:40 +02001717 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001718 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001719}
1720
Radek Krejci1d82ef62015-08-07 14:44:40 +02001721static void
1722lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001723{
Radek Krejci581ce772015-11-10 17:22:40 +01001724 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001725
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001726 /* handle only specific parts for LY_NODE_LIST */
1727 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001728 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001729 }
1730 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001731
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001732 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001733 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001734 }
1735 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001736
Radek Krejci1d82ef62015-08-07 14:44:40 +02001737 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001738
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001739 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001740 for (j = 0; j > list->unique[i].expr_size; j++) {
1741 lydict_remove(ctx, list->unique[i].expr[j]);
1742 }
1743 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001744 }
1745 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001746
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001747 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001748}
1749
Radek Krejci1d82ef62015-08-07 14:44:40 +02001750static void
1751lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001752{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001753 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001754
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001755 /* handle only specific parts for LY_NODE_CONTAINER */
1756 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001757
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001758 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001759 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001760 }
1761 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001762
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001763 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001764 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001765 }
1766 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001767
Radek Krejci1d82ef62015-08-07 14:44:40 +02001768 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001769}
1770
Radek Krejci1d82ef62015-08-07 14:44:40 +02001771static void
1772lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001773{
1774 lydict_remove(ctx, f->name);
1775 lydict_remove(ctx, f->dsc);
1776 lydict_remove(ctx, f->ref);
1777 free(f->features);
1778}
1779
Radek Krejci1d82ef62015-08-07 14:44:40 +02001780static void
Michal Vaskoff006c12016-02-17 11:15:19 +01001781lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001782{
Radek Krejci581ce772015-11-10 17:22:40 +01001783 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01001784 struct ly_ctx *ctx;
1785 struct lys_node *next, *elem;
1786
1787 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02001788
1789 lydict_remove(ctx, dev->target_name);
1790 lydict_remove(ctx, dev->dsc);
1791 lydict_remove(ctx, dev->ref);
1792
Michal Vaskoff006c12016-02-17 11:15:19 +01001793 /* the module was freed, but we only need the context from orig_node, use ours */
1794 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
1795 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
1796 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
1797 elem->module = module;
1798
1799 LY_TREE_DFS_END(dev->orig_node, next, elem);
1800 }
1801 lys_node_free(dev->orig_node, NULL, 0);
1802 } else {
1803 /* it's just a shallow copy, freeing one node */
1804 dev->orig_node->module = module;
1805 lys_node_free(dev->orig_node, NULL, 1);
1806 }
1807
Radek Krejcieb00f512015-07-01 16:44:58 +02001808 for (i = 0; i < dev->deviate_size; i++) {
1809 lydict_remove(ctx, dev->deviate[i].dflt);
1810 lydict_remove(ctx, dev->deviate[i].units);
1811
1812 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1813 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001814 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001815 }
1816 free(dev->deviate[i].must);
1817
1818 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001819 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1820 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1821 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01001822 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001823 }
1824 free(dev->deviate[i].unique);
1825 }
1826 }
1827 free(dev->deviate);
1828}
1829
Radek Krejci1d82ef62015-08-07 14:44:40 +02001830static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001831lys_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 +02001832{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001833 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001834
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001835 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001836 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001837 lydict_remove(ctx, uses->refine[i].dsc);
1838 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001839
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001840 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001841 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001842 }
1843 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001844
Radek Krejci76512572015-08-04 09:47:08 +02001845 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001846 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001847 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001848 lydict_remove(ctx, uses->refine[i].mod.presence);
1849 }
1850 }
1851 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001852
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001853 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001854 lys_augment_free(ctx, uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001855 }
1856 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001857
Radek Krejci1d82ef62015-08-07 14:44:40 +02001858 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001859}
1860
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001861void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001862lys_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 +02001863{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001864 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001865 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001866
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001867 if (!node) {
1868 return;
1869 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001870
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001871 assert(node->module);
1872 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001873
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001874 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001875
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001876 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01001877 if (node->priv && private_destructor) {
1878 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001879 }
1880
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001881 /* common part */
Radek Krejcid12f57b2015-08-06 10:43:39 +02001882 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1883 free(node->features);
1884 lydict_remove(ctx, node->name);
1885 lydict_remove(ctx, node->dsc);
1886 lydict_remove(ctx, node->ref);
1887 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001888
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001889 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01001890 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001891 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001892 }
1893 }
1894
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001895 /* specific part */
1896 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001897 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001898 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001899 break;
Radek Krejci76512572015-08-04 09:47:08 +02001900 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001901 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001902 break;
Radek Krejci76512572015-08-04 09:47:08 +02001903 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001904 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001905 break;
Radek Krejci76512572015-08-04 09:47:08 +02001906 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001907 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001908 break;
Radek Krejci76512572015-08-04 09:47:08 +02001909 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001910 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001911 break;
Radek Krejci76512572015-08-04 09:47:08 +02001912 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001913 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001914 break;
Radek Krejci76512572015-08-04 09:47:08 +02001915 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001916 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001917 break;
Radek Krejci76512572015-08-04 09:47:08 +02001918 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001919 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001920 break;
Radek Krejci76512572015-08-04 09:47:08 +02001921 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001922 /* do nothing */
1923 break;
Radek Krejci76512572015-08-04 09:47:08 +02001924 case LYS_GROUPING:
1925 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001926 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001927 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001928 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001929
1930 case LYS_INPUT:
1931 case LYS_OUTPUT:
1932 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1933 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001934 case LYS_UNKNOWN:
1935 LOGINT;
1936 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001937 }
Radek Krejci5a065542015-05-22 15:02:07 +02001938
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001939 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001940 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001941 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001942}
1943
Michal Vasko1e62a092015-12-01 12:27:20 +01001944const struct lys_module *
1945lys_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 +02001946{
Radek Krejcic071c542016-01-27 14:57:51 +01001947 const struct lys_module *main_module;
Michal Vasko3edeaf72016-02-11 13:17:43 +01001948 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02001949
Michal Vaskoa7789a82016-02-11 15:42:55 +01001950 assert(!prefix || !name);
1951
Michal Vaskob6729c62015-10-21 12:09:47 +02001952 if (prefix && !pref_len) {
1953 pref_len = strlen(prefix);
1954 }
1955 if (name && !name_len) {
1956 name_len = strlen(name);
1957 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02001958
Michal Vasko4f0dad02016-02-15 14:08:23 +01001959 main_module = lys_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01001960
1961 /* module own prefix, submodule own prefix, (sub)module own name */
1962 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
1963 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01001964 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01001965 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02001966 }
1967
Michal Vasko8ce24d72015-10-21 11:27:26 +02001968 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01001969 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
1970 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02001971 return module->imp[i].module;
1972 }
1973 }
1974
1975 return NULL;
1976}
1977
Michal Vasko13b15832015-08-19 11:04:48 +02001978/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001979static void
Michal Vaskob746fff2016-02-11 11:37:50 +01001980module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02001981{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001982 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01001983 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001984 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001985
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001986 assert(module->ctx);
1987 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001988
Michal Vaskob746fff2016-02-11 11:37:50 +01001989 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01001990 for (i = 0; i < module->imp_size; i++) {
Radek Krejci4f78b532016-02-17 13:43:00 +01001991 if (!module->imp[i].external) {
1992 lydict_remove(ctx, module->imp[i].prefix);
1993 }
Radek Krejci225376f2016-02-16 17:36:22 +01001994 }
Radek Krejcidce51452015-06-16 15:20:08 +02001995 free(module->imp);
1996
Radek Krejcic071c542016-01-27 14:57:51 +01001997 /* submodules don't have data tree, the data nodes
1998 * are placed in the main module altogether */
1999 if (!module->type) {
2000 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002001 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01002002 }
Radek Krejci21181962015-06-30 14:11:00 +02002003 }
Radek Krejci5a065542015-05-22 15:02:07 +02002004
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002005 lydict_remove(ctx, module->dsc);
2006 lydict_remove(ctx, module->ref);
2007 lydict_remove(ctx, module->org);
2008 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01002009 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002010
Radek Krejcieb00f512015-07-01 16:44:58 +02002011 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002012 for (i = 0; i < module->rev_size; i++) {
2013 lydict_remove(ctx, module->rev[i].dsc);
2014 lydict_remove(ctx, module->rev[i].ref);
2015 }
2016 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002017
Radek Krejcieb00f512015-07-01 16:44:58 +02002018 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002019 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002020 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002021 }
2022 module->ident_size = 0;
2023 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002024
Radek Krejcieb00f512015-07-01 16:44:58 +02002025 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002026 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002027 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002028 }
2029 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002030
Radek Krejcieb00f512015-07-01 16:44:58 +02002031 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002032 for (i = 0; i < module->inc_size; i++) {
Radek Krejcic071c542016-01-27 14:57:51 +01002033 /* complete submodule free is done only from main module since
2034 * submodules propagate their includes to the main module */
2035 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002036 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002037 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002038 }
2039 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002040
Radek Krejcieb00f512015-07-01 16:44:58 +02002041 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002042 for (i = 0; i < module->augment_size; i++) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002043 lys_augment_free(ctx, module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002044 }
2045 free(module->augment);
2046
Radek Krejcieb00f512015-07-01 16:44:58 +02002047 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002048 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002049 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002050 }
2051 free(module->features);
2052
Radek Krejcieb00f512015-07-01 16:44:58 +02002053 /* deviations */
2054 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002055 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002056 }
2057 free(module->deviation);
2058
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002059 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002060 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002061}
2062
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002063void
Michal Vaskob746fff2016-02-11 11:37:50 +01002064lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002065{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002066 if (!submodule) {
2067 return;
2068 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002069
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002070 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002071 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002073 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002074
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002075 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002076}
2077
Radek Krejci76512572015-08-04 09:47:08 +02002078struct lys_node *
Radek Krejcic071c542016-01-27 14:57:51 +01002079lys_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 +01002080 uint8_t nacm, struct unres_schema *unres, int shallow)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002081{
Radek Krejcic071c542016-01-27 14:57:51 +01002082 struct lys_node *retval = NULL, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002083 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002084 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002085
Michal Vaskoc07187d2015-08-13 15:20:57 +02002086 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002087 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002088 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002089 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002090 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002091 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002092 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002093 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002094 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002095 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002096 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002097 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002098 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002099 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002100 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002101 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002102 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002103 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002104 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002105 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002106 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002107 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002108 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002109 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002110
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002111 /* we cannot just duplicate memory since the strings are stored in
2112 * dictionary and we need to update dictionary counters.
2113 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002114
Radek Krejci1d82ef62015-08-07 14:44:40 +02002115 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002116 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002117 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002118 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002119 break;
2120
Radek Krejci76512572015-08-04 09:47:08 +02002121 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002122 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002123 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002124 break;
2125
Radek Krejci76512572015-08-04 09:47:08 +02002126 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002127 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002128 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002129 break;
2130
Radek Krejci76512572015-08-04 09:47:08 +02002131 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002132 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002133 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002134 break;
2135
Radek Krejci76512572015-08-04 09:47:08 +02002136 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002137 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002138 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002139 break;
2140
Radek Krejci76512572015-08-04 09:47:08 +02002141 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002142 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002143 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002144 break;
2145
Radek Krejci76512572015-08-04 09:47:08 +02002146 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002147 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002148 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002149 break;
2150
Radek Krejci76512572015-08-04 09:47:08 +02002151 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002152 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002153 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002154 break;
2155
Radek Krejci76512572015-08-04 09:47:08 +02002156 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002157 grp = calloc(1, sizeof *grp);
2158 retval = (struct lys_node *)grp;
2159 break;
2160
Radek Krejci76512572015-08-04 09:47:08 +02002161 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002162 rpc = calloc(1, sizeof *rpc);
2163 retval = (struct lys_node *)rpc;
2164 break;
2165
Radek Krejci76512572015-08-04 09:47:08 +02002166 case LYS_INPUT:
2167 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002168 io = calloc(1, sizeof *io);
2169 retval = (struct lys_node *)io;
2170 break;
2171
Radek Krejci76512572015-08-04 09:47:08 +02002172 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002173 ntf = calloc(1, sizeof *ntf);
2174 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002175 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002176
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002177 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002178 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002179 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002180 }
Radek Krejcib388c152015-06-04 17:03:03 +02002181
Michal Vasko253035f2015-12-17 16:58:13 +01002182 if (!retval) {
2183 LOGMEM;
2184 return NULL;
2185 }
2186
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002187 /*
2188 * duplicate generic part of the structure
2189 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002190 retval->name = lydict_insert(ctx, node->name, 0);
2191 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2192 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002193 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002194 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002195 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002196 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002197 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002198 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002199
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002200 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002201 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002202
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002203 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002204
Radek Krejci1d82ef62015-08-07 14:44:40 +02002205 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002206 retval->features = calloc(retval->features_size, sizeof *retval->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002207 if (!retval->features) {
2208 LOGMEM;
2209 goto error;
2210 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002211
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002212 if (!shallow) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002213 for (i = 0; i < node->features_size; ++i) {
2214 retval->features[i] = (struct lys_feature *)retval;
2215 if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
2216 retval->features[i] = node->features[i];
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002217 }
2218 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002219
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002220 /* connect it to the parent */
2221 if (lys_node_addchild(parent, retval->module, retval)) {
2222 goto error;
2223 }
Radek Krejcidce51452015-06-16 15:20:08 +02002224
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002225 /* go recursively */
2226 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2227 LY_TREE_FOR(node->child, child) {
2228 if (!lys_node_dup(module, retval, child, retval->flags, retval->nacm, unres, 0)) {
2229 goto error;
2230 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002231 }
2232 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002233 } else {
2234 memcpy(retval->features, node->features, retval->features_size * sizeof *retval->features);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002235 }
2236
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002237 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002238 * duplicate specific part of the structure
2239 */
2240 switch (node->nodetype) {
2241 case LYS_CONTAINER:
2242 if (cont_orig->when) {
2243 cont->when = lys_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002244 }
2245 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002246
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002247 cont->must_size = cont_orig->must_size;
2248 cont->tpdf_size = cont_orig->tpdf_size;
2249
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002250 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002251 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
2252 break;
2253
2254 case LYS_CHOICE:
2255 if (choice_orig->when) {
2256 choice->when = lys_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002257 }
2258
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002259 if (!shallow) {
2260 if (choice_orig->dflt) {
2261 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0, LYS_ANYXML
2262 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
2263 | LYS_LIST, (const struct lys_node **)&choice->dflt);
2264 if (rc) {
2265 if (rc == EXIT_FAILURE) {
2266 LOGINT;
2267 }
2268 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002269 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002270 } else {
2271 /* useless to check return value, we don't know whether
2272 * there really wasn't any default defined or it just hasn't
2273 * been resolved, we just hope for the best :)
2274 */
2275 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002276 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002277 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002278 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002279 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002280 break;
2281
2282 case LYS_LEAF:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002283 if (lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres)) {
2284 goto error;
2285 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002286 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2287
2288 if (leaf_orig->dflt) {
2289 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002290 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002291 goto error;
2292 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002293 }
2294
2295 leaf->must_size = leaf_orig->must_size;
2296 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002297
2298 if (leaf_orig->when) {
2299 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002300 }
2301 break;
2302
2303 case LYS_LEAFLIST:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002304 if (lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres)) {
2305 goto error;
2306 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002307 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
2308
2309 llist->min = llist_orig->min;
2310 llist->max = llist_orig->max;
2311
2312 llist->must_size = llist_orig->must_size;
2313 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002314
2315 if (llist_orig->when) {
2316 llist->when = lys_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002317 }
2318 break;
2319
2320 case LYS_LIST:
2321 list->min = list_orig->min;
2322 list->max = list_orig->max;
2323
2324 list->must_size = list_orig->must_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002325 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002326
Radek Krejci581ce772015-11-10 17:22:40 +01002327 list->tpdf_size = list_orig->tpdf_size;
Michal Vasko0ea41032015-06-16 08:53:55 +02002328 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02002329
Radek Krejci581ce772015-11-10 17:22:40 +01002330 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02002331 if (list->keys_size) {
2332 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01002333 if (!list->keys) {
2334 LOGMEM;
2335 goto error;
2336 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002337
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002338 if (!shallow) {
2339 /* we managed to resolve it before, resolve it again manually */
2340 if (list_orig->keys[0]) {
2341 for (i = 0; i < list->keys_size; ++i) {
2342 rc = lys_get_sibling(list->child, lys_node_module(retval)->name, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2343 (const struct lys_node **)&list->keys[i]);
2344 if (rc) {
2345 if (rc == EXIT_FAILURE) {
2346 LOGINT;
2347 }
2348 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002349 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002350 }
2351 /* it was not resolved yet, add unres copy */
2352 } else {
2353 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
2354 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002355 goto error;
2356 }
Michal Vasko38d01f72015-06-15 09:41:06 +02002357 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002358 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002359 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02002360 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002361 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002362
Radek Krejci581ce772015-11-10 17:22:40 +01002363 list->unique_size = list_orig->unique_size;
2364 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002365 if (!list->unique) {
2366 LOGMEM;
2367 goto error;
2368 }
Radek Krejci581ce772015-11-10 17:22:40 +01002369 for (i = 0; i < list->unique_size; ++i) {
2370 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2371 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002372 if (!list->unique[i].expr) {
2373 LOGMEM;
2374 goto error;
2375 }
Radek Krejci581ce772015-11-10 17:22:40 +01002376 for (j = 0; j < list->unique[i].expr_size; j++) {
2377 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2378
2379 /* if it stays in unres list, duplicate it also there */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002380 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002381 }
2382 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002383
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002384 if (list_orig->when) {
2385 list->when = lys_when_dup(ctx, list_orig->when);
Radek Krejciefaeba32015-05-27 14:30:57 +02002386 }
Radek Krejcidce51452015-06-16 15:20:08 +02002387 break;
2388
2389 case LYS_ANYXML:
2390 anyxml->must_size = anyxml_orig->must_size;
2391 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002392
2393 if (anyxml_orig->when) {
2394 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002395 }
2396 break;
2397
2398 case LYS_USES:
2399 uses->grp = uses_orig->grp;
2400
2401 if (uses_orig->when) {
2402 uses->when = lys_when_dup(ctx, uses_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002403 }
2404
2405 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002406 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002407 uses->augment_size = uses_orig->augment_size;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002408 if (!shallow) {
2409 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
2410 if (!uses->child) {
2411 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, 0) == -1) {
2412 goto error;
2413 }
Michal Vasko49168a22015-08-17 16:35:41 +02002414 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002415 } else {
2416 memcpy(uses->augment, uses_orig->augment, uses->augment_size * sizeof *uses->augment);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002417 }
2418 break;
2419
Radek Krejcidce51452015-06-16 15:20:08 +02002420 case LYS_CASE:
2421 if (cs_orig->when) {
2422 cs->when = lys_when_dup(ctx, cs_orig->when);
Radek Krejcidce51452015-06-16 15:20:08 +02002423 }
2424 break;
2425
2426 case LYS_GROUPING:
2427 grp->tpdf_size = grp_orig->tpdf_size;
2428 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
2429 break;
2430
2431 case LYS_RPC:
2432 rpc->tpdf_size = rpc_orig->tpdf_size;
2433 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
2434 break;
2435
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002436 case LYS_INPUT:
2437 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02002438 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002439 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
2440 break;
2441
Radek Krejcida04f4a2015-05-21 12:54:09 +02002442 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002443 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002444 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejci7e97c352015-06-19 16:26:34 +02002445 break;
2446
2447 default:
2448 /* LY_NODE_AUGMENT */
2449 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002450 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002451 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002452
2453 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002454
2455error:
2456
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002457 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02002458 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002459}
2460
Michal Vasko13b15832015-08-19 11:04:48 +02002461void
Michal Vaskoff006c12016-02-17 11:15:19 +01002462lys_node_switch(struct lys_node *dst, struct lys_node *src)
2463{
2464 struct lys_node *child;
2465
2466 assert((dst->module == src->module) && (dst->name == src->name) && (dst->nodetype == src->nodetype));
2467
2468 /* sibling next */
2469 if (dst->prev != dst) {
2470 dst->prev->next = src;
2471 }
2472
2473 /* sibling prev */
2474 if (dst->next) {
2475 dst->next->prev = src;
2476 }
2477
2478 /* parent child prev */
2479 if (!dst->next && dst->parent) {
2480 dst->parent->child->prev = src;
2481 }
2482
2483 /* next */
2484 src->next = dst->next;
2485 dst->next = NULL;
2486
2487 /* prev */
2488 if (dst->prev != dst) {
2489 src->prev = dst->prev;
2490 }
2491 dst->prev = dst;
2492
2493 /* parent child */
2494 if (dst->parent && (dst->parent->child == dst)) {
2495 dst->parent->child = src;
2496 }
2497
2498 /* parent */
2499 src->parent = dst->parent;
2500 dst->parent = NULL;
2501
2502 /* child parent */
2503 LY_TREE_FOR(dst->child, child) {
2504 if (child->parent == dst) {
2505 child->parent = src;
2506 }
2507 }
2508
2509 /* child */
2510 src->child = dst->child;
2511 dst->child = NULL;
2512}
2513
2514void
Michal Vasko627975a2016-02-11 11:39:03 +01002515lys_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 +02002516{
2517 struct ly_ctx *ctx;
2518 int i;
2519
2520 if (!module) {
2521 return;
2522 }
2523
2524 /* remove schema from the context */
2525 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01002526 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02002527 for (i = 0; i < ctx->models.used; i++) {
2528 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01002529 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02002530 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01002531 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 +02002532 ctx->models.list[ctx->models.used] = NULL;
2533 /* we are done */
2534 break;
2535 }
2536 }
2537 }
2538
2539 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01002540 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002541
2542 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01002543 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002544
2545 free(module);
2546}
Radek Krejci7e97c352015-06-19 16:26:34 +02002547
2548/*
2549 * op: 1 - enable, 0 - disable
2550 */
2551static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002552lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002553{
2554 int all = 0;
2555 int i, j, k;
2556
2557 if (!module || !name || !strlen(name)) {
2558 return EXIT_FAILURE;
2559 }
2560
2561 if (!strcmp(name, "*")) {
2562 /* enable all */
2563 all = 1;
2564 }
2565
2566 /* module itself */
2567 for (i = 0; i < module->features_size; i++) {
2568 if (all || !strcmp(module->features[i].name, name)) {
2569 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002570 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002571 /* enable referenced features (recursion) */
2572 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002573 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002574 module->features[i].features[k]->name, op);
2575 }
2576 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002577 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002578 }
2579 if (!all) {
2580 return EXIT_SUCCESS;
2581 }
2582 }
2583 }
2584
2585 /* submodules */
2586 for (j = 0; j < module->inc_size; j++) {
2587 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2588 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2589 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002590 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002591 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002592 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002593 }
2594 if (!all) {
2595 return EXIT_SUCCESS;
2596 }
2597 }
2598 }
2599 }
2600
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002601 /* TODO submodules of submodules ... */
2602
Radek Krejci7e97c352015-06-19 16:26:34 +02002603 if (all) {
2604 return EXIT_SUCCESS;
2605 } else {
2606 return EXIT_FAILURE;
2607 }
2608}
2609
2610API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002611lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002612{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002613 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002614}
2615
2616API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002617lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002618{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002619 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002620}
2621
2622API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002623lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002624{
2625 int i, j;
2626
2627 if (!module || !feature) {
2628 return -1;
2629 }
2630
2631 /* search for the specified feature */
2632 /* module itself */
2633 for (i = 0; i < module->features_size; i++) {
2634 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002635 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002636 return 1;
2637 } else {
2638 return 0;
2639 }
2640 }
2641 }
2642
2643 /* submodules */
2644 for (j = 0; j < module->inc_size; j++) {
2645 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2646 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002647 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002648 return 1;
2649 } else {
2650 return 0;
2651 }
2652 }
2653 }
2654 }
2655
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002656 /* feature definition not found */
2657 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002658}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002659
Radek Krejci96a10da2015-07-30 11:00:14 +02002660API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01002661lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002662{
Radek Krejci96a10da2015-07-30 11:00:14 +02002663 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002664 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002665 unsigned int count;
2666
2667 if (!module) {
2668 return NULL;
2669 }
2670
2671 count = module->features_size;
2672 for (i = 0; i < module->inc_size; i++) {
2673 count += module->inc[i].submodule->features_size;
2674 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002675 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01002676 if (!result) {
2677 LOGMEM;
2678 return NULL;
2679 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002680 if (states) {
2681 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01002682 if (!(*states)) {
2683 LOGMEM;
2684 free(result);
2685 return NULL;
2686 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002687 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002688 count = 0;
2689
2690 /* module itself */
2691 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002692 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002693 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002694 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002695 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002696 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002697 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002698 }
2699 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002700 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002701 }
2702
2703 /* submodules */
2704 for (j = 0; j < module->inc_size; j++) {
2705 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002706 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002707 if (states) {
2708 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2709 (*states)[count] = 1;
2710 } else {
2711 (*states)[count] = 0;
2712 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002713 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002714 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002715 }
2716 }
2717
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002718 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002719 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002720
2721 return result;
2722}
Michal Vaskobaefb032015-09-24 14:52:10 +02002723
Radek Krejcic071c542016-01-27 14:57:51 +01002724struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01002725lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01002726{
2727 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
2728}
2729
Michal Vasko320e8532016-02-15 13:11:57 +01002730struct lys_module *
2731lys_module(const struct lys_module *module)
2732{
2733 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
2734}
2735
Michal Vaskobaefb032015-09-24 14:52:10 +02002736API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002737lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02002738{
2739 if (!node || !node->parent) {
2740 return NULL;
2741 }
2742
2743 if (node->parent->nodetype == LYS_AUGMENT) {
2744 return ((struct lys_node_augment *)node->parent)->target;
2745 }
2746
2747 return node->parent;
2748}
Michal Vasko1b229152016-01-13 11:28:38 +01002749
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002750API void *
Michal Vasko1b229152016-01-13 11:28:38 +01002751lys_set_private(const struct lys_node *node, void *priv)
2752{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002753 void *prev;
2754
Michal Vasko1b229152016-01-13 11:28:38 +01002755 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002756 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2757 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01002758 }
2759
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002760 prev = node->priv;
2761 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002762
2763 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01002764}