blob: 6dcba579e7793f9723abdf64cb10ff547e6f26b9 [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 Krejci00768f42015-06-18 17:04:04 +0200719struct ly_when *
720ly_when_dup(struct ly_ctx *ctx, struct ly_when *old)
721{
722 struct ly_when *new;
723
724 if (!old) {
725 return NULL;
726 }
727
728 new = calloc(1, sizeof *new);
729 new->cond = lydict_insert(ctx, old->cond, 0);
730 new->dsc = lydict_insert(ctx, old->dsc, 0);
731 new->ref = lydict_insert(ctx, old->ref, 0);
732
733 return new;
734}
735
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200736void
737ly_when_free(struct ly_ctx *ctx, struct ly_when *w)
738{
739 if (!w) {
740 return;
741 }
742
743 lydict_remove(ctx, w->cond);
744 lydict_remove(ctx, w->dsc);
745 lydict_remove(ctx, w->ref);
746
747 free(w);
748}
749
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200750struct ly_augment *
751ly_augment_dup(struct ly_module *module, struct ly_mnode *parent, struct ly_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +0200752{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200753 struct ly_augment *new = NULL;
754 int i = -1;
Radek Krejci106efc02015-06-10 14:36:27 +0200755
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200756 if (!size) {
757 return NULL;
758 }
Radek Krejci106efc02015-06-10 14:36:27 +0200759
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200760 new = calloc(size, sizeof *new);
761 for (i = 0; i < size; i++) {
762 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
763 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
764 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
765 new[i].flags = old[i].flags;
766 /* .target = NULL; .nodetype = 0 */
Radek Krejci106efc02015-06-10 14:36:27 +0200767
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200768 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +0200769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200770 /* copy the definition of augment nodes */
771 if (old[i].child) {
772 new[i].child = (struct ly_mnode *)lyxml_dup_elem(module->ctx, (struct lyxml_elem *)old[i].child, NULL, 1);
773 }
774 }
Radek Krejci106efc02015-06-10 14:36:27 +0200775
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200776 return new;
Radek Krejci106efc02015-06-10 14:36:27 +0200777}
778
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200779struct ly_refine *
780ly_refine_dup(struct ly_ctx *ctx, struct ly_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +0200781{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200782 struct ly_refine *result;
783 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +0200784
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200785 if (!size) {
786 return NULL;
787 }
Michal Vasko1982cad2015-06-08 15:49:30 +0200788
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200789 result = calloc(size, sizeof *result);
790 for (i = 0; i < size; i++) {
791 result[i].target = lydict_insert(ctx, old[i].target, 0);
792 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
793 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
794 result[i].flags = old[i].flags;
795 result[i].target_type = old[i].target_type;
796 result[i].must_size = old[i].must_size;
797 result[i].must = ly_must_dup(ctx, old[i].must, old[i].must_size);
798 if (result[i].target_type & (LY_NODE_LEAF | LY_NODE_CHOICE)) {
799 result[i].mod.dflt = lydict_insert(ctx, old[i].mod.dflt, 0);
800 } else if (result[i].target_type == LY_NODE_CONTAINER) {
801 result[i].mod.presence = lydict_insert(ctx, old[i].mod.presence, 0);
802 } else if (result[i].target_type & (LY_NODE_LIST | LY_NODE_LEAFLIST)) {
803 result[i].mod.list = old[i].mod.list;
804 }
805 }
Michal Vasko1982cad2015-06-08 15:49:30 +0200806
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200807 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +0200808}
809
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200810void
811ly_ident_free(struct ly_ctx *ctx, struct ly_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +0200812{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200813 struct ly_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +0200814
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200815 assert(ctx);
816 if (!ident) {
817 return;
818 }
Radek Krejci812b10a2015-05-28 16:48:25 +0200819
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200820 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200821 * if caller free only a single data model which is used (its identity is
822 * reference from identity in another module), this silly freeing can lead
823 * to segmentation fault. But without noting if the module is used by some
824 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +0200825 *
826 * Possible solution is to not allow caller to remove particular schema
827 * from the context.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200828 */
829 while (ident->der) {
830 der = ident->der;
831 ident->der = der->next;
832 free(der);
833 }
Radek Krejci6793db02015-05-22 17:49:54 +0200834
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200835 lydict_remove(ctx, ident->name);
836 lydict_remove(ctx, ident->dsc);
837 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +0200838
839}
840
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200841void
842ly_grp_free(struct ly_ctx *ctx, struct ly_mnode_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200843{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200844 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200845
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200846 /* handle only specific parts for LY_NODE_GROUPING */
847 for (i = 0; i < grp->tpdf_size; i++) {
848 ly_tpdf_free(ctx, &grp->tpdf[i]);
849 }
850 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +0200851}
852
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200853void
854ly_anyxml_free(struct ly_ctx *ctx, struct ly_mnode_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +0200855{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200856 int i;
Radek Krejci537cf382015-06-04 11:07:01 +0200857
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200858 for (i = 0; i < anyxml->must_size; i++) {
859 ly_must_free(ctx, &anyxml->must[i]);
860 }
861 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200862
863 ly_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200864}
865
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200866void
867ly_leaf_free(struct ly_ctx *ctx, struct ly_mnode_leaf *leaf)
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 < leaf->must_size; i++) {
872 ly_must_free(ctx, &leaf->must[i]);
873 }
874 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +0200875
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200876 ly_when_free(ctx, leaf->when);
877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200878 ly_type_free(ctx, &leaf->type);
879 lydict_remove(ctx, leaf->units);
880 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +0200881}
882
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200883void
884ly_leaflist_free(struct ly_ctx *ctx, struct ly_mnode_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +0200885{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200886 int i;
Radek Krejci537cf382015-06-04 11:07:01 +0200887
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200888 for (i = 0; i < llist->must_size; i++) {
889 ly_must_free(ctx, &llist->must[i]);
890 }
891 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +0200892
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200893 ly_when_free(ctx, llist->when);
894
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200895 ly_type_free(ctx, &llist->type);
896 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +0200897}
898
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200899void
900ly_list_free(struct ly_ctx *ctx, struct ly_mnode_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200901{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200902 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200903
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200904 /* handle only specific parts for LY_NODE_LIST */
905 for (i = 0; i < list->tpdf_size; i++) {
906 ly_tpdf_free(ctx, &list->tpdf[i]);
907 }
908 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +0200909
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200910 for (i = 0; i < list->must_size; i++) {
911 ly_must_free(ctx, &list->must[i]);
912 }
913 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +0200914
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200915 ly_when_free(ctx, list->when);
916
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200917 for (i = 0; i < list->unique_size; i++) {
918 free(list->unique[i].leafs);
919 }
920 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +0200921
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200922 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200923}
924
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200925void
926ly_container_free(struct ly_ctx *ctx, struct ly_mnode_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200927{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200928 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200929
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200930 /* handle only specific parts for LY_NODE_CONTAINER */
931 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +0200932
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200933 for (i = 0; i < cont->tpdf_size; i++) {
934 ly_tpdf_free(ctx, &cont->tpdf[i]);
935 }
936 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +0200937
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200938 for (i = 0; i < cont->must_size; i++) {
939 ly_must_free(ctx, &cont->must[i]);
940 }
941 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200942
943 ly_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200944}
945
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200946void
Radek Krejci3cf9e222015-06-18 11:37:50 +0200947ly_feature_free(struct ly_ctx *ctx, struct ly_feature *f)
948{
949 lydict_remove(ctx, f->name);
950 lydict_remove(ctx, f->dsc);
951 lydict_remove(ctx, f->ref);
952 free(f->features);
953}
954
955void
Radek Krejcif5be10f2015-06-16 13:29:36 +0200956ly_augment_free(struct ly_ctx *ctx, struct ly_augment *aug)
957{
958 lydict_remove(ctx, aug->target_name);
959 lydict_remove(ctx, aug->dsc);
960 lydict_remove(ctx, aug->ref);
961
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200962 ly_when_free(ctx, aug->when);
963
Radek Krejcif5be10f2015-06-16 13:29:36 +0200964 lyxml_free_elem(ctx, (struct lyxml_elem *)aug->child);
965}
966
967void
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200968ly_uses_free(struct ly_ctx *ctx, struct ly_mnode_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +0200969{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200970 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +0200971
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200972 for (i = 0; i < uses->refine_size; i++) {
973 lydict_remove(ctx, uses->refine[i].target);
974 lydict_remove(ctx, uses->refine[i].dsc);
975 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +0200976
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200977 for (j = 0; j < uses->refine[j].must_size; j++) {
978 ly_must_free(ctx, &uses->refine[i].must[j]);
979 }
980 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +0200981
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200982 if (uses->refine[i].target_type & (LY_NODE_LEAF | LY_NODE_CHOICE)) {
983 lydict_remove(ctx, uses->refine[i].mod.dflt);
984 } else if (uses->refine[i].target_type & LY_NODE_CONTAINER) {
985 lydict_remove(ctx, uses->refine[i].mod.presence);
986 }
987 }
988 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +0200989
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200990 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200991 ly_augment_free(ctx, &uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200992 }
993 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +0200994
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200995 ly_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +0200996}
997
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200998void
999ly_mnode_free(struct ly_mnode *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001000{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001001 struct ly_ctx *ctx;
1002 struct ly_mnode *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001003
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001004 if (!node) {
1005 return;
1006 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001007
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001008 assert(node->module);
1009 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001010
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001011 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001012
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001013 /* common part */
1014 LY_TREE_FOR_SAFE(node->child, next, sub) {
1015 ly_mnode_free(sub);
1016 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001017 free(node->features);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001018
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001019 lydict_remove(ctx, node->name);
1020 lydict_remove(ctx, node->dsc);
1021 lydict_remove(ctx, node->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001022
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001023 /* specific part */
1024 switch (node->nodetype) {
1025 case LY_NODE_CONTAINER:
1026 ly_container_free(ctx, (struct ly_mnode_container *)node);
1027 break;
1028 case LY_NODE_CHOICE:
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001029 ly_when_free(ctx, ((struct ly_mnode_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001030 break;
1031 case LY_NODE_LEAF:
1032 ly_leaf_free(ctx, (struct ly_mnode_leaf *)node);
1033 break;
1034 case LY_NODE_LEAFLIST:
1035 ly_leaflist_free(ctx, (struct ly_mnode_leaflist *)node);
1036 break;
1037 case LY_NODE_LIST:
1038 ly_list_free(ctx, (struct ly_mnode_list *)node);
1039 break;
1040 case LY_NODE_ANYXML:
1041 ly_anyxml_free(ctx, (struct ly_mnode_anyxml *)node);
1042 break;
1043 case LY_NODE_USES:
1044 ly_uses_free(ctx, (struct ly_mnode_uses *)node);
1045 break;
1046 case LY_NODE_CASE:
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001047 ly_when_free(ctx, ((struct ly_mnode_case *)node)->when);
1048 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001049 case LY_NODE_AUGMENT:
1050 /* do nothing */
1051 break;
Michal Vasko0ea41032015-06-16 08:53:55 +02001052 case LY_NODE_GROUPING:
1053 case LY_NODE_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001054 case LY_NODE_INPUT:
1055 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001056 case LY_NODE_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001057 ly_grp_free(ctx, (struct ly_mnode_grp *)node);
1058 break;
1059 }
Radek Krejci5a065542015-05-22 15:02:07 +02001060
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001061 /* again common part */
1062 ly_mnode_unlink(node);
1063 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001064}
1065
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001066static void
1067module_free_common(struct ly_module *module)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001068{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001069 struct ly_ctx *ctx;
1070 struct ly_mnode *mnode;
1071 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001072 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001073
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001074 assert(module->ctx);
1075 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001076
Radek Krejcidce51452015-06-16 15:20:08 +02001077 /* as first step, free the imported modules */
1078 for (i = 0; i < module->imp_size; i++) {
1079 /* get the imported module from the context and then free,
1080 * this check is necessary because the imported module can
1081 * be already removed
1082 */
1083 l = ctx->models.used;
1084 for (j = 0; j < l; j++) {
1085 if (ctx->models.list[j] == module->imp[i].module) {
1086 ly_module_free(module->imp[i].module);
1087 break;
1088 }
1089 }
1090 }
1091 free(module->imp);
1092
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001093 while (module->data) {
1094 mnode = module->data;
1095 module->data = mnode;
1096 ly_mnode_free(mnode);
1097 }
Radek Krejci5a065542015-05-22 15:02:07 +02001098
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001099 lydict_remove(ctx, module->dsc);
1100 lydict_remove(ctx, module->ref);
1101 lydict_remove(ctx, module->org);
1102 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001104 for (i = 0; i < module->rev_size; i++) {
1105 lydict_remove(ctx, module->rev[i].dsc);
1106 lydict_remove(ctx, module->rev[i].ref);
1107 }
1108 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001109
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001110 for (i = 0; i < module->ident_size; i++) {
1111 ly_ident_free(ctx, &module->ident[i]);
1112 }
1113 module->ident_size = 0;
1114 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001115
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001116 for (i = 0; i < module->tpdf_size; i++) {
1117 ly_tpdf_free(ctx, &module->tpdf[i]);
1118 }
1119 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001120
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001121 for (i = 0; i < module->inc_size; i++) {
1122 ly_submodule_free(module->inc[i].submodule);
1123 }
1124 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001125
Radek Krejcif5be10f2015-06-16 13:29:36 +02001126 for (i = 0; i < module->augment_size; i++) {
1127 ly_augment_free(ctx, &module->augment[i]);
1128 }
1129 free(module->augment);
1130
Radek Krejci3cf9e222015-06-18 11:37:50 +02001131 for (i = 0; i < module->features_size; i++) {
1132 ly_feature_free(ctx, &module->features[i]);
1133 }
1134 free(module->features);
1135
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001136 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02001137}
1138
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001139void
1140ly_submodule_free(struct ly_submodule *submodule)
Radek Krejciefaeba32015-05-27 14:30:57 +02001141{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001142 if (!submodule) {
1143 return;
1144 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001145
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001146 submodule->inc_size = 0;
1147 free(submodule->inc);
1148 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02001149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001150 /* common part with struct ly_module */
1151 module_free_common((struct ly_module *)submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001152
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001153 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02001154
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001155 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001156}
1157
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001158struct ly_mnode *
1159ly_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 +02001160{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001161 struct ly_mnode *retval = NULL, *aux, *child;
1162 struct ly_ctx *ctx = module->ctx;
1163 int i, j;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001164
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001165 struct ly_mnode_container *cont;
1166 struct ly_mnode_container *cont_orig = (struct ly_mnode_container *)mnode;
1167 struct ly_mnode_choice *choice;
1168 struct ly_mnode_choice *choice_orig = (struct ly_mnode_choice *)mnode;
1169 struct ly_mnode_leaf *leaf;
1170 struct ly_mnode_leaf *leaf_orig = (struct ly_mnode_leaf *)mnode;
1171 struct ly_mnode_leaflist *llist;
1172 struct ly_mnode_leaflist *llist_orig = (struct ly_mnode_leaflist *)mnode;
1173 struct ly_mnode_list *list;
1174 struct ly_mnode_list *list_orig = (struct ly_mnode_list *)mnode;
1175 struct ly_mnode_anyxml *anyxml;
1176 struct ly_mnode_anyxml *anyxml_orig = (struct ly_mnode_anyxml *)mnode;
1177 struct ly_mnode_uses *uses;
1178 struct ly_mnode_uses *uses_orig = (struct ly_mnode_uses *)mnode;
1179 struct ly_mnode_grp *mix;
1180 struct ly_mnode_grp *mix_orig = (struct ly_mnode_grp *)mnode;
1181 struct ly_mnode_case *cs;
Radek Krejci00768f42015-06-18 17:04:04 +02001182 struct ly_mnode_case *cs_orig = (struct ly_mnode_case *)mnode;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001183
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001184 /* we cannot just duplicate memory since the strings are stored in
1185 * dictionary and we need to update dictionary counters.
1186 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001187
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001188 switch (mnode->nodetype) {
1189 case LY_NODE_CONTAINER:
1190 cont = calloc(1, sizeof *cont);
1191 retval = (struct ly_mnode *)cont;
1192 break;
1193
1194 case LY_NODE_CHOICE:
1195 choice = calloc(1, sizeof *choice);
1196 retval = (struct ly_mnode *)choice;
1197 break;
1198
1199 case LY_NODE_LEAF:
1200 leaf = calloc(1, sizeof *leaf);
1201 retval = (struct ly_mnode *)leaf;
1202 break;
1203
1204 case LY_NODE_LEAFLIST:
1205 llist = calloc(1, sizeof *llist);
1206 retval = (struct ly_mnode *)llist;
1207 break;
1208
1209 case LY_NODE_LIST:
1210 list = calloc(1, sizeof *list);
1211 retval = (struct ly_mnode *)list;
1212 break;
1213
1214 case LY_NODE_ANYXML:
1215 anyxml = calloc(1, sizeof *anyxml);
1216 retval = (struct ly_mnode *)anyxml;
1217 break;
1218
1219 case LY_NODE_USES:
1220 uses = calloc(1, sizeof *uses);
1221 retval = (struct ly_mnode *)uses;
1222 break;
1223
1224 case LY_NODE_CASE:
1225 cs = calloc(1, sizeof *cs);
1226 retval = (struct ly_mnode *)cs;
1227 break;
1228
1229 /* exact same structure */
Michal Vasko0ea41032015-06-16 08:53:55 +02001230 case LY_NODE_GROUPING:
Michal Vasko38d01f72015-06-15 09:41:06 +02001231 case LY_NODE_RPC:
Michal Vasko38d01f72015-06-15 09:41:06 +02001232 case LY_NODE_INPUT:
1233 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001234 case LY_NODE_NOTIF:
1235 mix = calloc(1, sizeof *mix);
1236 retval = (struct ly_mnode *)mix;
Michal Vasko38d01f72015-06-15 09:41:06 +02001237 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001238
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001239 default:
1240 goto error;
1241 }
Radek Krejcib388c152015-06-04 17:03:03 +02001242
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001243 /*
1244 * duplicate generic part of the structure
1245 */
1246 retval->name = lydict_insert(ctx, mnode->name, 0);
1247 retval->dsc = lydict_insert(ctx, mnode->dsc, 0);
1248 retval->ref = lydict_insert(ctx, mnode->ref, 0);
1249 retval->flags = mnode->flags;
1250 if (!(retval->flags & LY_NODE_CONFIG_MASK)) {
1251 /* set parent's config flag */
1252 retval->flags |= flags & LY_NODE_CONFIG_MASK;
1253 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001254
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001255 retval->module = module;
1256 retval->nodetype = mnode->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001257
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001258 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001259
Radek Krejci3cf9e222015-06-18 11:37:50 +02001260 retval->features_size = mnode->features_size;
1261 retval->features = calloc(retval->features_size, sizeof *retval->features);
1262 memcpy(retval->features, mnode->features, retval->features_size * sizeof *retval->features);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001263
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001264 if (recursive) {
1265 /* go recursively */
1266 LY_TREE_FOR(mnode->child, child) {
1267 aux = ly_mnode_dup(module, child, retval->flags, 1, line);
1268 if (!aux || ly_mnode_addchild(retval, aux)) {
1269 goto error;
1270 }
1271 }
1272 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001273
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001274 /*
1275 * duplicate specific part of the structure
1276 */
1277 switch (mnode->nodetype) {
1278 case LY_NODE_CONTAINER:
Radek Krejci00768f42015-06-18 17:04:04 +02001279 cont->when = ly_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001280 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001281
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001282 cont->must_size = cont_orig->must_size;
1283 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001285 cont->must = ly_must_dup(ctx, cont_orig->must, cont->must_size);
1286 cont->tpdf = ly_tpdf_dup(ctx, cont_orig->tpdf, cont->tpdf_size);
1287 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001288
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001289 case LY_NODE_CHOICE:
Radek Krejci00768f42015-06-18 17:04:04 +02001290 choice->when = ly_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001291 if (choice->dflt) {
1292 LY_TREE_FOR(choice->child, child) {
1293 if (child->name == choice_orig->dflt->name) {
1294 choice->dflt = child;
1295 break;
1296 }
1297 }
1298 }
1299 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001300
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001301 case LY_NODE_LEAF:
1302 ly_type_dup(ctx, &(leaf->type), &(leaf_orig->type));
1303 leaf->units = lydict_insert(ctx, leaf_orig->units, 0);
1304 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001305
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001306 leaf->must_size = leaf_orig->must_size;
1307 leaf->must = ly_must_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02001308
1309 leaf->when = ly_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001310 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001311
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001312 case LY_NODE_LEAFLIST:
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001313
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001314 ly_type_dup(ctx, &(llist->type), &(llist_orig->type));
1315 llist->units = lydict_insert(ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001316
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001317 llist->min = llist_orig->min;
1318 llist->max = llist_orig->max;
1319
1320 llist->must_size = llist_orig->must_size;
1321 llist->must = ly_must_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02001322
1323 llist->when = ly_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001324 break;
1325
1326 case LY_NODE_LIST:
1327 list->min = list_orig->min;
1328 list->max = list_orig->max;
1329
1330 list->must_size = list_orig->must_size;
1331 list->tpdf_size = list_orig->tpdf_size;
1332 list->keys_size = list_orig->keys_size;
1333 list->unique_size = list_orig->unique_size;
1334
1335 list->must = ly_must_dup(ctx, list_orig->must, list->must_size);
1336 list->tpdf = ly_tpdf_dup(ctx, list_orig->tpdf, list->tpdf_size);
1337
1338 if (list->keys_size) {
1339 list->keys = calloc(list->keys_size, sizeof *list->keys);
1340 for (i = 0; i < list->keys_size; i++) {
1341 list->keys[i] = find_leaf(retval, list_orig->keys[i]->name, 0);
1342 }
1343 }
1344 if (list->unique_size) {
1345 list->unique = calloc(list->unique_size, sizeof *list->unique);
1346 for (i = 0; i < list->unique_size; i++) {
1347 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
1348 for (j = 0; j < list->unique[i].leafs_size; j++) {
1349 list->unique[i].leafs[j] = find_leaf(retval, list_orig->unique[i].leafs[j]->name, 0);
1350 }
1351 }
1352 }
Radek Krejci00768f42015-06-18 17:04:04 +02001353 list->when = ly_when_dup(ctx, list_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001354 break;
1355
1356 case LY_NODE_ANYXML:
1357 anyxml->must_size = anyxml_orig->must_size;
1358 anyxml->must = ly_must_dup(ctx, anyxml_orig->must, anyxml->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02001359 anyxml->when = ly_when_dup(ctx, anyxml_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001360 break;
1361
1362 case LY_NODE_USES:
1363 uses->grp = uses_orig->grp;
Radek Krejci00768f42015-06-18 17:04:04 +02001364 uses->when = ly_when_dup(ctx, uses_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001365 uses->refine_size = uses_orig->refine_size;
1366 uses->refine = ly_refine_dup(ctx, uses_orig->refine, uses_orig->refine_size);
1367 uses->augment_size = uses_orig->augment_size;
1368 uses->augment = ly_augment_dup(module, (struct ly_mnode *)uses, uses_orig->augment, uses_orig->augment_size);
1369 if (resolve_uses(uses, line)) {
1370 goto error;
1371 }
1372 break;
1373
1374 case LY_NODE_CASE:
Radek Krejci00768f42015-06-18 17:04:04 +02001375 cs->when = ly_when_dup(ctx, cs_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001376 break;
1377
Michal Vasko0ea41032015-06-16 08:53:55 +02001378 case LY_NODE_GROUPING:
Michal Vasko38d01f72015-06-15 09:41:06 +02001379 case LY_NODE_RPC:
Michal Vasko38d01f72015-06-15 09:41:06 +02001380 case LY_NODE_INPUT:
1381 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001382 case LY_NODE_NOTIF:
1383 mix->tpdf_size = mix_orig->tpdf_size;
1384 mix->tpdf = ly_tpdf_dup(ctx, mix_orig->tpdf, mix->tpdf_size);
Radek Krejcia01e5432015-06-16 10:35:25 +02001385 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001386
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001387 default:
Radek Krejci00768f42015-06-18 17:04:04 +02001388 /* LY_NODE_AUGMENT */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001389 goto error;
1390 }
1391
1392 return retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001393
1394error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001395 LOGDBG("error: %s:%d", __FILE__, __LINE__);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001396
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001397 ly_mnode_free(retval);
1398 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001399}
1400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001401API void
1402ly_module_free(struct ly_module *module)
Radek Krejciefaeba32015-05-27 14:30:57 +02001403{
Radek Krejcidce51452015-06-16 15:20:08 +02001404 struct ly_ctx *ctx;
1405 int i;
1406
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001407 if (!module) {
1408 return;
1409 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001410
Radek Krejcidce51452015-06-16 15:20:08 +02001411 /* remove schema from the context */
1412 ctx = module->ctx;
1413 if (ctx->models.used) {
1414 for (i = 0; i < ctx->models.used; i++) {
1415 if (ctx->models.list[i] == module) {
1416 /* replace the position in the list by the last module in the list */
1417 ctx->models.used--;
1418 ctx->models.list[i] = ctx->models.list[ctx->models.used];
1419 ctx->models.list[ctx->models.used] = NULL;
1420 /* we are done */
1421 break;
1422 }
1423 }
1424 }
1425
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001426 /* common part with struct ly_submodule */
1427 module_free_common(module);
Radek Krejciefaeba32015-05-27 14:30:57 +02001428
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001429 /* specific items to free */
1430 lydict_remove(module->ctx, module->ns);
1431 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02001432
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001433 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001434}