blob: 515a481eb450e03e9cbb577154ea9c844ca59ab9 [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) {
615 case LY_TYPE_ENUM:
616 for (i = 0; i < type->info.enums.count; i++) {
617 lydict_remove(ctx, type->info.enums.list[i].name);
618 lydict_remove(ctx, type->info.enums.list[i].dsc);
619 lydict_remove(ctx, type->info.enums.list[i].ref);
620 }
621 free(type->info.enums.list);
622 break;
623 default:
624 /* TODO */
625 break;
626 }
Radek Krejci5a065542015-05-22 15:02:07 +0200627}
628
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200629struct ly_tpdf *
630ly_tpdf_dup(struct ly_ctx *ctx, struct ly_tpdf *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200631{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200632 struct ly_tpdf *result;
633 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200634
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200635 if (!size) {
636 return NULL;
637 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200638
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200639 result = calloc(size, sizeof *result);
640 for (i = 0; i < size; i++) {
641 result[i].name = lydict_insert(ctx, old[i].name, 0);
642 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
643 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
644 result[i].flags = old[i].flags;
645 result[i].module = old[i].module;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200646
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200647 ly_type_dup(ctx, &(result[i].type), &(old[i].type));
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200648
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200649 result[i].dflt = lydict_insert(ctx, old[i].dflt, 0);
650 result[i].units = lydict_insert(ctx, old[i].units, 0);
651 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200652
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200653 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200654}
655
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200656void
657ly_tpdf_free(struct ly_ctx *ctx, struct ly_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200658{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200659 assert(ctx);
660 if (!tpdf) {
661 return;
662 }
Radek Krejci812b10a2015-05-28 16:48:25 +0200663
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200664 lydict_remove(ctx, tpdf->name);
665 lydict_remove(ctx, tpdf->dsc);
666 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200667
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200668 ly_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200669
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200670 lydict_remove(ctx, tpdf->units);
671 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200672}
673
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200674struct ly_must *
675ly_must_dup(struct ly_ctx *ctx, struct ly_must *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200676{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200677 struct ly_must *result;
678 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200679
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200680 if (!size) {
681 return NULL;
682 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200683
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200684 result = calloc(size, sizeof *result);
685 for (i = 0; i < size; i++) {
686 result[i].cond = lydict_insert(ctx, old[i].cond, 0);
687 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
688 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
689 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
690 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
691 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200692
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200693 return result;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200694}
695
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200696void
697ly_must_free(struct ly_ctx *ctx, struct ly_must *must)
Radek Krejci800af702015-06-02 13:46:01 +0200698{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200699 assert(ctx);
700 if (!must) {
701 return;
702 }
Radek Krejci800af702015-06-02 13:46:01 +0200703
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200704 lydict_remove(ctx, must->cond);
705 lydict_remove(ctx, must->dsc);
706 lydict_remove(ctx, must->ref);
707 lydict_remove(ctx, must->eapptag);
708 lydict_remove(ctx, must->emsg);
Radek Krejci800af702015-06-02 13:46:01 +0200709}
710
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200711struct ly_augment *
712ly_augment_dup(struct ly_module *module, struct ly_mnode *parent, struct ly_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +0200713{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200714 struct ly_augment *new = NULL;
715 int i = -1;
Radek Krejci106efc02015-06-10 14:36:27 +0200716
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200717 if (!size) {
718 return NULL;
719 }
Radek Krejci106efc02015-06-10 14:36:27 +0200720
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200721 new = calloc(size, sizeof *new);
722 for (i = 0; i < size; i++) {
723 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
724 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
725 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
726 new[i].flags = old[i].flags;
727 /* .target = NULL; .nodetype = 0 */
Radek Krejci106efc02015-06-10 14:36:27 +0200728
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200729 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +0200730
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200731 /* copy the definition of augment nodes */
732 if (old[i].child) {
733 new[i].child = (struct ly_mnode *)lyxml_dup_elem(module->ctx, (struct lyxml_elem *)old[i].child, NULL, 1);
734 }
735 }
Radek Krejci106efc02015-06-10 14:36:27 +0200736
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200737 return new;
Radek Krejci106efc02015-06-10 14:36:27 +0200738}
739
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200740struct ly_refine *
741ly_refine_dup(struct ly_ctx *ctx, struct ly_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +0200742{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200743 struct ly_refine *result;
744 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +0200745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200746 if (!size) {
747 return NULL;
748 }
Michal Vasko1982cad2015-06-08 15:49:30 +0200749
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200750 result = calloc(size, sizeof *result);
751 for (i = 0; i < size; i++) {
752 result[i].target = lydict_insert(ctx, old[i].target, 0);
753 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
754 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
755 result[i].flags = old[i].flags;
756 result[i].target_type = old[i].target_type;
757 result[i].must_size = old[i].must_size;
758 result[i].must = ly_must_dup(ctx, old[i].must, old[i].must_size);
759 if (result[i].target_type & (LY_NODE_LEAF | LY_NODE_CHOICE)) {
760 result[i].mod.dflt = lydict_insert(ctx, old[i].mod.dflt, 0);
761 } else if (result[i].target_type == LY_NODE_CONTAINER) {
762 result[i].mod.presence = lydict_insert(ctx, old[i].mod.presence, 0);
763 } else if (result[i].target_type & (LY_NODE_LIST | LY_NODE_LEAFLIST)) {
764 result[i].mod.list = old[i].mod.list;
765 }
766 }
Michal Vasko1982cad2015-06-08 15:49:30 +0200767
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200768 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +0200769}
770
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200771void
772ly_ident_free(struct ly_ctx *ctx, struct ly_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +0200773{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200774 struct ly_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +0200775
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200776 assert(ctx);
777 if (!ident) {
778 return;
779 }
Radek Krejci812b10a2015-05-28 16:48:25 +0200780
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200781 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200782 * if caller free only a single data model which is used (its identity is
783 * reference from identity in another module), this silly freeing can lead
784 * to segmentation fault. But without noting if the module is used by some
785 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +0200786 *
787 * Possible solution is to not allow caller to remove particular schema
788 * from the context.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200789 */
790 while (ident->der) {
791 der = ident->der;
792 ident->der = der->next;
793 free(der);
794 }
Radek Krejci6793db02015-05-22 17:49:54 +0200795
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200796 lydict_remove(ctx, ident->name);
797 lydict_remove(ctx, ident->dsc);
798 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +0200799
800}
801
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200802void
803ly_grp_free(struct ly_ctx *ctx, struct ly_mnode_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200804{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200805 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200806
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200807 /* handle only specific parts for LY_NODE_GROUPING */
808 for (i = 0; i < grp->tpdf_size; i++) {
809 ly_tpdf_free(ctx, &grp->tpdf[i]);
810 }
811 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +0200812}
813
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200814void
815ly_anyxml_free(struct ly_ctx *ctx, struct ly_mnode_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +0200816{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200817 int i;
Radek Krejci537cf382015-06-04 11:07:01 +0200818
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200819 for (i = 0; i < anyxml->must_size; i++) {
820 ly_must_free(ctx, &anyxml->must[i]);
821 }
822 free(anyxml->must);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200823}
824
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200825void
826ly_leaf_free(struct ly_ctx *ctx, struct ly_mnode_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +0200827{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200828 int i;
Radek Krejci537cf382015-06-04 11:07:01 +0200829
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200830 for (i = 0; i < leaf->must_size; i++) {
831 ly_must_free(ctx, &leaf->must[i]);
832 }
833 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +0200834
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200835 ly_type_free(ctx, &leaf->type);
836 lydict_remove(ctx, leaf->units);
837 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +0200838}
839
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200840void
841ly_leaflist_free(struct ly_ctx *ctx, struct ly_mnode_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +0200842{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200843 int i;
Radek Krejci537cf382015-06-04 11:07:01 +0200844
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200845 for (i = 0; i < llist->must_size; i++) {
846 ly_must_free(ctx, &llist->must[i]);
847 }
848 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +0200849
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200850 ly_type_free(ctx, &llist->type);
851 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +0200852}
853
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200854void
855ly_list_free(struct ly_ctx *ctx, struct ly_mnode_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200856{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200857 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200858
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200859 /* handle only specific parts for LY_NODE_LIST */
860 for (i = 0; i < list->tpdf_size; i++) {
861 ly_tpdf_free(ctx, &list->tpdf[i]);
862 }
863 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +0200864
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200865 for (i = 0; i < list->must_size; i++) {
866 ly_must_free(ctx, &list->must[i]);
867 }
868 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +0200869
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200870 for (i = 0; i < list->unique_size; i++) {
871 free(list->unique[i].leafs);
872 }
873 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +0200874
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200875 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200876}
877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200878void
879ly_container_free(struct ly_ctx *ctx, struct ly_mnode_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200880{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200881 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200882
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200883 /* handle only specific parts for LY_NODE_CONTAINER */
884 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +0200885
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200886 for (i = 0; i < cont->tpdf_size; i++) {
887 ly_tpdf_free(ctx, &cont->tpdf[i]);
888 }
889 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +0200890
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200891 for (i = 0; i < cont->must_size; i++) {
892 ly_must_free(ctx, &cont->must[i]);
893 }
894 free(cont->must);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200895}
896
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200897void
Radek Krejcif5be10f2015-06-16 13:29:36 +0200898ly_augment_free(struct ly_ctx *ctx, struct ly_augment *aug)
899{
900 lydict_remove(ctx, aug->target_name);
901 lydict_remove(ctx, aug->dsc);
902 lydict_remove(ctx, aug->ref);
903
904 lyxml_free_elem(ctx, (struct lyxml_elem *)aug->child);
905}
906
907void
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200908ly_uses_free(struct ly_ctx *ctx, struct ly_mnode_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +0200909{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200910 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +0200911
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200912 for (i = 0; i < uses->refine_size; i++) {
913 lydict_remove(ctx, uses->refine[i].target);
914 lydict_remove(ctx, uses->refine[i].dsc);
915 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +0200916
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200917 for (j = 0; j < uses->refine[j].must_size; j++) {
918 ly_must_free(ctx, &uses->refine[i].must[j]);
919 }
920 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +0200921
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200922 if (uses->refine[i].target_type & (LY_NODE_LEAF | LY_NODE_CHOICE)) {
923 lydict_remove(ctx, uses->refine[i].mod.dflt);
924 } else if (uses->refine[i].target_type & LY_NODE_CONTAINER) {
925 lydict_remove(ctx, uses->refine[i].mod.presence);
926 }
927 }
928 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +0200929
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200930 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200931 ly_augment_free(ctx, &uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200932 }
933 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +0200934
935}
936
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200937void
938ly_mnode_free(struct ly_mnode *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200939{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200940 struct ly_ctx *ctx;
941 struct ly_mnode *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200942
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200943 if (!node) {
944 return;
945 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200946
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200947 assert(node->module);
948 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +0200949
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200950 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200951
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200952 /* common part */
953 LY_TREE_FOR_SAFE(node->child, next, sub) {
954 ly_mnode_free(sub);
955 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200956
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200957 lydict_remove(ctx, node->name);
958 lydict_remove(ctx, node->dsc);
959 lydict_remove(ctx, node->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200960
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200961 /* specific part */
962 switch (node->nodetype) {
963 case LY_NODE_CONTAINER:
964 ly_container_free(ctx, (struct ly_mnode_container *)node);
965 break;
966 case LY_NODE_CHOICE:
967 break;
968 case LY_NODE_LEAF:
969 ly_leaf_free(ctx, (struct ly_mnode_leaf *)node);
970 break;
971 case LY_NODE_LEAFLIST:
972 ly_leaflist_free(ctx, (struct ly_mnode_leaflist *)node);
973 break;
974 case LY_NODE_LIST:
975 ly_list_free(ctx, (struct ly_mnode_list *)node);
976 break;
977 case LY_NODE_ANYXML:
978 ly_anyxml_free(ctx, (struct ly_mnode_anyxml *)node);
979 break;
980 case LY_NODE_USES:
981 ly_uses_free(ctx, (struct ly_mnode_uses *)node);
982 break;
983 case LY_NODE_CASE:
984 case LY_NODE_AUGMENT:
985 /* do nothing */
986 break;
Michal Vasko0ea41032015-06-16 08:53:55 +0200987 case LY_NODE_GROUPING:
988 case LY_NODE_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200989 case LY_NODE_INPUT:
990 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +0200991 case LY_NODE_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200992 ly_grp_free(ctx, (struct ly_mnode_grp *)node);
993 break;
994 }
Radek Krejci5a065542015-05-22 15:02:07 +0200995
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200996 /* again common part */
997 ly_mnode_unlink(node);
998 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200999}
1000
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001001static void
1002module_free_common(struct ly_module *module)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001003{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001004 struct ly_ctx *ctx;
1005 struct ly_mnode *mnode;
1006 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001007 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001008
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001009 assert(module->ctx);
1010 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001011
Radek Krejcidce51452015-06-16 15:20:08 +02001012 /* as first step, free the imported modules */
1013 for (i = 0; i < module->imp_size; i++) {
1014 /* get the imported module from the context and then free,
1015 * this check is necessary because the imported module can
1016 * be already removed
1017 */
1018 l = ctx->models.used;
1019 for (j = 0; j < l; j++) {
1020 if (ctx->models.list[j] == module->imp[i].module) {
1021 ly_module_free(module->imp[i].module);
1022 break;
1023 }
1024 }
1025 }
1026 free(module->imp);
1027
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001028 while (module->data) {
1029 mnode = module->data;
1030 module->data = mnode;
1031 ly_mnode_free(mnode);
1032 }
Radek Krejci5a065542015-05-22 15:02:07 +02001033
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001034 lydict_remove(ctx, module->dsc);
1035 lydict_remove(ctx, module->ref);
1036 lydict_remove(ctx, module->org);
1037 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001038
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001039 for (i = 0; i < module->rev_size; i++) {
1040 lydict_remove(ctx, module->rev[i].dsc);
1041 lydict_remove(ctx, module->rev[i].ref);
1042 }
1043 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001044
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001045 for (i = 0; i < module->ident_size; i++) {
1046 ly_ident_free(ctx, &module->ident[i]);
1047 }
1048 module->ident_size = 0;
1049 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001050
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001051 for (i = 0; i < module->tpdf_size; i++) {
1052 ly_tpdf_free(ctx, &module->tpdf[i]);
1053 }
1054 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001055
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001056 for (i = 0; i < module->inc_size; i++) {
1057 ly_submodule_free(module->inc[i].submodule);
1058 }
1059 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001060
Radek Krejcif5be10f2015-06-16 13:29:36 +02001061 for (i = 0; i < module->augment_size; i++) {
1062 ly_augment_free(ctx, &module->augment[i]);
1063 }
1064 free(module->augment);
1065
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001066 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02001067}
1068
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001069void
1070ly_submodule_free(struct ly_submodule *submodule)
Radek Krejciefaeba32015-05-27 14:30:57 +02001071{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001072 if (!submodule) {
1073 return;
1074 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001076 submodule->inc_size = 0;
1077 free(submodule->inc);
1078 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02001079
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001080 /* common part with struct ly_module */
1081 module_free_common((struct ly_module *)submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001082
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001083 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02001084
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001085 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001086}
1087
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001088struct ly_mnode *
1089ly_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 +02001090{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001091 struct ly_mnode *retval = NULL, *aux, *child;
1092 struct ly_ctx *ctx = module->ctx;
1093 int i, j;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001094
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001095 struct ly_mnode_container *cont;
1096 struct ly_mnode_container *cont_orig = (struct ly_mnode_container *)mnode;
1097 struct ly_mnode_choice *choice;
1098 struct ly_mnode_choice *choice_orig = (struct ly_mnode_choice *)mnode;
1099 struct ly_mnode_leaf *leaf;
1100 struct ly_mnode_leaf *leaf_orig = (struct ly_mnode_leaf *)mnode;
1101 struct ly_mnode_leaflist *llist;
1102 struct ly_mnode_leaflist *llist_orig = (struct ly_mnode_leaflist *)mnode;
1103 struct ly_mnode_list *list;
1104 struct ly_mnode_list *list_orig = (struct ly_mnode_list *)mnode;
1105 struct ly_mnode_anyxml *anyxml;
1106 struct ly_mnode_anyxml *anyxml_orig = (struct ly_mnode_anyxml *)mnode;
1107 struct ly_mnode_uses *uses;
1108 struct ly_mnode_uses *uses_orig = (struct ly_mnode_uses *)mnode;
1109 struct ly_mnode_grp *mix;
1110 struct ly_mnode_grp *mix_orig = (struct ly_mnode_grp *)mnode;
1111 struct ly_mnode_case *cs;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001112
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001113 /* we cannot just duplicate memory since the strings are stored in
1114 * dictionary and we need to update dictionary counters.
1115 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001116
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001117 switch (mnode->nodetype) {
1118 case LY_NODE_CONTAINER:
1119 cont = calloc(1, sizeof *cont);
1120 retval = (struct ly_mnode *)cont;
1121 break;
1122
1123 case LY_NODE_CHOICE:
1124 choice = calloc(1, sizeof *choice);
1125 retval = (struct ly_mnode *)choice;
1126 break;
1127
1128 case LY_NODE_LEAF:
1129 leaf = calloc(1, sizeof *leaf);
1130 retval = (struct ly_mnode *)leaf;
1131 break;
1132
1133 case LY_NODE_LEAFLIST:
1134 llist = calloc(1, sizeof *llist);
1135 retval = (struct ly_mnode *)llist;
1136 break;
1137
1138 case LY_NODE_LIST:
1139 list = calloc(1, sizeof *list);
1140 retval = (struct ly_mnode *)list;
1141 break;
1142
1143 case LY_NODE_ANYXML:
1144 anyxml = calloc(1, sizeof *anyxml);
1145 retval = (struct ly_mnode *)anyxml;
1146 break;
1147
1148 case LY_NODE_USES:
1149 uses = calloc(1, sizeof *uses);
1150 retval = (struct ly_mnode *)uses;
1151 break;
1152
1153 case LY_NODE_CASE:
1154 cs = calloc(1, sizeof *cs);
1155 retval = (struct ly_mnode *)cs;
1156 break;
1157
1158 /* exact same structure */
Michal Vasko0ea41032015-06-16 08:53:55 +02001159 case LY_NODE_GROUPING:
Michal Vasko38d01f72015-06-15 09:41:06 +02001160 case LY_NODE_RPC:
Michal Vasko38d01f72015-06-15 09:41:06 +02001161 case LY_NODE_INPUT:
1162 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001163 case LY_NODE_NOTIF:
1164 mix = calloc(1, sizeof *mix);
1165 retval = (struct ly_mnode *)mix;
Michal Vasko38d01f72015-06-15 09:41:06 +02001166 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001167
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001168 default:
1169 goto error;
1170 }
Radek Krejcib388c152015-06-04 17:03:03 +02001171
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001172 /*
1173 * duplicate generic part of the structure
1174 */
1175 retval->name = lydict_insert(ctx, mnode->name, 0);
1176 retval->dsc = lydict_insert(ctx, mnode->dsc, 0);
1177 retval->ref = lydict_insert(ctx, mnode->ref, 0);
1178 retval->flags = mnode->flags;
1179 if (!(retval->flags & LY_NODE_CONFIG_MASK)) {
1180 /* set parent's config flag */
1181 retval->flags |= flags & LY_NODE_CONFIG_MASK;
1182 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001183
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001184 retval->module = module;
1185 retval->nodetype = mnode->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001186
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001187 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001188
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001189 retval->feature = NULL; /* TODO */
1190 retval->when = NULL; /* TODO */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001191
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001192 if (recursive) {
1193 /* go recursively */
1194 LY_TREE_FOR(mnode->child, child) {
1195 aux = ly_mnode_dup(module, child, retval->flags, 1, line);
1196 if (!aux || ly_mnode_addchild(retval, aux)) {
1197 goto error;
1198 }
1199 }
1200 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001201
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001202 /*
1203 * duplicate specific part of the structure
1204 */
1205 switch (mnode->nodetype) {
1206 case LY_NODE_CONTAINER:
1207 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001208
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001209 cont->must_size = cont_orig->must_size;
1210 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001211
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001212 cont->must = ly_must_dup(ctx, cont_orig->must, cont->must_size);
1213 cont->tpdf = ly_tpdf_dup(ctx, cont_orig->tpdf, cont->tpdf_size);
1214 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001215
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001216 case LY_NODE_CHOICE:
1217 if (choice->dflt) {
1218 LY_TREE_FOR(choice->child, child) {
1219 if (child->name == choice_orig->dflt->name) {
1220 choice->dflt = child;
1221 break;
1222 }
1223 }
1224 }
1225 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001226
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001227 case LY_NODE_LEAF:
1228 ly_type_dup(ctx, &(leaf->type), &(leaf_orig->type));
1229 leaf->units = lydict_insert(ctx, leaf_orig->units, 0);
1230 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001231
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001232 leaf->must_size = leaf_orig->must_size;
1233 leaf->must = ly_must_dup(ctx, leaf_orig->must, leaf->must_size);
1234 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001235
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001236 case LY_NODE_LEAFLIST:
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001237
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001238 ly_type_dup(ctx, &(llist->type), &(llist_orig->type));
1239 llist->units = lydict_insert(ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001240
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001241 llist->min = llist_orig->min;
1242 llist->max = llist_orig->max;
1243
1244 llist->must_size = llist_orig->must_size;
1245 llist->must = ly_must_dup(ctx, llist_orig->must, llist->must_size);
1246 break;
1247
1248 case LY_NODE_LIST:
1249 list->min = list_orig->min;
1250 list->max = list_orig->max;
1251
1252 list->must_size = list_orig->must_size;
1253 list->tpdf_size = list_orig->tpdf_size;
1254 list->keys_size = list_orig->keys_size;
1255 list->unique_size = list_orig->unique_size;
1256
1257 list->must = ly_must_dup(ctx, list_orig->must, list->must_size);
1258 list->tpdf = ly_tpdf_dup(ctx, list_orig->tpdf, list->tpdf_size);
1259
1260 if (list->keys_size) {
1261 list->keys = calloc(list->keys_size, sizeof *list->keys);
1262 for (i = 0; i < list->keys_size; i++) {
1263 list->keys[i] = find_leaf(retval, list_orig->keys[i]->name, 0);
1264 }
1265 }
1266 if (list->unique_size) {
1267 list->unique = calloc(list->unique_size, sizeof *list->unique);
1268 for (i = 0; i < list->unique_size; i++) {
1269 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
1270 for (j = 0; j < list->unique[i].leafs_size; j++) {
1271 list->unique[i].leafs[j] = find_leaf(retval, list_orig->unique[i].leafs[j]->name, 0);
1272 }
1273 }
1274 }
1275 break;
1276
1277 case LY_NODE_ANYXML:
1278 anyxml->must_size = anyxml_orig->must_size;
1279 anyxml->must = ly_must_dup(ctx, anyxml_orig->must, anyxml->must_size);
1280 break;
1281
1282 case LY_NODE_USES:
1283 uses->grp = uses_orig->grp;
1284 uses->refine_size = uses_orig->refine_size;
1285 uses->refine = ly_refine_dup(ctx, uses_orig->refine, uses_orig->refine_size);
1286 uses->augment_size = uses_orig->augment_size;
1287 uses->augment = ly_augment_dup(module, (struct ly_mnode *)uses, uses_orig->augment, uses_orig->augment_size);
1288 if (resolve_uses(uses, line)) {
1289 goto error;
1290 }
1291 break;
1292
1293 case LY_NODE_CASE:
1294 /* nothing to do */
1295 break;
1296
Michal Vasko0ea41032015-06-16 08:53:55 +02001297 case LY_NODE_GROUPING:
Michal Vasko38d01f72015-06-15 09:41:06 +02001298 case LY_NODE_RPC:
Michal Vasko38d01f72015-06-15 09:41:06 +02001299 case LY_NODE_INPUT:
1300 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001301 case LY_NODE_NOTIF:
1302 mix->tpdf_size = mix_orig->tpdf_size;
1303 mix->tpdf = ly_tpdf_dup(ctx, mix_orig->tpdf, mix->tpdf_size);
Radek Krejcia01e5432015-06-16 10:35:25 +02001304 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001305
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001306 default:
1307 /* LY_NODE_NOTIF */
1308 goto error;
1309 }
1310
1311 return retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001312
1313error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001314 LOGDBG("error: %s:%d", __FILE__, __LINE__);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001315
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001316 ly_mnode_free(retval);
1317 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001318}
1319
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001320API void
1321ly_module_free(struct ly_module *module)
Radek Krejciefaeba32015-05-27 14:30:57 +02001322{
Radek Krejcidce51452015-06-16 15:20:08 +02001323 struct ly_ctx *ctx;
1324 int i;
1325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001326 if (!module) {
1327 return;
1328 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001329
Radek Krejcidce51452015-06-16 15:20:08 +02001330 /* remove schema from the context */
1331 ctx = module->ctx;
1332 if (ctx->models.used) {
1333 for (i = 0; i < ctx->models.used; i++) {
1334 if (ctx->models.list[i] == module) {
1335 /* replace the position in the list by the last module in the list */
1336 ctx->models.used--;
1337 ctx->models.list[i] = ctx->models.list[ctx->models.used];
1338 ctx->models.list[ctx->models.used] = NULL;
1339 /* we are done */
1340 break;
1341 }
1342 }
1343 }
1344
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001345 /* common part with struct ly_submodule */
1346 module_free_common(module);
Radek Krejciefaeba32015-05-27 14:30:57 +02001347
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001348 /* specific items to free */
1349 lydict_remove(module->ctx, module->ns);
1350 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02001351
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001352 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001353}