blob: 74d7daf7c7b91903e8810c4d6f52ad384d1a0116 [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;
120 }
121 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200122
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200123 /* store pointers to important nodes */
124 parent = node->parent;
125 if (parent && !parent->nodetype) {
126 /* handle augments - first, unlink it from the augment parent ... */
127 if (parent->child == node) {
128 parent->child = node->next;
129 }
130 /* and then continue with the target parent */
131 parent = ((struct ly_augment *)parent)->target;
132 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200133
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200134 /* unlink from parent */
135 if (parent) {
136 if (parent->child == node) {
137 parent->child = node->next;
138 }
139 node->parent = NULL;
140 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200141
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200142 /* unlink from siblings */
143 if (node->prev == node) {
144 /* there are no more siblings */
145 return;
146 }
147 if (node->next) {
148 node->next->prev = node->prev;
149 } else {
150 /* unlinking the last element */
151 if (parent) {
152 first = parent->child;
153 } else {
154 first = node;
155 while (node->prev->next) {
156 first = node->prev;
157 }
158 }
159 first->prev = node->prev;
160 }
161 if (node->prev->next) {
162 node->prev->next = node->next;
163 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200164
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200165 /* clean up the unlinked element */
166 node->next = NULL;
167 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200168}
169
170/*
171 * Add child model node at the end of the parent's child list.
172 * If the child is connected somewhere (has a parent), it is completely
173 * unlinked and none of the following conditions applies.
174 * If the child has prev sibling(s), they are ignored (child is added at the
175 * end of the child list).
176 * If the child has next sibling(s), all of them are connected with the parent.
177 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200178int
179ly_mnode_addchild(struct ly_mnode *parent, struct ly_mnode *child)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200180{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200181 struct ly_mnode *last;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200182
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200183 assert(parent);
184 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200185
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200186 /* checks */
187 switch (parent->nodetype) {
188 case LY_NODE_CONTAINER:
189 case LY_NODE_LIST:
190 case LY_NODE_GROUPING:
191 case LY_NODE_USES:
Michal Vasko38d01f72015-06-15 09:41:06 +0200192 case LY_NODE_INPUT:
193 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +0200194 case LY_NODE_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200195 if (!(child->nodetype &
196 (LY_NODE_ANYXML | LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_GROUPING | LY_NODE_LEAF |
197 LY_NODE_LEAFLIST | LY_NODE_LIST | LY_NODE_USES))) {
198 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
199 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
200 return EXIT_FAILURE;
201 }
202 break;
203 case LY_NODE_CHOICE:
204 if (!(child->nodetype &
205 (LY_NODE_ANYXML | LY_NODE_CASE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST))) {
206 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"choice\" %s.",
207 strnodetype(child->nodetype), parent->name);
208 return EXIT_FAILURE;
209 }
210 break;
211 case LY_NODE_CASE:
212 if (!(child->nodetype &
213 (LY_NODE_ANYXML | LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST | LY_NODE_USES))) {
214 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"case\" %s.",
215 strnodetype(child->nodetype), parent->name);
216 return EXIT_FAILURE;
217 }
218 break;
Michal Vasko38d01f72015-06-15 09:41:06 +0200219 case LY_NODE_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200220 if (!(child->nodetype & (LY_NODE_INPUT | LY_NODE_OUTPUT | LY_NODE_GROUPING))) {
Michal Vasko38d01f72015-06-15 09:41:06 +0200221 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"rpc\" %s.",
222 strnodetype(child->nodetype), parent->name);
223 return EXIT_FAILURE;
224 }
225 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200226 case LY_NODE_LEAF:
227 case LY_NODE_LEAFLIST:
228 case LY_NODE_ANYXML:
229 LOGVAL(VE_SPEC, 0, "The \"%s\" statement (%s) cannot have any substatement.",
230 strnodetype(parent->nodetype), parent->name);
231 return EXIT_FAILURE;
232 case LY_NODE_AUGMENT:
233 LOGVAL(VE_SPEC, 0, "Internal error (%s:%d)", __FILE__, __LINE__);
234 return EXIT_FAILURE;
235 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200237 if (child->parent) {
238 ly_mnode_unlink(child);
239 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200240
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200241 if (!parent->child) {
242 /* the only/first child of the parent */
243 parent->child = child;
244 child->parent = parent;
245 last = child;
246 } else {
247 /* add a new child at the end of parent's child list */
248 last = parent->child->prev;
249 last->next = child;
250 child->prev = last;
251 }
252 while (last->next) {
253 last = last->next;
254 last->parent = parent;
255 }
256 parent->child->prev = last;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200257
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200258 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200259}
260
Radek Krejci3bde87f2015-06-05 16:51:58 +0200261/*
Michal Vasko25880b42015-06-12 10:16:33 +0200262 * id - schema-nodeid
Radek Krejci3bde87f2015-06-05 16:51:58 +0200263 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200264struct ly_mnode *
Radek Krejcif5be10f2015-06-16 13:29:36 +0200265resolve_schema_nodeid(const char *id, struct ly_mnode *start, struct ly_module *mod)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200266{
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200267 const char *name, *prefix, *ptr;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200268 struct ly_mnode *sibling;
Michal Vasko25880b42015-06-12 10:16:33 +0200269 struct ly_submodule *sub_mod;
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200270 uint32_t i, j, nam_len, pref_len;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200271
Radek Krejcif5be10f2015-06-16 13:29:36 +0200272 assert(mod);
273 assert(id);
274
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200275 if (id[0] == '/') {
276 ptr = strchr(id+1, '/');
277 prefix = id+1;
278 } else {
279 ptr = strchr(id, '/');
280 prefix = id;
281 }
282 pref_len = (ptr ? (unsigned)(ptr-prefix) : strlen(prefix));
Radek Krejci3bde87f2015-06-05 16:51:58 +0200283
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200284 ptr = strnchr(prefix, ':', pref_len);
285 /* there is prefix */
286 if (ptr) {
287 nam_len = (pref_len-(ptr-prefix))-1;
288 pref_len = ptr-prefix;
289 name = ptr+1;
290
291 /* no prefix used */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200292 } else {
293 name = prefix;
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200294 nam_len = pref_len;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200295 prefix = NULL;
296 }
Michal Vasko25880b42015-06-12 10:16:33 +0200297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200298 /* absolute-schema-nodeid */
299 if (id[0] == '/') {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200300 start = NULL;
301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200302 /* it is not the local prefix */
Radek Krejcif5be10f2015-06-16 13:29:36 +0200303 if (prefix && strncmp(prefix, mod->prefix, pref_len)) {
304 /* check imports */
305 for (i = 0; i < mod->imp_size; i++) {
306 if (!strncmp(mod->imp[i].prefix, prefix, pref_len)) {
307 start = mod->imp[i].module->data;
Michal Vasko25880b42015-06-12 10:16:33 +0200308 break;
309 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200310 }
Radek Krejcif5be10f2015-06-16 13:29:36 +0200311
312 /* no match - check include imports */
313 if (!start) {
314 for (i = 0; i < mod->inc_size; i++) {
315 sub_mod = mod->inc[i].submodule;
316 for (j = 0; j < sub_mod->imp_size; j++) {
317 if (!strncmp(sub_mod->imp[j].prefix, prefix, pref_len)) {
318 start = sub_mod->imp[j].module->data;
319 break;
320 }
321 }
322
323 if (start) {
324 break;
325 }
326 }
327 }
328
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200329 /* no match */
Radek Krejcif5be10f2015-06-16 13:29:36 +0200330 if (!start) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200331 return NULL;
332 }
Michal Vasko25880b42015-06-12 10:16:33 +0200333
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200334 /* it is likely the local prefix */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200335 } else {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200336 start = mod->data;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200337 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200338
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200339 /* descendant-schema-nodeid */
Radek Krejcif5be10f2015-06-16 13:29:36 +0200340 } else {
341 assert(start);
342 start = start->child;
343 }
344
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200345 while (1) {
346 if (!strcmp(name, ".")) {
347 /* this node - start does not change */
348 } else if (!strcmp(name, "..")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200349 if (!start) {
350 return NULL;
351 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200352 start = start->parent;
353 } else {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200354 sibling = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200355 LY_TREE_FOR(start, sibling) {
356 /* match */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200357 if (!strncmp(name, sibling->name, nam_len)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200358 /* prefix check, it's not our own */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200359 if (prefix && strncmp(sibling->module->prefix, prefix, pref_len)) {
Michal Vasko25880b42015-06-12 10:16:33 +0200360
361 /* import prefix check */
362 for (i = 0; i < sibling->module->imp_size; i++) {
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200363 if (!strncmp(sibling->module->imp[i].prefix, prefix, pref_len)
364 && (sibling->module->imp[i].module == sibling->module)) {
Michal Vasko25880b42015-06-12 10:16:33 +0200365 break;
366 }
367 }
368
369 /* import prefix check failed */
370 if (i == sibling->module->imp_size) {
371 /* include import prefix check */
372 for (i = 0; i < sibling->module->inc_size; i++) {
373 sub_mod = sibling->module->inc[i].submodule;
374 for (j = 0; j < sub_mod->imp_size; j++) {
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200375 if (!strncmp(sub_mod->imp[j].prefix, prefix, pref_len)
376 && (sub_mod->imp[j].module == sibling->module)) {
Michal Vasko25880b42015-06-12 10:16:33 +0200377 break;
378 }
379 }
380
381 if (j < sub_mod->imp_size) {
382 break;
383 }
384 }
385
386 /* include import prefix check failed too - definite fail */
387 if (i == sibling->module->inc_size) {
Michal Vasko25880b42015-06-12 10:16:33 +0200388 return NULL;
389 }
390 }
391 }
392
393 /* the result node? */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200394 ptr = name+nam_len;
395 if (!ptr[0]) {
Michal Vasko25880b42015-06-12 10:16:33 +0200396 return sibling;
397 }
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200398 assert(ptr[0] == '/');
399 prefix = ptr+1;
Michal Vasko25880b42015-06-12 10:16:33 +0200400
401 /* check for shorthand cases - then 'start' does not change */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200402 if (!sibling->parent || (sibling->parent->nodetype != LY_NODE_CHOICE)
403 || (sibling->nodetype == LY_NODE_CASE)) {
Michal Vasko25880b42015-06-12 10:16:33 +0200404 start = sibling->child;
405 }
406 break;
407 }
408 }
Radek Krejcif5be10f2015-06-16 13:29:36 +0200409
Michal Vasko25880b42015-06-12 10:16:33 +0200410 /* no match */
411 if (!sibling) {
Michal Vasko25880b42015-06-12 10:16:33 +0200412 return NULL;
413 }
414 }
415
416 /* parse prefix */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200417 ptr = strchr(prefix, '/');
418 pref_len = (ptr ? (unsigned)(ptr-prefix) : strlen(prefix));
419 ptr = strnchr(prefix, ':', pref_len);
420
421 /* there is prefix */
422 if (ptr) {
423 nam_len = pref_len-((ptr-prefix)-1);
424 pref_len = ptr-prefix;
425 name = ptr+1;
426
427 /* no prefix used */
Michal Vasko25880b42015-06-12 10:16:33 +0200428 } else {
429 name = prefix;
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200430 nam_len = pref_len;
Michal Vasko25880b42015-06-12 10:16:33 +0200431 prefix = NULL;
432 }
Michal Vasko25880b42015-06-12 10:16:33 +0200433 }
434
435 /* cannot get here */
436 return NULL;
Radek Krejci3bde87f2015-06-05 16:51:58 +0200437}
438
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200439API struct ly_module *
440ly_module_read(struct ly_ctx *ctx, const char *data, LY_MINFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200441{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200442 if (!ctx || !data) {
443 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
444 return NULL;
445 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200446
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200447 switch (format) {
448 case LY_IN_YIN:
449 return yin_read_module(ctx, data);
450 case LY_IN_YANG:
451 default:
452 /* TODO */
453 return NULL;
454 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200455
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200456 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200457}
458
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200459struct ly_submodule *
460ly_submodule_read(struct ly_module *module, const char *data, LY_MINFORMAT format)
Radek Krejciefaeba32015-05-27 14:30:57 +0200461{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200462 assert(module);
463 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200464
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200465 switch (format) {
466 case LY_IN_YIN:
467 return yin_read_submodule(module, data);
468 case LY_IN_YANG:
469 default:
470 /* TODO */
471 return NULL;
472 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200473
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200474 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +0200475}
476
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200477API struct ly_module *
478ly_module_read_fd(struct ly_ctx *ctx, int fd, LY_MINFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200479{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200480 struct ly_module *module;
481 struct stat sb;
482 char *addr;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200484 if (!ctx || fd < 0) {
485 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
486 return NULL;
487 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200488
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200489 /*
490 * TODO
491 * This is just a temporary solution to make working automatic search for
492 * imported modules. This doesn't work e.g. for streams (stdin)
493 */
494 fstat(fd, &sb);
495 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
496 module = ly_module_read(ctx, addr, format);
497 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200498
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200499 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200500}
501
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200502struct ly_submodule *
503ly_submodule_read_fd(struct ly_module *module, int fd, LY_MINFORMAT format)
Radek Krejciefaeba32015-05-27 14:30:57 +0200504{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200505 struct ly_submodule *submodule;
506 struct stat sb;
507 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +0200508
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200509 assert(module);
510 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +0200511
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200512 /*
513 * TODO
514 * This is just a temporary solution to make working automatic search for
515 * imported modules. This doesn't work e.g. for streams (stdin)
516 */
517 fstat(fd, &sb);
518 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
519 /* TODO addr error check */
520 submodule = ly_submodule_read(module, addr, format);
521 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +0200522
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200523 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +0200524
525}
526
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200527void
528ly_type_dup(struct ly_ctx *ctx, struct ly_type *new, struct ly_type *old)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200529{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200530 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200531
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200532 new->prefix = lydict_insert(ctx, old->prefix, 0);
533 new->base = old->base;
534 new->der = old->der;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200535
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200536 switch (new->base) {
537 case LY_TYPE_ENUM:
538 new->info.enums.count = old->info.enums.count;
539 if (new->info.enums.count) {
540 new->info.enums.list = calloc(new->info.enums.count, sizeof *new->info.enums.list);
541 for (i = 0; i < new->info.enums.count; i++) {
542 new->info.enums.list[i].name = lydict_insert(ctx, old->info.enums.list[i].name, 0);
543 new->info.enums.list[i].dsc = lydict_insert(ctx, old->info.enums.list[i].dsc, 0);
544 new->info.enums.list[i].ref = lydict_insert(ctx, old->info.enums.list[i].ref, 0);
545 }
546 }
547 break;
548 default:
549 /* TODO */
550 break;
551 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200552}
553
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200554void
555ly_type_free(struct ly_ctx *ctx, struct ly_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +0200556{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200557 int i;
Radek Krejci5a065542015-05-22 15:02:07 +0200558
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200559 assert(ctx);
560 if (!type) {
561 return;
562 }
Radek Krejci812b10a2015-05-28 16:48:25 +0200563
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200564 lydict_remove(ctx, type->prefix);
Radek Krejci5a065542015-05-22 15:02:07 +0200565
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200566 switch (type->base) {
567 case LY_TYPE_ENUM:
568 for (i = 0; i < type->info.enums.count; i++) {
569 lydict_remove(ctx, type->info.enums.list[i].name);
570 lydict_remove(ctx, type->info.enums.list[i].dsc);
571 lydict_remove(ctx, type->info.enums.list[i].ref);
572 }
573 free(type->info.enums.list);
574 break;
575 default:
576 /* TODO */
577 break;
578 }
Radek Krejci5a065542015-05-22 15:02:07 +0200579}
580
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200581struct ly_tpdf *
582ly_tpdf_dup(struct ly_ctx *ctx, struct ly_tpdf *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200583{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200584 struct ly_tpdf *result;
585 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200586
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200587 if (!size) {
588 return NULL;
589 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200590
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200591 result = calloc(size, sizeof *result);
592 for (i = 0; i < size; i++) {
593 result[i].name = lydict_insert(ctx, old[i].name, 0);
594 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
595 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
596 result[i].flags = old[i].flags;
597 result[i].module = old[i].module;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200598
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200599 ly_type_dup(ctx, &(result[i].type), &(old[i].type));
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200600
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200601 result[i].dflt = lydict_insert(ctx, old[i].dflt, 0);
602 result[i].units = lydict_insert(ctx, old[i].units, 0);
603 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200604
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200605 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200606}
607
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200608void
609ly_tpdf_free(struct ly_ctx *ctx, struct ly_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200610{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200611 assert(ctx);
612 if (!tpdf) {
613 return;
614 }
Radek Krejci812b10a2015-05-28 16:48:25 +0200615
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200616 lydict_remove(ctx, tpdf->name);
617 lydict_remove(ctx, tpdf->dsc);
618 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200619
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200620 ly_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200621
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200622 lydict_remove(ctx, tpdf->units);
623 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200624}
625
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200626struct ly_must *
627ly_must_dup(struct ly_ctx *ctx, struct ly_must *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200628{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200629 struct ly_must *result;
630 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200631
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200632 if (!size) {
633 return NULL;
634 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200635
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200636 result = calloc(size, sizeof *result);
637 for (i = 0; i < size; i++) {
638 result[i].cond = lydict_insert(ctx, old[i].cond, 0);
639 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
640 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
641 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
642 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
643 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200644
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200645 return result;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200646}
647
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200648void
649ly_must_free(struct ly_ctx *ctx, struct ly_must *must)
Radek Krejci800af702015-06-02 13:46:01 +0200650{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200651 assert(ctx);
652 if (!must) {
653 return;
654 }
Radek Krejci800af702015-06-02 13:46:01 +0200655
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200656 lydict_remove(ctx, must->cond);
657 lydict_remove(ctx, must->dsc);
658 lydict_remove(ctx, must->ref);
659 lydict_remove(ctx, must->eapptag);
660 lydict_remove(ctx, must->emsg);
Radek Krejci800af702015-06-02 13:46:01 +0200661}
662
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200663struct ly_augment *
664ly_augment_dup(struct ly_module *module, struct ly_mnode *parent, struct ly_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +0200665{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200666 struct ly_augment *new = NULL;
667 int i = -1;
Radek Krejci106efc02015-06-10 14:36:27 +0200668
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200669 if (!size) {
670 return NULL;
671 }
Radek Krejci106efc02015-06-10 14:36:27 +0200672
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200673 new = calloc(size, sizeof *new);
674 for (i = 0; i < size; i++) {
675 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
676 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
677 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
678 new[i].flags = old[i].flags;
679 /* .target = NULL; .nodetype = 0 */
Radek Krejci106efc02015-06-10 14:36:27 +0200680
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200681 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +0200682
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200683 /* copy the definition of augment nodes */
684 if (old[i].child) {
685 new[i].child = (struct ly_mnode *)lyxml_dup_elem(module->ctx, (struct lyxml_elem *)old[i].child, NULL, 1);
686 }
687 }
Radek Krejci106efc02015-06-10 14:36:27 +0200688
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200689 return new;
Radek Krejci106efc02015-06-10 14:36:27 +0200690}
691
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200692struct ly_refine *
693ly_refine_dup(struct ly_ctx *ctx, struct ly_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +0200694{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200695 struct ly_refine *result;
696 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +0200697
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200698 if (!size) {
699 return NULL;
700 }
Michal Vasko1982cad2015-06-08 15:49:30 +0200701
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200702 result = calloc(size, sizeof *result);
703 for (i = 0; i < size; i++) {
704 result[i].target = lydict_insert(ctx, old[i].target, 0);
705 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
706 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
707 result[i].flags = old[i].flags;
708 result[i].target_type = old[i].target_type;
709 result[i].must_size = old[i].must_size;
710 result[i].must = ly_must_dup(ctx, old[i].must, old[i].must_size);
711 if (result[i].target_type & (LY_NODE_LEAF | LY_NODE_CHOICE)) {
712 result[i].mod.dflt = lydict_insert(ctx, old[i].mod.dflt, 0);
713 } else if (result[i].target_type == LY_NODE_CONTAINER) {
714 result[i].mod.presence = lydict_insert(ctx, old[i].mod.presence, 0);
715 } else if (result[i].target_type & (LY_NODE_LIST | LY_NODE_LEAFLIST)) {
716 result[i].mod.list = old[i].mod.list;
717 }
718 }
Michal Vasko1982cad2015-06-08 15:49:30 +0200719
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200720 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +0200721}
722
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200723void
724ly_ident_free(struct ly_ctx *ctx, struct ly_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +0200725{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200726 struct ly_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +0200727
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200728 assert(ctx);
729 if (!ident) {
730 return;
731 }
Radek Krejci812b10a2015-05-28 16:48:25 +0200732
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200733 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200734 * if caller free only a single data model which is used (its identity is
735 * reference from identity in another module), this silly freeing can lead
736 * to segmentation fault. But without noting if the module is used by some
737 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +0200738 *
739 * Possible solution is to not allow caller to remove particular schema
740 * from the context.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200741 */
742 while (ident->der) {
743 der = ident->der;
744 ident->der = der->next;
745 free(der);
746 }
Radek Krejci6793db02015-05-22 17:49:54 +0200747
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200748 lydict_remove(ctx, ident->name);
749 lydict_remove(ctx, ident->dsc);
750 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +0200751
752}
753
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200754void
755ly_grp_free(struct ly_ctx *ctx, struct ly_mnode_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200756{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200757 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200758
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200759 /* handle only specific parts for LY_NODE_GROUPING */
760 for (i = 0; i < grp->tpdf_size; i++) {
761 ly_tpdf_free(ctx, &grp->tpdf[i]);
762 }
763 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +0200764}
765
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200766void
767ly_anyxml_free(struct ly_ctx *ctx, struct ly_mnode_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +0200768{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200769 int i;
Radek Krejci537cf382015-06-04 11:07:01 +0200770
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200771 for (i = 0; i < anyxml->must_size; i++) {
772 ly_must_free(ctx, &anyxml->must[i]);
773 }
774 free(anyxml->must);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200775}
776
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200777void
778ly_leaf_free(struct ly_ctx *ctx, struct ly_mnode_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +0200779{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200780 int i;
Radek Krejci537cf382015-06-04 11:07:01 +0200781
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200782 for (i = 0; i < leaf->must_size; i++) {
783 ly_must_free(ctx, &leaf->must[i]);
784 }
785 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +0200786
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200787 ly_type_free(ctx, &leaf->type);
788 lydict_remove(ctx, leaf->units);
789 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +0200790}
791
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200792void
793ly_leaflist_free(struct ly_ctx *ctx, struct ly_mnode_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +0200794{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200795 int i;
Radek Krejci537cf382015-06-04 11:07:01 +0200796
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200797 for (i = 0; i < llist->must_size; i++) {
798 ly_must_free(ctx, &llist->must[i]);
799 }
800 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +0200801
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200802 ly_type_free(ctx, &llist->type);
803 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +0200804}
805
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200806void
807ly_list_free(struct ly_ctx *ctx, struct ly_mnode_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200808{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200809 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200810
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200811 /* handle only specific parts for LY_NODE_LIST */
812 for (i = 0; i < list->tpdf_size; i++) {
813 ly_tpdf_free(ctx, &list->tpdf[i]);
814 }
815 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +0200816
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200817 for (i = 0; i < list->must_size; i++) {
818 ly_must_free(ctx, &list->must[i]);
819 }
820 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +0200821
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200822 for (i = 0; i < list->unique_size; i++) {
823 free(list->unique[i].leafs);
824 }
825 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +0200826
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200827 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200828}
829
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200830void
831ly_container_free(struct ly_ctx *ctx, struct ly_mnode_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200832{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200833 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200834
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200835 /* handle only specific parts for LY_NODE_CONTAINER */
836 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +0200837
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200838 for (i = 0; i < cont->tpdf_size; i++) {
839 ly_tpdf_free(ctx, &cont->tpdf[i]);
840 }
841 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +0200842
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200843 for (i = 0; i < cont->must_size; i++) {
844 ly_must_free(ctx, &cont->must[i]);
845 }
846 free(cont->must);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200847}
848
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200849void
Radek Krejcif5be10f2015-06-16 13:29:36 +0200850ly_augment_free(struct ly_ctx *ctx, struct ly_augment *aug)
851{
852 lydict_remove(ctx, aug->target_name);
853 lydict_remove(ctx, aug->dsc);
854 lydict_remove(ctx, aug->ref);
855
856 lyxml_free_elem(ctx, (struct lyxml_elem *)aug->child);
857}
858
859void
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200860ly_uses_free(struct ly_ctx *ctx, struct ly_mnode_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +0200861{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200862 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +0200863
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200864 for (i = 0; i < uses->refine_size; i++) {
865 lydict_remove(ctx, uses->refine[i].target);
866 lydict_remove(ctx, uses->refine[i].dsc);
867 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +0200868
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200869 for (j = 0; j < uses->refine[j].must_size; j++) {
870 ly_must_free(ctx, &uses->refine[i].must[j]);
871 }
872 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +0200873
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200874 if (uses->refine[i].target_type & (LY_NODE_LEAF | LY_NODE_CHOICE)) {
875 lydict_remove(ctx, uses->refine[i].mod.dflt);
876 } else if (uses->refine[i].target_type & LY_NODE_CONTAINER) {
877 lydict_remove(ctx, uses->refine[i].mod.presence);
878 }
879 }
880 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +0200881
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200882 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200883 ly_augment_free(ctx, &uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200884 }
885 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +0200886
887}
888
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200889void
890ly_mnode_free(struct ly_mnode *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200891{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200892 struct ly_ctx *ctx;
893 struct ly_mnode *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200894
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200895 if (!node) {
896 return;
897 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200898
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200899 assert(node->module);
900 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +0200901
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200902 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200903
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200904 /* common part */
905 LY_TREE_FOR_SAFE(node->child, next, sub) {
906 ly_mnode_free(sub);
907 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200908
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200909 lydict_remove(ctx, node->name);
910 lydict_remove(ctx, node->dsc);
911 lydict_remove(ctx, node->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200912
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200913 /* specific part */
914 switch (node->nodetype) {
915 case LY_NODE_CONTAINER:
916 ly_container_free(ctx, (struct ly_mnode_container *)node);
917 break;
918 case LY_NODE_CHOICE:
919 break;
920 case LY_NODE_LEAF:
921 ly_leaf_free(ctx, (struct ly_mnode_leaf *)node);
922 break;
923 case LY_NODE_LEAFLIST:
924 ly_leaflist_free(ctx, (struct ly_mnode_leaflist *)node);
925 break;
926 case LY_NODE_LIST:
927 ly_list_free(ctx, (struct ly_mnode_list *)node);
928 break;
929 case LY_NODE_ANYXML:
930 ly_anyxml_free(ctx, (struct ly_mnode_anyxml *)node);
931 break;
932 case LY_NODE_USES:
933 ly_uses_free(ctx, (struct ly_mnode_uses *)node);
934 break;
935 case LY_NODE_CASE:
936 case LY_NODE_AUGMENT:
937 /* do nothing */
938 break;
Michal Vasko0ea41032015-06-16 08:53:55 +0200939 case LY_NODE_GROUPING:
940 case LY_NODE_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200941 case LY_NODE_INPUT:
942 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +0200943 case LY_NODE_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200944 ly_grp_free(ctx, (struct ly_mnode_grp *)node);
945 break;
946 }
Radek Krejci5a065542015-05-22 15:02:07 +0200947
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200948 /* again common part */
949 ly_mnode_unlink(node);
950 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200951}
952
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200953static void
954module_free_common(struct ly_module *module)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200955{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200956 struct ly_ctx *ctx;
957 struct ly_mnode *mnode;
958 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +0200959 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200960
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200961 assert(module->ctx);
962 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200963
Radek Krejcidce51452015-06-16 15:20:08 +0200964 /* as first step, free the imported modules */
965 for (i = 0; i < module->imp_size; i++) {
966 /* get the imported module from the context and then free,
967 * this check is necessary because the imported module can
968 * be already removed
969 */
970 l = ctx->models.used;
971 for (j = 0; j < l; j++) {
972 if (ctx->models.list[j] == module->imp[i].module) {
973 ly_module_free(module->imp[i].module);
974 break;
975 }
976 }
977 }
978 free(module->imp);
979
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200980 while (module->data) {
981 mnode = module->data;
982 module->data = mnode;
983 ly_mnode_free(mnode);
984 }
Radek Krejci5a065542015-05-22 15:02:07 +0200985
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200986 lydict_remove(ctx, module->dsc);
987 lydict_remove(ctx, module->ref);
988 lydict_remove(ctx, module->org);
989 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200990
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200991 for (i = 0; i < module->rev_size; i++) {
992 lydict_remove(ctx, module->rev[i].dsc);
993 lydict_remove(ctx, module->rev[i].ref);
994 }
995 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200996
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200997 for (i = 0; i < module->ident_size; i++) {
998 ly_ident_free(ctx, &module->ident[i]);
999 }
1000 module->ident_size = 0;
1001 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001002
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001003 for (i = 0; i < module->tpdf_size; i++) {
1004 ly_tpdf_free(ctx, &module->tpdf[i]);
1005 }
1006 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001007
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001008 for (i = 0; i < module->inc_size; i++) {
1009 ly_submodule_free(module->inc[i].submodule);
1010 }
1011 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001012
Radek Krejcif5be10f2015-06-16 13:29:36 +02001013 for (i = 0; i < module->augment_size; i++) {
1014 ly_augment_free(ctx, &module->augment[i]);
1015 }
1016 free(module->augment);
1017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001018 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02001019}
1020
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001021void
1022ly_submodule_free(struct ly_submodule *submodule)
Radek Krejciefaeba32015-05-27 14:30:57 +02001023{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001024 if (!submodule) {
1025 return;
1026 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001027
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001028 submodule->inc_size = 0;
1029 free(submodule->inc);
1030 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02001031
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001032 /* common part with struct ly_module */
1033 module_free_common((struct ly_module *)submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001034
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001035 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02001036
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001037 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001038}
1039
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001040struct ly_mnode *
1041ly_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 +02001042{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001043 struct ly_mnode *retval = NULL, *aux, *child;
1044 struct ly_ctx *ctx = module->ctx;
1045 int i, j;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001046
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001047 struct ly_mnode_container *cont;
1048 struct ly_mnode_container *cont_orig = (struct ly_mnode_container *)mnode;
1049 struct ly_mnode_choice *choice;
1050 struct ly_mnode_choice *choice_orig = (struct ly_mnode_choice *)mnode;
1051 struct ly_mnode_leaf *leaf;
1052 struct ly_mnode_leaf *leaf_orig = (struct ly_mnode_leaf *)mnode;
1053 struct ly_mnode_leaflist *llist;
1054 struct ly_mnode_leaflist *llist_orig = (struct ly_mnode_leaflist *)mnode;
1055 struct ly_mnode_list *list;
1056 struct ly_mnode_list *list_orig = (struct ly_mnode_list *)mnode;
1057 struct ly_mnode_anyxml *anyxml;
1058 struct ly_mnode_anyxml *anyxml_orig = (struct ly_mnode_anyxml *)mnode;
1059 struct ly_mnode_uses *uses;
1060 struct ly_mnode_uses *uses_orig = (struct ly_mnode_uses *)mnode;
1061 struct ly_mnode_grp *mix;
1062 struct ly_mnode_grp *mix_orig = (struct ly_mnode_grp *)mnode;
1063 struct ly_mnode_case *cs;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001064
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001065 /* we cannot just duplicate memory since the strings are stored in
1066 * dictionary and we need to update dictionary counters.
1067 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001068
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001069 switch (mnode->nodetype) {
1070 case LY_NODE_CONTAINER:
1071 cont = calloc(1, sizeof *cont);
1072 retval = (struct ly_mnode *)cont;
1073 break;
1074
1075 case LY_NODE_CHOICE:
1076 choice = calloc(1, sizeof *choice);
1077 retval = (struct ly_mnode *)choice;
1078 break;
1079
1080 case LY_NODE_LEAF:
1081 leaf = calloc(1, sizeof *leaf);
1082 retval = (struct ly_mnode *)leaf;
1083 break;
1084
1085 case LY_NODE_LEAFLIST:
1086 llist = calloc(1, sizeof *llist);
1087 retval = (struct ly_mnode *)llist;
1088 break;
1089
1090 case LY_NODE_LIST:
1091 list = calloc(1, sizeof *list);
1092 retval = (struct ly_mnode *)list;
1093 break;
1094
1095 case LY_NODE_ANYXML:
1096 anyxml = calloc(1, sizeof *anyxml);
1097 retval = (struct ly_mnode *)anyxml;
1098 break;
1099
1100 case LY_NODE_USES:
1101 uses = calloc(1, sizeof *uses);
1102 retval = (struct ly_mnode *)uses;
1103 break;
1104
1105 case LY_NODE_CASE:
1106 cs = calloc(1, sizeof *cs);
1107 retval = (struct ly_mnode *)cs;
1108 break;
1109
1110 /* exact same structure */
Michal Vasko0ea41032015-06-16 08:53:55 +02001111 case LY_NODE_GROUPING:
Michal Vasko38d01f72015-06-15 09:41:06 +02001112 case LY_NODE_RPC:
Michal Vasko38d01f72015-06-15 09:41:06 +02001113 case LY_NODE_INPUT:
1114 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001115 case LY_NODE_NOTIF:
1116 mix = calloc(1, sizeof *mix);
1117 retval = (struct ly_mnode *)mix;
Michal Vasko38d01f72015-06-15 09:41:06 +02001118 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001119
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001120 default:
1121 goto error;
1122 }
Radek Krejcib388c152015-06-04 17:03:03 +02001123
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001124 /*
1125 * duplicate generic part of the structure
1126 */
1127 retval->name = lydict_insert(ctx, mnode->name, 0);
1128 retval->dsc = lydict_insert(ctx, mnode->dsc, 0);
1129 retval->ref = lydict_insert(ctx, mnode->ref, 0);
1130 retval->flags = mnode->flags;
1131 if (!(retval->flags & LY_NODE_CONFIG_MASK)) {
1132 /* set parent's config flag */
1133 retval->flags |= flags & LY_NODE_CONFIG_MASK;
1134 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001135
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001136 retval->module = module;
1137 retval->nodetype = mnode->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001138
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001139 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001140
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001141 retval->feature = NULL; /* TODO */
1142 retval->when = NULL; /* TODO */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001143
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001144 if (recursive) {
1145 /* go recursively */
1146 LY_TREE_FOR(mnode->child, child) {
1147 aux = ly_mnode_dup(module, child, retval->flags, 1, line);
1148 if (!aux || ly_mnode_addchild(retval, aux)) {
1149 goto error;
1150 }
1151 }
1152 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001154 /*
1155 * duplicate specific part of the structure
1156 */
1157 switch (mnode->nodetype) {
1158 case LY_NODE_CONTAINER:
1159 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001160
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001161 cont->must_size = cont_orig->must_size;
1162 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001163
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001164 cont->must = ly_must_dup(ctx, cont_orig->must, cont->must_size);
1165 cont->tpdf = ly_tpdf_dup(ctx, cont_orig->tpdf, cont->tpdf_size);
1166 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001167
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001168 case LY_NODE_CHOICE:
1169 if (choice->dflt) {
1170 LY_TREE_FOR(choice->child, child) {
1171 if (child->name == choice_orig->dflt->name) {
1172 choice->dflt = child;
1173 break;
1174 }
1175 }
1176 }
1177 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001178
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001179 case LY_NODE_LEAF:
1180 ly_type_dup(ctx, &(leaf->type), &(leaf_orig->type));
1181 leaf->units = lydict_insert(ctx, leaf_orig->units, 0);
1182 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001183
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001184 leaf->must_size = leaf_orig->must_size;
1185 leaf->must = ly_must_dup(ctx, leaf_orig->must, leaf->must_size);
1186 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001187
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001188 case LY_NODE_LEAFLIST:
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001189
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001190 ly_type_dup(ctx, &(llist->type), &(llist_orig->type));
1191 llist->units = lydict_insert(ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001192
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001193 llist->min = llist_orig->min;
1194 llist->max = llist_orig->max;
1195
1196 llist->must_size = llist_orig->must_size;
1197 llist->must = ly_must_dup(ctx, llist_orig->must, llist->must_size);
1198 break;
1199
1200 case LY_NODE_LIST:
1201 list->min = list_orig->min;
1202 list->max = list_orig->max;
1203
1204 list->must_size = list_orig->must_size;
1205 list->tpdf_size = list_orig->tpdf_size;
1206 list->keys_size = list_orig->keys_size;
1207 list->unique_size = list_orig->unique_size;
1208
1209 list->must = ly_must_dup(ctx, list_orig->must, list->must_size);
1210 list->tpdf = ly_tpdf_dup(ctx, list_orig->tpdf, list->tpdf_size);
1211
1212 if (list->keys_size) {
1213 list->keys = calloc(list->keys_size, sizeof *list->keys);
1214 for (i = 0; i < list->keys_size; i++) {
1215 list->keys[i] = find_leaf(retval, list_orig->keys[i]->name, 0);
1216 }
1217 }
1218 if (list->unique_size) {
1219 list->unique = calloc(list->unique_size, sizeof *list->unique);
1220 for (i = 0; i < list->unique_size; i++) {
1221 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
1222 for (j = 0; j < list->unique[i].leafs_size; j++) {
1223 list->unique[i].leafs[j] = find_leaf(retval, list_orig->unique[i].leafs[j]->name, 0);
1224 }
1225 }
1226 }
1227 break;
1228
1229 case LY_NODE_ANYXML:
1230 anyxml->must_size = anyxml_orig->must_size;
1231 anyxml->must = ly_must_dup(ctx, anyxml_orig->must, anyxml->must_size);
1232 break;
1233
1234 case LY_NODE_USES:
1235 uses->grp = uses_orig->grp;
1236 uses->refine_size = uses_orig->refine_size;
1237 uses->refine = ly_refine_dup(ctx, uses_orig->refine, uses_orig->refine_size);
1238 uses->augment_size = uses_orig->augment_size;
1239 uses->augment = ly_augment_dup(module, (struct ly_mnode *)uses, uses_orig->augment, uses_orig->augment_size);
1240 if (resolve_uses(uses, line)) {
1241 goto error;
1242 }
1243 break;
1244
1245 case LY_NODE_CASE:
1246 /* nothing to do */
1247 break;
1248
Michal Vasko0ea41032015-06-16 08:53:55 +02001249 case LY_NODE_GROUPING:
Michal Vasko38d01f72015-06-15 09:41:06 +02001250 case LY_NODE_RPC:
Michal Vasko38d01f72015-06-15 09:41:06 +02001251 case LY_NODE_INPUT:
1252 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001253 case LY_NODE_NOTIF:
1254 mix->tpdf_size = mix_orig->tpdf_size;
1255 mix->tpdf = ly_tpdf_dup(ctx, mix_orig->tpdf, mix->tpdf_size);
Radek Krejcia01e5432015-06-16 10:35:25 +02001256 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001257
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001258 default:
1259 /* LY_NODE_NOTIF */
1260 goto error;
1261 }
1262
1263 return retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001264
1265error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001266 LOGDBG("error: %s:%d", __FILE__, __LINE__);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001267
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001268 ly_mnode_free(retval);
1269 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001270}
1271
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001272API void
1273ly_module_free(struct ly_module *module)
Radek Krejciefaeba32015-05-27 14:30:57 +02001274{
Radek Krejcidce51452015-06-16 15:20:08 +02001275 struct ly_ctx *ctx;
1276 int i;
1277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001278 if (!module) {
1279 return;
1280 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001281
Radek Krejcidce51452015-06-16 15:20:08 +02001282 /* remove schema from the context */
1283 ctx = module->ctx;
1284 if (ctx->models.used) {
1285 for (i = 0; i < ctx->models.used; i++) {
1286 if (ctx->models.list[i] == module) {
1287 /* replace the position in the list by the last module in the list */
1288 ctx->models.used--;
1289 ctx->models.list[i] = ctx->models.list[ctx->models.used];
1290 ctx->models.list[ctx->models.used] = NULL;
1291 /* we are done */
1292 break;
1293 }
1294 }
1295 }
1296
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001297 /* common part with struct ly_submodule */
1298 module_free_common(module);
Radek Krejciefaeba32015-05-27 14:30:57 +02001299
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001300 /* specific items to free */
1301 lydict_remove(module->ctx, module->ns);
1302 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02001303
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001304 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001305}