blob: ef5e2f4826e314a95d5779d7366c442a06277a0b [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
Michal Vasko6f6ac232015-06-18 11:11:46 +0200263 *
264 * node_type - LY_NODE_AUGMENT (searches also RPCs and notifications)
265 * - LY_NODE_USES (the caller is actually either an augment or refine in a uses, only
266 * descendant-schema-nodeid allowed, ".." not allowed)
267 * - LY_NODE_CHOICE (search only start->child, only descendant-schema-nodeid allowed)
Radek Krejci3bde87f2015-06-05 16:51:58 +0200268 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200269struct ly_mnode *
Michal Vasko6f6ac232015-06-18 11:11:46 +0200270resolve_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 +0200271{
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200272 const char *name, *prefix, *ptr;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200273 struct ly_mnode *sibling;
Michal Vasko25880b42015-06-12 10:16:33 +0200274 struct ly_submodule *sub_mod;
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200275 uint32_t i, j, nam_len, pref_len;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200276
Radek Krejcif5be10f2015-06-16 13:29:36 +0200277 assert(mod);
278 assert(id);
279
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200280 if (id[0] == '/') {
Michal Vasko6f6ac232015-06-18 11:11:46 +0200281 if (node_type & (LY_NODE_USES | LY_NODE_CHOICE)) {
282 return NULL;
283 }
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200284 ptr = strchr(id+1, '/');
285 prefix = id+1;
286 } else {
287 ptr = strchr(id, '/');
288 prefix = id;
289 }
290 pref_len = (ptr ? (unsigned)(ptr-prefix) : strlen(prefix));
Radek Krejci3bde87f2015-06-05 16:51:58 +0200291
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200292 ptr = strnchr(prefix, ':', pref_len);
293 /* there is prefix */
294 if (ptr) {
295 nam_len = (pref_len-(ptr-prefix))-1;
296 pref_len = ptr-prefix;
297 name = ptr+1;
298
299 /* no prefix used */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200300 } else {
301 name = prefix;
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200302 nam_len = pref_len;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200303 prefix = NULL;
304 }
Michal Vasko25880b42015-06-12 10:16:33 +0200305
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200306 /* absolute-schema-nodeid */
307 if (id[0] == '/') {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200308 start = NULL;
309
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200310 /* it is not the local prefix */
Radek Krejcif5be10f2015-06-16 13:29:36 +0200311 if (prefix && strncmp(prefix, mod->prefix, pref_len)) {
312 /* check imports */
313 for (i = 0; i < mod->imp_size; i++) {
314 if (!strncmp(mod->imp[i].prefix, prefix, pref_len)) {
315 start = mod->imp[i].module->data;
Michal Vasko25880b42015-06-12 10:16:33 +0200316 break;
317 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200318 }
Radek Krejcif5be10f2015-06-16 13:29:36 +0200319
320 /* no match - check include imports */
321 if (!start) {
322 for (i = 0; i < mod->inc_size; i++) {
323 sub_mod = mod->inc[i].submodule;
324 for (j = 0; j < sub_mod->imp_size; j++) {
325 if (!strncmp(sub_mod->imp[j].prefix, prefix, pref_len)) {
326 start = sub_mod->imp[j].module->data;
327 break;
328 }
329 }
330
331 if (start) {
332 break;
333 }
334 }
335 }
336
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200337 /* no match */
Radek Krejcif5be10f2015-06-16 13:29:36 +0200338 if (!start) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200339 return NULL;
340 }
Michal Vasko25880b42015-06-12 10:16:33 +0200341
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200342 /* it is likely the local prefix */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200343 } else {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200344 start = mod->data;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200345 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200346
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200347 /* descendant-schema-nodeid */
Radek Krejcif5be10f2015-06-16 13:29:36 +0200348 } else {
349 assert(start);
350 start = start->child;
351 }
352
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200353 while (1) {
354 if (!strcmp(name, ".")) {
355 /* this node - start does not change */
356 } else if (!strcmp(name, "..")) {
Michal Vasko6f6ac232015-06-18 11:11:46 +0200357 /* ".." is not allowed in refines and augment sin uses, there is no need for it there */
358 if (!start || (node_type == LY_NODE_USES)) {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200359 return NULL;
360 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200361 start = start->parent;
362 } else {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200363 sibling = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200364 LY_TREE_FOR(start, sibling) {
365 /* match */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200366 if (!strncmp(name, sibling->name, nam_len)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200367 /* prefix check, it's not our own */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200368 if (prefix && strncmp(sibling->module->prefix, prefix, pref_len)) {
Michal Vasko25880b42015-06-12 10:16:33 +0200369
Michal Vasko6f6ac232015-06-18 11:11:46 +0200370 /* in choice and the prefix is not ours, error for sure */
371 if (node_type == LY_NODE_CHOICE) {
372 return NULL;
373 }
374
Michal Vasko25880b42015-06-12 10:16:33 +0200375 /* import prefix check */
376 for (i = 0; i < sibling->module->imp_size; i++) {
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200377 if (!strncmp(sibling->module->imp[i].prefix, prefix, pref_len)
378 && (sibling->module->imp[i].module == sibling->module)) {
Michal Vasko25880b42015-06-12 10:16:33 +0200379 break;
380 }
381 }
382
383 /* import prefix check failed */
384 if (i == sibling->module->imp_size) {
385 /* include import prefix check */
386 for (i = 0; i < sibling->module->inc_size; i++) {
387 sub_mod = sibling->module->inc[i].submodule;
388 for (j = 0; j < sub_mod->imp_size; j++) {
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200389 if (!strncmp(sub_mod->imp[j].prefix, prefix, pref_len)
390 && (sub_mod->imp[j].module == sibling->module)) {
Michal Vasko25880b42015-06-12 10:16:33 +0200391 break;
392 }
393 }
394
395 if (j < sub_mod->imp_size) {
396 break;
397 }
398 }
399
400 /* include import prefix check failed too - definite fail */
401 if (i == sibling->module->inc_size) {
Michal Vasko25880b42015-06-12 10:16:33 +0200402 return NULL;
403 }
404 }
405 }
406
407 /* the result node? */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200408 ptr = name+nam_len;
409 if (!ptr[0]) {
Michal Vasko25880b42015-06-12 10:16:33 +0200410 return sibling;
411 }
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200412 assert(ptr[0] == '/');
Michal Vasko25880b42015-06-12 10:16:33 +0200413
414 /* check for shorthand cases - then 'start' does not change */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200415 if (!sibling->parent || (sibling->parent->nodetype != LY_NODE_CHOICE)
416 || (sibling->nodetype == LY_NODE_CASE)) {
Michal Vasko25880b42015-06-12 10:16:33 +0200417 start = sibling->child;
418 }
419 break;
420 }
421 }
Radek Krejcif5be10f2015-06-16 13:29:36 +0200422
Michal Vasko6f6ac232015-06-18 11:11:46 +0200423 /* we did not find the case in direct siblings */
424 if (node_type == LY_NODE_CHOICE) {
425 return NULL;
426 }
427
Michal Vasko25880b42015-06-12 10:16:33 +0200428 /* no match */
429 if (!sibling) {
Michal Vasko6f6ac232015-06-18 11:11:46 +0200430 /* on augment search also RPCs and notifications, if we are in top-level */
431 if ((node_type == LY_NODE_AUGMENT) && !start->parent) {
432 /* we have searched all the data nodes */
433 if (start == start->module->data) {
434 start = start->module->rpc;
435 if (start) {
436 continue;
437 }
438 }
439 /* we have searched all the RPCs */
440 if (start == start->module->rpc) {
441 start = start->module->notif;
442 if (start) {
443 continue;
444 }
445 }
446 /* we have searched all the notifications, nothing else to search in */
447 if (start == start->module->notif) {
448 return NULL;
449 }
450 }
Michal Vasko25880b42015-06-12 10:16:33 +0200451 return NULL;
452 }
453 }
454
Michal Vaskoa158c682015-06-17 09:25:38 +0200455 assert((*(name+nam_len) == '/') || (*(name+nam_len) == '\0'));
456
457 /* make prefix point to the next node name */
458 prefix = name+nam_len;
459 if (!prefix[0]) {
460 return start;
461 }
462 ++prefix;
463
464 /* parse prefix and node name */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200465 ptr = strchr(prefix, '/');
466 pref_len = (ptr ? (unsigned)(ptr-prefix) : strlen(prefix));
467 ptr = strnchr(prefix, ':', pref_len);
468
469 /* there is prefix */
470 if (ptr) {
Michal Vaskoa158c682015-06-17 09:25:38 +0200471 nam_len = (pref_len-(ptr-prefix))-1;
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200472 pref_len = ptr-prefix;
473 name = ptr+1;
474
475 /* no prefix used */
Michal Vasko25880b42015-06-12 10:16:33 +0200476 } else {
477 name = prefix;
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200478 nam_len = pref_len;
Michal Vasko25880b42015-06-12 10:16:33 +0200479 prefix = NULL;
480 }
Michal Vasko25880b42015-06-12 10:16:33 +0200481 }
482
483 /* cannot get here */
484 return NULL;
Radek Krejci3bde87f2015-06-05 16:51:58 +0200485}
486
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200487API struct ly_module *
488ly_module_read(struct ly_ctx *ctx, const char *data, LY_MINFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200489{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200490 if (!ctx || !data) {
491 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
492 return NULL;
493 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200494
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200495 switch (format) {
496 case LY_IN_YIN:
497 return yin_read_module(ctx, data);
498 case LY_IN_YANG:
499 default:
500 /* TODO */
501 return NULL;
502 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200503
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200504 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200505}
506
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200507struct ly_submodule *
508ly_submodule_read(struct ly_module *module, const char *data, LY_MINFORMAT format)
Radek Krejciefaeba32015-05-27 14:30:57 +0200509{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200510 assert(module);
511 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200512
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200513 switch (format) {
514 case LY_IN_YIN:
515 return yin_read_submodule(module, data);
516 case LY_IN_YANG:
517 default:
518 /* TODO */
519 return NULL;
520 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200521
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200522 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +0200523}
524
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200525API struct ly_module *
526ly_module_read_fd(struct ly_ctx *ctx, int fd, LY_MINFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200527{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200528 struct ly_module *module;
529 struct stat sb;
530 char *addr;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200531
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200532 if (!ctx || fd < 0) {
533 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
534 return NULL;
535 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200537 /*
538 * TODO
539 * This is just a temporary solution to make working automatic search for
540 * imported modules. This doesn't work e.g. for streams (stdin)
541 */
542 fstat(fd, &sb);
543 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
544 module = ly_module_read(ctx, addr, format);
545 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200546
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200547 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200548}
549
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200550struct ly_submodule *
551ly_submodule_read_fd(struct ly_module *module, int fd, LY_MINFORMAT format)
Radek Krejciefaeba32015-05-27 14:30:57 +0200552{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200553 struct ly_submodule *submodule;
554 struct stat sb;
555 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +0200556
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200557 assert(module);
558 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +0200559
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200560 /*
561 * TODO
562 * This is just a temporary solution to make working automatic search for
563 * imported modules. This doesn't work e.g. for streams (stdin)
564 */
565 fstat(fd, &sb);
566 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
567 /* TODO addr error check */
568 submodule = ly_submodule_read(module, addr, format);
569 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +0200570
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200571 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +0200572
573}
574
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200575void
576ly_type_dup(struct ly_ctx *ctx, struct ly_type *new, struct ly_type *old)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200577{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200578 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200579
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200580 new->prefix = lydict_insert(ctx, old->prefix, 0);
581 new->base = old->base;
582 new->der = old->der;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200583
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200584 switch (new->base) {
585 case LY_TYPE_ENUM:
586 new->info.enums.count = old->info.enums.count;
587 if (new->info.enums.count) {
588 new->info.enums.list = calloc(new->info.enums.count, sizeof *new->info.enums.list);
589 for (i = 0; i < new->info.enums.count; i++) {
590 new->info.enums.list[i].name = lydict_insert(ctx, old->info.enums.list[i].name, 0);
591 new->info.enums.list[i].dsc = lydict_insert(ctx, old->info.enums.list[i].dsc, 0);
592 new->info.enums.list[i].ref = lydict_insert(ctx, old->info.enums.list[i].ref, 0);
593 }
594 }
595 break;
596 default:
597 /* TODO */
598 break;
599 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200600}
601
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200602void
603ly_type_free(struct ly_ctx *ctx, struct ly_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +0200604{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200605 int i;
Radek Krejci5a065542015-05-22 15:02:07 +0200606
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200607 assert(ctx);
608 if (!type) {
609 return;
610 }
Radek Krejci812b10a2015-05-28 16:48:25 +0200611
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200612 lydict_remove(ctx, type->prefix);
Radek Krejci5a065542015-05-22 15:02:07 +0200613
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200614 switch (type->base) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200615 case LY_TYPE_BITS:
616 for (i = 0; i < type->info.bits.count; i++) {
617 lydict_remove(ctx, type->info.bits.bit[i].name);
618 lydict_remove(ctx, type->info.bits.bit[i].dsc);
619 lydict_remove(ctx, type->info.bits.bit[i].ref);
620 }
621 free(type->info.bits.bit);
622 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200623 case LY_TYPE_ENUM:
624 for (i = 0; i < type->info.enums.count; i++) {
625 lydict_remove(ctx, type->info.enums.list[i].name);
626 lydict_remove(ctx, type->info.enums.list[i].dsc);
627 lydict_remove(ctx, type->info.enums.list[i].ref);
628 }
629 free(type->info.enums.list);
630 break;
631 default:
632 /* TODO */
633 break;
634 }
Radek Krejci5a065542015-05-22 15:02:07 +0200635}
636
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200637struct ly_tpdf *
638ly_tpdf_dup(struct ly_ctx *ctx, struct ly_tpdf *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200639{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200640 struct ly_tpdf *result;
641 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200642
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200643 if (!size) {
644 return NULL;
645 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200646
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200647 result = calloc(size, sizeof *result);
648 for (i = 0; i < size; i++) {
649 result[i].name = lydict_insert(ctx, old[i].name, 0);
650 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
651 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
652 result[i].flags = old[i].flags;
653 result[i].module = old[i].module;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200654
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200655 ly_type_dup(ctx, &(result[i].type), &(old[i].type));
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200657 result[i].dflt = lydict_insert(ctx, old[i].dflt, 0);
658 result[i].units = lydict_insert(ctx, old[i].units, 0);
659 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200660
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200661 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200662}
663
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200664void
665ly_tpdf_free(struct ly_ctx *ctx, struct ly_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200666{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200667 assert(ctx);
668 if (!tpdf) {
669 return;
670 }
Radek Krejci812b10a2015-05-28 16:48:25 +0200671
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200672 lydict_remove(ctx, tpdf->name);
673 lydict_remove(ctx, tpdf->dsc);
674 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200675
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200676 ly_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200677
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200678 lydict_remove(ctx, tpdf->units);
679 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200680}
681
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200682struct ly_must *
683ly_must_dup(struct ly_ctx *ctx, struct ly_must *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200684{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200685 struct ly_must *result;
686 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200687
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200688 if (!size) {
689 return NULL;
690 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200691
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200692 result = calloc(size, sizeof *result);
693 for (i = 0; i < size; i++) {
694 result[i].cond = lydict_insert(ctx, old[i].cond, 0);
695 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
696 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
697 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
698 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
699 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200700
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200701 return result;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200702}
703
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200704void
705ly_must_free(struct ly_ctx *ctx, struct ly_must *must)
Radek Krejci800af702015-06-02 13:46:01 +0200706{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200707 assert(ctx);
708 if (!must) {
709 return;
710 }
Radek Krejci800af702015-06-02 13:46:01 +0200711
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200712 lydict_remove(ctx, must->cond);
713 lydict_remove(ctx, must->dsc);
714 lydict_remove(ctx, must->ref);
715 lydict_remove(ctx, must->eapptag);
716 lydict_remove(ctx, must->emsg);
Radek Krejci800af702015-06-02 13:46:01 +0200717}
718
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200719void
720ly_when_free(struct ly_ctx *ctx, struct ly_when *w)
721{
722 if (!w) {
723 return;
724 }
725
726 lydict_remove(ctx, w->cond);
727 lydict_remove(ctx, w->dsc);
728 lydict_remove(ctx, w->ref);
729
730 free(w);
731}
732
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200733struct ly_augment *
734ly_augment_dup(struct ly_module *module, struct ly_mnode *parent, struct ly_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +0200735{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200736 struct ly_augment *new = NULL;
737 int i = -1;
Radek Krejci106efc02015-06-10 14:36:27 +0200738
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200739 if (!size) {
740 return NULL;
741 }
Radek Krejci106efc02015-06-10 14:36:27 +0200742
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200743 new = calloc(size, sizeof *new);
744 for (i = 0; i < size; i++) {
745 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
746 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
747 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
748 new[i].flags = old[i].flags;
749 /* .target = NULL; .nodetype = 0 */
Radek Krejci106efc02015-06-10 14:36:27 +0200750
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200751 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +0200752
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200753 /* copy the definition of augment nodes */
754 if (old[i].child) {
755 new[i].child = (struct ly_mnode *)lyxml_dup_elem(module->ctx, (struct lyxml_elem *)old[i].child, NULL, 1);
756 }
757 }
Radek Krejci106efc02015-06-10 14:36:27 +0200758
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200759 return new;
Radek Krejci106efc02015-06-10 14:36:27 +0200760}
761
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200762struct ly_refine *
763ly_refine_dup(struct ly_ctx *ctx, struct ly_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +0200764{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200765 struct ly_refine *result;
766 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +0200767
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200768 if (!size) {
769 return NULL;
770 }
Michal Vasko1982cad2015-06-08 15:49:30 +0200771
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200772 result = calloc(size, sizeof *result);
773 for (i = 0; i < size; i++) {
774 result[i].target = lydict_insert(ctx, old[i].target, 0);
775 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
776 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
777 result[i].flags = old[i].flags;
778 result[i].target_type = old[i].target_type;
779 result[i].must_size = old[i].must_size;
780 result[i].must = ly_must_dup(ctx, old[i].must, old[i].must_size);
781 if (result[i].target_type & (LY_NODE_LEAF | LY_NODE_CHOICE)) {
782 result[i].mod.dflt = lydict_insert(ctx, old[i].mod.dflt, 0);
783 } else if (result[i].target_type == LY_NODE_CONTAINER) {
784 result[i].mod.presence = lydict_insert(ctx, old[i].mod.presence, 0);
785 } else if (result[i].target_type & (LY_NODE_LIST | LY_NODE_LEAFLIST)) {
786 result[i].mod.list = old[i].mod.list;
787 }
788 }
Michal Vasko1982cad2015-06-08 15:49:30 +0200789
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200790 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +0200791}
792
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200793void
794ly_ident_free(struct ly_ctx *ctx, struct ly_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +0200795{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200796 struct ly_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +0200797
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200798 assert(ctx);
799 if (!ident) {
800 return;
801 }
Radek Krejci812b10a2015-05-28 16:48:25 +0200802
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200803 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200804 * if caller free only a single data model which is used (its identity is
805 * reference from identity in another module), this silly freeing can lead
806 * to segmentation fault. But without noting if the module is used by some
807 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +0200808 *
809 * Possible solution is to not allow caller to remove particular schema
810 * from the context.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200811 */
812 while (ident->der) {
813 der = ident->der;
814 ident->der = der->next;
815 free(der);
816 }
Radek Krejci6793db02015-05-22 17:49:54 +0200817
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200818 lydict_remove(ctx, ident->name);
819 lydict_remove(ctx, ident->dsc);
820 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +0200821
822}
823
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200824void
825ly_grp_free(struct ly_ctx *ctx, struct ly_mnode_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200826{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200827 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200828
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200829 /* handle only specific parts for LY_NODE_GROUPING */
830 for (i = 0; i < grp->tpdf_size; i++) {
831 ly_tpdf_free(ctx, &grp->tpdf[i]);
832 }
833 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +0200834}
835
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200836void
837ly_anyxml_free(struct ly_ctx *ctx, struct ly_mnode_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +0200838{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200839 int i;
Radek Krejci537cf382015-06-04 11:07:01 +0200840
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200841 for (i = 0; i < anyxml->must_size; i++) {
842 ly_must_free(ctx, &anyxml->must[i]);
843 }
844 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200845
846 ly_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200847}
848
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200849void
850ly_leaf_free(struct ly_ctx *ctx, struct ly_mnode_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +0200851{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200852 int i;
Radek Krejci537cf382015-06-04 11:07:01 +0200853
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200854 for (i = 0; i < leaf->must_size; i++) {
855 ly_must_free(ctx, &leaf->must[i]);
856 }
857 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +0200858
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200859 ly_when_free(ctx, leaf->when);
860
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200861 ly_type_free(ctx, &leaf->type);
862 lydict_remove(ctx, leaf->units);
863 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +0200864}
865
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200866void
867ly_leaflist_free(struct ly_ctx *ctx, struct ly_mnode_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +0200868{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200869 int i;
Radek Krejci537cf382015-06-04 11:07:01 +0200870
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200871 for (i = 0; i < llist->must_size; i++) {
872 ly_must_free(ctx, &llist->must[i]);
873 }
874 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +0200875
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200876 ly_when_free(ctx, llist->when);
877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200878 ly_type_free(ctx, &llist->type);
879 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +0200880}
881
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200882void
883ly_list_free(struct ly_ctx *ctx, struct ly_mnode_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200884{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200885 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200886
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200887 /* handle only specific parts for LY_NODE_LIST */
888 for (i = 0; i < list->tpdf_size; i++) {
889 ly_tpdf_free(ctx, &list->tpdf[i]);
890 }
891 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +0200892
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200893 for (i = 0; i < list->must_size; i++) {
894 ly_must_free(ctx, &list->must[i]);
895 }
896 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +0200897
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200898 ly_when_free(ctx, list->when);
899
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200900 for (i = 0; i < list->unique_size; i++) {
901 free(list->unique[i].leafs);
902 }
903 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +0200904
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200905 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200906}
907
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200908void
909ly_container_free(struct ly_ctx *ctx, struct ly_mnode_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200910{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200911 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200912
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200913 /* handle only specific parts for LY_NODE_CONTAINER */
914 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +0200915
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200916 for (i = 0; i < cont->tpdf_size; i++) {
917 ly_tpdf_free(ctx, &cont->tpdf[i]);
918 }
919 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +0200920
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200921 for (i = 0; i < cont->must_size; i++) {
922 ly_must_free(ctx, &cont->must[i]);
923 }
924 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200925
926 ly_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200927}
928
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200929void
Radek Krejci3cf9e222015-06-18 11:37:50 +0200930ly_feature_free(struct ly_ctx *ctx, struct ly_feature *f)
931{
932 lydict_remove(ctx, f->name);
933 lydict_remove(ctx, f->dsc);
934 lydict_remove(ctx, f->ref);
935 free(f->features);
936}
937
938void
Radek Krejcif5be10f2015-06-16 13:29:36 +0200939ly_augment_free(struct ly_ctx *ctx, struct ly_augment *aug)
940{
941 lydict_remove(ctx, aug->target_name);
942 lydict_remove(ctx, aug->dsc);
943 lydict_remove(ctx, aug->ref);
944
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200945 ly_when_free(ctx, aug->when);
946
Radek Krejcif5be10f2015-06-16 13:29:36 +0200947 lyxml_free_elem(ctx, (struct lyxml_elem *)aug->child);
948}
949
950void
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200951ly_uses_free(struct ly_ctx *ctx, struct ly_mnode_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +0200952{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200953 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +0200954
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200955 for (i = 0; i < uses->refine_size; i++) {
956 lydict_remove(ctx, uses->refine[i].target);
957 lydict_remove(ctx, uses->refine[i].dsc);
958 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +0200959
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200960 for (j = 0; j < uses->refine[j].must_size; j++) {
961 ly_must_free(ctx, &uses->refine[i].must[j]);
962 }
963 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +0200964
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200965 if (uses->refine[i].target_type & (LY_NODE_LEAF | LY_NODE_CHOICE)) {
966 lydict_remove(ctx, uses->refine[i].mod.dflt);
967 } else if (uses->refine[i].target_type & LY_NODE_CONTAINER) {
968 lydict_remove(ctx, uses->refine[i].mod.presence);
969 }
970 }
971 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +0200972
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200973 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200974 ly_augment_free(ctx, &uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200975 }
976 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +0200977
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200978 ly_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +0200979}
980
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200981void
982ly_mnode_free(struct ly_mnode *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200983{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200984 struct ly_ctx *ctx;
985 struct ly_mnode *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200986
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200987 if (!node) {
988 return;
989 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200990
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200991 assert(node->module);
992 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +0200993
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200994 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200995
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200996 /* common part */
997 LY_TREE_FOR_SAFE(node->child, next, sub) {
998 ly_mnode_free(sub);
999 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001000 free(node->features);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001001
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001002 lydict_remove(ctx, node->name);
1003 lydict_remove(ctx, node->dsc);
1004 lydict_remove(ctx, node->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001005
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001006 /* specific part */
1007 switch (node->nodetype) {
1008 case LY_NODE_CONTAINER:
1009 ly_container_free(ctx, (struct ly_mnode_container *)node);
1010 break;
1011 case LY_NODE_CHOICE:
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001012 ly_when_free(ctx, ((struct ly_mnode_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001013 break;
1014 case LY_NODE_LEAF:
1015 ly_leaf_free(ctx, (struct ly_mnode_leaf *)node);
1016 break;
1017 case LY_NODE_LEAFLIST:
1018 ly_leaflist_free(ctx, (struct ly_mnode_leaflist *)node);
1019 break;
1020 case LY_NODE_LIST:
1021 ly_list_free(ctx, (struct ly_mnode_list *)node);
1022 break;
1023 case LY_NODE_ANYXML:
1024 ly_anyxml_free(ctx, (struct ly_mnode_anyxml *)node);
1025 break;
1026 case LY_NODE_USES:
1027 ly_uses_free(ctx, (struct ly_mnode_uses *)node);
1028 break;
1029 case LY_NODE_CASE:
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001030 ly_when_free(ctx, ((struct ly_mnode_case *)node)->when);
1031 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001032 case LY_NODE_AUGMENT:
1033 /* do nothing */
1034 break;
Michal Vasko0ea41032015-06-16 08:53:55 +02001035 case LY_NODE_GROUPING:
1036 case LY_NODE_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001037 case LY_NODE_INPUT:
1038 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001039 case LY_NODE_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001040 ly_grp_free(ctx, (struct ly_mnode_grp *)node);
1041 break;
1042 }
Radek Krejci5a065542015-05-22 15:02:07 +02001043
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001044 /* again common part */
1045 ly_mnode_unlink(node);
1046 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001047}
1048
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001049static void
1050module_free_common(struct ly_module *module)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001051{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001052 struct ly_ctx *ctx;
1053 struct ly_mnode *mnode;
1054 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001055 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001056
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001057 assert(module->ctx);
1058 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001059
Radek Krejcidce51452015-06-16 15:20:08 +02001060 /* as first step, free the imported modules */
1061 for (i = 0; i < module->imp_size; i++) {
1062 /* get the imported module from the context and then free,
1063 * this check is necessary because the imported module can
1064 * be already removed
1065 */
1066 l = ctx->models.used;
1067 for (j = 0; j < l; j++) {
1068 if (ctx->models.list[j] == module->imp[i].module) {
1069 ly_module_free(module->imp[i].module);
1070 break;
1071 }
1072 }
1073 }
1074 free(module->imp);
1075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001076 while (module->data) {
1077 mnode = module->data;
1078 module->data = mnode;
1079 ly_mnode_free(mnode);
1080 }
Radek Krejci5a065542015-05-22 15:02:07 +02001081
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001082 lydict_remove(ctx, module->dsc);
1083 lydict_remove(ctx, module->ref);
1084 lydict_remove(ctx, module->org);
1085 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001086
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001087 for (i = 0; i < module->rev_size; i++) {
1088 lydict_remove(ctx, module->rev[i].dsc);
1089 lydict_remove(ctx, module->rev[i].ref);
1090 }
1091 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001092
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001093 for (i = 0; i < module->ident_size; i++) {
1094 ly_ident_free(ctx, &module->ident[i]);
1095 }
1096 module->ident_size = 0;
1097 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001098
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001099 for (i = 0; i < module->tpdf_size; i++) {
1100 ly_tpdf_free(ctx, &module->tpdf[i]);
1101 }
1102 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001104 for (i = 0; i < module->inc_size; i++) {
1105 ly_submodule_free(module->inc[i].submodule);
1106 }
1107 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001108
Radek Krejcif5be10f2015-06-16 13:29:36 +02001109 for (i = 0; i < module->augment_size; i++) {
1110 ly_augment_free(ctx, &module->augment[i]);
1111 }
1112 free(module->augment);
1113
Radek Krejci3cf9e222015-06-18 11:37:50 +02001114 for (i = 0; i < module->features_size; i++) {
1115 ly_feature_free(ctx, &module->features[i]);
1116 }
1117 free(module->features);
1118
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001119 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02001120}
1121
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001122void
1123ly_submodule_free(struct ly_submodule *submodule)
Radek Krejciefaeba32015-05-27 14:30:57 +02001124{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001125 if (!submodule) {
1126 return;
1127 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001128
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001129 submodule->inc_size = 0;
1130 free(submodule->inc);
1131 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02001132
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001133 /* common part with struct ly_module */
1134 module_free_common((struct ly_module *)submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001135
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001136 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02001137
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001138 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001139}
1140
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001141struct ly_mnode *
1142ly_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 +02001143{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001144 struct ly_mnode *retval = NULL, *aux, *child;
1145 struct ly_ctx *ctx = module->ctx;
1146 int i, j;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001147
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001148 struct ly_mnode_container *cont;
1149 struct ly_mnode_container *cont_orig = (struct ly_mnode_container *)mnode;
1150 struct ly_mnode_choice *choice;
1151 struct ly_mnode_choice *choice_orig = (struct ly_mnode_choice *)mnode;
1152 struct ly_mnode_leaf *leaf;
1153 struct ly_mnode_leaf *leaf_orig = (struct ly_mnode_leaf *)mnode;
1154 struct ly_mnode_leaflist *llist;
1155 struct ly_mnode_leaflist *llist_orig = (struct ly_mnode_leaflist *)mnode;
1156 struct ly_mnode_list *list;
1157 struct ly_mnode_list *list_orig = (struct ly_mnode_list *)mnode;
1158 struct ly_mnode_anyxml *anyxml;
1159 struct ly_mnode_anyxml *anyxml_orig = (struct ly_mnode_anyxml *)mnode;
1160 struct ly_mnode_uses *uses;
1161 struct ly_mnode_uses *uses_orig = (struct ly_mnode_uses *)mnode;
1162 struct ly_mnode_grp *mix;
1163 struct ly_mnode_grp *mix_orig = (struct ly_mnode_grp *)mnode;
1164 struct ly_mnode_case *cs;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001165
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001166 /* we cannot just duplicate memory since the strings are stored in
1167 * dictionary and we need to update dictionary counters.
1168 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001169
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001170 switch (mnode->nodetype) {
1171 case LY_NODE_CONTAINER:
1172 cont = calloc(1, sizeof *cont);
1173 retval = (struct ly_mnode *)cont;
1174 break;
1175
1176 case LY_NODE_CHOICE:
1177 choice = calloc(1, sizeof *choice);
1178 retval = (struct ly_mnode *)choice;
1179 break;
1180
1181 case LY_NODE_LEAF:
1182 leaf = calloc(1, sizeof *leaf);
1183 retval = (struct ly_mnode *)leaf;
1184 break;
1185
1186 case LY_NODE_LEAFLIST:
1187 llist = calloc(1, sizeof *llist);
1188 retval = (struct ly_mnode *)llist;
1189 break;
1190
1191 case LY_NODE_LIST:
1192 list = calloc(1, sizeof *list);
1193 retval = (struct ly_mnode *)list;
1194 break;
1195
1196 case LY_NODE_ANYXML:
1197 anyxml = calloc(1, sizeof *anyxml);
1198 retval = (struct ly_mnode *)anyxml;
1199 break;
1200
1201 case LY_NODE_USES:
1202 uses = calloc(1, sizeof *uses);
1203 retval = (struct ly_mnode *)uses;
1204 break;
1205
1206 case LY_NODE_CASE:
1207 cs = calloc(1, sizeof *cs);
1208 retval = (struct ly_mnode *)cs;
1209 break;
1210
1211 /* exact same structure */
Michal Vasko0ea41032015-06-16 08:53:55 +02001212 case LY_NODE_GROUPING:
Michal Vasko38d01f72015-06-15 09:41:06 +02001213 case LY_NODE_RPC:
Michal Vasko38d01f72015-06-15 09:41:06 +02001214 case LY_NODE_INPUT:
1215 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001216 case LY_NODE_NOTIF:
1217 mix = calloc(1, sizeof *mix);
1218 retval = (struct ly_mnode *)mix;
Michal Vasko38d01f72015-06-15 09:41:06 +02001219 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001220
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001221 default:
1222 goto error;
1223 }
Radek Krejcib388c152015-06-04 17:03:03 +02001224
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001225 /*
1226 * duplicate generic part of the structure
1227 */
1228 retval->name = lydict_insert(ctx, mnode->name, 0);
1229 retval->dsc = lydict_insert(ctx, mnode->dsc, 0);
1230 retval->ref = lydict_insert(ctx, mnode->ref, 0);
1231 retval->flags = mnode->flags;
1232 if (!(retval->flags & LY_NODE_CONFIG_MASK)) {
1233 /* set parent's config flag */
1234 retval->flags |= flags & LY_NODE_CONFIG_MASK;
1235 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001237 retval->module = module;
1238 retval->nodetype = mnode->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001239
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001240 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001241
Radek Krejci3cf9e222015-06-18 11:37:50 +02001242 retval->features_size = mnode->features_size;
1243 retval->features = calloc(retval->features_size, sizeof *retval->features);
1244 memcpy(retval->features, mnode->features, retval->features_size * sizeof *retval->features);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001245
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001246 if (recursive) {
1247 /* go recursively */
1248 LY_TREE_FOR(mnode->child, child) {
1249 aux = ly_mnode_dup(module, child, retval->flags, 1, line);
1250 if (!aux || ly_mnode_addchild(retval, aux)) {
1251 goto error;
1252 }
1253 }
1254 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001255
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001256 /*
1257 * duplicate specific part of the structure
1258 */
1259 switch (mnode->nodetype) {
1260 case LY_NODE_CONTAINER:
1261 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001262
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001263 cont->must_size = cont_orig->must_size;
1264 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001265
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001266 cont->must = ly_must_dup(ctx, cont_orig->must, cont->must_size);
1267 cont->tpdf = ly_tpdf_dup(ctx, cont_orig->tpdf, cont->tpdf_size);
1268 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001269
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001270 case LY_NODE_CHOICE:
1271 if (choice->dflt) {
1272 LY_TREE_FOR(choice->child, child) {
1273 if (child->name == choice_orig->dflt->name) {
1274 choice->dflt = child;
1275 break;
1276 }
1277 }
1278 }
1279 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001280
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001281 case LY_NODE_LEAF:
1282 ly_type_dup(ctx, &(leaf->type), &(leaf_orig->type));
1283 leaf->units = lydict_insert(ctx, leaf_orig->units, 0);
1284 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001286 leaf->must_size = leaf_orig->must_size;
1287 leaf->must = ly_must_dup(ctx, leaf_orig->must, leaf->must_size);
1288 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001289
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001290 case LY_NODE_LEAFLIST:
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001291
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001292 ly_type_dup(ctx, &(llist->type), &(llist_orig->type));
1293 llist->units = lydict_insert(ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001294
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001295 llist->min = llist_orig->min;
1296 llist->max = llist_orig->max;
1297
1298 llist->must_size = llist_orig->must_size;
1299 llist->must = ly_must_dup(ctx, llist_orig->must, llist->must_size);
1300 break;
1301
1302 case LY_NODE_LIST:
1303 list->min = list_orig->min;
1304 list->max = list_orig->max;
1305
1306 list->must_size = list_orig->must_size;
1307 list->tpdf_size = list_orig->tpdf_size;
1308 list->keys_size = list_orig->keys_size;
1309 list->unique_size = list_orig->unique_size;
1310
1311 list->must = ly_must_dup(ctx, list_orig->must, list->must_size);
1312 list->tpdf = ly_tpdf_dup(ctx, list_orig->tpdf, list->tpdf_size);
1313
1314 if (list->keys_size) {
1315 list->keys = calloc(list->keys_size, sizeof *list->keys);
1316 for (i = 0; i < list->keys_size; i++) {
1317 list->keys[i] = find_leaf(retval, list_orig->keys[i]->name, 0);
1318 }
1319 }
1320 if (list->unique_size) {
1321 list->unique = calloc(list->unique_size, sizeof *list->unique);
1322 for (i = 0; i < list->unique_size; i++) {
1323 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
1324 for (j = 0; j < list->unique[i].leafs_size; j++) {
1325 list->unique[i].leafs[j] = find_leaf(retval, list_orig->unique[i].leafs[j]->name, 0);
1326 }
1327 }
1328 }
1329 break;
1330
1331 case LY_NODE_ANYXML:
1332 anyxml->must_size = anyxml_orig->must_size;
1333 anyxml->must = ly_must_dup(ctx, anyxml_orig->must, anyxml->must_size);
1334 break;
1335
1336 case LY_NODE_USES:
1337 uses->grp = uses_orig->grp;
1338 uses->refine_size = uses_orig->refine_size;
1339 uses->refine = ly_refine_dup(ctx, uses_orig->refine, uses_orig->refine_size);
1340 uses->augment_size = uses_orig->augment_size;
1341 uses->augment = ly_augment_dup(module, (struct ly_mnode *)uses, uses_orig->augment, uses_orig->augment_size);
1342 if (resolve_uses(uses, line)) {
1343 goto error;
1344 }
1345 break;
1346
1347 case LY_NODE_CASE:
1348 /* nothing to do */
1349 break;
1350
Michal Vasko0ea41032015-06-16 08:53:55 +02001351 case LY_NODE_GROUPING:
Michal Vasko38d01f72015-06-15 09:41:06 +02001352 case LY_NODE_RPC:
Michal Vasko38d01f72015-06-15 09:41:06 +02001353 case LY_NODE_INPUT:
1354 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001355 case LY_NODE_NOTIF:
1356 mix->tpdf_size = mix_orig->tpdf_size;
1357 mix->tpdf = ly_tpdf_dup(ctx, mix_orig->tpdf, mix->tpdf_size);
Radek Krejcia01e5432015-06-16 10:35:25 +02001358 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001359
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001360 default:
1361 /* LY_NODE_NOTIF */
1362 goto error;
1363 }
1364
1365 return retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001366
1367error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001368 LOGDBG("error: %s:%d", __FILE__, __LINE__);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001369
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001370 ly_mnode_free(retval);
1371 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001372}
1373
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001374API void
1375ly_module_free(struct ly_module *module)
Radek Krejciefaeba32015-05-27 14:30:57 +02001376{
Radek Krejcidce51452015-06-16 15:20:08 +02001377 struct ly_ctx *ctx;
1378 int i;
1379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001380 if (!module) {
1381 return;
1382 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001383
Radek Krejcidce51452015-06-16 15:20:08 +02001384 /* remove schema from the context */
1385 ctx = module->ctx;
1386 if (ctx->models.used) {
1387 for (i = 0; i < ctx->models.used; i++) {
1388 if (ctx->models.list[i] == module) {
1389 /* replace the position in the list by the last module in the list */
1390 ctx->models.used--;
1391 ctx->models.list[i] = ctx->models.list[ctx->models.used];
1392 ctx->models.list[ctx->models.used] = NULL;
1393 /* we are done */
1394 break;
1395 }
1396 }
1397 }
1398
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001399 /* common part with struct ly_submodule */
1400 module_free_common(module);
Radek Krejciefaeba32015-05-27 14:30:57 +02001401
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001402 /* specific items to free */
1403 lydict_remove(module->ctx, module->ns);
1404 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02001405
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001406 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001407}