blob: 1bcda4af252aeb8aead5a19a2313dad2396eb95d [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 Krejcif5be10f2015-06-16 13:29:36 +02001093ly_augment_free(struct ly_ctx *ctx, struct ly_augment *aug)
1094{
1095 lydict_remove(ctx, aug->target_name);
1096 lydict_remove(ctx, aug->dsc);
1097 lydict_remove(ctx, aug->ref);
1098
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001099 ly_when_free(ctx, aug->when);
1100
Radek Krejcif5be10f2015-06-16 13:29:36 +02001101 lyxml_free_elem(ctx, (struct lyxml_elem *)aug->child);
1102}
1103
1104void
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001105ly_uses_free(struct ly_ctx *ctx, struct ly_mnode_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +02001106{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001107 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001108
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001109 for (i = 0; i < uses->refine_size; i++) {
1110 lydict_remove(ctx, uses->refine[i].target);
1111 lydict_remove(ctx, uses->refine[i].dsc);
1112 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001113
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001114 for (j = 0; j < uses->refine[j].must_size; j++) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001115 ly_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001116 }
1117 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001118
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001119 if (uses->refine[i].target_type & (LY_NODE_LEAF | LY_NODE_CHOICE)) {
1120 lydict_remove(ctx, uses->refine[i].mod.dflt);
1121 } else if (uses->refine[i].target_type & LY_NODE_CONTAINER) {
1122 lydict_remove(ctx, uses->refine[i].mod.presence);
1123 }
1124 }
1125 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001126
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001127 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02001128 ly_augment_free(ctx, &uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001129 }
1130 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001131
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001132 ly_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001133}
1134
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001135void
1136ly_mnode_free(struct ly_mnode *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001137{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001138 struct ly_ctx *ctx;
1139 struct ly_mnode *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001140
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001141 if (!node) {
1142 return;
1143 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001145 assert(node->module);
1146 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001147
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001148 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001150 /* common part */
1151 LY_TREE_FOR_SAFE(node->child, next, sub) {
1152 ly_mnode_free(sub);
1153 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001154 free(node->features);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001155
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001156 lydict_remove(ctx, node->name);
1157 lydict_remove(ctx, node->dsc);
1158 lydict_remove(ctx, node->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001159
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001160 /* specific part */
1161 switch (node->nodetype) {
1162 case LY_NODE_CONTAINER:
1163 ly_container_free(ctx, (struct ly_mnode_container *)node);
1164 break;
1165 case LY_NODE_CHOICE:
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001166 ly_when_free(ctx, ((struct ly_mnode_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001167 break;
1168 case LY_NODE_LEAF:
1169 ly_leaf_free(ctx, (struct ly_mnode_leaf *)node);
1170 break;
1171 case LY_NODE_LEAFLIST:
1172 ly_leaflist_free(ctx, (struct ly_mnode_leaflist *)node);
1173 break;
1174 case LY_NODE_LIST:
1175 ly_list_free(ctx, (struct ly_mnode_list *)node);
1176 break;
1177 case LY_NODE_ANYXML:
1178 ly_anyxml_free(ctx, (struct ly_mnode_anyxml *)node);
1179 break;
1180 case LY_NODE_USES:
1181 ly_uses_free(ctx, (struct ly_mnode_uses *)node);
1182 break;
1183 case LY_NODE_CASE:
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001184 ly_when_free(ctx, ((struct ly_mnode_case *)node)->when);
1185 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001186 case LY_NODE_AUGMENT:
1187 /* do nothing */
1188 break;
Michal Vasko0ea41032015-06-16 08:53:55 +02001189 case LY_NODE_GROUPING:
1190 case LY_NODE_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001191 case LY_NODE_INPUT:
1192 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001193 case LY_NODE_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001194 ly_grp_free(ctx, (struct ly_mnode_grp *)node);
1195 break;
1196 }
Radek Krejci5a065542015-05-22 15:02:07 +02001197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001198 /* again common part */
1199 ly_mnode_unlink(node);
1200 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001201}
1202
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001203static void
1204module_free_common(struct ly_module *module)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001205{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001206 struct ly_ctx *ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001207 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001208 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001209
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001210 assert(module->ctx);
1211 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001212
Radek Krejcidce51452015-06-16 15:20:08 +02001213 /* as first step, free the imported modules */
1214 for (i = 0; i < module->imp_size; i++) {
1215 /* get the imported module from the context and then free,
1216 * this check is necessary because the imported module can
1217 * be already removed
1218 */
1219 l = ctx->models.used;
1220 for (j = 0; j < l; j++) {
1221 if (ctx->models.list[j] == module->imp[i].module) {
1222 ly_module_free(module->imp[i].module);
1223 break;
1224 }
1225 }
1226 }
1227 free(module->imp);
1228
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001229 while (module->data) {
Radek Krejci21181962015-06-30 14:11:00 +02001230 ly_mnode_free(module->data);
1231 }
1232 while (module->rpc) {
1233 ly_mnode_free(module->rpc);
1234 }
1235 while (module->notif) {
1236 ly_mnode_free(module->notif);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001237 }
Radek Krejci5a065542015-05-22 15:02:07 +02001238
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001239 lydict_remove(ctx, module->dsc);
1240 lydict_remove(ctx, module->ref);
1241 lydict_remove(ctx, module->org);
1242 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001243
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001244 for (i = 0; i < module->rev_size; i++) {
1245 lydict_remove(ctx, module->rev[i].dsc);
1246 lydict_remove(ctx, module->rev[i].ref);
1247 }
1248 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001249
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001250 for (i = 0; i < module->ident_size; i++) {
1251 ly_ident_free(ctx, &module->ident[i]);
1252 }
1253 module->ident_size = 0;
1254 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001255
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001256 for (i = 0; i < module->tpdf_size; i++) {
1257 ly_tpdf_free(ctx, &module->tpdf[i]);
1258 }
1259 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001260
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001261 for (i = 0; i < module->inc_size; i++) {
1262 ly_submodule_free(module->inc[i].submodule);
1263 }
1264 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001265
Radek Krejcif5be10f2015-06-16 13:29:36 +02001266 for (i = 0; i < module->augment_size; i++) {
1267 ly_augment_free(ctx, &module->augment[i]);
1268 }
1269 free(module->augment);
1270
Radek Krejci3cf9e222015-06-18 11:37:50 +02001271 for (i = 0; i < module->features_size; i++) {
1272 ly_feature_free(ctx, &module->features[i]);
1273 }
1274 free(module->features);
1275
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001276 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02001277}
1278
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001279void
1280ly_submodule_free(struct ly_submodule *submodule)
Radek Krejciefaeba32015-05-27 14:30:57 +02001281{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001282 if (!submodule) {
1283 return;
1284 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001286 submodule->inc_size = 0;
1287 free(submodule->inc);
1288 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02001289
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001290 /* common part with struct ly_module */
1291 module_free_common((struct ly_module *)submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001292
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001293 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02001294
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001295 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001296}
1297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001298struct ly_mnode *
1299ly_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 +02001300{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001301 struct ly_mnode *retval = NULL, *aux, *child;
1302 struct ly_ctx *ctx = module->ctx;
1303 int i, j;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001304
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001305 struct ly_mnode_container *cont;
1306 struct ly_mnode_container *cont_orig = (struct ly_mnode_container *)mnode;
1307 struct ly_mnode_choice *choice;
1308 struct ly_mnode_choice *choice_orig = (struct ly_mnode_choice *)mnode;
1309 struct ly_mnode_leaf *leaf;
1310 struct ly_mnode_leaf *leaf_orig = (struct ly_mnode_leaf *)mnode;
1311 struct ly_mnode_leaflist *llist;
1312 struct ly_mnode_leaflist *llist_orig = (struct ly_mnode_leaflist *)mnode;
1313 struct ly_mnode_list *list;
1314 struct ly_mnode_list *list_orig = (struct ly_mnode_list *)mnode;
1315 struct ly_mnode_anyxml *anyxml;
1316 struct ly_mnode_anyxml *anyxml_orig = (struct ly_mnode_anyxml *)mnode;
1317 struct ly_mnode_uses *uses;
1318 struct ly_mnode_uses *uses_orig = (struct ly_mnode_uses *)mnode;
1319 struct ly_mnode_grp *mix;
1320 struct ly_mnode_grp *mix_orig = (struct ly_mnode_grp *)mnode;
1321 struct ly_mnode_case *cs;
Radek Krejci00768f42015-06-18 17:04:04 +02001322 struct ly_mnode_case *cs_orig = (struct ly_mnode_case *)mnode;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001323
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001324 /* we cannot just duplicate memory since the strings are stored in
1325 * dictionary and we need to update dictionary counters.
1326 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001327
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001328 switch (mnode->nodetype) {
1329 case LY_NODE_CONTAINER:
1330 cont = calloc(1, sizeof *cont);
1331 retval = (struct ly_mnode *)cont;
1332 break;
1333
1334 case LY_NODE_CHOICE:
1335 choice = calloc(1, sizeof *choice);
1336 retval = (struct ly_mnode *)choice;
1337 break;
1338
1339 case LY_NODE_LEAF:
1340 leaf = calloc(1, sizeof *leaf);
1341 retval = (struct ly_mnode *)leaf;
1342 break;
1343
1344 case LY_NODE_LEAFLIST:
1345 llist = calloc(1, sizeof *llist);
1346 retval = (struct ly_mnode *)llist;
1347 break;
1348
1349 case LY_NODE_LIST:
1350 list = calloc(1, sizeof *list);
1351 retval = (struct ly_mnode *)list;
1352 break;
1353
1354 case LY_NODE_ANYXML:
1355 anyxml = calloc(1, sizeof *anyxml);
1356 retval = (struct ly_mnode *)anyxml;
1357 break;
1358
1359 case LY_NODE_USES:
1360 uses = calloc(1, sizeof *uses);
1361 retval = (struct ly_mnode *)uses;
1362 break;
1363
1364 case LY_NODE_CASE:
1365 cs = calloc(1, sizeof *cs);
1366 retval = (struct ly_mnode *)cs;
1367 break;
1368
1369 /* exact same structure */
Michal Vasko0ea41032015-06-16 08:53:55 +02001370 case LY_NODE_GROUPING:
Michal Vasko38d01f72015-06-15 09:41:06 +02001371 case LY_NODE_RPC:
Michal Vasko38d01f72015-06-15 09:41:06 +02001372 case LY_NODE_INPUT:
1373 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001374 case LY_NODE_NOTIF:
1375 mix = calloc(1, sizeof *mix);
1376 retval = (struct ly_mnode *)mix;
Michal Vasko38d01f72015-06-15 09:41:06 +02001377 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001378
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001379 default:
1380 goto error;
1381 }
Radek Krejcib388c152015-06-04 17:03:03 +02001382
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001383 /*
1384 * duplicate generic part of the structure
1385 */
1386 retval->name = lydict_insert(ctx, mnode->name, 0);
1387 retval->dsc = lydict_insert(ctx, mnode->dsc, 0);
1388 retval->ref = lydict_insert(ctx, mnode->ref, 0);
1389 retval->flags = mnode->flags;
1390 if (!(retval->flags & LY_NODE_CONFIG_MASK)) {
1391 /* set parent's config flag */
1392 retval->flags |= flags & LY_NODE_CONFIG_MASK;
1393 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001395 retval->module = module;
1396 retval->nodetype = mnode->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001397
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001398 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001399
Radek Krejci3cf9e222015-06-18 11:37:50 +02001400 retval->features_size = mnode->features_size;
1401 retval->features = calloc(retval->features_size, sizeof *retval->features);
1402 memcpy(retval->features, mnode->features, retval->features_size * sizeof *retval->features);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001403
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001404 if (recursive) {
1405 /* go recursively */
1406 LY_TREE_FOR(mnode->child, child) {
1407 aux = ly_mnode_dup(module, child, retval->flags, 1, line);
1408 if (!aux || ly_mnode_addchild(retval, aux)) {
1409 goto error;
1410 }
1411 }
1412 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001413
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001414 /*
1415 * duplicate specific part of the structure
1416 */
1417 switch (mnode->nodetype) {
1418 case LY_NODE_CONTAINER:
Radek Krejci00768f42015-06-18 17:04:04 +02001419 cont->when = ly_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001420 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001421
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001422 cont->must_size = cont_orig->must_size;
1423 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001424
Radek Krejci0bd5db42015-06-19 13:30:07 +02001425 cont->must = ly_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001426 cont->tpdf = ly_tpdf_dup(ctx, cont_orig->tpdf, cont->tpdf_size);
1427 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001428
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001429 case LY_NODE_CHOICE:
Radek Krejci00768f42015-06-18 17:04:04 +02001430 choice->when = ly_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001431 if (choice->dflt) {
1432 LY_TREE_FOR(choice->child, child) {
1433 if (child->name == choice_orig->dflt->name) {
1434 choice->dflt = child;
1435 break;
1436 }
1437 }
1438 }
1439 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001440
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001441 case LY_NODE_LEAF:
1442 ly_type_dup(ctx, &(leaf->type), &(leaf_orig->type));
1443 leaf->units = lydict_insert(ctx, leaf_orig->units, 0);
1444 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001445
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001446 leaf->must_size = leaf_orig->must_size;
Radek Krejci0bd5db42015-06-19 13:30:07 +02001447 leaf->must = ly_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02001448
1449 leaf->when = ly_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001450 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001451
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001452 case LY_NODE_LEAFLIST:
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001453
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001454 ly_type_dup(ctx, &(llist->type), &(llist_orig->type));
1455 llist->units = lydict_insert(ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001456
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001457 llist->min = llist_orig->min;
1458 llist->max = llist_orig->max;
1459
1460 llist->must_size = llist_orig->must_size;
Radek Krejci0bd5db42015-06-19 13:30:07 +02001461 llist->must = ly_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02001462
1463 llist->when = ly_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001464 break;
1465
1466 case LY_NODE_LIST:
1467 list->min = list_orig->min;
1468 list->max = list_orig->max;
1469
1470 list->must_size = list_orig->must_size;
1471 list->tpdf_size = list_orig->tpdf_size;
1472 list->keys_size = list_orig->keys_size;
1473 list->unique_size = list_orig->unique_size;
1474
Radek Krejci0bd5db42015-06-19 13:30:07 +02001475 list->must = ly_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001476 list->tpdf = ly_tpdf_dup(ctx, list_orig->tpdf, list->tpdf_size);
1477
1478 if (list->keys_size) {
1479 list->keys = calloc(list->keys_size, sizeof *list->keys);
1480 for (i = 0; i < list->keys_size; i++) {
1481 list->keys[i] = find_leaf(retval, list_orig->keys[i]->name, 0);
1482 }
1483 }
1484 if (list->unique_size) {
1485 list->unique = calloc(list->unique_size, sizeof *list->unique);
1486 for (i = 0; i < list->unique_size; i++) {
1487 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
1488 for (j = 0; j < list->unique[i].leafs_size; j++) {
1489 list->unique[i].leafs[j] = find_leaf(retval, list_orig->unique[i].leafs[j]->name, 0);
1490 }
1491 }
1492 }
Radek Krejci00768f42015-06-18 17:04:04 +02001493 list->when = ly_when_dup(ctx, list_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001494 break;
1495
1496 case LY_NODE_ANYXML:
1497 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci0bd5db42015-06-19 13:30:07 +02001498 anyxml->must = ly_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02001499 anyxml->when = ly_when_dup(ctx, anyxml_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001500 break;
1501
1502 case LY_NODE_USES:
1503 uses->grp = uses_orig->grp;
Radek Krejci00768f42015-06-18 17:04:04 +02001504 uses->when = ly_when_dup(ctx, uses_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001505 uses->refine_size = uses_orig->refine_size;
1506 uses->refine = ly_refine_dup(ctx, uses_orig->refine, uses_orig->refine_size);
1507 uses->augment_size = uses_orig->augment_size;
1508 uses->augment = ly_augment_dup(module, (struct ly_mnode *)uses, uses_orig->augment, uses_orig->augment_size);
1509 if (resolve_uses(uses, line)) {
1510 goto error;
1511 }
1512 break;
1513
1514 case LY_NODE_CASE:
Radek Krejci00768f42015-06-18 17:04:04 +02001515 cs->when = ly_when_dup(ctx, cs_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001516 break;
1517
Michal Vasko0ea41032015-06-16 08:53:55 +02001518 case LY_NODE_GROUPING:
Michal Vasko38d01f72015-06-15 09:41:06 +02001519 case LY_NODE_RPC:
Michal Vasko38d01f72015-06-15 09:41:06 +02001520 case LY_NODE_INPUT:
1521 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001522 case LY_NODE_NOTIF:
1523 mix->tpdf_size = mix_orig->tpdf_size;
1524 mix->tpdf = ly_tpdf_dup(ctx, mix_orig->tpdf, mix->tpdf_size);
Radek Krejcia01e5432015-06-16 10:35:25 +02001525 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001526
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001527 default:
Radek Krejci00768f42015-06-18 17:04:04 +02001528 /* LY_NODE_AUGMENT */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001529 goto error;
1530 }
1531
1532 return retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001533
1534error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001535 LOGDBG("error: %s:%d", __FILE__, __LINE__);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001537 ly_mnode_free(retval);
1538 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001539}
1540
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001541API void
1542ly_module_free(struct ly_module *module)
Radek Krejciefaeba32015-05-27 14:30:57 +02001543{
Radek Krejcidce51452015-06-16 15:20:08 +02001544 struct ly_ctx *ctx;
1545 int i;
1546
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001547 if (!module) {
1548 return;
1549 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001550
Radek Krejcidce51452015-06-16 15:20:08 +02001551 /* remove schema from the context */
1552 ctx = module->ctx;
1553 if (ctx->models.used) {
1554 for (i = 0; i < ctx->models.used; i++) {
1555 if (ctx->models.list[i] == module) {
1556 /* replace the position in the list by the last module in the list */
1557 ctx->models.used--;
1558 ctx->models.list[i] = ctx->models.list[ctx->models.used];
1559 ctx->models.list[ctx->models.used] = NULL;
1560 /* we are done */
1561 break;
1562 }
1563 }
1564 }
1565
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001566 /* common part with struct ly_submodule */
1567 module_free_common(module);
Radek Krejciefaeba32015-05-27 14:30:57 +02001568
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001569 /* specific items to free */
1570 lydict_remove(module->ctx, module->ns);
1571 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02001572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001573 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001574}
Radek Krejci7e97c352015-06-19 16:26:34 +02001575
1576/*
1577 * op: 1 - enable, 0 - disable
1578 */
1579static int
1580ly_features_change(struct ly_module *module, const char *name, int op)
1581{
1582 int all = 0;
1583 int i, j, k;
1584
1585 if (!module || !name || !strlen(name)) {
1586 return EXIT_FAILURE;
1587 }
1588
1589 if (!strcmp(name, "*")) {
1590 /* enable all */
1591 all = 1;
1592 }
1593
1594 /* module itself */
1595 for (i = 0; i < module->features_size; i++) {
1596 if (all || !strcmp(module->features[i].name, name)) {
1597 if (op) {
1598 module->features[i].flags |= LY_NODE_FENABLED;
1599 /* enable referenced features (recursion) */
1600 for (k = 0; k < module->features[i].features_size; k++) {
1601 ly_features_change(module->features[i].features[k]->module,
1602 module->features[i].features[k]->name, op);
1603 }
1604 } else {
1605 module->features[i].flags &= ~LY_NODE_FENABLED;
1606 }
1607 if (!all) {
1608 return EXIT_SUCCESS;
1609 }
1610 }
1611 }
1612
1613 /* submodules */
1614 for (j = 0; j < module->inc_size; j++) {
1615 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
1616 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
1617 if (op) {
1618 module->inc[j].submodule->features[i].flags |= LY_NODE_FENABLED;
1619 } else {
1620 module->inc[j].submodule->features[i].flags &= ~LY_NODE_FENABLED;
1621 }
1622 if (!all) {
1623 return EXIT_SUCCESS;
1624 }
1625 }
1626 }
1627 }
1628
1629 if (all) {
1630 return EXIT_SUCCESS;
1631 } else {
1632 return EXIT_FAILURE;
1633 }
1634}
1635
1636API int
1637ly_features_enable(struct ly_module *module, const char *name)
1638{
1639 return ly_features_change(module, name, 1);
1640}
1641
1642API int
1643ly_features_disable(struct ly_module *module, const char *name)
1644{
1645 return ly_features_change(module, name, 1);
1646}