blob: d22e36d75af885f48c51bfb8b5e88dfeab1060fb [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
2 * @file tree.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Manipulation with libyang data structures
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 */
21
Radek Krejci812b10a2015-05-28 16:48:25 +020022#include <assert.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020023#include <stdlib.h>
24#include <sys/mman.h>
25#include <sys/stat.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020026#include <string.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020027
28#include "common.h"
29#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020030#include "parser.h"
Radek Krejci106efc02015-06-10 14:36:27 +020031#include "xml.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020032#include "tree_internal.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020033
34void ly_submodule_free(struct ly_submodule *submodule);
35
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020036static const char *
37strnodetype(LY_NODE_TYPE type)
Radek Krejcib7155b52015-06-10 17:03:01 +020038{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020039 switch (type) {
40 case LY_NODE_AUGMENT:
41 return "augment";
42 case LY_NODE_CONTAINER:
43 return "container";
44 case LY_NODE_CHOICE:
45 return "choice";
46 case LY_NODE_LEAF:
47 return "leaf";
48 case LY_NODE_LEAFLIST:
49 return "leaf-list";
50 case LY_NODE_LIST:
51 return "list";
52 case LY_NODE_ANYXML:
53 return "anyxml";
54 case LY_NODE_USES:
55 return "uses";
56 case LY_NODE_GROUPING:
57 return "grouping";
58 case LY_NODE_CASE:
59 return "case";
60 case LY_NODE_INPUT:
61 return "input";
62 case LY_NODE_OUTPUT:
63 return "output";
64 case LY_NODE_NOTIF:
65 return "notification";
Michal Vasko38d01f72015-06-15 09:41:06 +020066 case LY_NODE_RPC:
67 return "rpc";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020068 }
Radek Krejcib7155b52015-06-10 17:03:01 +020069
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020070 return NULL;
Radek Krejcib7155b52015-06-10 17:03:01 +020071}
72
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020073struct ly_mnode_leaf *
74find_leaf(struct ly_mnode *parent, const char *name, int len)
Radek Krejci8bc9ca02015-06-04 15:52:46 +020075{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020076 struct ly_mnode *child;
77 struct ly_mnode_leaf *result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +020078
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020079 if (!len) {
80 len = strlen(name);
81 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +020082
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020083 LY_TREE_FOR(parent->child, child) {
84 switch (child->nodetype) {
85 case LY_NODE_LEAF:
86 /* direct check */
87 if (child->name == name || (!strncmp(child->name, name, len) && !child->name[len])) {
88 return (struct ly_mnode_leaf *)child;
89 }
90 break;
91 case LY_NODE_USES:
92 /* search recursively */
93 result = find_leaf(child, name, len);
94 if (result) {
95 return result;
96 }
97 break;
98 default:
99 /* ignore */
100 break;
101 }
102 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200104 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200105}
Radek Krejcida04f4a2015-05-21 12:54:09 +0200106
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200107void
108ly_mnode_unlink(struct ly_mnode *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200109{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200110 struct ly_mnode *parent, *first;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200111
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200112 if (!node) {
113 return;
114 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200115
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200116 /* unlink from data model if necessary */
117 if (node->module) {
118 if (node->module->data == node) {
119 node->module->data = node->next;
Radek Krejci21181962015-06-30 14:11:00 +0200120 } else if (node->module->rpc == node) {
121 node->module->rpc = node->next;
122 } else if (node->module->notif == node) {
123 node->module->notif = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200124 }
125 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200126
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200127 /* store pointers to important nodes */
128 parent = node->parent;
129 if (parent && !parent->nodetype) {
130 /* handle augments - first, unlink it from the augment parent ... */
131 if (parent->child == node) {
132 parent->child = node->next;
133 }
134 /* and then continue with the target parent */
135 parent = ((struct ly_augment *)parent)->target;
136 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200137
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200138 /* unlink from parent */
139 if (parent) {
140 if (parent->child == node) {
141 parent->child = node->next;
142 }
143 node->parent = NULL;
144 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200145
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200146 /* unlink from siblings */
147 if (node->prev == node) {
148 /* there are no more siblings */
149 return;
150 }
151 if (node->next) {
152 node->next->prev = node->prev;
153 } else {
154 /* unlinking the last element */
155 if (parent) {
156 first = parent->child;
157 } else {
158 first = node;
159 while (node->prev->next) {
160 first = node->prev;
161 }
162 }
163 first->prev = node->prev;
164 }
165 if (node->prev->next) {
166 node->prev->next = node->next;
167 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200168
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200169 /* clean up the unlinked element */
170 node->next = NULL;
171 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200172}
173
174/*
175 * Add child model node at the end of the parent's child list.
176 * If the child is connected somewhere (has a parent), it is completely
177 * unlinked and none of the following conditions applies.
178 * If the child has prev sibling(s), they are ignored (child is added at the
179 * end of the child list).
180 * If the child has next sibling(s), all of them are connected with the parent.
181 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200182int
183ly_mnode_addchild(struct ly_mnode *parent, struct ly_mnode *child)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200184{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200185 struct ly_mnode *last;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200186
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200187 assert(parent);
188 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200189
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200190 /* checks */
191 switch (parent->nodetype) {
192 case LY_NODE_CONTAINER:
193 case LY_NODE_LIST:
194 case LY_NODE_GROUPING:
195 case LY_NODE_USES:
Michal Vasko38d01f72015-06-15 09:41:06 +0200196 case LY_NODE_INPUT:
197 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +0200198 case LY_NODE_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200199 if (!(child->nodetype &
200 (LY_NODE_ANYXML | LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_GROUPING | LY_NODE_LEAF |
201 LY_NODE_LEAFLIST | LY_NODE_LIST | LY_NODE_USES))) {
202 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
203 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
204 return EXIT_FAILURE;
205 }
206 break;
207 case LY_NODE_CHOICE:
208 if (!(child->nodetype &
209 (LY_NODE_ANYXML | LY_NODE_CASE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST))) {
210 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"choice\" %s.",
211 strnodetype(child->nodetype), parent->name);
212 return EXIT_FAILURE;
213 }
214 break;
215 case LY_NODE_CASE:
216 if (!(child->nodetype &
217 (LY_NODE_ANYXML | LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST | LY_NODE_USES))) {
218 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"case\" %s.",
219 strnodetype(child->nodetype), parent->name);
220 return EXIT_FAILURE;
221 }
222 break;
Michal Vasko38d01f72015-06-15 09:41:06 +0200223 case LY_NODE_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200224 if (!(child->nodetype & (LY_NODE_INPUT | LY_NODE_OUTPUT | LY_NODE_GROUPING))) {
Michal Vasko38d01f72015-06-15 09:41:06 +0200225 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"rpc\" %s.",
226 strnodetype(child->nodetype), parent->name);
227 return EXIT_FAILURE;
228 }
229 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200230 case LY_NODE_LEAF:
231 case LY_NODE_LEAFLIST:
232 case LY_NODE_ANYXML:
233 LOGVAL(VE_SPEC, 0, "The \"%s\" statement (%s) cannot have any substatement.",
234 strnodetype(parent->nodetype), parent->name);
235 return EXIT_FAILURE;
236 case LY_NODE_AUGMENT:
237 LOGVAL(VE_SPEC, 0, "Internal error (%s:%d)", __FILE__, __LINE__);
238 return EXIT_FAILURE;
239 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200240
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200241 if (child->parent) {
242 ly_mnode_unlink(child);
243 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200244
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200245 if (!parent->child) {
246 /* the only/first child of the parent */
247 parent->child = child;
248 child->parent = parent;
249 last = child;
250 } else {
251 /* add a new child at the end of parent's child list */
252 last = parent->child->prev;
253 last->next = child;
254 child->prev = last;
255 }
256 while (last->next) {
257 last = last->next;
258 last->parent = parent;
259 }
260 parent->child->prev = last;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200261
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200262 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200263}
264
Radek Krejci3bde87f2015-06-05 16:51:58 +0200265/*
Michal Vasko25880b42015-06-12 10:16:33 +0200266 * id - schema-nodeid
Michal Vasko6f6ac232015-06-18 11:11:46 +0200267 *
268 * node_type - LY_NODE_AUGMENT (searches also RPCs and notifications)
269 * - LY_NODE_USES (the caller is actually either an augment or refine in a uses, only
270 * descendant-schema-nodeid allowed, ".." not allowed)
271 * - LY_NODE_CHOICE (search only start->child, only descendant-schema-nodeid allowed)
Radek Krejci3bde87f2015-06-05 16:51:58 +0200272 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200273struct ly_mnode *
Michal Vasko6f6ac232015-06-18 11:11:46 +0200274resolve_schema_nodeid(const char *id, struct ly_mnode *start, struct ly_module *mod, LY_NODE_TYPE node_type)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200275{
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200276 const char *name, *prefix, *ptr;
Michal Vaskoaf989e62015-06-29 14:57:45 +0200277 struct ly_mnode *sibling;
Michal Vasko25880b42015-06-12 10:16:33 +0200278 struct ly_submodule *sub_mod;
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200279 uint32_t i, j, nam_len, pref_len;
Michal Vaskoaf989e62015-06-29 14:57:45 +0200280 /* 0 - in module, 1 - in 1st submodule, 2 - in second submodule, ... */
281 uint8_t in_submod;
282 /* 0 - in data, 1 - in RPCs, 2 - in notifications */
283 uint8_t in_mod_part;
284 int found;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200285
Radek Krejcif5be10f2015-06-16 13:29:36 +0200286 assert(mod);
287 assert(id);
288
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200289 if (id[0] == '/') {
Michal Vasko6f6ac232015-06-18 11:11:46 +0200290 if (node_type & (LY_NODE_USES | LY_NODE_CHOICE)) {
291 return NULL;
292 }
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200293 ptr = strchr(id+1, '/');
294 prefix = id+1;
295 } else {
296 ptr = strchr(id, '/');
297 prefix = id;
298 }
299 pref_len = (ptr ? (unsigned)(ptr-prefix) : strlen(prefix));
Radek Krejci3bde87f2015-06-05 16:51:58 +0200300
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200301 ptr = strnchr(prefix, ':', pref_len);
302 /* there is prefix */
303 if (ptr) {
304 nam_len = (pref_len-(ptr-prefix))-1;
305 pref_len = ptr-prefix;
306 name = ptr+1;
307
308 /* no prefix used */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200309 } else {
310 name = prefix;
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200311 nam_len = pref_len;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200312 prefix = NULL;
313 }
Michal Vasko25880b42015-06-12 10:16:33 +0200314
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200315 /* absolute-schema-nodeid */
316 if (id[0] == '/') {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200317 start = NULL;
Michal Vaskoaf989e62015-06-29 14:57:45 +0200318 found = 0;
Radek Krejcif5be10f2015-06-16 13:29:36 +0200319
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200320 /* it is not the local prefix */
Michal Vasko3b2b0412015-07-01 12:15:02 +0200321 if (prefix && ((pref_len != strlen(mod->prefix)) || strncmp(prefix, mod->prefix, pref_len))) {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200322 /* check imports */
323 for (i = 0; i < mod->imp_size; i++) {
Michal Vasko3b2b0412015-07-01 12:15:02 +0200324 if ((pref_len == strlen(mod->imp[i].prefix)) && !strncmp(mod->imp[i].prefix, prefix, pref_len)) {
Michal Vaskoaf989e62015-06-29 14:57:45 +0200325 mod = mod->imp[i].module;
326 start = mod->data;
327 found = 1;
Michal Vasko25880b42015-06-12 10:16:33 +0200328 break;
329 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200330 }
Radek Krejcif5be10f2015-06-16 13:29:36 +0200331
332 /* no match - check include imports */
Michal Vaskoaf989e62015-06-29 14:57:45 +0200333 if (!found) {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200334 for (i = 0; i < mod->inc_size; i++) {
335 sub_mod = mod->inc[i].submodule;
336 for (j = 0; j < sub_mod->imp_size; j++) {
Michal Vasko3b2b0412015-07-01 12:15:02 +0200337 if ((pref_len == strlen(sub_mod->imp[j].prefix))
338 && !strncmp(sub_mod->imp[j].prefix, prefix, pref_len)) {
Michal Vaskoaf989e62015-06-29 14:57:45 +0200339 mod = sub_mod->imp[j].module;
340 start = mod->data;
341 found = 1;
Radek Krejcif5be10f2015-06-16 13:29:36 +0200342 break;
343 }
344 }
345
Michal Vaskoaf989e62015-06-29 14:57:45 +0200346 if (found) {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200347 break;
348 }
349 }
350 }
351
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200352 /* no match */
Michal Vaskoaf989e62015-06-29 14:57:45 +0200353 if (!found) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200354 return NULL;
355 }
Michal Vasko25880b42015-06-12 10:16:33 +0200356
Michal Vasko3ea42992015-06-22 10:51:02 +0200357 /* it is likely the local prefix (checked later) */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200358 } else {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200359 start = mod->data;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200360 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200361
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200362 /* descendant-schema-nodeid */
Radek Krejcif5be10f2015-06-16 13:29:36 +0200363 } else {
364 assert(start);
365 start = start->child;
366 }
367
Michal Vaskoaf989e62015-06-29 14:57:45 +0200368 in_submod = 0;
369 in_mod_part = 0;
370
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200371 while (1) {
372 if (!strcmp(name, ".")) {
373 /* this node - start does not change */
374 } else if (!strcmp(name, "..")) {
Michal Vaskoaf989e62015-06-29 14:57:45 +0200375 /* ".." is not allowed in refines and augments in uses, there is no need for it there */
Michal Vasko6f6ac232015-06-18 11:11:46 +0200376 if (!start || (node_type == LY_NODE_USES)) {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200377 return NULL;
378 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200379 start = start->parent;
380 } else {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200381 sibling = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200382 LY_TREE_FOR(start, sibling) {
383 /* match */
Michal Vasko3ea42992015-06-22 10:51:02 +0200384 if (!strncmp(name, sibling->name, nam_len)
385 && ((sibling->name[nam_len] == '/') || (sibling->name[nam_len] == '\0'))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200386 /* prefix check, it's not our own */
Michal Vasko3b2b0412015-07-01 12:15:02 +0200387 if (prefix && ((pref_len != strlen(sibling->module->prefix))
388 || strncmp(prefix, sibling->module->prefix, pref_len))) {
Michal Vasko25880b42015-06-12 10:16:33 +0200389
Michal Vasko6f6ac232015-06-18 11:11:46 +0200390 /* in choice and the prefix is not ours, error for sure */
391 if (node_type == LY_NODE_CHOICE) {
392 return NULL;
393 }
394
Michal Vasko25880b42015-06-12 10:16:33 +0200395 /* import prefix check */
396 for (i = 0; i < sibling->module->imp_size; i++) {
Michal Vasko3b2b0412015-07-01 12:15:02 +0200397 if ((pref_len == strlen(sibling->module->imp[i].prefix))
398 && !strncmp(sibling->module->imp[i].prefix, prefix, pref_len)
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200399 && (sibling->module->imp[i].module == sibling->module)) {
Michal Vasko25880b42015-06-12 10:16:33 +0200400 break;
401 }
402 }
403
404 /* import prefix check failed */
405 if (i == sibling->module->imp_size) {
406 /* include import prefix check */
407 for (i = 0; i < sibling->module->inc_size; i++) {
408 sub_mod = sibling->module->inc[i].submodule;
409 for (j = 0; j < sub_mod->imp_size; j++) {
Michal Vasko3b2b0412015-07-01 12:15:02 +0200410 if ((pref_len == strlen(sub_mod->imp[j].prefix))
411 && !strncmp(sub_mod->imp[j].prefix, prefix, pref_len)
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200412 && (sub_mod->imp[j].module == sibling->module)) {
Michal Vasko25880b42015-06-12 10:16:33 +0200413 break;
414 }
415 }
416
417 if (j < sub_mod->imp_size) {
418 break;
419 }
420 }
421
422 /* include import prefix check failed too - definite fail */
423 if (i == sibling->module->inc_size) {
Michal Vasko25880b42015-06-12 10:16:33 +0200424 return NULL;
425 }
426 }
427 }
428
429 /* the result node? */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200430 ptr = name+nam_len;
431 if (!ptr[0]) {
Michal Vasko25880b42015-06-12 10:16:33 +0200432 return sibling;
433 }
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200434 assert(ptr[0] == '/');
Michal Vasko25880b42015-06-12 10:16:33 +0200435
436 /* check for shorthand cases - then 'start' does not change */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200437 if (!sibling->parent || (sibling->parent->nodetype != LY_NODE_CHOICE)
438 || (sibling->nodetype == LY_NODE_CASE)) {
Michal Vasko25880b42015-06-12 10:16:33 +0200439 start = sibling->child;
440 }
441 break;
442 }
443 }
Radek Krejcif5be10f2015-06-16 13:29:36 +0200444
Michal Vasko6f6ac232015-06-18 11:11:46 +0200445 /* we did not find the case in direct siblings */
446 if (node_type == LY_NODE_CHOICE) {
447 return NULL;
448 }
449
Michal Vasko25880b42015-06-12 10:16:33 +0200450 /* no match */
451 if (!sibling) {
Michal Vasko6f6ac232015-06-18 11:11:46 +0200452 /* on augment search also RPCs and notifications, if we are in top-level */
Michal Vaskoaf989e62015-06-29 14:57:45 +0200453 if ((node_type == LY_NODE_AUGMENT) && (!start || !start->parent)) {
Michal Vasko6f6ac232015-06-18 11:11:46 +0200454 /* we have searched all the data nodes */
Michal Vaskoaf989e62015-06-29 14:57:45 +0200455 if (in_mod_part == 0) {
456 if (!in_submod) {
457 start = mod->rpc;
458 } else {
459 start = mod->inc[in_submod-1].submodule->rpc;
Michal Vasko6f6ac232015-06-18 11:11:46 +0200460 }
Michal Vaskoaf989e62015-06-29 14:57:45 +0200461 in_mod_part = 1;
462 continue;
Michal Vasko6f6ac232015-06-18 11:11:46 +0200463 }
464 /* we have searched all the RPCs */
Michal Vaskoaf989e62015-06-29 14:57:45 +0200465 if (in_mod_part == 1) {
466 if (!in_submod) {
467 start = mod->notif;
468 } else {
469 start = mod->inc[in_submod-1].submodule->notif;
Michal Vasko6f6ac232015-06-18 11:11:46 +0200470 }
Michal Vaskoaf989e62015-06-29 14:57:45 +0200471 in_mod_part = 2;
472 continue;
Michal Vasko6f6ac232015-06-18 11:11:46 +0200473 }
Michal Vaskoaf989e62015-06-29 14:57:45 +0200474 /* we have searched all the notifications, nothing else to search in this module */
475 }
476
477 /* are we done with the included submodules as well? */
478 if (in_submod-1 == mod->inc_size) {
Michal Vasko86b84452015-06-22 10:54:05 +0200479 return NULL;
Michal Vasko6f6ac232015-06-18 11:11:46 +0200480 }
Michal Vaskoaf989e62015-06-29 14:57:45 +0200481
482 /* we aren't, check the next one */
483 ++in_submod;
484 in_mod_part = 0;
485 start = mod->inc[in_submod-1].submodule->data;
486 continue;
Michal Vasko25880b42015-06-12 10:16:33 +0200487 }
488 }
489
Michal Vaskoa158c682015-06-17 09:25:38 +0200490 assert((*(name+nam_len) == '/') || (*(name+nam_len) == '\0'));
491
492 /* make prefix point to the next node name */
493 prefix = name+nam_len;
494 if (!prefix[0]) {
495 return start;
496 }
497 ++prefix;
498
499 /* parse prefix and node name */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200500 ptr = strchr(prefix, '/');
501 pref_len = (ptr ? (unsigned)(ptr-prefix) : strlen(prefix));
502 ptr = strnchr(prefix, ':', pref_len);
503
504 /* there is prefix */
505 if (ptr) {
Michal Vaskoa158c682015-06-17 09:25:38 +0200506 nam_len = (pref_len-(ptr-prefix))-1;
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200507 pref_len = ptr-prefix;
508 name = ptr+1;
509
510 /* no prefix used */
Michal Vasko25880b42015-06-12 10:16:33 +0200511 } else {
512 name = prefix;
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200513 nam_len = pref_len;
Michal Vasko25880b42015-06-12 10:16:33 +0200514 prefix = NULL;
515 }
Michal Vasko25880b42015-06-12 10:16:33 +0200516 }
517
518 /* cannot get here */
519 return NULL;
Radek Krejci3bde87f2015-06-05 16:51:58 +0200520}
521
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200522API struct ly_module *
523ly_module_read(struct ly_ctx *ctx, const char *data, LY_MINFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200524{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200525 if (!ctx || !data) {
526 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
527 return NULL;
528 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200529
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200530 switch (format) {
531 case LY_IN_YIN:
532 return yin_read_module(ctx, data);
533 case LY_IN_YANG:
534 default:
535 /* TODO */
536 return NULL;
537 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200538
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200539 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200540}
541
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200542struct ly_submodule *
543ly_submodule_read(struct ly_module *module, const char *data, LY_MINFORMAT format)
Radek Krejciefaeba32015-05-27 14:30:57 +0200544{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200545 assert(module);
546 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200547
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200548 switch (format) {
549 case LY_IN_YIN:
550 return yin_read_submodule(module, data);
551 case LY_IN_YANG:
552 default:
553 /* TODO */
554 return NULL;
555 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200556
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200557 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +0200558}
559
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200560API struct ly_module *
561ly_module_read_fd(struct ly_ctx *ctx, int fd, LY_MINFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200562{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200563 struct ly_module *module;
564 struct stat sb;
565 char *addr;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200566
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200567 if (!ctx || fd < 0) {
568 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
569 return NULL;
570 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200571
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200572 /*
573 * TODO
574 * This is just a temporary solution to make working automatic search for
575 * imported modules. This doesn't work e.g. for streams (stdin)
576 */
577 fstat(fd, &sb);
578 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
579 module = ly_module_read(ctx, addr, format);
580 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200581
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200582 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200583}
584
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200585struct ly_submodule *
586ly_submodule_read_fd(struct ly_module *module, int fd, LY_MINFORMAT format)
Radek Krejciefaeba32015-05-27 14:30:57 +0200587{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200588 struct ly_submodule *submodule;
589 struct stat sb;
590 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +0200591
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200592 assert(module);
593 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +0200594
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200595 /*
596 * TODO
597 * This is just a temporary solution to make working automatic search for
598 * imported modules. This doesn't work e.g. for streams (stdin)
599 */
600 fstat(fd, &sb);
601 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
602 /* TODO addr error check */
603 submodule = ly_submodule_read(module, addr, format);
604 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +0200605
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200606 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +0200607
608}
609
Radek Krejci3733a802015-06-19 13:43:21 +0200610struct ly_restr *
611ly_restr_dup(struct ly_ctx *ctx, struct ly_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200612{
Radek Krejci3733a802015-06-19 13:43:21 +0200613 struct ly_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200614 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200615
Radek Krejci3733a802015-06-19 13:43:21 +0200616 if (!size) {
617 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200618 }
Radek Krejci3733a802015-06-19 13:43:21 +0200619
620 result = calloc(size, sizeof *result);
621 for (i = 0; i < size; i++) {
622 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
623 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
624 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
625 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
626 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
627 }
628
629 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200630}
631
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200632void
Radek Krejci0bd5db42015-06-19 13:30:07 +0200633ly_restr_free(struct ly_ctx *ctx, struct ly_restr *restr)
634{
635 assert(ctx);
636 if (!restr) {
637 return;
638 }
639
640 lydict_remove(ctx, restr->expr);
641 lydict_remove(ctx, restr->dsc);
642 lydict_remove(ctx, restr->ref);
643 lydict_remove(ctx, restr->eapptag);
644 lydict_remove(ctx, restr->emsg);
645}
646
647void
Radek Krejci3733a802015-06-19 13:43:21 +0200648ly_type_dup(struct ly_ctx *ctx, struct ly_type *new, struct ly_type *old)
649{
650 int i;
651
652 new->prefix = lydict_insert(ctx, old->prefix, 0);
653 new->base = old->base;
654 new->der = old->der;
655
656 switch (new->base) {
657 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +0200658 if (old->info.binary.length) {
659 new->info.binary.length = ly_restr_dup(ctx, old->info.binary.length, 1);
660 }
Radek Krejci3733a802015-06-19 13:43:21 +0200661 break;
662
663 case LY_TYPE_BITS:
664 new->info.bits.count = old->info.bits.count;
665 if (new->info.bits.count) {
666 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
667 for (i = 0; i < new->info.bits.count; i++) {
668 new->info.bits.bit[i].name = lydict_insert(ctx, old->info.bits.bit[i].name, 0);
669 new->info.bits.bit[i].dsc = lydict_insert(ctx, old->info.bits.bit[i].dsc, 0);
670 new->info.bits.bit[i].ref = lydict_insert(ctx, old->info.bits.bit[i].ref, 0);
671 new->info.bits.bit[i].status = old->info.bits.bit[i].status;
672 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
673 }
674 }
675 break;
676
Radek Krejcif9401c32015-06-26 16:47:36 +0200677 case LY_TYPE_DEC64:
678 new->info.dec64.dig = old->info.dec64.dig;
679 if (old->info.dec64.range) {
680 new->info.dec64.range = ly_restr_dup(ctx, old->info.dec64.range, 1);
681 }
682 break;
683
Radek Krejci3733a802015-06-19 13:43:21 +0200684 case LY_TYPE_ENUM:
685 new->info.enums.count = old->info.enums.count;
686 if (new->info.enums.count) {
687 new->info.enums.list = calloc(new->info.enums.count, sizeof *new->info.enums.list);
688 for (i = 0; i < new->info.enums.count; i++) {
689 new->info.enums.list[i].name = lydict_insert(ctx, old->info.enums.list[i].name, 0);
690 new->info.enums.list[i].dsc = lydict_insert(ctx, old->info.enums.list[i].dsc, 0);
691 new->info.enums.list[i].ref = lydict_insert(ctx, old->info.enums.list[i].ref, 0);
692 new->info.enums.list[i].status = old->info.enums.list[i].status;
693 new->info.enums.list[i].value = old->info.enums.list[i].value;
694 }
695 }
696 break;
697
Radek Krejci4a7b5ee2015-06-19 14:56:43 +0200698 case LY_TYPE_IDENT:
699 new->info.ident.ref = old->info.ident.ref;
700 break;
701
Radek Krejciaf351422015-06-19 14:49:38 +0200702 case LY_TYPE_INST:
703 new->info.inst.req = old->info.inst.req;
704 break;
705
Radek Krejcif2860132015-06-20 12:37:20 +0200706 case LY_TYPE_INT8:
707 case LY_TYPE_INT16:
708 case LY_TYPE_INT32:
709 case LY_TYPE_INT64:
710 case LY_TYPE_UINT8:
711 case LY_TYPE_UINT16:
712 case LY_TYPE_UINT32:
713 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +0200714 if (old->info.num.range) {
715 new->info.num.range = ly_restr_dup(ctx, old->info.num.range, 1);
716 }
Radek Krejcif2860132015-06-20 12:37:20 +0200717 break;
718
Radek Krejcidc4c1412015-06-19 15:39:54 +0200719 case LY_TYPE_LEAFREF:
720 new->info.lref.path = lydict_insert(ctx, old->info.lref.path, 0);
721 break;
722
Radek Krejci3733a802015-06-19 13:43:21 +0200723 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +0200724 if (old->info.str.length) {
725 new->info.str.length = ly_restr_dup(ctx, old->info.str.length, 1);
726 }
727 new->info.str.patterns = ly_restr_dup(ctx, old->info.str.patterns, old->info.str.pat_count);
Radek Krejci3733a802015-06-19 13:43:21 +0200728 break;
729
730 default:
Radek Krejci4a7b5ee2015-06-19 14:56:43 +0200731 /* TODO - remove default to make sure that all types are covered */
Radek Krejci3733a802015-06-19 13:43:21 +0200732 break;
733 }
734}
735
736void
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200737ly_type_free(struct ly_ctx *ctx, struct ly_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +0200738{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200739 int i;
Radek Krejci5a065542015-05-22 15:02:07 +0200740
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200741 assert(ctx);
742 if (!type) {
743 return;
744 }
Radek Krejci812b10a2015-05-28 16:48:25 +0200745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200746 lydict_remove(ctx, type->prefix);
Radek Krejci5a065542015-05-22 15:02:07 +0200747
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200748 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +0200749 case LY_TYPE_BINARY:
750 ly_restr_free(ctx, type->info.binary.length);
751 free(type->info.binary.length);
752 break;
Radek Krejci994b6f62015-06-18 16:47:27 +0200753 case LY_TYPE_BITS:
754 for (i = 0; i < type->info.bits.count; i++) {
755 lydict_remove(ctx, type->info.bits.bit[i].name);
756 lydict_remove(ctx, type->info.bits.bit[i].dsc);
757 lydict_remove(ctx, type->info.bits.bit[i].ref);
758 }
759 free(type->info.bits.bit);
760 break;
Radek Krejcif9401c32015-06-26 16:47:36 +0200761
762 case LY_TYPE_DEC64:
763 ly_restr_free(ctx, type->info.dec64.range);
764 free(type->info.dec64.range);
765 break;
766
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200767 case LY_TYPE_ENUM:
768 for (i = 0; i < type->info.enums.count; i++) {
769 lydict_remove(ctx, type->info.enums.list[i].name);
770 lydict_remove(ctx, type->info.enums.list[i].dsc);
771 lydict_remove(ctx, type->info.enums.list[i].ref);
772 }
773 free(type->info.enums.list);
774 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +0200775
Radek Krejci6fcb9dd2015-06-22 10:16:37 +0200776 case LY_TYPE_INT8:
777 case LY_TYPE_INT16:
778 case LY_TYPE_INT32:
779 case LY_TYPE_INT64:
780 case LY_TYPE_UINT8:
781 case LY_TYPE_UINT16:
782 case LY_TYPE_UINT32:
783 case LY_TYPE_UINT64:
784 ly_restr_free(ctx, type->info.num.range);
785 free(type->info.num.range);
786 break;
787
Radek Krejcidc4c1412015-06-19 15:39:54 +0200788 case LY_TYPE_LEAFREF:
789 lydict_remove(ctx, type->info.lref.path);
790 break;
791
Radek Krejci3733a802015-06-19 13:43:21 +0200792 case LY_TYPE_STRING:
793 ly_restr_free(ctx, type->info.str.length);
794 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200795 for (i = 0; i < type->info.str.pat_count; i++) {
796 ly_restr_free(ctx, &type->info.str.patterns[i]);
797 }
798 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +0200799 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +0200800
801 case LY_TYPE_IDENT:
802 /* nothing to do */
803 break;
804
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200805 default:
Radek Krejci4a7b5ee2015-06-19 14:56:43 +0200806 /* TODO - remove default to make sure that all types are covered */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200807 break;
808 }
Radek Krejci5a065542015-05-22 15:02:07 +0200809}
810
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200811struct ly_tpdf *
812ly_tpdf_dup(struct ly_ctx *ctx, struct ly_tpdf *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200813{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200814 struct ly_tpdf *result;
815 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200816
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200817 if (!size) {
818 return NULL;
819 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200820
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200821 result = calloc(size, sizeof *result);
822 for (i = 0; i < size; i++) {
823 result[i].name = lydict_insert(ctx, old[i].name, 0);
824 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
825 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
826 result[i].flags = old[i].flags;
827 result[i].module = old[i].module;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200828
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200829 ly_type_dup(ctx, &(result[i].type), &(old[i].type));
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200830
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200831 result[i].dflt = lydict_insert(ctx, old[i].dflt, 0);
832 result[i].units = lydict_insert(ctx, old[i].units, 0);
833 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200834
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200835 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200836}
837
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200838void
839ly_tpdf_free(struct ly_ctx *ctx, struct ly_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200840{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200841 assert(ctx);
842 if (!tpdf) {
843 return;
844 }
Radek Krejci812b10a2015-05-28 16:48:25 +0200845
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200846 lydict_remove(ctx, tpdf->name);
847 lydict_remove(ctx, tpdf->dsc);
848 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200849
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200850 ly_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200851
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200852 lydict_remove(ctx, tpdf->units);
853 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200854}
855
Radek Krejci00768f42015-06-18 17:04:04 +0200856struct ly_when *
857ly_when_dup(struct ly_ctx *ctx, struct ly_when *old)
858{
859 struct ly_when *new;
860
861 if (!old) {
862 return NULL;
863 }
864
865 new = calloc(1, sizeof *new);
866 new->cond = lydict_insert(ctx, old->cond, 0);
867 new->dsc = lydict_insert(ctx, old->dsc, 0);
868 new->ref = lydict_insert(ctx, old->ref, 0);
869
870 return new;
871}
872
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200873void
874ly_when_free(struct ly_ctx *ctx, struct ly_when *w)
875{
876 if (!w) {
877 return;
878 }
879
880 lydict_remove(ctx, w->cond);
881 lydict_remove(ctx, w->dsc);
882 lydict_remove(ctx, w->ref);
883
884 free(w);
885}
886
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200887struct ly_augment *
888ly_augment_dup(struct ly_module *module, struct ly_mnode *parent, struct ly_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +0200889{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200890 struct ly_augment *new = NULL;
891 int i = -1;
Radek Krejci106efc02015-06-10 14:36:27 +0200892
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200893 if (!size) {
894 return NULL;
895 }
Radek Krejci106efc02015-06-10 14:36:27 +0200896
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200897 new = calloc(size, sizeof *new);
898 for (i = 0; i < size; i++) {
899 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
900 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
901 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
902 new[i].flags = old[i].flags;
903 /* .target = NULL; .nodetype = 0 */
Radek Krejci106efc02015-06-10 14:36:27 +0200904
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200905 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +0200906
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200907 /* copy the definition of augment nodes */
908 if (old[i].child) {
909 new[i].child = (struct ly_mnode *)lyxml_dup_elem(module->ctx, (struct lyxml_elem *)old[i].child, NULL, 1);
910 }
911 }
Radek Krejci106efc02015-06-10 14:36:27 +0200912
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200913 return new;
Radek Krejci106efc02015-06-10 14:36:27 +0200914}
915
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200916struct ly_refine *
917ly_refine_dup(struct ly_ctx *ctx, struct ly_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +0200918{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200919 struct ly_refine *result;
920 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +0200921
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200922 if (!size) {
923 return NULL;
924 }
Michal Vasko1982cad2015-06-08 15:49:30 +0200925
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200926 result = calloc(size, sizeof *result);
927 for (i = 0; i < size; i++) {
928 result[i].target = lydict_insert(ctx, old[i].target, 0);
929 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
930 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
931 result[i].flags = old[i].flags;
932 result[i].target_type = old[i].target_type;
933 result[i].must_size = old[i].must_size;
Radek Krejci0bd5db42015-06-19 13:30:07 +0200934 result[i].must = ly_restr_dup(ctx, old[i].must, old[i].must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200935 if (result[i].target_type & (LY_NODE_LEAF | LY_NODE_CHOICE)) {
936 result[i].mod.dflt = lydict_insert(ctx, old[i].mod.dflt, 0);
937 } else if (result[i].target_type == LY_NODE_CONTAINER) {
938 result[i].mod.presence = lydict_insert(ctx, old[i].mod.presence, 0);
939 } else if (result[i].target_type & (LY_NODE_LIST | LY_NODE_LEAFLIST)) {
940 result[i].mod.list = old[i].mod.list;
941 }
942 }
Michal Vasko1982cad2015-06-08 15:49:30 +0200943
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200944 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +0200945}
946
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200947void
948ly_ident_free(struct ly_ctx *ctx, struct ly_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +0200949{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200950 struct ly_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +0200951
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200952 assert(ctx);
953 if (!ident) {
954 return;
955 }
Radek Krejci812b10a2015-05-28 16:48:25 +0200956
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200957 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200958 * if caller free only a single data model which is used (its identity is
959 * reference from identity in another module), this silly freeing can lead
960 * to segmentation fault. But without noting if the module is used by some
961 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +0200962 *
963 * Possible solution is to not allow caller to remove particular schema
964 * from the context.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200965 */
966 while (ident->der) {
967 der = ident->der;
968 ident->der = der->next;
969 free(der);
970 }
Radek Krejci6793db02015-05-22 17:49:54 +0200971
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200972 lydict_remove(ctx, ident->name);
973 lydict_remove(ctx, ident->dsc);
974 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +0200975
976}
977
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200978void
979ly_grp_free(struct ly_ctx *ctx, struct ly_mnode_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200980{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200981 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200982
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200983 /* handle only specific parts for LY_NODE_GROUPING */
984 for (i = 0; i < grp->tpdf_size; i++) {
985 ly_tpdf_free(ctx, &grp->tpdf[i]);
986 }
987 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +0200988}
989
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200990void
991ly_anyxml_free(struct ly_ctx *ctx, struct ly_mnode_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +0200992{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200993 int i;
Radek Krejci537cf382015-06-04 11:07:01 +0200994
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200995 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci0bd5db42015-06-19 13:30:07 +0200996 ly_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200997 }
998 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200999
1000 ly_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001001}
1002
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001003void
1004ly_leaf_free(struct ly_ctx *ctx, struct ly_mnode_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001005{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001006 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001007
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001008 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001009 ly_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001010 }
1011 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001012
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001013 ly_when_free(ctx, leaf->when);
1014
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001015 ly_type_free(ctx, &leaf->type);
1016 lydict_remove(ctx, leaf->units);
1017 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001018}
1019
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001020void
1021ly_leaflist_free(struct ly_ctx *ctx, struct ly_mnode_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001022{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001023 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001024
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001025 for (i = 0; i < llist->must_size; i++) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001026 ly_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001027 }
1028 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001029
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001030 ly_when_free(ctx, llist->when);
1031
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001032 ly_type_free(ctx, &llist->type);
1033 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001034}
1035
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001036void
1037ly_list_free(struct ly_ctx *ctx, struct ly_mnode_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001038{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001039 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001040
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001041 /* handle only specific parts for LY_NODE_LIST */
1042 for (i = 0; i < list->tpdf_size; i++) {
1043 ly_tpdf_free(ctx, &list->tpdf[i]);
1044 }
1045 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001046
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001047 for (i = 0; i < list->must_size; i++) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001048 ly_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001049 }
1050 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001051
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001052 ly_when_free(ctx, list->when);
1053
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001054 for (i = 0; i < list->unique_size; i++) {
1055 free(list->unique[i].leafs);
1056 }
1057 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001058
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001059 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001060}
1061
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001062void
1063ly_container_free(struct ly_ctx *ctx, struct ly_mnode_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001064{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001065 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001066
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001067 /* handle only specific parts for LY_NODE_CONTAINER */
1068 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001069
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001070 for (i = 0; i < cont->tpdf_size; i++) {
1071 ly_tpdf_free(ctx, &cont->tpdf[i]);
1072 }
1073 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001074
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001075 for (i = 0; i < cont->must_size; i++) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001076 ly_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001077 }
1078 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001079
1080 ly_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001081}
1082
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001083void
Radek Krejci3cf9e222015-06-18 11:37:50 +02001084ly_feature_free(struct ly_ctx *ctx, struct ly_feature *f)
1085{
1086 lydict_remove(ctx, f->name);
1087 lydict_remove(ctx, f->dsc);
1088 lydict_remove(ctx, f->ref);
1089 free(f->features);
1090}
1091
1092void
Radek Krejcieb00f512015-07-01 16:44:58 +02001093ly_deviation_free(struct ly_ctx *ctx, struct ly_deviation *dev)
1094{
1095 int i, j;
1096
1097 lydict_remove(ctx, dev->target_name);
1098 lydict_remove(ctx, dev->dsc);
1099 lydict_remove(ctx, dev->ref);
1100
1101 for (i = 0; i < dev->deviate_size; i++) {
1102 lydict_remove(ctx, dev->deviate[i].dflt);
1103 lydict_remove(ctx, dev->deviate[i].units);
1104
1105 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1106 for (j = 0; j < dev->deviate[i].must_size; j++) {
1107 ly_restr_free(ctx, &dev->deviate[i].must[j]);
1108 }
1109 free(dev->deviate[i].must);
1110
1111 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1112 free(dev->deviate[j].unique[j].leafs);
1113 }
1114 free(dev->deviate[i].unique);
1115 }
1116 }
1117 free(dev->deviate);
1118}
1119
1120void
Radek Krejcif5be10f2015-06-16 13:29:36 +02001121ly_augment_free(struct ly_ctx *ctx, struct ly_augment *aug)
1122{
1123 lydict_remove(ctx, aug->target_name);
1124 lydict_remove(ctx, aug->dsc);
1125 lydict_remove(ctx, aug->ref);
1126
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001127 ly_when_free(ctx, aug->when);
1128
Radek Krejcif5be10f2015-06-16 13:29:36 +02001129 lyxml_free_elem(ctx, (struct lyxml_elem *)aug->child);
1130}
1131
1132void
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001133ly_uses_free(struct ly_ctx *ctx, struct ly_mnode_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +02001134{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001135 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001136
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001137 for (i = 0; i < uses->refine_size; i++) {
1138 lydict_remove(ctx, uses->refine[i].target);
1139 lydict_remove(ctx, uses->refine[i].dsc);
1140 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001141
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001142 for (j = 0; j < uses->refine[j].must_size; j++) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001143 ly_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001144 }
1145 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001146
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001147 if (uses->refine[i].target_type & (LY_NODE_LEAF | LY_NODE_CHOICE)) {
1148 lydict_remove(ctx, uses->refine[i].mod.dflt);
1149 } else if (uses->refine[i].target_type & LY_NODE_CONTAINER) {
1150 lydict_remove(ctx, uses->refine[i].mod.presence);
1151 }
1152 }
1153 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001154
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001155 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02001156 ly_augment_free(ctx, &uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001157 }
1158 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001159
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001160 ly_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001161}
1162
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001163void
1164ly_mnode_free(struct ly_mnode *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001165{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001166 struct ly_ctx *ctx;
1167 struct ly_mnode *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001168
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001169 if (!node) {
1170 return;
1171 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001172
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001173 assert(node->module);
1174 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001175
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001176 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001177
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001178 /* common part */
1179 LY_TREE_FOR_SAFE(node->child, next, sub) {
1180 ly_mnode_free(sub);
1181 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001182 free(node->features);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001183
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001184 lydict_remove(ctx, node->name);
1185 lydict_remove(ctx, node->dsc);
1186 lydict_remove(ctx, node->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001187
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001188 /* specific part */
1189 switch (node->nodetype) {
1190 case LY_NODE_CONTAINER:
1191 ly_container_free(ctx, (struct ly_mnode_container *)node);
1192 break;
1193 case LY_NODE_CHOICE:
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001194 ly_when_free(ctx, ((struct ly_mnode_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001195 break;
1196 case LY_NODE_LEAF:
1197 ly_leaf_free(ctx, (struct ly_mnode_leaf *)node);
1198 break;
1199 case LY_NODE_LEAFLIST:
1200 ly_leaflist_free(ctx, (struct ly_mnode_leaflist *)node);
1201 break;
1202 case LY_NODE_LIST:
1203 ly_list_free(ctx, (struct ly_mnode_list *)node);
1204 break;
1205 case LY_NODE_ANYXML:
1206 ly_anyxml_free(ctx, (struct ly_mnode_anyxml *)node);
1207 break;
1208 case LY_NODE_USES:
1209 ly_uses_free(ctx, (struct ly_mnode_uses *)node);
1210 break;
1211 case LY_NODE_CASE:
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001212 ly_when_free(ctx, ((struct ly_mnode_case *)node)->when);
1213 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001214 case LY_NODE_AUGMENT:
1215 /* do nothing */
1216 break;
Michal Vasko0ea41032015-06-16 08:53:55 +02001217 case LY_NODE_GROUPING:
1218 case LY_NODE_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001219 case LY_NODE_INPUT:
1220 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001221 case LY_NODE_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001222 ly_grp_free(ctx, (struct ly_mnode_grp *)node);
1223 break;
1224 }
Radek Krejci5a065542015-05-22 15:02:07 +02001225
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001226 /* again common part */
1227 ly_mnode_unlink(node);
1228 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001229}
1230
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001231static void
1232module_free_common(struct ly_module *module)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001233{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001234 struct ly_ctx *ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001235 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001236 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001237
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001238 assert(module->ctx);
1239 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001240
Radek Krejcidce51452015-06-16 15:20:08 +02001241 /* as first step, free the imported modules */
1242 for (i = 0; i < module->imp_size; i++) {
1243 /* get the imported module from the context and then free,
1244 * this check is necessary because the imported module can
1245 * be already removed
1246 */
1247 l = ctx->models.used;
1248 for (j = 0; j < l; j++) {
1249 if (ctx->models.list[j] == module->imp[i].module) {
1250 ly_module_free(module->imp[i].module);
1251 break;
1252 }
1253 }
1254 }
1255 free(module->imp);
1256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001257 while (module->data) {
Radek Krejci21181962015-06-30 14:11:00 +02001258 ly_mnode_free(module->data);
1259 }
1260 while (module->rpc) {
1261 ly_mnode_free(module->rpc);
1262 }
1263 while (module->notif) {
1264 ly_mnode_free(module->notif);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001265 }
Radek Krejci5a065542015-05-22 15:02:07 +02001266
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001267 lydict_remove(ctx, module->dsc);
1268 lydict_remove(ctx, module->ref);
1269 lydict_remove(ctx, module->org);
1270 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001271
Radek Krejcieb00f512015-07-01 16:44:58 +02001272 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001273 for (i = 0; i < module->rev_size; i++) {
1274 lydict_remove(ctx, module->rev[i].dsc);
1275 lydict_remove(ctx, module->rev[i].ref);
1276 }
1277 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001278
Radek Krejcieb00f512015-07-01 16:44:58 +02001279 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001280 for (i = 0; i < module->ident_size; i++) {
1281 ly_ident_free(ctx, &module->ident[i]);
1282 }
1283 module->ident_size = 0;
1284 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001285
Radek Krejcieb00f512015-07-01 16:44:58 +02001286 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001287 for (i = 0; i < module->tpdf_size; i++) {
1288 ly_tpdf_free(ctx, &module->tpdf[i]);
1289 }
1290 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001291
Radek Krejcieb00f512015-07-01 16:44:58 +02001292 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001293 for (i = 0; i < module->inc_size; i++) {
1294 ly_submodule_free(module->inc[i].submodule);
1295 }
1296 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001297
Radek Krejcieb00f512015-07-01 16:44:58 +02001298 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02001299 for (i = 0; i < module->augment_size; i++) {
1300 ly_augment_free(ctx, &module->augment[i]);
1301 }
1302 free(module->augment);
1303
Radek Krejcieb00f512015-07-01 16:44:58 +02001304 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001305 for (i = 0; i < module->features_size; i++) {
1306 ly_feature_free(ctx, &module->features[i]);
1307 }
1308 free(module->features);
1309
Radek Krejcieb00f512015-07-01 16:44:58 +02001310 /* deviations */
1311 for (i = 0; i < module->deviation_size; i++) {
1312 ly_deviation_free(ctx, &module->deviation[i]);
1313 }
1314 free(module->deviation);
1315
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001316 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02001317}
1318
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001319void
1320ly_submodule_free(struct ly_submodule *submodule)
Radek Krejciefaeba32015-05-27 14:30:57 +02001321{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001322 if (!submodule) {
1323 return;
1324 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001326 submodule->inc_size = 0;
1327 free(submodule->inc);
1328 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02001329
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001330 /* common part with struct ly_module */
1331 module_free_common((struct ly_module *)submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001332
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001333 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02001334
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001335 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001336}
1337
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001338struct ly_mnode *
1339ly_mnode_dup(struct ly_module *module, struct ly_mnode *mnode, uint8_t flags, int recursive, unsigned int line)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001340{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001341 struct ly_mnode *retval = NULL, *aux, *child;
1342 struct ly_ctx *ctx = module->ctx;
1343 int i, j;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001344
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001345 struct ly_mnode_container *cont;
1346 struct ly_mnode_container *cont_orig = (struct ly_mnode_container *)mnode;
1347 struct ly_mnode_choice *choice;
1348 struct ly_mnode_choice *choice_orig = (struct ly_mnode_choice *)mnode;
1349 struct ly_mnode_leaf *leaf;
1350 struct ly_mnode_leaf *leaf_orig = (struct ly_mnode_leaf *)mnode;
1351 struct ly_mnode_leaflist *llist;
1352 struct ly_mnode_leaflist *llist_orig = (struct ly_mnode_leaflist *)mnode;
1353 struct ly_mnode_list *list;
1354 struct ly_mnode_list *list_orig = (struct ly_mnode_list *)mnode;
1355 struct ly_mnode_anyxml *anyxml;
1356 struct ly_mnode_anyxml *anyxml_orig = (struct ly_mnode_anyxml *)mnode;
1357 struct ly_mnode_uses *uses;
1358 struct ly_mnode_uses *uses_orig = (struct ly_mnode_uses *)mnode;
1359 struct ly_mnode_grp *mix;
1360 struct ly_mnode_grp *mix_orig = (struct ly_mnode_grp *)mnode;
1361 struct ly_mnode_case *cs;
Radek Krejci00768f42015-06-18 17:04:04 +02001362 struct ly_mnode_case *cs_orig = (struct ly_mnode_case *)mnode;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001363
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001364 /* we cannot just duplicate memory since the strings are stored in
1365 * dictionary and we need to update dictionary counters.
1366 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001367
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001368 switch (mnode->nodetype) {
1369 case LY_NODE_CONTAINER:
1370 cont = calloc(1, sizeof *cont);
1371 retval = (struct ly_mnode *)cont;
1372 break;
1373
1374 case LY_NODE_CHOICE:
1375 choice = calloc(1, sizeof *choice);
1376 retval = (struct ly_mnode *)choice;
1377 break;
1378
1379 case LY_NODE_LEAF:
1380 leaf = calloc(1, sizeof *leaf);
1381 retval = (struct ly_mnode *)leaf;
1382 break;
1383
1384 case LY_NODE_LEAFLIST:
1385 llist = calloc(1, sizeof *llist);
1386 retval = (struct ly_mnode *)llist;
1387 break;
1388
1389 case LY_NODE_LIST:
1390 list = calloc(1, sizeof *list);
1391 retval = (struct ly_mnode *)list;
1392 break;
1393
1394 case LY_NODE_ANYXML:
1395 anyxml = calloc(1, sizeof *anyxml);
1396 retval = (struct ly_mnode *)anyxml;
1397 break;
1398
1399 case LY_NODE_USES:
1400 uses = calloc(1, sizeof *uses);
1401 retval = (struct ly_mnode *)uses;
1402 break;
1403
1404 case LY_NODE_CASE:
1405 cs = calloc(1, sizeof *cs);
1406 retval = (struct ly_mnode *)cs;
1407 break;
1408
1409 /* exact same structure */
Michal Vasko0ea41032015-06-16 08:53:55 +02001410 case LY_NODE_GROUPING:
Michal Vasko38d01f72015-06-15 09:41:06 +02001411 case LY_NODE_RPC:
Michal Vasko38d01f72015-06-15 09:41:06 +02001412 case LY_NODE_INPUT:
1413 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001414 case LY_NODE_NOTIF:
1415 mix = calloc(1, sizeof *mix);
1416 retval = (struct ly_mnode *)mix;
Michal Vasko38d01f72015-06-15 09:41:06 +02001417 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001418
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001419 default:
1420 goto error;
1421 }
Radek Krejcib388c152015-06-04 17:03:03 +02001422
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001423 /*
1424 * duplicate generic part of the structure
1425 */
1426 retval->name = lydict_insert(ctx, mnode->name, 0);
1427 retval->dsc = lydict_insert(ctx, mnode->dsc, 0);
1428 retval->ref = lydict_insert(ctx, mnode->ref, 0);
1429 retval->flags = mnode->flags;
1430 if (!(retval->flags & LY_NODE_CONFIG_MASK)) {
1431 /* set parent's config flag */
1432 retval->flags |= flags & LY_NODE_CONFIG_MASK;
1433 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001434
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001435 retval->module = module;
1436 retval->nodetype = mnode->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001437
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001438 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001439
Radek Krejci3cf9e222015-06-18 11:37:50 +02001440 retval->features_size = mnode->features_size;
1441 retval->features = calloc(retval->features_size, sizeof *retval->features);
1442 memcpy(retval->features, mnode->features, retval->features_size * sizeof *retval->features);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001443
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001444 if (recursive) {
1445 /* go recursively */
1446 LY_TREE_FOR(mnode->child, child) {
1447 aux = ly_mnode_dup(module, child, retval->flags, 1, line);
1448 if (!aux || ly_mnode_addchild(retval, aux)) {
1449 goto error;
1450 }
1451 }
1452 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001453
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001454 /*
1455 * duplicate specific part of the structure
1456 */
1457 switch (mnode->nodetype) {
1458 case LY_NODE_CONTAINER:
Radek Krejci00768f42015-06-18 17:04:04 +02001459 cont->when = ly_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001460 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001461
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001462 cont->must_size = cont_orig->must_size;
1463 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001464
Radek Krejci0bd5db42015-06-19 13:30:07 +02001465 cont->must = ly_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001466 cont->tpdf = ly_tpdf_dup(ctx, cont_orig->tpdf, cont->tpdf_size);
1467 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001468
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001469 case LY_NODE_CHOICE:
Radek Krejci00768f42015-06-18 17:04:04 +02001470 choice->when = ly_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001471 if (choice->dflt) {
1472 LY_TREE_FOR(choice->child, child) {
1473 if (child->name == choice_orig->dflt->name) {
1474 choice->dflt = child;
1475 break;
1476 }
1477 }
1478 }
1479 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001480
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001481 case LY_NODE_LEAF:
1482 ly_type_dup(ctx, &(leaf->type), &(leaf_orig->type));
1483 leaf->units = lydict_insert(ctx, leaf_orig->units, 0);
1484 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001485
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001486 leaf->must_size = leaf_orig->must_size;
Radek Krejci0bd5db42015-06-19 13:30:07 +02001487 leaf->must = ly_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02001488
1489 leaf->when = ly_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001490 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001491
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001492 case LY_NODE_LEAFLIST:
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001493
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001494 ly_type_dup(ctx, &(llist->type), &(llist_orig->type));
1495 llist->units = lydict_insert(ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001496
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001497 llist->min = llist_orig->min;
1498 llist->max = llist_orig->max;
1499
1500 llist->must_size = llist_orig->must_size;
Radek Krejci0bd5db42015-06-19 13:30:07 +02001501 llist->must = ly_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02001502
1503 llist->when = ly_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001504 break;
1505
1506 case LY_NODE_LIST:
1507 list->min = list_orig->min;
1508 list->max = list_orig->max;
1509
1510 list->must_size = list_orig->must_size;
1511 list->tpdf_size = list_orig->tpdf_size;
1512 list->keys_size = list_orig->keys_size;
1513 list->unique_size = list_orig->unique_size;
1514
Radek Krejci0bd5db42015-06-19 13:30:07 +02001515 list->must = ly_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001516 list->tpdf = ly_tpdf_dup(ctx, list_orig->tpdf, list->tpdf_size);
1517
1518 if (list->keys_size) {
1519 list->keys = calloc(list->keys_size, sizeof *list->keys);
1520 for (i = 0; i < list->keys_size; i++) {
1521 list->keys[i] = find_leaf(retval, list_orig->keys[i]->name, 0);
1522 }
1523 }
1524 if (list->unique_size) {
1525 list->unique = calloc(list->unique_size, sizeof *list->unique);
1526 for (i = 0; i < list->unique_size; i++) {
1527 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
1528 for (j = 0; j < list->unique[i].leafs_size; j++) {
1529 list->unique[i].leafs[j] = find_leaf(retval, list_orig->unique[i].leafs[j]->name, 0);
1530 }
1531 }
1532 }
Radek Krejci00768f42015-06-18 17:04:04 +02001533 list->when = ly_when_dup(ctx, list_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001534 break;
1535
1536 case LY_NODE_ANYXML:
1537 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci0bd5db42015-06-19 13:30:07 +02001538 anyxml->must = ly_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02001539 anyxml->when = ly_when_dup(ctx, anyxml_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001540 break;
1541
1542 case LY_NODE_USES:
1543 uses->grp = uses_orig->grp;
Radek Krejci00768f42015-06-18 17:04:04 +02001544 uses->when = ly_when_dup(ctx, uses_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001545 uses->refine_size = uses_orig->refine_size;
1546 uses->refine = ly_refine_dup(ctx, uses_orig->refine, uses_orig->refine_size);
1547 uses->augment_size = uses_orig->augment_size;
1548 uses->augment = ly_augment_dup(module, (struct ly_mnode *)uses, uses_orig->augment, uses_orig->augment_size);
1549 if (resolve_uses(uses, line)) {
1550 goto error;
1551 }
1552 break;
1553
1554 case LY_NODE_CASE:
Radek Krejci00768f42015-06-18 17:04:04 +02001555 cs->when = ly_when_dup(ctx, cs_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001556 break;
1557
Michal Vasko0ea41032015-06-16 08:53:55 +02001558 case LY_NODE_GROUPING:
Michal Vasko38d01f72015-06-15 09:41:06 +02001559 case LY_NODE_RPC:
Michal Vasko38d01f72015-06-15 09:41:06 +02001560 case LY_NODE_INPUT:
1561 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001562 case LY_NODE_NOTIF:
1563 mix->tpdf_size = mix_orig->tpdf_size;
1564 mix->tpdf = ly_tpdf_dup(ctx, mix_orig->tpdf, mix->tpdf_size);
Radek Krejcia01e5432015-06-16 10:35:25 +02001565 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001566
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001567 default:
Radek Krejci00768f42015-06-18 17:04:04 +02001568 /* LY_NODE_AUGMENT */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001569 goto error;
1570 }
1571
1572 return retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001573
1574error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001575 LOGDBG("error: %s:%d", __FILE__, __LINE__);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001576
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001577 ly_mnode_free(retval);
1578 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001579}
1580
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001581API void
1582ly_module_free(struct ly_module *module)
Radek Krejciefaeba32015-05-27 14:30:57 +02001583{
Radek Krejcidce51452015-06-16 15:20:08 +02001584 struct ly_ctx *ctx;
1585 int i;
1586
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001587 if (!module) {
1588 return;
1589 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001590
Radek Krejcidce51452015-06-16 15:20:08 +02001591 /* remove schema from the context */
1592 ctx = module->ctx;
1593 if (ctx->models.used) {
1594 for (i = 0; i < ctx->models.used; i++) {
1595 if (ctx->models.list[i] == module) {
1596 /* replace the position in the list by the last module in the list */
1597 ctx->models.used--;
1598 ctx->models.list[i] = ctx->models.list[ctx->models.used];
1599 ctx->models.list[ctx->models.used] = NULL;
1600 /* we are done */
1601 break;
1602 }
1603 }
1604 }
1605
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001606 /* common part with struct ly_submodule */
1607 module_free_common(module);
Radek Krejciefaeba32015-05-27 14:30:57 +02001608
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001609 /* specific items to free */
1610 lydict_remove(module->ctx, module->ns);
1611 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02001612
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001613 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001614}
Radek Krejci7e97c352015-06-19 16:26:34 +02001615
1616/*
1617 * op: 1 - enable, 0 - disable
1618 */
1619static int
1620ly_features_change(struct ly_module *module, const char *name, int op)
1621{
1622 int all = 0;
1623 int i, j, k;
1624
1625 if (!module || !name || !strlen(name)) {
1626 return EXIT_FAILURE;
1627 }
1628
1629 if (!strcmp(name, "*")) {
1630 /* enable all */
1631 all = 1;
1632 }
1633
1634 /* module itself */
1635 for (i = 0; i < module->features_size; i++) {
1636 if (all || !strcmp(module->features[i].name, name)) {
1637 if (op) {
1638 module->features[i].flags |= LY_NODE_FENABLED;
1639 /* enable referenced features (recursion) */
1640 for (k = 0; k < module->features[i].features_size; k++) {
1641 ly_features_change(module->features[i].features[k]->module,
1642 module->features[i].features[k]->name, op);
1643 }
1644 } else {
1645 module->features[i].flags &= ~LY_NODE_FENABLED;
1646 }
1647 if (!all) {
1648 return EXIT_SUCCESS;
1649 }
1650 }
1651 }
1652
1653 /* submodules */
1654 for (j = 0; j < module->inc_size; j++) {
1655 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
1656 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
1657 if (op) {
1658 module->inc[j].submodule->features[i].flags |= LY_NODE_FENABLED;
1659 } else {
1660 module->inc[j].submodule->features[i].flags &= ~LY_NODE_FENABLED;
1661 }
1662 if (!all) {
1663 return EXIT_SUCCESS;
1664 }
1665 }
1666 }
1667 }
1668
1669 if (all) {
1670 return EXIT_SUCCESS;
1671 } else {
1672 return EXIT_FAILURE;
1673 }
1674}
1675
1676API int
1677ly_features_enable(struct ly_module *module, const char *name)
1678{
1679 return ly_features_change(module, name, 1);
1680}
1681
1682API int
1683ly_features_disable(struct ly_module *module, const char *name)
1684{
1685 return ly_features_change(module, name, 1);
1686}