blob: bbaebfd13ceb6ee82b310e5b7297b5006e9018c4 [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 Vasko5b3492c2016-07-20 09:37:40 +020034#include "xpath.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020035#include "xml_internal.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020036#include "tree_internal.h"
Radek Krejcieab784a2015-08-27 09:56:53 +020037#include "validation.h"
Pavol Vicanf7cc2852016-03-22 23:27:35 +010038#include "parser_yang.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020039
Pavol Vicanacb9d0d2016-04-04 13:57:23 +020040static int
41lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci3a5501d2016-07-18 22:03:34 +020042 int tpdftype, struct unres_schema *unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +020043
Radek Krejci9ff0a922016-07-14 13:08:05 +020044API const struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +010045lys_is_disabled(const struct lys_node *node, int recursive)
Radek Krejci48061fb2015-08-05 15:41:07 +020046{
Radek Krejci9ff0a922016-07-14 13:08:05 +020047 int i;
Radek Krejci48061fb2015-08-05 15:41:07 +020048
Radek Krejci27fe55e2016-09-13 17:13:35 +020049 if (!node) {
50 return NULL;
51 }
52
Radek Krejci48061fb2015-08-05 15:41:07 +020053check:
54 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
55 /* input/output does not have if-feature, so skip them */
56
57 /* check local if-features */
Michal Vaskoc5c26b02016-06-29 11:10:29 +020058 for (i = 0; i < node->iffeature_size; i++) {
Radek Krejci69b8d922016-07-27 13:13:41 +020059 if (!resolve_iffeature(&node->iffeature[i])) {
Radek Krejci9ff0a922016-07-14 13:08:05 +020060 return node;
Radek Krejci48061fb2015-08-05 15:41:07 +020061 }
62 }
63 }
64
65 if (!recursive) {
66 return NULL;
67 }
68
69 /* go through parents */
70 if (node->nodetype == LYS_AUGMENT) {
71 /* go to parent actually means go to the target node */
72 node = ((struct lys_node_augment *)node)->target;
Radek Krejci48061fb2015-08-05 15:41:07 +020073 } else if (node->parent) {
74 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020075 } else {
76 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020077 }
78
Radek Krejci074bf852015-08-19 14:22:16 +020079 if (recursive == 2) {
80 /* continue only if the node cannot have a data instance */
81 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
82 return NULL;
83 }
84 }
85 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020086}
87
Michal Vasko1dca6882015-10-22 14:29:42 +020088int
Michal Vasko36cbaa42015-12-14 13:15:48 +010089lys_get_sibling(const struct lys_node *siblings, const char *mod_name, int mod_name_len, const char *name,
90 int nam_len, LYS_NODE type, const struct lys_node **ret)
Michal Vasko1dca6882015-10-22 14:29:42 +020091{
Radek Krejcic071c542016-01-27 14:57:51 +010092 const struct lys_node *node, *parent = NULL;
93 const struct lys_module *mod = NULL;
Michal Vasko36cbaa42015-12-14 13:15:48 +010094 const char *node_mod_name;
Michal Vasko1dca6882015-10-22 14:29:42 +020095
Michal Vasko36cbaa42015-12-14 13:15:48 +010096 assert(siblings && mod_name && name);
Michal Vasko165dc4a2015-10-23 09:44:27 +020097 assert(!(type & (LYS_USES | LYS_GROUPING)));
Michal Vasko1dca6882015-10-22 14:29:42 +020098
Michal Vasko36cbaa42015-12-14 13:15:48 +010099 /* fill the lengths in case the caller is so indifferent */
100 if (!mod_name_len) {
101 mod_name_len = strlen(mod_name);
102 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200103 if (!nam_len) {
104 nam_len = strlen(name);
105 }
106
Michal Vasko36cbaa42015-12-14 13:15:48 +0100107 /* set mod correctly */
Radek Krejcic071c542016-01-27 14:57:51 +0100108 parent = lys_parent(siblings);
109 if (!parent) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100110 mod = lys_node_module(siblings);
Michal Vasko1dca6882015-10-22 14:29:42 +0200111 }
112
Radek Krejcic071c542016-01-27 14:57:51 +0100113 /* try to find the node */
114 node = NULL;
115 while ((node = lys_getnext(node, parent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
116 if (!type || (node->nodetype & type)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100117 /* module name comparison */
118 node_mod_name = lys_node_module(node)->name;
Michal Vaskob42b6972016-06-06 14:21:30 +0200119 if (!ly_strequal(node_mod_name, mod_name, 1) && (strncmp(node_mod_name, mod_name, mod_name_len) || node_mod_name[mod_name_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100120 continue;
121 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200122
Radek Krejcic071c542016-01-27 14:57:51 +0100123 /* direct name check */
Michal Vaskob42b6972016-06-06 14:21:30 +0200124 if (ly_strequal(node->name, name, 1) || (!strncmp(node->name, name, nam_len) && !node->name[nam_len])) {
Radek Krejcic071c542016-01-27 14:57:51 +0100125 if (ret) {
126 *ret = node;
Michal Vasko1dca6882015-10-22 14:29:42 +0200127 }
Radek Krejcic071c542016-01-27 14:57:51 +0100128 return EXIT_SUCCESS;
Michal Vasko1dca6882015-10-22 14:29:42 +0200129 }
130 }
Michal Vasko1dca6882015-10-22 14:29:42 +0200131 }
132
133 return EXIT_FAILURE;
134}
135
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200136int
Michal Vasko1e62a092015-12-01 12:27:20 +0100137lys_get_data_sibling(const struct lys_module *mod, const struct lys_node *siblings, const char *name, LYS_NODE type,
138 const struct lys_node **ret)
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200139{
Michal Vasko1e62a092015-12-01 12:27:20 +0100140 const struct lys_node *node;
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200141
142 assert(siblings && name);
143 assert(!(type & (LYS_AUGMENT | LYS_USES | LYS_GROUPING | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT)));
144
145 /* find the beginning */
146 while (siblings->prev->next) {
147 siblings = siblings->prev;
148 }
149
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200150 if (!mod) {
151 mod = siblings->module;
152 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200153
Michal Vasko4f0dad02016-02-15 14:08:23 +0100154 /* try to find the node */
155 node = NULL;
Michal Vaskodcf98e62016-05-05 17:53:53 +0200156 while ((node = lys_getnext(node, lys_parent(siblings), mod, 0))) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100157 if (!type || (node->nodetype & type)) {
158 /* module check */
Radek Krejcic4283442016-04-22 09:19:27 +0200159 if (lys_node_module(node) != lys_main_module(mod)) {
Radek Krejcic071c542016-01-27 14:57:51 +0100160 continue;
161 }
162
Michal Vasko4f0dad02016-02-15 14:08:23 +0100163 /* direct name check */
Radek Krejci749190d2016-02-18 16:26:25 +0100164 if (ly_strequal(node->name, name, 0)) {
Michal Vasko4f0dad02016-02-15 14:08:23 +0100165 if (ret) {
166 *ret = node;
167 }
168 return EXIT_SUCCESS;
169 }
Radek Krejcic071c542016-01-27 14:57:51 +0100170 }
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200171 }
172
173 return EXIT_FAILURE;
174}
175
Michal Vasko1e62a092015-12-01 12:27:20 +0100176API const struct lys_node *
177lys_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 +0200178{
Michal Vasko1e62a092015-12-01 12:27:20 +0100179 const struct lys_node *next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200180
Radek Krejci8bc87f62015-09-02 16:19:05 +0200181 if (!last) {
182 /* first call */
183
184 /* get know where to start */
185 if (parent) {
186 /* schema subtree */
187 next = last = parent->child;
188 } else {
189 /* top level data */
190 assert(module);
191 next = last = module->data;
192 }
Radek Krejci972724f2016-08-12 15:24:40 +0200193 } else if ((last->nodetype == LYS_USES) && (options & LYS_GETNEXT_INTOUSES) && last->child) {
194 /* continue with uses content */
195 next = last->child;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200196 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200197 /* continue after the last returned value */
198 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200199 }
200
201repeat:
Michal Vasko7c386e72015-10-07 15:13:33 +0200202 while (next && (next->nodetype == LYS_GROUPING)) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200203 if (options & LYS_GETNEXT_WITHGROUPING) {
204 return next;
205 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200206 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200207 }
208
Radek Krejci972724f2016-08-12 15:24:40 +0200209 if (!next) { /* cover case when parent is augment */
210 if (!last || last->parent == parent || lys_parent(last) == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200211 /* no next element */
212 return NULL;
213 }
Michal Vasko7c386e72015-10-07 15:13:33 +0200214 last = lys_parent(last);
Radek Krejci8bc87f62015-09-02 16:19:05 +0200215 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200216 goto repeat;
Radek Krejci972724f2016-08-12 15:24:40 +0200217 } else {
218 last = next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200219 }
220
221 switch (next->nodetype) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200222 case LYS_INPUT:
223 case LYS_OUTPUT:
224 if (options & LYS_GETNEXT_WITHINOUT) {
225 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200226 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200227 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200228 } else {
229 next = next->next;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200230 }
Radek Krejci972724f2016-08-12 15:24:40 +0200231 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200232
Michal Vaskoa5835e92015-10-20 15:07:39 +0200233 case LYS_CASE:
Michal Vasko1dca6882015-10-22 14:29:42 +0200234 if (options & LYS_GETNEXT_WITHCASE) {
235 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200236 } else if (next->child) {
Michal Vaskob6eedf02015-10-22 16:07:03 +0200237 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200238 } else {
239 next = next->next;
Michal Vasko1dca6882015-10-22 14:29:42 +0200240 }
Radek Krejci972724f2016-08-12 15:24:40 +0200241 goto repeat;
Michal Vaskob6eedf02015-10-22 16:07:03 +0200242
Michal Vasko1dca6882015-10-22 14:29:42 +0200243 case LYS_USES:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200244 /* go into */
Radek Krejci972724f2016-08-12 15:24:40 +0200245 if (options & LYS_GETNEXT_WITHUSES) {
246 return next;
247 } else if (next->child) {
248 next = next->child;
249 } else {
250 next = next->next;
251 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200252 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200253
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200254 case LYS_RPC:
Michal Vaskob1b19442016-07-13 12:26:01 +0200255 case LYS_ACTION:
Radek Krejcidfcae7d2015-10-20 17:13:01 +0200256 case LYS_NOTIF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200257 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200258 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200259 case LYS_ANYDATA:
Radek Krejci14a11a62015-08-17 17:27:38 +0200260 case LYS_LIST:
261 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200262 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200263
Radek Krejci972724f2016-08-12 15:24:40 +0200264 case LYS_CONTAINER:
265 if (!((struct lys_node_container *)next)->presence && (options & LYS_GETNEXT_INTONPCONT)) {
266 if (next->child) {
267 /* go into */
268 next = next->child;
269 } else {
270 next = next->next;
271 }
272 goto repeat;
273 } else {
274 return next;
275 }
276
Radek Krejci8bc87f62015-09-02 16:19:05 +0200277 case LYS_CHOICE:
278 if (options & LYS_GETNEXT_WITHCHOICE) {
279 return next;
Radek Krejci972724f2016-08-12 15:24:40 +0200280 } else if (next->child) {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200281 /* go into */
282 next = next->child;
Radek Krejci972724f2016-08-12 15:24:40 +0200283 } else {
284 next = next->next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200285 }
Radek Krejci972724f2016-08-12 15:24:40 +0200286 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200287
Radek Krejci7f40ce32015-08-12 20:38:46 +0200288 default:
289 /* we should not be here */
290 return NULL;
291 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200292
293
294}
295
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200296void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200297lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200298{
Radek Krejci76512572015-08-04 09:47:08 +0200299 struct lys_node *parent, *first;
Radek Krejcic071c542016-01-27 14:57:51 +0100300 struct lys_module *main_module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200302 if (!node) {
303 return;
304 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200305
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200306 /* unlink from data model if necessary */
307 if (node->module) {
Radek Krejcic071c542016-01-27 14:57:51 +0100308 /* get main module with data tree */
Michal Vasko4f0dad02016-02-15 14:08:23 +0100309 main_module = lys_node_module(node);
Radek Krejcic071c542016-01-27 14:57:51 +0100310 if (main_module->data == node) {
311 main_module->data = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200312 }
313 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200314
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200315 /* store pointers to important nodes */
316 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200317 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200318 /* handle augments - first, unlink it from the augment parent ... */
319 if (parent->child == node) {
320 parent->child = node->next;
321 }
322 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200323 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200324 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200326 /* unlink from parent */
327 if (parent) {
328 if (parent->child == node) {
329 parent->child = node->next;
330 }
331 node->parent = NULL;
332 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200333
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200334 /* unlink from siblings */
335 if (node->prev == node) {
336 /* there are no more siblings */
337 return;
338 }
339 if (node->next) {
340 node->next->prev = node->prev;
341 } else {
342 /* unlinking the last element */
343 if (parent) {
344 first = parent->child;
345 } else {
346 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200347 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200348 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200349 }
350 }
351 first->prev = node->prev;
352 }
353 if (node->prev->next) {
354 node->prev->next = node->next;
355 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200357 /* clean up the unlinked element */
358 node->next = NULL;
359 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200360}
361
Michal Vasko563ef092015-09-04 13:17:23 +0200362struct lys_node_grp *
Radek Krejcic071c542016-01-27 14:57:51 +0100363lys_find_grouping_up(const char *name, struct lys_node *start)
Michal Vasko563ef092015-09-04 13:17:23 +0200364{
365 struct lys_node *par_iter, *iter, *stop;
Michal Vasko563ef092015-09-04 13:17:23 +0200366
367 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200368 /* top-level augment, look into module (uses augment is handled correctly below) */
369 if (par_iter->parent && !par_iter->parent->parent && (par_iter->parent->nodetype == LYS_AUGMENT)) {
370 par_iter = par_iter->parent->module->data;
371 if (!par_iter) {
Michal Vaskoccbdb4e2015-10-21 15:09:02 +0200372 break;
373 }
374 }
375
Michal Vasko6f929da2015-10-02 16:23:25 +0200376 if (par_iter->parent && (par_iter->parent->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES))) {
Michal Vasko563ef092015-09-04 13:17:23 +0200377 continue;
378 }
379
380 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
381 if (!stop) {
382 stop = par_iter;
383 } else if (iter == stop) {
384 break;
385 }
386 if (iter->nodetype != LYS_GROUPING) {
387 continue;
388 }
389
Radek Krejcif8426a72015-10-31 23:14:03 +0100390 if (!strcmp(name, iter->name)) {
Michal Vasko563ef092015-09-04 13:17:23 +0200391 return (struct lys_node_grp *)iter;
392 }
393 }
394 }
395
Michal Vasko563ef092015-09-04 13:17:23 +0200396 return NULL;
397}
398
Radek Krejci10c760e2015-08-14 14:45:43 +0200399/*
400 * get next grouping in the root's subtree, in the
401 * first call, tha last is NULL
402 */
403static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200404lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200405{
Radek Krejci10c760e2015-08-14 14:45:43 +0200406 struct lys_node *last = (struct lys_node *)lastgrp;
407 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200408
Radek Krejci10c760e2015-08-14 14:45:43 +0200409 assert(root);
410
411 if (!last) {
412 last = root;
413 }
414
415 while (1) {
416 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
417 next = last->child;
418 } else {
419 next = NULL;
420 }
421 if (!next) {
422 if (last == root) {
423 /* we are done */
424 return NULL;
425 }
426
427 /* no children, go to siblings */
428 next = last->next;
429 }
430 while (!next) {
431 /* go back through parents */
Radek Krejcic071c542016-01-27 14:57:51 +0100432 if (lys_parent(last) == root) {
Radek Krejci10c760e2015-08-14 14:45:43 +0200433 /* we are done */
434 return NULL;
435 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200436 next = last->next;
Radek Krejcic071c542016-01-27 14:57:51 +0100437 last = lys_parent(last);
Radek Krejci10c760e2015-08-14 14:45:43 +0200438 }
439
440 if (next->nodetype == LYS_GROUPING) {
441 return (struct lys_node_grp *)next;
442 }
443
444 last = next;
445 }
446}
447
Michal Vasko0d343d12015-08-24 14:57:36 +0200448/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200449int
Radek Krejci07911992015-08-14 15:13:31 +0200450lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
451{
Michal Vasko563ef092015-09-04 13:17:23 +0200452 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200453 struct lys_node_grp *grp;
454 int down;
455
456 assert(node);
457
458 if (!parent) {
459 assert(module);
460 } else {
461 module = parent->module;
462 }
463
464 switch (node->nodetype) {
465 case LYS_GROUPING:
466 /* 6.2.1, rule 6 */
467 if (parent) {
468 if (parent->child) {
469 down = 1;
470 start = parent->child;
471 } else {
472 down = 0;
473 start = parent;
474 }
475 } else {
476 down = 1;
477 start = module->data;
478 }
479 /* go up */
Radek Krejcic071c542016-01-27 14:57:51 +0100480 if (lys_find_grouping_up(node->name, start)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100481 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "grouping", node->name);
Michal Vasko563ef092015-09-04 13:17:23 +0200482 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200483 }
484 /* go down, because grouping can be defined after e.g. container in which is collision */
485 if (down) {
486 for (iter = start, stop = NULL; iter; iter = iter->prev) {
487 if (!stop) {
488 stop = start;
489 } else if (iter == stop) {
490 break;
491 }
492 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
493 continue;
494 }
495
496 grp = NULL;
497 while ((grp = lys_get_next_grouping(grp, iter))) {
Radek Krejci749190d2016-02-18 16:26:25 +0100498 if (ly_strequal(node->name, grp->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100499 LOGVAL(LYE_DUPID,LY_VLOG_LYS, node, "grouping", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200500 return EXIT_FAILURE;
501 }
502 }
503 }
504 }
505 break;
506 case LYS_LEAF:
507 case LYS_LEAFLIST:
508 case LYS_LIST:
509 case LYS_CONTAINER:
510 case LYS_CHOICE:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200511 case LYS_ANYDATA:
Radek Krejci07911992015-08-14 15:13:31 +0200512 /* 6.2.1, rule 7 */
513 if (parent) {
514 iter = parent;
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200515 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_AUGMENT))) {
516 if (iter->nodetype == LYS_AUGMENT) {
517 if (((struct lys_node_augment *)iter)->target) {
518 /* augment is resolved, go up */
519 iter = ((struct lys_node_augment *)iter)->target;
520 continue;
521 }
522 /* augment is not resolved, this is the final parent */
523 break;
524 }
Radek Krejci07911992015-08-14 15:13:31 +0200525 iter = iter->parent;
526 }
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200527
Radek Krejci07911992015-08-14 15:13:31 +0200528 if (!iter) {
529 stop = NULL;
530 iter = module->data;
531 } else {
532 stop = iter;
533 iter = iter->child;
534 }
535 } else {
536 stop = NULL;
537 iter = module->data;
538 }
539 while (iter) {
540 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
541 iter = iter->child;
542 continue;
543 }
544
Radek Krejcibf2abff2016-08-23 15:51:52 +0200545 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYDATA)) {
Radek Krejci749190d2016-02-18 16:26:25 +0100546 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100547 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200548 return EXIT_FAILURE;
549 }
550 }
551
552 /* special case for choice - we must check the choice's name as
553 * well as the names of nodes under the choice
554 */
555 if (iter->nodetype == LYS_CHOICE) {
556 iter = iter->child;
557 continue;
558 }
559
560 /* go to siblings */
561 if (!iter->next) {
562 /* no sibling, go to parent's sibling */
563 do {
Michal Vasko2afc1ca2016-05-03 11:38:53 +0200564 /* for parent LYS_AUGMENT */
565 if (iter->parent == stop) {
566 iter = stop;
567 break;
568 }
569 iter = lys_parent(iter);
Radek Krejci07911992015-08-14 15:13:31 +0200570 if (iter && iter->next) {
571 break;
572 }
573 } while (iter != stop);
574
575 if (iter == stop) {
576 break;
577 }
578 }
579 iter = iter->next;
580 }
581 break;
582 case LYS_CASE:
583 /* 6.2.1, rule 8 */
Radek Krejcic071c542016-01-27 14:57:51 +0100584 if (parent) {
585 start = parent->child;
586 } else {
587 start = module->data;
588 }
589
590 LY_TREE_FOR(start, iter) {
Radek Krejcibf2abff2016-08-23 15:51:52 +0200591 if (!(iter->nodetype & (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Radek Krejci07911992015-08-14 15:13:31 +0200592 continue;
593 }
594
Radek Krejci749190d2016-02-18 16:26:25 +0100595 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100596 LOGVAL(LYE_DUPID, LY_VLOG_LYS, node, "case", node->name);
Radek Krejci07911992015-08-14 15:13:31 +0200597 return EXIT_FAILURE;
598 }
599 }
600 break;
601 default:
602 /* no check needed */
603 break;
604 }
605
606 return EXIT_SUCCESS;
607}
608
Michal Vasko0d343d12015-08-24 14:57:36 +0200609/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200610int
Radek Krejci10c760e2015-08-14 14:45:43 +0200611lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
612{
Radek Krejci92720552015-10-05 15:28:27 +0200613 struct lys_node *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200614 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200615
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200616 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200617
Radek Krejci10c760e2015-08-14 14:45:43 +0200618 if (parent) {
619 type = parent->nodetype;
620 module = parent->module;
621 } else {
622 assert(module);
623 type = 0;
Radek Krejci10c760e2015-08-14 14:45:43 +0200624 }
625
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200626 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200627 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200628 case LYS_CONTAINER:
629 case LYS_LIST:
630 case LYS_GROUPING:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200631 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200632 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Michal Vaskob15cae22016-09-15 09:40:56 +0200633 LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION | LYS_NOTIF))) {
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200634 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
635 return EXIT_FAILURE;
636 }
637 break;
Radek Krejci76512572015-08-04 09:47:08 +0200638 case LYS_USES:
639 case LYS_INPUT:
640 case LYS_OUTPUT:
641 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200642 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200643 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
Radek Krejci76512572015-08-04 09:47:08 +0200644 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100645 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200646 return EXIT_FAILURE;
647 }
648 break;
Radek Krejci76512572015-08-04 09:47:08 +0200649 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200650 if (!(child->nodetype &
Pavol Vican47a1b0a2016-09-20 10:18:24 +0200651 (LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100652 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200653 return EXIT_FAILURE;
654 }
655 break;
Radek Krejci76512572015-08-04 09:47:08 +0200656 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200657 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200658 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100659 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200660 return EXIT_FAILURE;
661 }
662 break;
Radek Krejci76512572015-08-04 09:47:08 +0200663 case LYS_RPC:
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200664 case LYS_ACTION:
Radek Krejci76512572015-08-04 09:47:08 +0200665 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100666 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
Michal Vasko38d01f72015-06-15 09:41:06 +0200667 return EXIT_FAILURE;
668 }
669 break;
Radek Krejci76512572015-08-04 09:47:08 +0200670 case LYS_LEAF:
671 case LYS_LEAFLIST:
672 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200673 case LYS_ANYDATA:
Radek Krejci48464ed2016-03-17 15:44:09 +0100674 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
675 LOGVAL(LYE_SPEC, LY_VLOG_LYS, NULL, "The \"%s\" statement cannot have any data substatement.",
Michal Vasko6ea3e362016-03-11 10:25:36 +0100676 strnodetype(parent->nodetype));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200677 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200678 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200679 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200680 (LYS_ANYDATA | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200681 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100682 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200683 return EXIT_FAILURE;
684 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200685 break;
686 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200687 /* top level */
688 if (!(child->nodetype &
Radek Krejcibf2abff2016-08-23 15:51:52 +0200689 (LYS_ANYDATA | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
Radek Krejci10c760e2015-08-14 14:45:43 +0200690 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100691 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
Radek Krejci10c760e2015-08-14 14:45:43 +0200692 return EXIT_FAILURE;
693 }
694
Radek Krejcic071c542016-01-27 14:57:51 +0100695 break;
Radek Krejci10c760e2015-08-14 14:45:43 +0200696 }
697
698 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200699 if (lys_check_id(child, parent, module)) {
700 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200701 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200702
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200703 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200704 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200705 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200706
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200707 /* connect the child correctly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200708 if (!parent) {
Radek Krejci92720552015-10-05 15:28:27 +0200709 if (module->data) {
710 module->data->prev->next = child;
711 child->prev = module->data->prev;
712 module->data->prev = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200713 } else {
Radek Krejci92720552015-10-05 15:28:27 +0200714 module->data = child;
Radek Krejci10c760e2015-08-14 14:45:43 +0200715 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200716 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +0200717 if (!parent->child) {
718 /* the only/first child of the parent */
719 parent->child = child;
720 child->parent = parent;
721 iter = child;
722 } else {
723 /* add a new child at the end of parent's child list */
724 iter = parent->child->prev;
725 iter->next = child;
726 child->prev = iter;
727 }
728 while (iter->next) {
729 iter = iter->next;
730 iter->parent = parent;
731 }
732 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200733 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200734
Michal Vaskoe022a562016-09-27 14:24:15 +0200735 /* check config value (but ignore them in groupings and augments) */
736 for (iter = parent; iter && !(iter->nodetype & (LYS_GROUPING | LYS_AUGMENT)); iter = iter->parent);
737 if (parent && !iter) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +0200738 for (iter = child; iter && !(iter->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); iter = iter->parent);
739 if (!iter && (parent->flags & LYS_CONFIG_R) && (child->flags & LYS_CONFIG_W)) {
740 LOGVAL(LYE_INARG, LY_VLOG_LYS, child, "true", "config");
741 LOGVAL(LYE_SPEC, LY_VLOG_LYS, child, "State nodes cannot have configuration nodes as children.");
742 return EXIT_FAILURE;
743 }
744 }
745
Radek Krejci41771502016-04-14 17:52:32 +0200746 /* propagate information about status data presence */
Radek Krejcibf2abff2016-08-23 15:51:52 +0200747 if ((child->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)) &&
Radek Krejci41771502016-04-14 17:52:32 +0200748 (child->flags & LYS_INCL_STATUS)) {
Michal Vaskodcf98e62016-05-05 17:53:53 +0200749 for(iter = parent; iter; iter = lys_parent(iter)) {
Radek Krejci41771502016-04-14 17:52:32 +0200750 /* store it only into container or list - the only data inner nodes */
751 if (iter->nodetype & (LYS_CONTAINER | LYS_LIST)) {
752 if (iter->flags & LYS_INCL_STATUS) {
753 /* done, someone else set it already from here */
754 break;
755 }
756 /* set flag about including status data */
757 iter->flags |= LYS_INCL_STATUS;
758 }
759 }
760 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200761 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200762}
763
Radek Krejcia1df1682016-04-11 14:56:59 +0200764static const struct lys_module *
765lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, int internal)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200766{
Radek Krejcia1df1682016-04-11 14:56:59 +0200767 char *enlarged_data = NULL;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200768 struct lys_module *mod = NULL;
Radek Krejcia1df1682016-04-11 14:56:59 +0200769 unsigned int len;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200770
Radek Krejcif347abc2016-06-22 10:18:47 +0200771 ly_errno = LY_SUCCESS;
772
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200773 if (!ctx || !data) {
774 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
775 return NULL;
776 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200777
Radek Krejcia1df1682016-04-11 14:56:59 +0200778 if (!internal && format == LYS_IN_YANG) {
779 /* enlarge data by 2 bytes for flex */
780 len = strlen(data);
781 enlarged_data = malloc((len + 2) * sizeof *enlarged_data);
782 if (!enlarged_data) {
783 LOGMEM;
784 return NULL;
785 }
786 memcpy(enlarged_data, data, len);
787 enlarged_data[len] = enlarged_data[len + 1] = '\0';
788 data = enlarged_data;
789 }
790
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200791 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200792 case LYS_IN_YIN:
Radek Krejciff4874d2016-03-07 12:30:50 +0100793 mod = yin_read_module(ctx, data, NULL, 1);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200794 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200795 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100796 mod = yang_read_module(ctx, data, 0, NULL, 1);
797 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200798 default:
Radek Krejcia1df1682016-04-11 14:56:59 +0200799 LOGERR(LY_EINVAL, "Invalid schema input format.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200800 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200801 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200802
Radek Krejcia1df1682016-04-11 14:56:59 +0200803 free(enlarged_data);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200804 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200805}
806
Radek Krejcia1df1682016-04-11 14:56:59 +0200807API const struct lys_module *
808lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
809{
810 return lys_parse_mem_(ctx, data, format, 0);
811}
812
Michal Vasko5a721fd2016-02-16 12:16:48 +0100813struct lys_submodule *
814lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +0200815{
Michal Vasko5a721fd2016-02-16 12:16:48 +0100816 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200817
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200818 assert(module);
819 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200820
Radek Krejcic071c542016-01-27 14:57:51 +0100821 /* get the main module */
Radek Krejcic4283442016-04-22 09:19:27 +0200822 module = lys_main_module(module);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200823
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200824 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200825 case LYS_IN_YIN:
Michal Vasko5a721fd2016-02-16 12:16:48 +0100826 submod = yin_read_submodule(module, data, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200827 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200828 case LYS_IN_YANG:
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100829 submod = yang_read_submodule(module, data, 0, unres);
830 break;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200831 default:
Radek Krejci90a550a2016-04-13 16:00:58 +0200832 assert(0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200833 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200834 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200835
Michal Vasko5a721fd2016-02-16 12:16:48 +0100836 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +0200837}
838
Michal Vasko1e62a092015-12-01 12:27:20 +0100839API const struct lys_module *
Michal Vasko662610a2015-12-07 11:25:45 +0100840lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
841{
842 int fd;
843 const struct lys_module *ret;
844
845 if (!ctx || !path) {
846 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
847 return NULL;
848 }
849
850 fd = open(path, O_RDONLY);
851 if (fd == -1) {
852 LOGERR(LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno));
853 return NULL;
854 }
855
856 ret = lys_parse_fd(ctx, fd, format);
857 close(fd);
Radek Krejci23f5de52016-02-25 15:53:17 +0100858
Radek Krejcia77904e2016-02-25 16:23:45 +0100859 if (ret && !ret->filepath) {
Radek Krejci23f5de52016-02-25 15:53:17 +0100860 /* store URI */
Radek Krejcia77904e2016-02-25 16:23:45 +0100861 ((struct lys_module *)ret)->filepath = lydict_insert(ctx, path, 0);
Radek Krejci23f5de52016-02-25 15:53:17 +0100862 }
863
Michal Vasko662610a2015-12-07 11:25:45 +0100864 return ret;
865}
866
867API const struct lys_module *
868lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +0200869{
Michal Vasko1e62a092015-12-01 12:27:20 +0100870 const struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +0200871 struct stat sb;
872 char *addr;
Radek Krejcib051f722016-02-25 15:12:21 +0100873 char buf[PATH_MAX];
874 int len;
Radek Krejci63a91a92015-07-29 13:31:04 +0200875
876 if (!ctx || fd < 0) {
877 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
878 return NULL;
879 }
880
Radek Krejci10a833c2015-12-16 15:28:37 +0100881 if (fstat(fd, &sb) == -1) {
882 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
883 return NULL;
884 }
Radek Krejcib051f722016-02-25 15:12:21 +0100885 if (!S_ISREG(sb.st_mode)) {
886 LOGERR(LY_EINVAL, "Invalid parameter, input file is not a regular file");
887 return NULL;
888 }
889
Michal Vasko164d9012016-04-01 10:16:59 +0200890 if (!sb.st_size) {
891 LOGERR(LY_EINVAL, "File empty.");
892 return NULL;
893 }
894
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100895 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +0100896 if (addr == MAP_FAILED) {
Michal Vasko662610a2015-12-07 11:25:45 +0100897 LOGERR(LY_EMEM, "Map file into memory failed (%s()).",__func__);
Pavol Vicane36ea262015-11-12 11:57:47 +0100898 return NULL;
899 }
Radek Krejcia1df1682016-04-11 14:56:59 +0200900 module = lys_parse_mem_(ctx, addr, format, 1);
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100901 munmap(addr, sb.st_size + 2);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200902
Radek Krejcia77904e2016-02-25 16:23:45 +0100903 if (module && !module->filepath) {
Radek Krejcib051f722016-02-25 15:12:21 +0100904 /* get URI if there is /proc */
905 addr = NULL;
Radek Krejci15412ca2016-03-03 11:16:52 +0100906 if (asprintf(&addr, "/proc/self/fd/%d", fd) != -1) {
907 if ((len = readlink(addr, buf, PATH_MAX - 1)) > 0) {
908 ((struct lys_module *)module)->filepath = lydict_insert(ctx, buf, len);
909 }
910 free(addr);
Radek Krejcib051f722016-02-25 15:12:21 +0100911 }
Radek Krejcib051f722016-02-25 15:12:21 +0100912 }
913
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200914 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200915}
916
Michal Vasko5a721fd2016-02-16 12:16:48 +0100917struct lys_submodule *
918lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +0200919{
Michal Vasko5a721fd2016-02-16 12:16:48 +0100920 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200921 struct stat sb;
922 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +0200923
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200924 assert(module);
925 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +0200926
Radek Krejci10a833c2015-12-16 15:28:37 +0100927 if (fstat(fd, &sb) == -1) {
928 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
Michal Vasko5a721fd2016-02-16 12:16:48 +0100929 return NULL;
Radek Krejci10a833c2015-12-16 15:28:37 +0100930 }
Michal Vasko164d9012016-04-01 10:16:59 +0200931
932 if (!sb.st_size) {
933 LOGERR(LY_EINVAL, "File empty.");
934 return NULL;
935 }
936
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100937 addr = mmap(NULL, sb.st_size + 2, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
Pavol Vicane36ea262015-11-12 11:57:47 +0100938 if (addr == MAP_FAILED) {
939 LOGERR(LY_EMEM,"Map file into memory failed (%s()).",__func__);
Michal Vasko5a721fd2016-02-16 12:16:48 +0100940 return NULL;
Pavol Vicane36ea262015-11-12 11:57:47 +0100941 }
Michal Vasko5a721fd2016-02-16 12:16:48 +0100942 submodule = lys_submodule_parse(module, addr, format, unres);
Pavol Vicanf7cc2852016-03-22 23:27:35 +0100943 munmap(addr, sb.st_size + 2);
Radek Krejciefaeba32015-05-27 14:30:57 +0200944
Michal Vasko5a721fd2016-02-16 12:16:48 +0100945 return submodule;
946
Radek Krejciefaeba32015-05-27 14:30:57 +0200947}
948
Radek Krejci1d82ef62015-08-07 14:44:40 +0200949static struct lys_restr *
950lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200951{
Radek Krejci1574a8d2015-08-03 14:16:52 +0200952 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200953 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200954
Radek Krejci3733a802015-06-19 13:43:21 +0200955 if (!size) {
956 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200957 }
Radek Krejci3733a802015-06-19 13:43:21 +0200958
959 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +0100960 if (!result) {
Radek Krejciaa2a8932016-02-17 15:03:14 +0100961 LOGMEM;
Michal Vasko253035f2015-12-17 16:58:13 +0100962 return NULL;
963 }
Radek Krejci3733a802015-06-19 13:43:21 +0200964 for (i = 0; i < size; i++) {
965 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
966 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
967 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
968 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
969 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
970 }
971
972 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200973}
974
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200975void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200976lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +0200977{
978 assert(ctx);
979 if (!restr) {
980 return;
981 }
982
983 lydict_remove(ctx, restr->expr);
984 lydict_remove(ctx, restr->dsc);
985 lydict_remove(ctx, restr->ref);
986 lydict_remove(ctx, restr->eapptag);
987 lydict_remove(ctx, restr->emsg);
988}
989
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200990static void
991lys_iffeature_free(struct lys_iffeature *iffeature, uint8_t iffeature_size)
992{
993 uint8_t i;
994
995 for (i = 0; i < iffeature_size; ++i) {
996 free(iffeature[i].expr);
997 free(iffeature[i].features);
998 }
999 free(iffeature);
1000}
1001
Michal Vaskob84f88a2015-09-24 13:16:10 +02001002static int
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001003type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci3a5501d2016-07-18 22:03:34 +02001004 LY_DATA_TYPE base, int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001005{
1006 int i;
1007
1008 switch (base) {
1009 case LY_TYPE_BINARY:
1010 if (old->info.binary.length) {
1011 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
1012 }
1013 break;
1014
1015 case LY_TYPE_BITS:
1016 new->info.bits.count = old->info.bits.count;
1017 if (new->info.bits.count) {
1018 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1019 if (!new->info.bits.bit) {
1020 LOGMEM;
1021 return -1;
1022 }
1023 for (i = 0; i < new->info.bits.count; i++) {
1024 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1025 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1026 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
1027 new->info.bits.bit[i].flags = old->info.bits.bit[i].flags;
1028 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1029 }
1030 }
1031 break;
1032
1033 case LY_TYPE_DEC64:
1034 new->info.dec64.dig = old->info.dec64.dig;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001035 new->info.dec64.div = old->info.dec64.div;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001036 if (old->info.dec64.range) {
1037 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
1038 }
1039 break;
1040
1041 case LY_TYPE_ENUM:
1042 new->info.enums.count = old->info.enums.count;
1043 if (new->info.enums.count) {
1044 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
1045 if (!new->info.enums.enm) {
1046 LOGMEM;
1047 return -1;
1048 }
1049 for (i = 0; i < new->info.enums.count; i++) {
1050 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1051 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1052 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1053 new->info.enums.enm[i].flags = old->info.enums.enm[i].flags;
1054 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
1055 }
1056 }
1057 break;
1058
1059 case LY_TYPE_IDENT:
Michal Vaskoaffc37f2016-10-10 18:05:03 +00001060 new->info.ident.count = old->info.ident.count;
Michal Vasko878e38d2016-09-05 12:17:53 +02001061 if (old->info.ident.count) {
1062 new->info.ident.ref = malloc(old->info.ident.count * sizeof *new->info.ident.ref);
1063 if (!new->info.ident.ref) {
1064 LOGMEM;
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001065 return -1;
1066 }
Michal Vasko878e38d2016-09-05 12:17:53 +02001067 memcpy(new->info.ident.ref, old->info.ident.ref, old->info.ident.count * sizeof *new->info.ident.ref);
1068 } else {
1069 /* there can be several unresolved base identities, duplicate them all */
1070 i = -1;
1071 while ((i = unres_schema_find(unres, i, old, UNRES_TYPE_IDENTREF)) != -1) {
1072 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i]) == -1) {
1073 return -1;
1074 }
1075 --i;
1076 }
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001077 }
1078 break;
1079
1080 case LY_TYPE_INST:
1081 new->info.inst.req = old->info.inst.req;
1082 break;
1083
1084 case LY_TYPE_INT8:
1085 case LY_TYPE_INT16:
1086 case LY_TYPE_INT32:
1087 case LY_TYPE_INT64:
1088 case LY_TYPE_UINT8:
1089 case LY_TYPE_UINT16:
1090 case LY_TYPE_UINT32:
1091 case LY_TYPE_UINT64:
1092 if (old->info.num.range) {
1093 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
1094 }
1095 break;
1096
1097 case LY_TYPE_LEAFREF:
1098 if (old->info.lref.path) {
1099 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko5d631402016-07-21 13:15:15 +02001100 if (!tpdftype && unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001101 return -1;
1102 }
1103 }
1104 break;
1105
1106 case LY_TYPE_STRING:
1107 if (old->info.str.length) {
1108 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
1109 }
1110 new->info.str.patterns = lys_restr_dup(mod->ctx, old->info.str.patterns, old->info.str.pat_count);
1111 new->info.str.pat_count = old->info.str.pat_count;
1112 break;
1113
1114 case LY_TYPE_UNION:
1115 new->info.uni.count = old->info.uni.count;
1116 if (new->info.uni.count) {
1117 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
1118 if (!new->info.uni.types) {
1119 LOGMEM;
1120 return -1;
1121 }
1122 for (i = 0; i < new->info.uni.count; i++) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001123 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), tpdftype, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001124 return -1;
1125 }
1126 }
1127 }
1128 break;
1129
1130 default:
1131 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
1132 break;
1133 }
1134 return EXIT_SUCCESS;
1135}
1136
1137struct yang_type *
Radek Krejci3a5501d2016-07-18 22:03:34 +02001138lys_yang_type_dup(struct lys_module *module, struct lys_node *parent, struct yang_type *old, struct lys_type *type,
1139 int tpdftype, struct unres_schema *unres)
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001140{
1141 struct yang_type *new;
1142
1143 new = calloc(1, sizeof *new);
1144 if (!new) {
1145 LOGMEM;
1146 return NULL;
1147 }
1148 new->flags = old->flags;
1149 new->base = old->base;
Pavol Vican66586292016-04-07 11:38:52 +02001150 new->name = lydict_insert(module->ctx, old->name, 0);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001151 new->type = type;
1152 if (!new->name) {
1153 LOGMEM;
1154 goto error;
1155 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001156 if (type_dup(module, parent, type, old->type, new->base, tpdftype, unres)) {
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001157 new->type->base = new->base;
1158 lys_type_free(module->ctx, new->type);
1159 memset(&new->type->info, 0, sizeof new->type->info);
1160 goto error;
1161 }
1162 return new;
1163
1164 error:
1165 free(new);
1166 return NULL;
1167}
1168
1169static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001170lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Radek Krejci3a5501d2016-07-18 22:03:34 +02001171 int tpdftype, struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001172{
1173 int i;
1174
Michal Vasko1dca6882015-10-22 14:29:42 +02001175 new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001176 new->base = old->base;
1177 new->der = old->der;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001178 new->parent = (struct lys_tpdf *)parent;
Radek Krejci3733a802015-06-19 13:43:21 +02001179
Michal Vasko878e38d2016-09-05 12:17:53 +02001180 i = unres_schema_find(unres, -1, old, tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001181 if (i != -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01001182 /* HACK (serious one) for unres */
1183 /* nothing else we can do but duplicate it immediately */
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001184 if (((struct lyxml_elem *)old->der)->flags & LY_YANG_STRUCTURE_FLAG) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001185 new->der = (struct lys_tpdf *)lys_yang_type_dup(mod, parent, (struct yang_type *)old->der, new, tpdftype, unres);
Pavol Vicanacb9d0d2016-04-04 13:57:23 +02001186 } else {
1187 new->der = (struct lys_tpdf *)lyxml_dup_elem(mod->ctx, (struct lyxml_elem *)old->der, NULL, 1);
1188 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001189 /* all these unres additions can fail even though they did not before */
Radek Krejci3a5501d2016-07-18 22:03:34 +02001190 if (!new->der || unres_schema_add_node(mod, unres, new,
Michal Vasko5d631402016-07-21 13:15:15 +02001191 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001192 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001193 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001194 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001195 }
1196
Radek Krejci3a5501d2016-07-18 22:03:34 +02001197 return type_dup(mod, parent, new, old, new->base, tpdftype, unres);
Radek Krejci3733a802015-06-19 13:43:21 +02001198}
1199
1200void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001201lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001202{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001203 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001204
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001205 assert(ctx);
1206 if (!type) {
1207 return;
1208 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001209
Michal Vasko1dca6882015-10-22 14:29:42 +02001210 lydict_remove(ctx, type->module_name);
Radek Krejci5a065542015-05-22 15:02:07 +02001211
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001212 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001213 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001214 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001215 free(type->info.binary.length);
1216 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001217 case LY_TYPE_BITS:
1218 for (i = 0; i < type->info.bits.count; i++) {
1219 lydict_remove(ctx, type->info.bits.bit[i].name);
1220 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1221 lydict_remove(ctx, type->info.bits.bit[i].ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001222 lys_iffeature_free(type->info.bits.bit[i].iffeature, type->info.bits.bit[i].iffeature_size);
Radek Krejci994b6f62015-06-18 16:47:27 +02001223 }
1224 free(type->info.bits.bit);
1225 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001226
1227 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001228 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001229 free(type->info.dec64.range);
1230 break;
1231
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001232 case LY_TYPE_ENUM:
1233 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001234 lydict_remove(ctx, type->info.enums.enm[i].name);
1235 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1236 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001237 lys_iffeature_free(type->info.enums.enm[i].iffeature, type->info.enums.enm[i].iffeature_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001238 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001239 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001240 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001241
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001242 case LY_TYPE_INT8:
1243 case LY_TYPE_INT16:
1244 case LY_TYPE_INT32:
1245 case LY_TYPE_INT64:
1246 case LY_TYPE_UINT8:
1247 case LY_TYPE_UINT16:
1248 case LY_TYPE_UINT32:
1249 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001250 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001251 free(type->info.num.range);
1252 break;
1253
Radek Krejcidc4c1412015-06-19 15:39:54 +02001254 case LY_TYPE_LEAFREF:
1255 lydict_remove(ctx, type->info.lref.path);
1256 break;
1257
Radek Krejci3733a802015-06-19 13:43:21 +02001258 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001259 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001260 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001261 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001262 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001263 }
1264 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001265 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001266
Radek Krejcie4c366b2015-07-02 10:11:31 +02001267 case LY_TYPE_UNION:
1268 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001269 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001270 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001271 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001272 break;
1273
Michal Vaskod3282192016-09-05 11:27:57 +02001274 case LY_TYPE_IDENT:
1275 free(type->info.ident.ref);
1276 break;
1277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001278 default:
Michal Vaskod3282192016-09-05 11:27:57 +02001279 /* nothing to do for LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001280 break;
1281 }
Radek Krejci5a065542015-05-22 15:02:07 +02001282}
1283
Radek Krejci1d82ef62015-08-07 14:44:40 +02001284static void
1285lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001286{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001287 assert(ctx);
1288 if (!tpdf) {
1289 return;
1290 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001291
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001292 lydict_remove(ctx, tpdf->name);
1293 lydict_remove(ctx, tpdf->dsc);
1294 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001295
Radek Krejci1d82ef62015-08-07 14:44:40 +02001296 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001298 lydict_remove(ctx, tpdf->units);
1299 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001300}
1301
Michal Vaskob84f88a2015-09-24 13:16:10 +02001302static struct lys_tpdf *
1303lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1304{
1305 struct lys_tpdf *result;
1306 int i, j;
1307
1308 if (!size) {
1309 return NULL;
1310 }
1311
1312 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001313 if (!result) {
1314 LOGMEM;
1315 return NULL;
1316 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001317 for (i = 0; i < size; i++) {
1318 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1319 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1320 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1321 result[i].flags = old[i].flags;
1322 result[i].module = old[i].module;
1323
Radek Krejci3a5501d2016-07-18 22:03:34 +02001324 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), 1, unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001325 for (j = 0; j <= i; ++j) {
1326 lys_tpdf_free(mod->ctx, &result[j]);
1327 }
1328 free(result);
1329 return NULL;
1330 }
1331
1332 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1333 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1334 }
1335
1336 return result;
1337}
1338
Radek Krejci1d82ef62015-08-07 14:44:40 +02001339static struct lys_when *
1340lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001341{
Radek Krejci76512572015-08-04 09:47:08 +02001342 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001343
1344 if (!old) {
1345 return NULL;
1346 }
1347
1348 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001349 if (!new) {
1350 LOGMEM;
1351 return NULL;
1352 }
Radek Krejci00768f42015-06-18 17:04:04 +02001353 new->cond = lydict_insert(ctx, old->cond, 0);
1354 new->dsc = lydict_insert(ctx, old->dsc, 0);
1355 new->ref = lydict_insert(ctx, old->ref, 0);
1356
1357 return new;
1358}
1359
Michal Vasko0308dd62015-10-07 09:14:40 +02001360void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001361lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001362{
1363 if (!w) {
1364 return;
1365 }
1366
1367 lydict_remove(ctx, w->cond);
1368 lydict_remove(ctx, w->dsc);
1369 lydict_remove(ctx, w->ref);
1370
1371 free(w);
1372}
1373
Radek Krejcib7f5e412015-08-13 10:15:51 +02001374static void
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001375lys_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 +02001376{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001377 struct lys_node *next, *sub;
1378
Radek Krejcic071c542016-01-27 14:57:51 +01001379 /* children from a resolved augment are freed under the target node */
Michal Vaskod2fbade2016-05-02 17:14:00 +02001380 if (!aug->target) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001381 LY_TREE_FOR_SAFE(aug->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001382 lys_node_free(sub, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001383 }
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001384 }
1385
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001386 lydict_remove(ctx, aug->target_name);
1387 lydict_remove(ctx, aug->dsc);
1388 lydict_remove(ctx, aug->ref);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001389
Radek Krejci9ff0a922016-07-14 13:08:05 +02001390 lys_iffeature_free(aug->iffeature, aug->iffeature_size);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001391
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001392 lys_when_free(ctx, aug->when);
Radek Krejcib7f5e412015-08-13 10:15:51 +02001393}
1394
Radek Krejci76512572015-08-04 09:47:08 +02001395static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001396lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001397{
Radek Krejci76512572015-08-04 09:47:08 +02001398 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001399 struct lys_node *old_child, *new_child;
1400 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001401
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001402 if (!size) {
1403 return NULL;
1404 }
Radek Krejci106efc02015-06-10 14:36:27 +02001405
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001406 new = calloc(size, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001407 if (!new) {
1408 LOGMEM;
1409 return NULL;
1410 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001411 for (i = 0; i < size; i++) {
1412 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1413 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1414 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1415 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001416 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001417 new[i].nodetype = old[i].nodetype;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001418
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001419 /* this must succeed, it was already resolved once */
Michal Vasko3edeaf72016-02-11 13:17:43 +01001420 if (resolve_augment_schema_nodeid(new[i].target_name, parent->child, NULL,
1421 (const struct lys_node **)&new[i].target)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001422 LOGINT;
1423 free(new);
1424 return NULL;
1425 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001426 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001427
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001428 /* Correct the augment nodes.
1429 * This function can only be called from lys_node_dup() with uses
1430 * being the node duplicated, so we must have a case of grouping
1431 * with a uses with augments. The augmented nodes have already been
1432 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001433 * (it was set to their actual data parent, not an augment), and
1434 * the new augment does not have child pointer to its augment nodes,
1435 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001436 */
1437 LY_TREE_FOR(new[i].target->child, new_child) {
Radek Krejci749190d2016-02-18 16:26:25 +01001438 if (ly_strequal(new_child->name, old[i].child->name, 1)) {
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001439 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001440 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001441 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001442 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001443 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001444 LY_TREE_FOR(old[i].child, old_child) {
1445 /* all augment nodes were connected as siblings, there can be no more after this */
1446 if (old_child->parent != (struct lys_node *)&old[i]) {
1447 break;
1448 }
1449
Radek Krejci749190d2016-02-18 16:26:25 +01001450 assert(ly_strequal(old_child->name, new_child->name, 1));
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001451
1452 new_child->parent = (struct lys_node *)&new[i];
1453 new_child = new_child->next;
1454 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001455 }
Radek Krejci106efc02015-06-10 14:36:27 +02001456
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001457 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001458}
1459
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001460static const char **
1461lys_dflt_dup(struct ly_ctx *ctx, const char **old, int size)
1462{
1463 int i;
1464 const char **result;
1465
1466 if (!size) {
1467 return NULL;
1468 }
1469
1470 result = calloc(size, sizeof *result);
1471 if (!result) {
1472 LOGMEM;
1473 return NULL;
1474 }
1475
1476 for (i = 0; i < size; i++) {
1477 result[i] = lydict_insert(ctx, old[i], 0);
1478 }
1479 return result;
1480}
1481
Radek Krejci76512572015-08-04 09:47:08 +02001482static struct lys_refine *
Michal Vasko0d204592015-10-07 09:50:04 +02001483lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001484{
Radek Krejci76512572015-08-04 09:47:08 +02001485 struct lys_refine *result;
Michal Vasko0d204592015-10-07 09:50:04 +02001486 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001487
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001488 if (!size) {
1489 return NULL;
1490 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001491
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001492 result = calloc(size, sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01001493 if (!result) {
1494 LOGMEM;
1495 return NULL;
1496 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001497 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001498 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001499 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1500 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001501 result[i].flags = old[i].flags;
1502 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001503
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001504 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001505 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001506
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001507 result[i].dflt_size = old[i].dflt_size;
1508 result[i].dflt = lys_dflt_dup(mod->ctx, old[i].dflt, old[i].dflt_size);
1509
1510 if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001511 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001512 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001513 result[i].mod.list = old[i].mod.list;
1514 }
1515 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001516
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001517 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001518}
1519
Radek Krejci1d82ef62015-08-07 14:44:40 +02001520static void
1521lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001522{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001523 assert(ctx);
1524 if (!ident) {
1525 return;
1526 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001527
Radek Krejci018f1f52016-08-03 16:01:20 +02001528 free(ident->base);
Radek Krejci1b61d0e2016-04-15 13:55:44 +02001529 free(ident->der);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001530 lydict_remove(ctx, ident->name);
1531 lydict_remove(ctx, ident->dsc);
1532 lydict_remove(ctx, ident->ref);
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001533 lys_iffeature_free(ident->iffeature, ident->iffeature_size);
Radek Krejci6793db02015-05-22 17:49:54 +02001534
1535}
1536
Radek Krejci1d82ef62015-08-07 14:44:40 +02001537static void
1538lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001539{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001540 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001541
Radek Krejcid12f57b2015-08-06 10:43:39 +02001542 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001543 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001544 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001545 }
1546 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001547}
1548
Radek Krejci1d82ef62015-08-07 14:44:40 +02001549static void
Michal Vasko44fb6382016-06-29 11:12:27 +02001550lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io)
Radek Krejcid12f57b2015-08-06 10:43:39 +02001551{
1552 int i;
1553
1554 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1555 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001556 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001557 }
1558 free(io->tpdf);
Pavol Vican7cff97e2016-08-09 14:56:08 +02001559
1560 for (i = 0; i < io->must_size; i++) {
1561 lys_restr_free(ctx, &io->must[i]);
1562 }
1563 free(io->must);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001564}
1565
Radek Krejci1d82ef62015-08-07 14:44:40 +02001566static void
Pavol Vican7cff97e2016-08-09 14:56:08 +02001567lys_notif_free(struct ly_ctx *ctx, struct lys_node_notif *notif)
1568{
1569 int i;
1570
1571 for (i = 0; i < notif->must_size; i++) {
1572 lys_restr_free(ctx, &notif->must[i]);
1573 }
1574 free(notif->must);
1575
1576 for (i = 0; i < notif->tpdf_size; i++) {
1577 lys_tpdf_free(ctx, &notif->tpdf[i]);
1578 }
1579 free(notif->tpdf);
1580}
1581static void
Radek Krejcibf2abff2016-08-23 15:51:52 +02001582lys_anydata_free(struct ly_ctx *ctx, struct lys_node_anydata *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001583{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001584 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001585
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001586 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001587 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001588 }
1589 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001590
Radek Krejci1d82ef62015-08-07 14:44:40 +02001591 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001592}
1593
Radek Krejci1d82ef62015-08-07 14:44:40 +02001594static void
1595lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001596{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001597 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001598
Radek Krejci46c4cd72016-01-21 15:13:52 +01001599 if (leaf->child) {
1600 /* leafref backlinks */
1601 ly_set_free((struct ly_set *)leaf->child);
1602 }
1603
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001604 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001605 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001606 }
1607 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001608
Radek Krejci1d82ef62015-08-07 14:44:40 +02001609 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001610
Radek Krejci1d82ef62015-08-07 14:44:40 +02001611 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001612 lydict_remove(ctx, leaf->units);
1613 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001614}
1615
Radek Krejci1d82ef62015-08-07 14:44:40 +02001616static void
1617lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001618{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001619 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001620
Radek Krejci46c4cd72016-01-21 15:13:52 +01001621 if (llist->child) {
1622 /* leafref backlinks */
1623 ly_set_free((struct ly_set *)llist->child);
1624 }
1625
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001626 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001627 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001628 }
1629 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001630
Pavol Vican38321d02016-08-16 14:56:02 +02001631 for (i = 0; i < llist->dflt_size; i++) {
1632 lydict_remove(ctx, llist->dflt[i]);
1633 }
1634 free(llist->dflt);
1635
Radek Krejci1d82ef62015-08-07 14:44:40 +02001636 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001637
Radek Krejci1d82ef62015-08-07 14:44:40 +02001638 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001639 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001640}
1641
Radek Krejci1d82ef62015-08-07 14:44:40 +02001642static void
1643lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001644{
Radek Krejci581ce772015-11-10 17:22:40 +01001645 int i, j;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001646
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001647 /* handle only specific parts for LY_NODE_LIST */
1648 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001649 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001650 }
1651 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001652
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001653 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001654 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001655 }
1656 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001657
Radek Krejci1d82ef62015-08-07 14:44:40 +02001658 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001659
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001660 for (i = 0; i < list->unique_size; i++) {
Michal Vaskof5e940a2016-06-07 09:39:26 +02001661 for (j = 0; j < list->unique[i].expr_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001662 lydict_remove(ctx, list->unique[i].expr[j]);
1663 }
1664 free(list->unique[i].expr);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001665 }
1666 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001667
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001668 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001669}
1670
Radek Krejci1d82ef62015-08-07 14:44:40 +02001671static void
1672lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001673{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001674 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001675
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001676 /* handle only specific parts for LY_NODE_CONTAINER */
1677 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001678
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001679 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001680 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001681 }
1682 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001683
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001684 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001685 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001686 }
1687 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001688
Radek Krejci1d82ef62015-08-07 14:44:40 +02001689 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001690}
1691
Radek Krejci1d82ef62015-08-07 14:44:40 +02001692static void
1693lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001694{
1695 lydict_remove(ctx, f->name);
1696 lydict_remove(ctx, f->dsc);
1697 lydict_remove(ctx, f->ref);
Radek Krejci9ff0a922016-07-14 13:08:05 +02001698 lys_iffeature_free(f->iffeature, f->iffeature_size);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001699}
1700
Radek Krejci1d82ef62015-08-07 14:44:40 +02001701static void
Michal Vaskoff006c12016-02-17 11:15:19 +01001702lys_deviation_free(struct lys_module *module, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001703{
Radek Krejci581ce772015-11-10 17:22:40 +01001704 int i, j, k;
Michal Vaskoff006c12016-02-17 11:15:19 +01001705 struct ly_ctx *ctx;
1706 struct lys_node *next, *elem;
1707
1708 ctx = module->ctx;
Radek Krejcieb00f512015-07-01 16:44:58 +02001709
1710 lydict_remove(ctx, dev->target_name);
1711 lydict_remove(ctx, dev->dsc);
1712 lydict_remove(ctx, dev->ref);
1713
Pavol Vican64d0b762016-08-25 10:44:59 +02001714 if (!dev->deviate) {
1715 return ;
1716 }
1717
Michal Vaskoff006c12016-02-17 11:15:19 +01001718 /* the module was freed, but we only need the context from orig_node, use ours */
1719 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
1720 /* it's actually a node subtree, we need to update modules on all the nodes :-/ */
1721 LY_TREE_DFS_BEGIN(dev->orig_node, next, elem) {
1722 elem->module = module;
1723
1724 LY_TREE_DFS_END(dev->orig_node, next, elem);
1725 }
1726 lys_node_free(dev->orig_node, NULL, 0);
1727 } else {
1728 /* it's just a shallow copy, freeing one node */
1729 dev->orig_node->module = module;
1730 lys_node_free(dev->orig_node, NULL, 1);
1731 }
1732
Radek Krejcieb00f512015-07-01 16:44:58 +02001733 for (i = 0; i < dev->deviate_size; i++) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02001734 for (j = 0; j < dev->deviate[i].dflt_size; j++) {
Pavol Vican38321d02016-08-16 14:56:02 +02001735 lydict_remove(ctx, dev->deviate[i].dflt[j]);
Radek Krejcid5a5c282016-08-15 15:38:08 +02001736 }
1737 free(dev->deviate[i].dflt);
1738
Radek Krejcieb00f512015-07-01 16:44:58 +02001739 lydict_remove(ctx, dev->deviate[i].units);
1740
1741 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1742 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001743 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001744 }
1745 free(dev->deviate[i].must);
1746
1747 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001748 for (k = 0; k < dev->deviate[i].unique[j].expr_size; k++) {
1749 lydict_remove(ctx, dev->deviate[i].unique[j].expr[k]);
1750 }
Michal Vasko0238ccf2016-03-07 15:02:18 +01001751 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001752 }
1753 free(dev->deviate[i].unique);
1754 }
1755 }
1756 free(dev->deviate);
1757}
1758
Radek Krejci1d82ef62015-08-07 14:44:40 +02001759static void
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001760lys_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 +02001761{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001762 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001763
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001764 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001765 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001766 lydict_remove(ctx, uses->refine[i].dsc);
1767 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001768
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001769 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001770 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001771 }
1772 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001773
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001774 for (j = 0; j < uses->refine[i].dflt_size; j++) {
Pavol Vican855ca622016-09-05 13:07:54 +02001775 lydict_remove(ctx, uses->refine[i].dflt[j]);
Pavol Vican3e7c73a2016-08-17 10:24:11 +02001776 }
1777 free(uses->refine[i].dflt);
1778
1779 if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001780 lydict_remove(ctx, uses->refine[i].mod.presence);
1781 }
1782 }
1783 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001784
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001785 for (i = 0; i < uses->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001786 lys_augment_free(ctx, &uses->augment[i], private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001787 }
1788 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001789
Radek Krejci1d82ef62015-08-07 14:44:40 +02001790 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001791}
1792
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001793void
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001794lys_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 +02001795{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001796 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001797 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001798
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001799 if (!node) {
1800 return;
1801 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001802
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001803 assert(node->module);
1804 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001805
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001806 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001807
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001808 /* remove private object */
Mislav Novakovicb5529e52016-02-29 11:42:43 +01001809 if (node->priv && private_destructor) {
1810 private_destructor(node, node->priv);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001811 }
1812
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001813 /* common part */
Michal Vasko0a1aaa42016-04-19 09:48:25 +02001814 lydict_remove(ctx, node->name);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001815 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02001816 lys_iffeature_free(node->iffeature, node->iffeature_size);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001817 lydict_remove(ctx, node->dsc);
1818 lydict_remove(ctx, node->ref);
1819 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001820
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001821 if (!shallow && !(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Radek Krejci46c4cd72016-01-21 15:13:52 +01001822 LY_TREE_FOR_SAFE(node->child, next, sub) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001823 lys_node_free(sub, private_destructor, 0);
Radek Krejci46c4cd72016-01-21 15:13:52 +01001824 }
1825 }
1826
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001827 /* specific part */
1828 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001829 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001830 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001831 break;
Radek Krejci76512572015-08-04 09:47:08 +02001832 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001833 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001834 break;
Radek Krejci76512572015-08-04 09:47:08 +02001835 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001836 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001837 break;
Radek Krejci76512572015-08-04 09:47:08 +02001838 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001839 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001840 break;
Radek Krejci76512572015-08-04 09:47:08 +02001841 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001842 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001843 break;
Radek Krejci76512572015-08-04 09:47:08 +02001844 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02001845 case LYS_ANYDATA:
1846 lys_anydata_free(ctx, (struct lys_node_anydata *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001847 break;
Radek Krejci76512572015-08-04 09:47:08 +02001848 case LYS_USES:
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001849 lys_uses_free(ctx, (struct lys_node_uses *)node, private_destructor);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001850 break;
Radek Krejci76512572015-08-04 09:47:08 +02001851 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001852 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001853 break;
Radek Krejci76512572015-08-04 09:47:08 +02001854 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001855 /* do nothing */
1856 break;
Radek Krejci76512572015-08-04 09:47:08 +02001857 case LYS_GROUPING:
1858 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02001859 case LYS_ACTION:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001860 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001861 break;
Pavol Vican7cff97e2016-08-09 14:56:08 +02001862 case LYS_NOTIF:
1863 lys_notif_free(ctx, (struct lys_node_notif *)node);
1864 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001865 case LYS_INPUT:
1866 case LYS_OUTPUT:
Michal Vasko44fb6382016-06-29 11:12:27 +02001867 lys_inout_free(ctx, (struct lys_node_inout *)node);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001868 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001869 case LYS_UNKNOWN:
1870 LOGINT;
1871 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001872 }
Radek Krejci5a065542015-05-22 15:02:07 +02001873
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001874 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001875 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001876 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001877}
1878
Michal Vasko1e62a092015-12-01 12:27:20 +01001879const struct lys_module *
Radek Krejci0fa54e92016-09-14 14:01:05 +02001880lys_get_implemented_module(const struct lys_module *mod)
1881{
1882 struct ly_ctx *ctx;
1883 int i;
1884
1885 if (!mod || mod->implemented) {
1886 /* invalid argument or the module itself is implemented */
1887 return mod;
1888 }
1889
1890 ctx = mod->ctx;
1891 for (i = 0; i < ctx->models.used; i++) {
1892 if (!ctx->models.list[i]->implemented) {
1893 continue;
1894 }
1895
1896 if (ly_strequal(mod->name, ctx->models.list[i]->name, 1)) {
1897 /* we have some revision of the module implemented */
1898 return ctx->models.list[i];
1899 }
1900 }
1901
1902 /* we have no revision of the module implemented, return the module itself,
1903 * it is up to the caller to set the module implemented when needed */
1904 return mod;
1905}
1906
1907const struct lys_module *
Michal Vasko1e62a092015-12-01 12:27:20 +01001908lys_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 +02001909{
Radek Krejcic071c542016-01-27 14:57:51 +01001910 const struct lys_module *main_module;
Michal Vasko89563fc2016-07-28 16:19:35 +02001911 char *str;
Michal Vasko3edeaf72016-02-11 13:17:43 +01001912 int i;
Michal Vaskob6729c62015-10-21 12:09:47 +02001913
Michal Vaskoa7789a82016-02-11 15:42:55 +01001914 assert(!prefix || !name);
1915
Michal Vaskob6729c62015-10-21 12:09:47 +02001916 if (prefix && !pref_len) {
1917 pref_len = strlen(prefix);
1918 }
1919 if (name && !name_len) {
1920 name_len = strlen(name);
1921 }
Michal Vasko8ce24d72015-10-21 11:27:26 +02001922
Radek Krejcic4283442016-04-22 09:19:27 +02001923 main_module = lys_main_module(module);
Michal Vaskoa7789a82016-02-11 15:42:55 +01001924
1925 /* module own prefix, submodule own prefix, (sub)module own name */
1926 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
1927 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
Michal Vasko3edeaf72016-02-11 13:17:43 +01001928 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
Radek Krejcic071c542016-01-27 14:57:51 +01001929 return main_module;
Michal Vaskod8da86b2015-10-21 13:35:37 +02001930 }
1931
Michal Vasko89563fc2016-07-28 16:19:35 +02001932 /* standard import */
Michal Vasko8ce24d72015-10-21 11:27:26 +02001933 for (i = 0; i < module->imp_size; ++i) {
Michal Vasko3edeaf72016-02-11 13:17:43 +01001934 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
1935 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
Michal Vasko8ce24d72015-10-21 11:27:26 +02001936 return module->imp[i].module;
1937 }
1938 }
1939
Michal Vasko89563fc2016-07-28 16:19:35 +02001940 /* module required by a foreign grouping, deviation, or submodule */
1941 if (name) {
1942 str = strndup(name, name_len);
1943 if (!str) {
1944 LOGMEM;
1945 return NULL;
1946 }
1947 main_module = ly_ctx_get_module(module->ctx, str, NULL);
1948 free(str);
1949 return main_module;
1950 }
1951
Michal Vasko8ce24d72015-10-21 11:27:26 +02001952 return NULL;
1953}
1954
Michal Vasko13b15832015-08-19 11:04:48 +02001955/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001956static void
Michal Vaskob746fff2016-02-11 11:37:50 +01001957module_free_common(struct lys_module *module, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejcida04f4a2015-05-21 12:54:09 +02001958{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001959 struct ly_ctx *ctx;
Radek Krejcic071c542016-01-27 14:57:51 +01001960 struct lys_node *next, *iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001961 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001962
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001963 assert(module->ctx);
1964 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001965
Michal Vaskob746fff2016-02-11 11:37:50 +01001966 /* just free the import array, imported modules will stay in the context */
Radek Krejci225376f2016-02-16 17:36:22 +01001967 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa99c1632016-06-06 16:23:52 +02001968 lydict_remove(ctx, module->imp[i].prefix);
Michal Vasko8bfe3812016-07-27 13:37:52 +02001969 lydict_remove(ctx, module->imp[i].dsc);
1970 lydict_remove(ctx, module->imp[i].ref);
Radek Krejci225376f2016-02-16 17:36:22 +01001971 }
Radek Krejcidce51452015-06-16 15:20:08 +02001972 free(module->imp);
1973
Radek Krejcic071c542016-01-27 14:57:51 +01001974 /* submodules don't have data tree, the data nodes
1975 * are placed in the main module altogether */
1976 if (!module->type) {
1977 LY_TREE_FOR_SAFE(module->data, next, iter) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01001978 lys_node_free(iter, private_destructor, 0);
Radek Krejcic071c542016-01-27 14:57:51 +01001979 }
Radek Krejci21181962015-06-30 14:11:00 +02001980 }
Radek Krejci5a065542015-05-22 15:02:07 +02001981
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001982 lydict_remove(ctx, module->dsc);
1983 lydict_remove(ctx, module->ref);
1984 lydict_remove(ctx, module->org);
1985 lydict_remove(ctx, module->contact);
Radek Krejcia77904e2016-02-25 16:23:45 +01001986 lydict_remove(ctx, module->filepath);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001987
Radek Krejcieb00f512015-07-01 16:44:58 +02001988 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001989 for (i = 0; i < module->rev_size; i++) {
1990 lydict_remove(ctx, module->rev[i].dsc);
1991 lydict_remove(ctx, module->rev[i].ref);
1992 }
1993 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001994
Radek Krejcieb00f512015-07-01 16:44:58 +02001995 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001996 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001997 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001998 }
1999 module->ident_size = 0;
2000 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002001
Radek Krejcieb00f512015-07-01 16:44:58 +02002002 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002003 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002004 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002005 }
2006 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002007
Radek Krejcieb00f512015-07-01 16:44:58 +02002008 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002009 for (i = 0; i < module->inc_size; i++) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002010 lydict_remove(ctx, module->inc[i].dsc);
2011 lydict_remove(ctx, module->inc[i].ref);
Radek Krejcic071c542016-01-27 14:57:51 +01002012 /* complete submodule free is done only from main module since
2013 * submodules propagate their includes to the main module */
2014 if (!module->type) {
Michal Vaskob746fff2016-02-11 11:37:50 +01002015 lys_submodule_free(module->inc[i].submodule, private_destructor);
Radek Krejcic071c542016-01-27 14:57:51 +01002016 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002017 }
2018 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02002019
Radek Krejcieb00f512015-07-01 16:44:58 +02002020 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02002021 for (i = 0; i < module->augment_size; i++) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002022 lys_augment_free(ctx, &module->augment[i], private_destructor);
Radek Krejcif5be10f2015-06-16 13:29:36 +02002023 }
2024 free(module->augment);
2025
Radek Krejcieb00f512015-07-01 16:44:58 +02002026 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002027 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002028 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002029 }
2030 free(module->features);
2031
Radek Krejcieb00f512015-07-01 16:44:58 +02002032 /* deviations */
2033 for (i = 0; i < module->deviation_size; i++) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002034 lys_deviation_free(module, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002035 }
2036 free(module->deviation);
2037
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002038 lydict_remove(ctx, module->name);
Radek Krejci4f78b532016-02-17 13:43:00 +01002039 lydict_remove(ctx, module->prefix);
Radek Krejciefaeba32015-05-27 14:30:57 +02002040}
2041
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002042void
Michal Vaskob746fff2016-02-11 11:37:50 +01002043lys_submodule_free(struct lys_submodule *submodule, void (*private_destructor)(const struct lys_node *node, void *priv))
Radek Krejciefaeba32015-05-27 14:30:57 +02002044{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002045 if (!submodule) {
2046 return;
2047 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002048
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002049 /* common part with struct ly_module */
Michal Vaskob746fff2016-02-11 11:37:50 +01002050 module_free_common((struct lys_module *)submodule, private_destructor);
Radek Krejciefaeba32015-05-27 14:30:57 +02002051
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002052 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02002053
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002054 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02002055}
2056
Radek Krejci3a5501d2016-07-18 22:03:34 +02002057static int
2058ingrouping(const struct lys_node *node)
2059{
2060 const struct lys_node *iter = node;
2061 assert(node);
2062
2063 for(iter = node; iter && iter->nodetype != LYS_GROUPING; iter = lys_parent(iter));
2064 if (!iter) {
2065 return 0;
2066 } else {
2067 return 1;
2068 }
2069}
2070
Radek Krejci76512572015-08-04 09:47:08 +02002071struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02002072lys_node_dup(struct lys_module *module, struct lys_node *parent, const struct lys_node *node, uint8_t nacm,
2073 struct unres_schema *unres, int shallow)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002074{
Radek Krejcic071c542016-01-27 14:57:51 +01002075 struct lys_node *retval = NULL, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002076 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002077 int i, j, rc;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002078 unsigned int size, size1, size2;
Radek Krejcid09d1a52016-08-11 14:05:45 +02002079 struct unres_list_uniq *unique_info;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002080
Michal Vaskoc07187d2015-08-13 15:20:57 +02002081 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002082 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002083 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002084 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002085 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002086 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002087 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002088 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002089 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002090 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Radek Krejcibf2abff2016-08-23 15:51:52 +02002091 struct lys_node_anydata *any = NULL;
2092 struct lys_node_anydata *any_orig = (struct lys_node_anydata *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002093 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002094 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002095 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002096 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vasko44fb6382016-06-29 11:12:27 +02002097 struct lys_node_rpc_action *rpc = NULL;
2098 struct lys_node_rpc_action *rpc_orig = (struct lys_node_rpc_action *)node;
2099 struct lys_node_inout *io = NULL;
2100 struct lys_node_inout *io_orig = (struct lys_node_inout *)node;
2101 struct lys_node_rpc_action *ntf = NULL;
2102 struct lys_node_rpc_action *ntf_orig = (struct lys_node_rpc_action *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02002103 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002104 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002105
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002106 /* we cannot just duplicate memory since the strings are stored in
2107 * dictionary and we need to update dictionary counters.
2108 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002109
Radek Krejci1d82ef62015-08-07 14:44:40 +02002110 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002111 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002112 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02002113 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002114 break;
2115
Radek Krejci76512572015-08-04 09:47:08 +02002116 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002117 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002118 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002119 break;
2120
Radek Krejci76512572015-08-04 09:47:08 +02002121 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002122 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002123 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002124 break;
2125
Radek Krejci76512572015-08-04 09:47:08 +02002126 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002127 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02002128 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002129 break;
2130
Radek Krejci76512572015-08-04 09:47:08 +02002131 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002132 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02002133 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002134 break;
2135
Radek Krejci76512572015-08-04 09:47:08 +02002136 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002137 case LYS_ANYDATA:
2138 any = calloc(1, sizeof *any);
2139 retval = (struct lys_node *)any;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002140 break;
2141
Radek Krejci76512572015-08-04 09:47:08 +02002142 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002143 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002144 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002145 break;
2146
Radek Krejci76512572015-08-04 09:47:08 +02002147 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002148 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002149 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002150 break;
2151
Radek Krejci76512572015-08-04 09:47:08 +02002152 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002153 grp = calloc(1, sizeof *grp);
2154 retval = (struct lys_node *)grp;
2155 break;
2156
Radek Krejci76512572015-08-04 09:47:08 +02002157 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02002158 case LYS_ACTION:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002159 rpc = calloc(1, sizeof *rpc);
2160 retval = (struct lys_node *)rpc;
2161 break;
2162
Radek Krejci76512572015-08-04 09:47:08 +02002163 case LYS_INPUT:
2164 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002165 io = calloc(1, sizeof *io);
2166 retval = (struct lys_node *)io;
2167 break;
2168
Radek Krejci76512572015-08-04 09:47:08 +02002169 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002170 ntf = calloc(1, sizeof *ntf);
2171 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002172 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002173
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002174 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002175 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002176 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002177 }
Radek Krejcib388c152015-06-04 17:03:03 +02002178
Michal Vasko253035f2015-12-17 16:58:13 +01002179 if (!retval) {
2180 LOGMEM;
2181 return NULL;
2182 }
2183
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002184 /*
2185 * duplicate generic part of the structure
2186 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002187 retval->name = lydict_insert(ctx, node->name, 0);
2188 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2189 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002190 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002191 retval->flags = node->flags;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002192
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002193 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002194 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002195
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002196 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002197
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002198 retval->iffeature_size = node->iffeature_size;
2199 retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
2200 if (!retval->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002201 LOGMEM;
2202 goto error;
2203 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002204
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002205 if (!shallow) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002206 for (i = 0; i < node->iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002207 resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
2208 if (size1) {
2209 /* there is something to duplicate */
2210
2211 /* duplicate compiled expression */
2212 size = (size1 / 4) + (size1 % 4) ? 1 : 0;
2213 retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
2214 memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
2215
2216 /* list of feature pointer must be updated to point to the resulting tree */
Radek Krejcicbb473e2016-09-16 14:48:32 +02002217 retval->iffeature[i].features = calloc(size2, sizeof *retval->iffeature[i].features);
Radek Krejci9ff0a922016-07-14 13:08:05 +02002218 for (j = 0; (unsigned int)j < size2; j++) {
2219 rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
2220 &retval->iffeature[i].features[j]);
Radek Krejcicbb473e2016-09-16 14:48:32 +02002221 if (rc == EXIT_FAILURE) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002222 /* feature is resolved in origin, so copy it
2223 * - duplication is used for instantiating groupings
2224 * and if-feature inside grouping is supposed to be
2225 * resolved inside the original grouping, so we want
2226 * to keep pointers to features from the grouping
2227 * context */
2228 retval->iffeature[i].features[j] = node->iffeature[i].features[j];
2229 } else if (rc == -1) {
2230 goto error;
Radek Krejcicbb473e2016-09-16 14:48:32 +02002231 } /* else unres was duplicated */
Radek Krejci9ff0a922016-07-14 13:08:05 +02002232 }
2233 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002234 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002235
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002236 /* connect it to the parent */
2237 if (lys_node_addchild(parent, retval->module, retval)) {
2238 goto error;
2239 }
Radek Krejcidce51452015-06-16 15:20:08 +02002240
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002241 /* go recursively */
2242 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
2243 LY_TREE_FOR(node->child, child) {
Michal Vaskoe022a562016-09-27 14:24:15 +02002244 if (!lys_node_dup(module, retval, child, retval->nacm, unres, 0)) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002245 goto error;
2246 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002247 }
2248 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002249 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002250 memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002251 }
2252
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002253 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002254 * duplicate specific part of the structure
2255 */
2256 switch (node->nodetype) {
2257 case LYS_CONTAINER:
2258 if (cont_orig->when) {
2259 cont->when = lys_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002260 }
2261 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002262
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002263 cont->must_size = cont_orig->must_size;
2264 cont->tpdf_size = cont_orig->tpdf_size;
2265
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002266 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Michal Vaskodcf98e62016-05-05 17:53:53 +02002267 cont->tpdf = lys_tpdf_dup(module, lys_parent(node), cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002268 break;
2269
2270 case LYS_CHOICE:
2271 if (choice_orig->when) {
2272 choice->when = lys_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002273 }
2274
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002275 if (!shallow) {
2276 if (choice_orig->dflt) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002277 rc = lys_get_sibling(choice->child, lys_node_module(retval)->name, 0, choice_orig->dflt->name, 0,
2278 LYS_ANYDATA | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST,
2279 (const struct lys_node **)&choice->dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002280 if (rc) {
2281 if (rc == EXIT_FAILURE) {
2282 LOGINT;
2283 }
2284 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002285 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002286 } else {
2287 /* useless to check return value, we don't know whether
2288 * there really wasn't any default defined or it just hasn't
2289 * been resolved, we just hope for the best :)
2290 */
2291 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Michal Vasko49168a22015-08-17 16:35:41 +02002292 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002293 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002294 choice->dflt = choice_orig->dflt;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002295 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002296 break;
2297
2298 case LYS_LEAF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002299 if (lys_type_dup(module, retval, &(leaf->type), &(leaf_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002300 goto error;
2301 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002302 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2303
2304 if (leaf_orig->dflt) {
2305 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci48464ed2016-03-17 15:44:09 +01002306 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002307 goto error;
2308 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002309 }
2310
2311 leaf->must_size = leaf_orig->must_size;
2312 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002313
2314 if (leaf_orig->when) {
2315 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002316 }
2317 break;
2318
2319 case LYS_LEAFLIST:
Radek Krejci3a5501d2016-07-18 22:03:34 +02002320 if (lys_type_dup(module, retval, &(llist->type), &(llist_orig->type), ingrouping(retval), unres)) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02002321 goto error;
2322 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002323 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
2324
2325 llist->min = llist_orig->min;
2326 llist->max = llist_orig->max;
2327
2328 llist->must_size = llist_orig->must_size;
2329 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002330
2331 if (llist_orig->when) {
2332 llist->when = lys_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002333 }
2334 break;
2335
2336 case LYS_LIST:
2337 list->min = list_orig->min;
2338 list->max = list_orig->max;
2339
2340 list->must_size = list_orig->must_size;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002341 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002342
Radek Krejci581ce772015-11-10 17:22:40 +01002343 list->tpdf_size = list_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002344 list->tpdf = lys_tpdf_dup(module, lys_parent(node), list_orig->tpdf, list->tpdf_size, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02002345
Radek Krejci581ce772015-11-10 17:22:40 +01002346 list->keys_size = list_orig->keys_size;
Michal Vasko38d01f72015-06-15 09:41:06 +02002347 if (list->keys_size) {
2348 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01002349 if (!list->keys) {
2350 LOGMEM;
2351 goto error;
2352 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002353
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002354 if (!shallow) {
2355 /* we managed to resolve it before, resolve it again manually */
2356 if (list_orig->keys[0]) {
2357 for (i = 0; i < list->keys_size; ++i) {
2358 rc = lys_get_sibling(list->child, lys_node_module(retval)->name, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2359 (const struct lys_node **)&list->keys[i]);
2360 if (rc) {
2361 if (rc == EXIT_FAILURE) {
2362 LOGINT;
2363 }
2364 goto error;
Michal Vasko49168a22015-08-17 16:35:41 +02002365 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002366 }
2367 /* it was not resolved yet, add unres copy */
2368 } else {
2369 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
2370 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002371 goto error;
2372 }
Michal Vasko38d01f72015-06-15 09:41:06 +02002373 }
Michal Vasko0ea41032015-06-16 08:53:55 +02002374 } else {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002375 memcpy(list->keys, list_orig->keys, list->keys_size * sizeof *list->keys);
Radek Krejcia01e5432015-06-16 10:35:25 +02002376 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002377 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002378
Radek Krejci581ce772015-11-10 17:22:40 +01002379 list->unique_size = list_orig->unique_size;
2380 list->unique = malloc(list->unique_size * sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01002381 if (!list->unique) {
2382 LOGMEM;
2383 goto error;
2384 }
Radek Krejci581ce772015-11-10 17:22:40 +01002385 for (i = 0; i < list->unique_size; ++i) {
2386 list->unique[i].expr_size = list_orig->unique[i].expr_size;
2387 list->unique[i].expr = malloc(list->unique[i].expr_size * sizeof *list->unique[i].expr);
Michal Vasko253035f2015-12-17 16:58:13 +01002388 if (!list->unique[i].expr) {
2389 LOGMEM;
2390 goto error;
2391 }
Radek Krejci581ce772015-11-10 17:22:40 +01002392 for (j = 0; j < list->unique[i].expr_size; j++) {
2393 list->unique[i].expr[j] = lydict_insert(ctx, list_orig->unique[i].expr[j], 0);
2394
2395 /* if it stays in unres list, duplicate it also there */
Radek Krejcid09d1a52016-08-11 14:05:45 +02002396 unique_info = malloc(sizeof *unique_info);
2397 unique_info->list = (struct lys_node *)list;
2398 unique_info->expr = list->unique[i].expr[j];
2399 unique_info->trg_type = &list->unique[i].trg_type;
2400 unres_schema_dup(module, unres, &list_orig, UNRES_LIST_UNIQ, unique_info);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002401 }
2402 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002403
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002404 if (list_orig->when) {
2405 list->when = lys_when_dup(ctx, list_orig->when);
Radek Krejciefaeba32015-05-27 14:30:57 +02002406 }
Radek Krejcidce51452015-06-16 15:20:08 +02002407 break;
2408
2409 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002410 case LYS_ANYDATA:
2411 any->must_size = any_orig->must_size;
2412 any->must = lys_restr_dup(ctx, any_orig->must, any->must_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002413
Radek Krejcibf2abff2016-08-23 15:51:52 +02002414 if (any_orig->when) {
2415 any->when = lys_when_dup(ctx, any_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002416 }
2417 break;
2418
2419 case LYS_USES:
2420 uses->grp = uses_orig->grp;
2421
2422 if (uses_orig->when) {
2423 uses->when = lys_when_dup(ctx, uses_orig->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002424 }
2425
2426 uses->refine_size = uses_orig->refine_size;
Michal Vasko0d204592015-10-07 09:50:04 +02002427 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002428 uses->augment_size = uses_orig->augment_size;
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002429 if (!shallow) {
2430 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Michal Vaskocda51712016-05-19 15:22:11 +02002431 if (!uses->grp || uses->grp->nacm) {
2432 assert(!uses->child);
Radek Krejci48464ed2016-03-17 15:44:09 +01002433 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002434 goto error;
2435 }
Michal Vasko49168a22015-08-17 16:35:41 +02002436 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002437 } else {
2438 memcpy(uses->augment, uses_orig->augment, uses->augment_size * sizeof *uses->augment);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002439 }
2440 break;
2441
Radek Krejcidce51452015-06-16 15:20:08 +02002442 case LYS_CASE:
2443 if (cs_orig->when) {
2444 cs->when = lys_when_dup(ctx, cs_orig->when);
Radek Krejcidce51452015-06-16 15:20:08 +02002445 }
2446 break;
2447
2448 case LYS_GROUPING:
2449 grp->tpdf_size = grp_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002450 grp->tpdf = lys_tpdf_dup(module, lys_parent(node), grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002451 break;
2452
2453 case LYS_RPC:
2454 rpc->tpdf_size = rpc_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002455 rpc->tpdf = lys_tpdf_dup(module, lys_parent(node), rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcidce51452015-06-16 15:20:08 +02002456 break;
2457
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002458 case LYS_INPUT:
2459 case LYS_OUTPUT:
Radek Krejcida04f4a2015-05-21 12:54:09 +02002460 io->tpdf_size = io_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002461 io->tpdf = lys_tpdf_dup(module, lys_parent(node), io_orig->tpdf, io->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002462 break;
2463
Radek Krejcida04f4a2015-05-21 12:54:09 +02002464 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002465 ntf->tpdf_size = ntf_orig->tpdf_size;
Michal Vaskodcf98e62016-05-05 17:53:53 +02002466 ntf->tpdf = lys_tpdf_dup(module, lys_parent(node), ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002467 break;
2468
2469 default:
2470 /* LY_NODE_AUGMENT */
2471 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002472 goto error;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002473 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002474
2475 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002476
2477error:
2478
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002479 lys_node_free(retval, NULL, 0);
Michal Vasko49168a22015-08-17 16:35:41 +02002480 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002481}
2482
Michal Vasko13b15832015-08-19 11:04:48 +02002483void
Michal Vaskoff006c12016-02-17 11:15:19 +01002484lys_node_switch(struct lys_node *dst, struct lys_node *src)
2485{
2486 struct lys_node *child;
2487
Michal Vaskob42b6972016-06-06 14:21:30 +02002488 assert((dst->module == src->module) && ly_strequal(dst->name, src->name, 1) && (dst->nodetype == src->nodetype));
Michal Vaskoff006c12016-02-17 11:15:19 +01002489
2490 /* sibling next */
Michal Vasko8328da82016-08-25 09:27:22 +02002491 if (dst->prev->next) {
Michal Vaskoff006c12016-02-17 11:15:19 +01002492 dst->prev->next = src;
2493 }
2494
2495 /* sibling prev */
2496 if (dst->next) {
2497 dst->next->prev = src;
Michal Vasko8328da82016-08-25 09:27:22 +02002498 } else {
2499 for (child = dst->prev; child->prev->next; child = child->prev);
2500 child->prev = src;
Michal Vaskoff006c12016-02-17 11:15:19 +01002501 }
2502
2503 /* next */
2504 src->next = dst->next;
2505 dst->next = NULL;
2506
2507 /* prev */
2508 if (dst->prev != dst) {
2509 src->prev = dst->prev;
2510 }
2511 dst->prev = dst;
2512
2513 /* parent child */
2514 if (dst->parent && (dst->parent->child == dst)) {
2515 dst->parent->child = src;
2516 }
2517
2518 /* parent */
2519 src->parent = dst->parent;
2520 dst->parent = NULL;
2521
2522 /* child parent */
2523 LY_TREE_FOR(dst->child, child) {
2524 if (child->parent == dst) {
2525 child->parent = src;
2526 }
2527 }
2528
2529 /* child */
2530 src->child = dst->child;
2531 dst->child = NULL;
2532}
2533
2534void
Michal Vasko627975a2016-02-11 11:39:03 +01002535lys_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 +02002536{
2537 struct ly_ctx *ctx;
2538 int i;
2539
2540 if (!module) {
2541 return;
2542 }
2543
2544 /* remove schema from the context */
2545 ctx = module->ctx;
Michal Vasko627975a2016-02-11 11:39:03 +01002546 if (remove_from_ctx && ctx->models.used) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02002547 for (i = 0; i < ctx->models.used; i++) {
2548 if (ctx->models.list[i] == module) {
Michal Vasko627975a2016-02-11 11:39:03 +01002549 /* move all the models to not change the order in the list */
Radek Krejcida04f4a2015-05-21 12:54:09 +02002550 ctx->models.used--;
Michal Vasko627975a2016-02-11 11:39:03 +01002551 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 +02002552 ctx->models.list[ctx->models.used] = NULL;
2553 /* we are done */
2554 break;
2555 }
2556 }
2557 }
2558
2559 /* common part with struct ly_submodule */
Michal Vaskob746fff2016-02-11 11:37:50 +01002560 module_free_common(module, private_destructor);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002561
2562 /* specific items to free */
Michal Vaskob746fff2016-02-11 11:37:50 +01002563 lydict_remove(ctx, module->ns);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002564
2565 free(module);
2566}
Radek Krejci7e97c352015-06-19 16:26:34 +02002567
2568/*
2569 * op: 1 - enable, 0 - disable
2570 */
2571static int
Michal Vasko1e62a092015-12-01 12:27:20 +01002572lys_features_change(const struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002573{
2574 int all = 0;
Radek Krejci9ff0a922016-07-14 13:08:05 +02002575 int i, j, k;
Radek Krejci7e97c352015-06-19 16:26:34 +02002576
2577 if (!module || !name || !strlen(name)) {
2578 return EXIT_FAILURE;
2579 }
2580
2581 if (!strcmp(name, "*")) {
2582 /* enable all */
2583 all = 1;
2584 }
2585
2586 /* module itself */
2587 for (i = 0; i < module->features_size; i++) {
2588 if (all || !strcmp(module->features[i].name, name)) {
2589 if (op) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002590 /* check referenced features if they are enabled */
2591 for (j = 0; j < module->features[i].iffeature_size; j++) {
Radek Krejci69b8d922016-07-27 13:13:41 +02002592 if (!resolve_iffeature(&module->features[i].iffeature[j])) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002593 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
2594 module->features[i].name, j + 1);
2595 return EXIT_FAILURE;
2596 }
2597 }
2598
Radek Krejci1574a8d2015-08-03 14:16:52 +02002599 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002600 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002601 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002602 }
2603 if (!all) {
2604 return EXIT_SUCCESS;
2605 }
2606 }
2607 }
2608
2609 /* submodules */
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002610 for (i = 0; i < module->inc_size; i++) {
2611 for (j = 0; j < module->inc[i].submodule->features_size; j++) {
2612 if (all || !strcmp(module->inc[i].submodule->features[j].name, name)) {
Radek Krejci7e97c352015-06-19 16:26:34 +02002613 if (op) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002614 /* check referenced features if they are enabled */
2615 for (k = 0; k < module->inc[i].submodule->features[j].iffeature_size; k++) {
Radek Krejci69b8d922016-07-27 13:13:41 +02002616 if (!resolve_iffeature(&module->inc[i].submodule->features[j].iffeature[k])) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02002617 LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
2618 module->inc[i].submodule->features[j].name, k + 1);
2619 return EXIT_FAILURE;
2620 }
2621 }
2622
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002623 module->inc[i].submodule->features[j].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002624 } else {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002625 module->inc[i].submodule->features[j].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002626 }
2627 if (!all) {
2628 return EXIT_SUCCESS;
2629 }
2630 }
2631 }
2632 }
2633
2634 if (all) {
2635 return EXIT_SUCCESS;
2636 } else {
2637 return EXIT_FAILURE;
2638 }
2639}
2640
2641API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002642lys_features_enable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002643{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002644 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002645}
2646
2647API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002648lys_features_disable(const struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002649{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002650 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002651}
2652
2653API int
Michal Vasko1e62a092015-12-01 12:27:20 +01002654lys_features_state(const struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002655{
2656 int i, j;
2657
2658 if (!module || !feature) {
2659 return -1;
2660 }
2661
2662 /* search for the specified feature */
2663 /* module itself */
2664 for (i = 0; i < module->features_size; i++) {
2665 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002666 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002667 return 1;
2668 } else {
2669 return 0;
2670 }
2671 }
2672 }
2673
2674 /* submodules */
2675 for (j = 0; j < module->inc_size; j++) {
2676 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2677 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002678 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002679 return 1;
2680 } else {
2681 return 0;
2682 }
2683 }
2684 }
2685 }
2686
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002687 /* feature definition not found */
2688 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002689}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002690
Radek Krejci96a10da2015-07-30 11:00:14 +02002691API const char **
Michal Vasko1e62a092015-12-01 12:27:20 +01002692lys_features_list(const struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002693{
Radek Krejci96a10da2015-07-30 11:00:14 +02002694 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002695 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002696 unsigned int count;
2697
2698 if (!module) {
2699 return NULL;
2700 }
2701
2702 count = module->features_size;
2703 for (i = 0; i < module->inc_size; i++) {
2704 count += module->inc[i].submodule->features_size;
2705 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002706 result = malloc((count + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +01002707 if (!result) {
2708 LOGMEM;
2709 return NULL;
2710 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002711 if (states) {
2712 *states = malloc((count + 1) * sizeof **states);
Michal Vasko253035f2015-12-17 16:58:13 +01002713 if (!(*states)) {
2714 LOGMEM;
2715 free(result);
2716 return NULL;
2717 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002718 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002719 count = 0;
2720
2721 /* module itself */
2722 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002723 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002724 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002725 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002726 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002727 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002728 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002729 }
2730 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002731 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002732 }
2733
2734 /* submodules */
2735 for (j = 0; j < module->inc_size; j++) {
2736 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002737 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002738 if (states) {
2739 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2740 (*states)[count] = 1;
2741 } else {
2742 (*states)[count] = 0;
2743 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002744 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002745 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002746 }
2747 }
2748
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002749 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002750 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002751
2752 return result;
2753}
Michal Vaskobaefb032015-09-24 14:52:10 +02002754
Radek Krejci6910a032016-04-13 10:06:21 +02002755API struct lys_module *
Michal Vasko320e8532016-02-15 13:11:57 +01002756lys_node_module(const struct lys_node *node)
Radek Krejcic071c542016-01-27 14:57:51 +01002757{
2758 return node->module->type ? ((struct lys_submodule *)node->module)->belongsto : node->module;
2759}
2760
Radek Krejci6910a032016-04-13 10:06:21 +02002761API struct lys_module *
Radek Krejcic4283442016-04-22 09:19:27 +02002762lys_main_module(const struct lys_module *module)
Michal Vasko320e8532016-02-15 13:11:57 +01002763{
2764 return (module->type ? ((struct lys_submodule *)module)->belongsto : (struct lys_module *)module);
2765}
2766
Michal Vaskobaefb032015-09-24 14:52:10 +02002767API struct lys_node *
Michal Vasko1e62a092015-12-01 12:27:20 +01002768lys_parent(const struct lys_node *node)
Michal Vaskobaefb032015-09-24 14:52:10 +02002769{
2770 if (!node || !node->parent) {
2771 return NULL;
2772 }
2773
2774 if (node->parent->nodetype == LYS_AUGMENT) {
2775 return ((struct lys_node_augment *)node->parent)->target;
2776 }
2777
2778 return node->parent;
2779}
Michal Vasko1b229152016-01-13 11:28:38 +01002780
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002781API void *
Michal Vasko1b229152016-01-13 11:28:38 +01002782lys_set_private(const struct lys_node *node, void *priv)
2783{
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002784 void *prev;
2785
Michal Vasko1b229152016-01-13 11:28:38 +01002786 if (!node) {
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002787 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2788 return NULL;
Michal Vasko1b229152016-01-13 11:28:38 +01002789 }
2790
Mislav Novakovicb5529e52016-02-29 11:42:43 +01002791 prev = node->priv;
2792 ((struct lys_node *)node)->priv = priv;
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002793
2794 return prev;
Michal Vasko1b229152016-01-13 11:28:38 +01002795}
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002796
Michal Vasko01c6fd22016-05-20 11:43:05 +02002797int
2798lys_leaf_add_leafref_target(struct lys_node_leaf *leafref_target, struct lys_node *leafref)
2799{
Radek Krejcid8fb03c2016-06-13 15:52:22 +02002800 struct lys_node_leaf *iter = leafref_target;
2801
Michal Vasko48a573d2016-07-01 11:46:02 +02002802 if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02002803 LOGINT;
2804 return -1;
2805 }
2806
Pavol Vican93175152016-08-30 15:34:44 +02002807 /* check for config flag */
2808 if ((leafref->flags & LYS_CONFIG_W) && (leafref_target->flags & LYS_CONFIG_R)) {
2809 LOGVAL(LYE_SPEC, LY_VLOG_LYS, leafref,
2810 "The %s is config but refers to a non-config %s.",
2811 strnodetype(leafref->nodetype), strnodetype(leafref_target->nodetype));
2812 return -1;
2813 }
Radek Krejcid8fb03c2016-06-13 15:52:22 +02002814 /* check for cycles */
2815 while (iter && iter->type.base == LY_TYPE_LEAFREF) {
2816 if ((void *)iter == (void *)leafref) {
2817 /* cycle detected */
2818 LOGVAL(LYE_CIRC_LEAFREFS, LY_VLOG_LYS, leafref);
2819 return -1;
2820 }
2821 iter = iter->type.info.lref.target;
2822 }
2823
2824 /* create fake child - the ly_set structure to hold the list of
Michal Vasko48a573d2016-07-01 11:46:02 +02002825 * leafrefs referencing the leaf(-list) */
Michal Vasko01c6fd22016-05-20 11:43:05 +02002826 if (!leafref_target->child) {
2827 leafref_target->child = (void*)ly_set_new();
2828 if (!leafref_target->child) {
2829 LOGMEM;
2830 return -1;
2831 }
2832 }
Radek Krejci09891a22016-06-10 10:59:22 +02002833 ly_set_add((struct ly_set *)leafref_target->child, leafref, 0);
Michal Vasko01c6fd22016-05-20 11:43:05 +02002834
2835 return 0;
2836}
2837
Michal Vasko8548e082016-07-22 12:00:18 +02002838/* not needed currently */
2839#if 0
2840
Michal Vasko5b3492c2016-07-20 09:37:40 +02002841static const char *
2842lys_data_path_reverse(const struct lys_node *node, char * const buf, uint32_t buf_len)
2843{
2844 struct lys_module *prev_mod;
2845 uint32_t str_len, mod_len, buf_idx;
2846
Radek Krejcibf2abff2016-08-23 15:51:52 +02002847 if (!(node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02002848 LOGINT;
2849 return NULL;
2850 }
2851
2852 buf_idx = buf_len - 1;
2853 buf[buf_idx] = '\0';
2854
2855 while (node) {
2856 if (lys_parent(node)) {
2857 prev_mod = lys_node_module(lys_parent(node));
2858 } else {
2859 prev_mod = NULL;
2860 }
2861
Radek Krejcibf2abff2016-08-23 15:51:52 +02002862 if (node->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02002863 str_len = strlen(node->name);
2864
2865 if (prev_mod != node->module) {
2866 mod_len = strlen(node->module->name);
2867 } else {
2868 mod_len = 0;
2869 }
2870
2871 if (buf_idx < 1 + (mod_len ? mod_len + 1 : 0) + str_len) {
2872 LOGINT;
2873 return NULL;
2874 }
2875
2876 buf_idx -= 1 + (mod_len ? mod_len + 1 : 0) + str_len;
2877
2878 buf[buf_idx] = '/';
2879 if (mod_len) {
2880 memcpy(buf + buf_idx + 1, node->module->name, mod_len);
2881 buf[buf_idx + 1 + mod_len] = ':';
2882 }
2883 memcpy(buf + buf_idx + 1 + (mod_len ? mod_len + 1 : 0), node->name, str_len);
2884 }
2885
2886 node = lys_parent(node);
2887 }
2888
2889 return buf + buf_idx;
2890}
2891
Michal Vasko8548e082016-07-22 12:00:18 +02002892#endif
2893
2894API struct ly_set *
Michal Vaskof06fb5b2016-09-08 10:05:56 +02002895lys_find_xpath(const struct lys_node *node, const char *expr, int options)
Michal Vasko46a4bf92016-09-08 08:23:49 +02002896{
2897 struct lyxp_set set;
2898 struct ly_set *ret_set;
2899 uint32_t i;
Michal Vaskodb1da032016-09-08 10:07:38 +02002900 int opts;
Michal Vasko46a4bf92016-09-08 08:23:49 +02002901
2902 if (!node || !expr) {
2903 ly_errno = LY_EINVAL;
2904 return NULL;
2905 }
2906
2907 memset(&set, 0, sizeof set);
2908
Michal Vaskodb1da032016-09-08 10:07:38 +02002909 opts = LYXP_SNODE;
2910 if (options & LYS_FIND_OUTPUT) {
2911 opts |= LYXP_SNODE_OUTPUT;
2912 }
2913
Michal Vasko46a4bf92016-09-08 08:23:49 +02002914 /* node and nodetype won't matter at all since it is absolute */
Michal Vaskodb1da032016-09-08 10:07:38 +02002915 if (lyxp_atomize(expr, node, LYXP_NODE_ELEM, &set, opts)) {
Michal Vasko46a4bf92016-09-08 08:23:49 +02002916 free(set.val.snodes);
2917 return NULL;
2918 }
2919
2920 ret_set = ly_set_new();
2921
2922 for (i = 0; i < set.used; ++i) {
2923 if (!set.val.snodes[i].in_ctx) {
2924 continue;
2925 }
2926 assert(set.val.snodes[i].in_ctx == 1);
2927
2928 switch (set.val.snodes[i].type) {
2929 case LYXP_NODE_ELEM:
2930 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
2931 ly_set_free(ret_set);
2932 free(set.val.snodes);
2933 return NULL;
2934 }
2935 break;
2936 default:
2937 /* ignore roots, text and attr should not ever appear */
2938 break;
2939 }
2940 }
2941
2942 free(set.val.snodes);
2943 return ret_set;
2944}
2945
2946API struct ly_set *
Michal Vasko508a50d2016-09-07 14:50:33 +02002947lys_xpath_atomize(const struct lys_node *cur_snode, enum lyxp_node_type cur_snode_type, const char *expr, int options)
Michal Vasko5b3492c2016-07-20 09:37:40 +02002948{
Michal Vasko508a50d2016-09-07 14:50:33 +02002949 struct lyxp_set set;
Michal Vasko8548e082016-07-22 12:00:18 +02002950 struct ly_set *ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02002951 uint32_t i;
2952
Michal Vaskob94a5e42016-09-08 14:01:56 +02002953 if (!cur_snode || !expr) {
Michal Vasko8548e082016-07-22 12:00:18 +02002954 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02002955 }
2956
Michal Vaskob94a5e42016-09-08 14:01:56 +02002957 /* adjust the root */
2958 if ((cur_snode_type == LYXP_NODE_ROOT) || (cur_snode_type == LYXP_NODE_ROOT_CONFIG)) {
2959 do {
2960 cur_snode = lys_getnext(NULL, NULL, lys_node_module(cur_snode), 0);
2961 } while ((cur_snode_type == LYXP_NODE_ROOT_CONFIG) && (cur_snode->flags & LYS_CONFIG_R));
2962 }
2963
Michal Vasko508a50d2016-09-07 14:50:33 +02002964 memset(&set, 0, sizeof set);
Michal Vasko5b3492c2016-07-20 09:37:40 +02002965
2966 if (options & LYXP_MUST) {
2967 options &= ~LYXP_MUST;
2968 options |= LYXP_SNODE_MUST;
2969 } else if (options & LYXP_WHEN) {
2970 options &= ~LYXP_WHEN;
2971 options |= LYXP_SNODE_WHEN;
2972 } else {
2973 options |= LYXP_SNODE;
2974 }
2975
Michal Vasko508a50d2016-09-07 14:50:33 +02002976 if (lyxp_atomize(expr, cur_snode, cur_snode_type, &set, options)) {
2977 free(set.val.snodes);
Michal Vasko8548e082016-07-22 12:00:18 +02002978 return NULL;
Michal Vasko5b3492c2016-07-20 09:37:40 +02002979 }
2980
Michal Vasko8548e082016-07-22 12:00:18 +02002981 ret_set = ly_set_new();
Michal Vasko5b3492c2016-07-20 09:37:40 +02002982
Michal Vasko508a50d2016-09-07 14:50:33 +02002983 for (i = 0; i < set.used; ++i) {
2984 switch (set.val.snodes[i].type) {
Michal Vasko5b3492c2016-07-20 09:37:40 +02002985 case LYXP_NODE_ELEM:
Michal Vasko508a50d2016-09-07 14:50:33 +02002986 if (ly_set_add(ret_set, set.val.snodes[i].snode, LY_SET_OPT_USEASLIST) == -1) {
Michal Vasko8548e082016-07-22 12:00:18 +02002987 ly_set_free(ret_set);
Michal Vasko508a50d2016-09-07 14:50:33 +02002988 free(set.val.snodes);
Michal Vasko8548e082016-07-22 12:00:18 +02002989 return NULL;
2990 }
Michal Vasko5b3492c2016-07-20 09:37:40 +02002991 break;
2992 default:
Michal Vasko508a50d2016-09-07 14:50:33 +02002993 /* ignore roots, text and attr should not ever appear */
Michal Vasko5b3492c2016-07-20 09:37:40 +02002994 break;
2995 }
2996 }
2997
Michal Vasko508a50d2016-09-07 14:50:33 +02002998 free(set.val.snodes);
2999 return ret_set;
3000}
3001
3002API struct ly_set *
3003lys_node_xpath_atomize(const struct lys_node *node, int options)
3004{
3005 const struct lys_node *next, *elem, *parent, *tmp;
3006 struct lyxp_set set;
3007 struct ly_set *ret_set;
3008 uint16_t i;
3009
3010 if (!node) {
3011 return NULL;
3012 }
3013
3014 for (parent = node; parent && !(parent->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)); parent = lys_parent(parent));
3015 if (!parent) {
3016 /* not in input, output, or notification */
3017 return NULL;
3018 }
3019
3020 ret_set = ly_set_new();
Radek Krejcid9af8d22016-09-07 18:44:26 +02003021 if (!ret_set) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003022 return NULL;
3023 }
3024
3025 LY_TREE_DFS_BEGIN(node, next, elem) {
Michal Vaskoe9914d12016-10-07 14:32:37 +02003026 if ((options & LYXP_NO_LOCAL) && !(elem->flags & LYS_VALID_DEP)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003027 /* elem has no dependencies from other subtrees and local nodes get discarded */
3028 goto next_iter;
3029 }
3030
3031 if (lyxp_node_atomize(elem, &set)) {
3032 ly_set_free(ret_set);
3033 free(set.val.snodes);
3034 return NULL;
3035 }
3036
3037 for (i = 0; i < set.used; ++i) {
3038 switch (set.val.snodes[i].type) {
3039 case LYXP_NODE_ELEM:
3040 if (options & LYXP_NO_LOCAL) {
3041 for (tmp = set.val.snodes[i].snode; tmp && (tmp != parent); tmp = lys_parent(tmp));
3042 if (tmp) {
3043 /* in local subtree, discard */
3044 break;
3045 }
3046 }
3047 if (ly_set_add(ret_set, set.val.snodes[i].snode, 0) == -1) {
3048 ly_set_free(ret_set);
3049 free(set.val.snodes);
3050 return NULL;
3051 }
3052 break;
3053 default:
3054 /* ignore roots, text and attr should not ever appear */
3055 break;
3056 }
3057 }
3058
3059 free(set.val.snodes);
3060 if (!(options & LYXP_RECURSIVE)) {
3061 break;
3062 }
3063next_iter:
3064 LY_TREE_DFS_END(node, next, elem);
3065 }
3066
Michal Vasko8548e082016-07-22 12:00:18 +02003067 return ret_set;
Michal Vasko5b3492c2016-07-20 09:37:40 +02003068}
3069
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003070static void
Michal Vasko89563fc2016-07-28 16:19:35 +02003071lys_switch_deviation(struct lys_deviation *dev, const struct lys_module *target_module)
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003072{
3073 int ret;
3074 char *parent_path;
3075 struct lys_node *target;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003076
Pavol Vican64d0b762016-08-25 10:44:59 +02003077 if (!dev->deviate) {
3078 return ;
3079 }
3080
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003081 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
3082 if (dev->orig_node) {
3083 /* removing not-supported deviation ... */
3084 if (strrchr(dev->target_name, '/') != dev->target_name) {
3085 /* ... from a parent */
3086 parent_path = strndup(dev->target_name, strrchr(dev->target_name, '/') - dev->target_name);
3087
3088 target = NULL;
3089 ret = resolve_augment_schema_nodeid(parent_path, NULL, target_module, (const struct lys_node **)&target);
3090 free(parent_path);
3091 if (ret || !target) {
3092 LOGINT;
3093 return;
3094 }
3095
3096 lys_node_addchild(target, NULL, dev->orig_node);
3097 } else {
3098 /* ... from top-level data */
3099 lys_node_addchild(NULL, (struct lys_module *)target_module, dev->orig_node);
3100 }
3101
3102 dev->orig_node = NULL;
3103 } else {
3104 /* adding not-supported deviation */
3105 target = NULL;
3106 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, (const struct lys_node **)&target);
3107 if (ret || !target) {
3108 LOGINT;
3109 return;
3110 }
3111
3112 lys_node_unlink(target);
3113 dev->orig_node = target;
3114 }
3115 } else {
3116 target = NULL;
3117 ret = resolve_augment_schema_nodeid(dev->target_name, NULL, target_module, (const struct lys_node **)&target);
3118 if (ret || !target) {
3119 LOGINT;
3120 return;
3121 }
3122
3123 lys_node_switch(target, dev->orig_node);
3124 dev->orig_node = target;
3125 }
3126}
3127
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003128/* temporarily removes or applies deviations, updates module deviation flag accordingly */
3129void
3130lys_switch_deviations(struct lys_module *module)
3131{
Michal Vasko89563fc2016-07-28 16:19:35 +02003132 uint32_t i = 0, j;
3133 const struct lys_module *mod;
3134 const char *ptr;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003135
Michal Vasko89563fc2016-07-28 16:19:35 +02003136 if (module->deviated) {
3137 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
3138 if (mod == module) {
3139 continue;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003140 }
3141
Michal Vasko89563fc2016-07-28 16:19:35 +02003142 for (j = 0; j < mod->deviation_size; ++j) {
3143 ptr = strstr(mod->deviation[j].target_name, module->name);
3144 if (ptr && ptr[strlen(module->name)] == ':') {
3145 lys_switch_deviation(&mod->deviation[j], module);
3146 }
3147 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003148 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003149
Michal Vasko89563fc2016-07-28 16:19:35 +02003150 if (module->deviated == 2) {
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003151 module->deviated = 1;
Michal Vasko89563fc2016-07-28 16:19:35 +02003152 } else {
3153 module->deviated = 2;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003154 }
3155 }
3156}
3157
3158/* not needed currently, but tested and working */
3159#if 0
3160
3161void
3162lys_sub_module_apply_devs_augs(struct lys_module *module)
3163{
3164 int i;
3165 struct lys_node_augment *aug;
3166 struct lys_node *last;
3167
3168 /* re-apply deviations */
3169 for (i = 0; i < module->deviation_size; ++i) {
3170 lys_switch_deviation(&module->deviation[i], module);
3171 assert(module->deviation[i].orig_node);
Michal Vasko89563fc2016-07-28 16:19:35 +02003172 lys_node_module(module->deviation[i].orig_node)->deviated = 1;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003173 }
3174
3175 /* re-apply augments */
3176 for (i = 0; i < module->augment_size; ++i) {
3177 aug = &module->augment[i];
3178 assert(aug->target);
3179
3180 /* reconnect augmenting data into the target - add them to the target child list */
3181 if (aug->target->child) {
3182 last = aug->target->child->prev;
3183 last->next = aug->child;
3184 aug->target->child->prev = aug->child->prev;
3185 aug->child->prev = last;
3186 } else {
3187 aug->target->child = aug->child;
3188 }
3189 }
3190}
3191
3192#endif
3193
3194void
3195lys_sub_module_remove_devs_augs(struct lys_module *module)
3196{
Michal Vasko89563fc2016-07-28 16:19:35 +02003197 uint32_t i = 0, j;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003198 struct lys_node *last, *elem;
Michal Vasko89563fc2016-07-28 16:19:35 +02003199 const struct lys_module *mod;
3200 struct lys_module *target_mod;
3201 const char *ptr;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003202
3203 /* remove applied deviations */
3204 for (i = 0; i < module->deviation_size; ++i) {
Pavol Vican64d0b762016-08-25 10:44:59 +02003205 if (module->deviation[i].orig_node) {
3206 target_mod = lys_node_module(module->deviation[i].orig_node);
3207 } else {
3208 target_mod = (struct lys_module *)lys_get_import_module(module, NULL, 0, module->deviation[i].target_name + 1,
3209 strcspn(module->deviation[i].target_name, ":") - 1);
Radek Krejci0fa54e92016-09-14 14:01:05 +02003210 target_mod = (struct lys_module *)lys_get_implemented_module(target_mod);
Pavol Vican64d0b762016-08-25 10:44:59 +02003211 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003212 lys_switch_deviation(&module->deviation[i], module);
3213
Michal Vasko89563fc2016-07-28 16:19:35 +02003214 /* clear the deviation flag if possible */
3215 while ((mod = ly_ctx_get_module_iter(module->ctx, &i))) {
3216 if ((mod == module) || (mod == target_mod)) {
3217 continue;
3218 }
3219
3220 for (j = 0; j < mod->deviation_size; ++j) {
3221 ptr = strstr(mod->deviation[j].target_name, target_mod->name);
3222 if (ptr && (ptr[strlen(target_mod->name)] == ':')) {
3223 /* some other module deviation targets the inspected module, flag remains */
3224 break;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003225 }
3226 }
Michal Vasko89563fc2016-07-28 16:19:35 +02003227
3228 if (j < mod->deviation_size) {
3229 break;
3230 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003231 }
Michal Vasko89563fc2016-07-28 16:19:35 +02003232
3233 if (!mod) {
3234 target_mod->deviated = 0;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003235 }
3236 }
3237
3238 /* remove applied augments */
3239 for (i = 0; i < module->augment_size; ++i) {
Radek Krejcidbc15262016-06-16 14:58:29 +02003240 if (!module->augment[i].target) {
3241 /* skip not resolved augments */
3242 continue;
3243 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003244
3245 elem = module->augment[i].child;
3246 if (elem) {
3247 LY_TREE_FOR(elem, last) {
3248 if (!last->next || (last->next->parent != (struct lys_node *)&module->augment[i])) {
3249 break;
3250 }
3251 }
3252 /* elem is first augment child, last is the last child */
3253
3254 /* parent child ptr */
3255 if (module->augment[i].target->child == elem) {
3256 module->augment[i].target->child = last->next;
3257 }
3258
3259 /* parent child next ptr */
3260 if (elem->prev->next) {
3261 elem->prev->next = last->next;
3262 }
3263
3264 /* parent child prev ptr */
3265 if (last->next) {
3266 last->next->prev = elem->prev;
3267 } else if (module->augment[i].target->child) {
3268 module->augment[i].target->child->prev = elem->prev;
3269 }
3270
3271 /* update augment children themselves */
3272 elem->prev = last;
3273 last->next = NULL;
3274 }
Michal Vaskob8f71322016-05-03 11:39:56 +02003275
3276 /* needs to be NULL for lys_augment_free() to free the children */
3277 module->augment[i].target = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003278 }
3279}
3280
Radek Krejci27fe55e2016-09-13 17:13:35 +02003281static int
3282lys_set_implemented_recursion(struct lys_module *module, struct unres_schema *unres)
3283{
3284 struct lys_node *root, *next, *node;
3285 uint8_t i;
3286
3287 for (i = 0; i < module->augment_size; i++) {
3288 /* apply augment */
Michal Vaskoa1911b92016-09-19 14:57:34 +02003289 if (!module->augment[i].target
3290 && (unres_schema_add_node(module, unres, &module->augment[i], UNRES_AUGMENT, NULL) == -1)) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02003291 return -1;
3292 }
3293 }
3294 LY_TREE_FOR(module->data, root) {
3295 /* handle leafrefs and recursively change the implemented flags in the leafref targets */
3296 LY_TREE_DFS_BEGIN(root, next, node) {
3297 if (node->nodetype == LYS_GROUPING) {
3298 goto nextsibling;
3299 }
3300 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
3301 if (((struct lys_node_leaf *)node)->type.base == LY_TYPE_LEAFREF) {
3302 if (unres_schema_add_node(module, unres, &((struct lys_node_leaf *)node)->type,
3303 UNRES_TYPE_LEAFREF, node) == -1) {
3304 return EXIT_FAILURE;
3305 }
3306 }
3307 }
3308
3309 /* modified LY_TREE_DFS_END */
3310 next = node->child;
3311 /* child exception for leafs, leaflists and anyxml without children */
3312 if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
3313 next = NULL;
3314 }
3315 if (!next) {
3316nextsibling:
3317 /* no children */
3318 if (node == root) {
3319 /* we are done, root has no children */
3320 break;
3321 }
3322 /* try siblings */
3323 next = node->next;
3324 }
3325 while (!next) {
3326 /* parent is already processed, go to its sibling */
3327 node = lys_parent(node);
3328 /* no siblings, go back through parents */
3329 if (lys_parent(node) == lys_parent(root)) {
3330 /* we are done, no next element to process */
3331 break;
3332 }
3333 next = node->next;
3334 }
3335 }
3336 }
3337
3338 return EXIT_SUCCESS;
3339}
3340
3341API int
3342lys_set_implemented(const struct lys_module *module)
Michal Vasko26055752016-05-03 11:36:31 +02003343{
3344 struct ly_ctx *ctx;
Radek Krejci27fe55e2016-09-13 17:13:35 +02003345 struct unres_schema *unres;
3346 int i, j;
Michal Vasko26055752016-05-03 11:36:31 +02003347
Radek Krejci27fe55e2016-09-13 17:13:35 +02003348 if (!module) {
3349 ly_errno = LY_EINVAL;
3350 return EXIT_FAILURE;
3351 }
3352
3353 module = lys_main_module(module);
Michal Vasko26055752016-05-03 11:36:31 +02003354 if (module->implemented) {
3355 return EXIT_SUCCESS;
3356 }
3357
3358 ctx = module->ctx;
3359
3360 for (i = 0; i < ctx->models.used; ++i) {
3361 if (module == ctx->models.list[i]) {
3362 continue;
3363 }
3364
3365 if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
3366 LOGERR(LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
3367 return EXIT_FAILURE;
3368 }
3369 }
3370
Radek Krejci27fe55e2016-09-13 17:13:35 +02003371 unres = calloc(1, sizeof *unres);
3372 if (!unres) {
3373 LOGMEM;
3374 return EXIT_FAILURE;
3375 }
3376 /* recursively make the module implemented */
3377 ((struct lys_module *)module)->implemented = 1;
3378 if (lys_set_implemented_recursion((struct lys_module *)module, unres)) {
3379 goto error;
3380 }
3381 /* process augments in submodules */
3382 for (i = 0; i < module->inc_size; ++i) {
3383 if (!module->inc[i].submodule) {
3384 continue;
3385 }
3386 for (j = 0; j < module->inc[i].submodule->augment_size; j++) {
3387 /* apply augment */
Michal Vaskoa1911b92016-09-19 14:57:34 +02003388 if (!module->inc[i].submodule->augment[i].target
3389 && (unres_schema_add_node((struct lys_module *)module->inc[i].submodule, unres,
3390 &module->inc[i].submodule->augment[i], UNRES_AUGMENT, NULL) == -1)) {
Radek Krejci27fe55e2016-09-13 17:13:35 +02003391 goto error;
3392 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003393 }
3394 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02003395 /* resolve rest of unres items */
3396 if (unres->count && resolve_unres_schema((struct lys_module *)module, unres)) {
3397 goto error;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003398 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02003399 unres_schema_free((struct lys_module *)module, &unres);
Michal Vasko26055752016-05-03 11:36:31 +02003400
3401 return EXIT_SUCCESS;
Radek Krejci27fe55e2016-09-13 17:13:35 +02003402
3403error:
3404 ((struct lys_module *)module)->implemented = 0;
3405 unres_schema_free((struct lys_module *)module, &unres);
3406 return EXIT_FAILURE;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02003407}
3408
3409void
3410lys_submodule_module_data_free(struct lys_submodule *submodule)
3411{
3412 struct lys_node *next, *elem;
3413
3414 /* remove parsed data */
3415 LY_TREE_FOR_SAFE(submodule->belongsto->data, next, elem) {
3416 if (elem->module == (struct lys_module *)submodule) {
3417 lys_node_free(elem, NULL, 0);
3418 }
3419 }
3420}
Radek Krejcia1c33bf2016-09-07 12:38:49 +02003421
3422int
3423lys_is_key(struct lys_node_list *list, struct lys_node_leaf *leaf)
3424{
3425 uint8_t i;
3426
3427 for (i = 0; i < list->keys_size; i++) {
3428 if (list->keys[i] == leaf) {
3429 return i + 1;
3430 }
3431 }
3432
3433 return 0;
3434}