blob: f0cd6d629f2582c7c068656c16a3018baa04d10e [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 +020036struct ly_mnode_leaf *
37find_leaf(struct ly_mnode *parent, const char *name, int len)
Radek Krejci8bc9ca02015-06-04 15:52:46 +020038{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020039 struct ly_mnode *child;
40 struct ly_mnode_leaf *result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +020041
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020042 if (!len) {
43 len = strlen(name);
44 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +020045
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020046 LY_TREE_FOR(parent->child, child) {
47 switch (child->nodetype) {
48 case LY_NODE_LEAF:
49 /* direct check */
50 if (child->name == name || (!strncmp(child->name, name, len) && !child->name[len])) {
51 return (struct ly_mnode_leaf *)child;
52 }
53 break;
54 case LY_NODE_USES:
55 /* search recursively */
56 result = find_leaf(child, name, len);
57 if (result) {
58 return result;
59 }
60 break;
61 default:
62 /* ignore */
63 break;
64 }
65 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +020066
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020067 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +020068}
Radek Krejcida04f4a2015-05-21 12:54:09 +020069
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020070void
71ly_mnode_unlink(struct ly_mnode *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +020072{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020073 struct ly_mnode *parent, *first;
Radek Krejcida04f4a2015-05-21 12:54:09 +020074
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020075 if (!node) {
76 return;
77 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020078
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020079 /* unlink from data model if necessary */
80 if (node->module) {
81 if (node->module->data == node) {
82 node->module->data = node->next;
Radek Krejci21181962015-06-30 14:11:00 +020083 } else if (node->module->rpc == node) {
84 node->module->rpc = node->next;
85 } else if (node->module->notif == node) {
86 node->module->notif = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020087 }
88 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020089
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020090 /* store pointers to important nodes */
91 parent = node->parent;
92 if (parent && !parent->nodetype) {
93 /* handle augments - first, unlink it from the augment parent ... */
94 if (parent->child == node) {
95 parent->child = node->next;
96 }
97 /* and then continue with the target parent */
98 parent = ((struct ly_augment *)parent)->target;
99 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200100
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200101 /* unlink from parent */
102 if (parent) {
103 if (parent->child == node) {
104 parent->child = node->next;
105 }
106 node->parent = NULL;
107 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200108
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200109 /* unlink from siblings */
110 if (node->prev == node) {
111 /* there are no more siblings */
112 return;
113 }
114 if (node->next) {
115 node->next->prev = node->prev;
116 } else {
117 /* unlinking the last element */
118 if (parent) {
119 first = parent->child;
120 } else {
121 first = node;
122 while (node->prev->next) {
123 first = node->prev;
124 }
125 }
126 first->prev = node->prev;
127 }
128 if (node->prev->next) {
129 node->prev->next = node->next;
130 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200131
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200132 /* clean up the unlinked element */
133 node->next = NULL;
134 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200135}
136
137/*
138 * Add child model node at the end of the parent's child list.
139 * If the child is connected somewhere (has a parent), it is completely
140 * unlinked and none of the following conditions applies.
141 * If the child has prev sibling(s), they are ignored (child is added at the
142 * end of the child list).
143 * If the child has next sibling(s), all of them are connected with the parent.
144 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200145int
146ly_mnode_addchild(struct ly_mnode *parent, struct ly_mnode *child)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200147{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200148 struct ly_mnode *last;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200150 assert(parent);
151 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200152
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200153 /* checks */
154 switch (parent->nodetype) {
155 case LY_NODE_CONTAINER:
156 case LY_NODE_LIST:
157 case LY_NODE_GROUPING:
158 case LY_NODE_USES:
Michal Vasko38d01f72015-06-15 09:41:06 +0200159 case LY_NODE_INPUT:
160 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +0200161 case LY_NODE_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200162 if (!(child->nodetype &
163 (LY_NODE_ANYXML | LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_GROUPING | LY_NODE_LEAF |
164 LY_NODE_LEAFLIST | LY_NODE_LIST | LY_NODE_USES))) {
165 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
166 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
167 return EXIT_FAILURE;
168 }
169 break;
170 case LY_NODE_CHOICE:
171 if (!(child->nodetype &
172 (LY_NODE_ANYXML | LY_NODE_CASE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST))) {
173 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"choice\" %s.",
174 strnodetype(child->nodetype), parent->name);
175 return EXIT_FAILURE;
176 }
177 break;
178 case LY_NODE_CASE:
179 if (!(child->nodetype &
180 (LY_NODE_ANYXML | LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST | LY_NODE_USES))) {
181 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"case\" %s.",
182 strnodetype(child->nodetype), parent->name);
183 return EXIT_FAILURE;
184 }
185 break;
Michal Vasko38d01f72015-06-15 09:41:06 +0200186 case LY_NODE_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200187 if (!(child->nodetype & (LY_NODE_INPUT | LY_NODE_OUTPUT | LY_NODE_GROUPING))) {
Michal Vasko38d01f72015-06-15 09:41:06 +0200188 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"rpc\" %s.",
189 strnodetype(child->nodetype), parent->name);
190 return EXIT_FAILURE;
191 }
192 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200193 case LY_NODE_LEAF:
194 case LY_NODE_LEAFLIST:
195 case LY_NODE_ANYXML:
196 LOGVAL(VE_SPEC, 0, "The \"%s\" statement (%s) cannot have any substatement.",
197 strnodetype(parent->nodetype), parent->name);
198 return EXIT_FAILURE;
199 case LY_NODE_AUGMENT:
200 LOGVAL(VE_SPEC, 0, "Internal error (%s:%d)", __FILE__, __LINE__);
201 return EXIT_FAILURE;
202 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200203
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200204 if (child->parent) {
205 ly_mnode_unlink(child);
206 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200207
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200208 if (!parent->child) {
209 /* the only/first child of the parent */
210 parent->child = child;
211 child->parent = parent;
212 last = child;
213 } else {
214 /* add a new child at the end of parent's child list */
215 last = parent->child->prev;
216 last->next = child;
217 child->prev = last;
218 }
219 while (last->next) {
220 last = last->next;
221 last->parent = parent;
222 }
223 parent->child->prev = last;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200224
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200225 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200226}
227
Michal Vaskodb7f2292015-07-02 11:52:13 +0200228static struct ly_module *
229find_import_in_includes_recursive(struct ly_module *mod, const char *prefix, uint32_t pref_len)
230{
231 int i, j;
232 struct ly_submodule *sub_mod;
233 struct ly_module *ret;
234
235 for (i = 0; i < mod->inc_size; i++) {
236 sub_mod = mod->inc[i].submodule;
237 for (j = 0; j < sub_mod->imp_size; j++) {
238 if ((pref_len == strlen(sub_mod->imp[j].prefix))
239 && !strncmp(sub_mod->imp[j].prefix, prefix, pref_len)) {
240 return sub_mod->imp[j].module;
241 }
242 }
243 }
244
245 for (i = 0; i < mod->inc_size; i++) {
246 ret = find_import_in_includes_recursive((struct ly_module *)mod->inc[i].submodule, prefix, pref_len);
247 if (ret) {
248 return ret;
249 }
250 }
251
252 return NULL;
253}
254
255static struct ly_module *
256find_import_in_module(struct ly_module *mod, const char *prefix, uint32_t pref_len)
257{
258 int i;
259
260 for (i = 0; i < mod->imp_size; i++) {
261 if ((pref_len == strlen(mod->imp[i].prefix)) && !strncmp(mod->imp[i].prefix, prefix, pref_len)) {
262 return mod->imp[i].module;
263 }
264 }
265
266 return find_import_in_includes_recursive(mod, prefix, pref_len);
267}
268
Radek Krejci3bde87f2015-06-05 16:51:58 +0200269/*
Michal Vasko25880b42015-06-12 10:16:33 +0200270 * id - schema-nodeid
Michal Vasko6f6ac232015-06-18 11:11:46 +0200271 *
272 * node_type - LY_NODE_AUGMENT (searches also RPCs and notifications)
Michal Vaskodb7f2292015-07-02 11:52:13 +0200273 * - LY_NODE_USES (only descendant-schema-nodeid allowed, ".." not allowed)
Michal Vasko6f6ac232015-06-18 11:11:46 +0200274 * - LY_NODE_CHOICE (search only start->child, only descendant-schema-nodeid allowed)
Radek Krejci3bde87f2015-06-05 16:51:58 +0200275 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200276struct ly_mnode *
Michal Vasko6f6ac232015-06-18 11:11:46 +0200277resolve_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 +0200278{
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200279 const char *name, *prefix, *ptr;
Michal Vaskoaf989e62015-06-29 14:57:45 +0200280 struct ly_mnode *sibling;
Michal Vaskodb7f2292015-07-02 11:52:13 +0200281 uint32_t nam_len, pref_len;
282 struct ly_module *prefix_mod, *start_mod;
283 /* 0 - in module, 1 - in 1st submodule, 2 - in 2nd submodule, ... */
284 uint8_t in_submod = 0;
285 /* 0 - in data, 1 - in RPCs, 2 - in notifications (relevant only with LY_NODE_AUGMENT) */
286 uint8_t in_mod_part = 0;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200287
Radek Krejcif5be10f2015-06-16 13:29:36 +0200288 assert(mod);
289 assert(id);
290
Michal Vasko92f4b2e2015-07-03 14:19:49 +0200291 if (id[strlen(id)-1] == '/') {
292 LOGERR(LY_EINVAL, "%s: Path ending with '/' is not valid.", __func__);
293 return NULL;
294 }
295
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200296 if (id[0] == '/') {
Michal Vasko6f6ac232015-06-18 11:11:46 +0200297 if (node_type & (LY_NODE_USES | LY_NODE_CHOICE)) {
298 return NULL;
299 }
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200300 ptr = strchr(id+1, '/');
301 prefix = id+1;
302 } else {
303 ptr = strchr(id, '/');
304 prefix = id;
305 }
306 pref_len = (ptr ? (unsigned)(ptr-prefix) : strlen(prefix));
Radek Krejci3bde87f2015-06-05 16:51:58 +0200307
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200308 ptr = strnchr(prefix, ':', pref_len);
Michal Vaskodb7f2292015-07-02 11:52:13 +0200309 /* there is a prefix */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200310 if (ptr) {
311 nam_len = (pref_len-(ptr-prefix))-1;
312 pref_len = ptr-prefix;
313 name = ptr+1;
314
315 /* no prefix used */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200316 } else {
317 name = prefix;
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200318 nam_len = pref_len;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200319 prefix = NULL;
320 }
Michal Vasko25880b42015-06-12 10:16:33 +0200321
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200322 /* absolute-schema-nodeid */
323 if (id[0] == '/') {
Michal Vaskodb7f2292015-07-02 11:52:13 +0200324 if (prefix) {
325 start_mod = find_import_in_module(mod, prefix, pref_len);
326 if (!start_mod) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200327 return NULL;
328 }
Michal Vaskodb7f2292015-07-02 11:52:13 +0200329 start = start_mod->data;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200330 } else {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200331 start = mod->data;
Michal Vaskodb7f2292015-07-02 11:52:13 +0200332 start_mod = mod;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200333 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200334 /* descendant-schema-nodeid */
Radek Krejcif5be10f2015-06-16 13:29:36 +0200335 } else {
336 assert(start);
337 start = start->child;
Michal Vaskodb7f2292015-07-02 11:52:13 +0200338 start_mod = start->module;
Radek Krejcif5be10f2015-06-16 13:29:36 +0200339 }
340
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200341 while (1) {
342 if (!strcmp(name, ".")) {
343 /* this node - start does not change */
344 } else if (!strcmp(name, "..")) {
Michal Vaskoaf989e62015-06-29 14:57:45 +0200345 /* ".." is not allowed in refines and augments in uses, there is no need for it there */
Michal Vasko6f6ac232015-06-18 11:11:46 +0200346 if (!start || (node_type == LY_NODE_USES)) {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200347 return NULL;
348 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200349 start = start->parent;
350 } else {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200351 sibling = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200352 LY_TREE_FOR(start, sibling) {
Michal Vaskodb7f2292015-07-02 11:52:13 +0200353 /* name match */
Michal Vasko69b42912015-07-03 13:43:15 +0200354 if ((sibling->name && !strncmp(name, sibling->name, nam_len) && (strlen(sibling->name) == nam_len))
355 || (!strncmp(name, "input", 5) && (nam_len == 5) && (sibling->nodetype == LY_NODE_INPUT))
356 || (!strncmp(name, "output", 6) && (nam_len == 6) && (sibling->nodetype == LY_NODE_OUTPUT))) {
Michal Vasko25880b42015-06-12 10:16:33 +0200357
Michal Vaskodb7f2292015-07-02 11:52:13 +0200358 /* prefix match check */
359 if (prefix) {
360
361 prefix_mod = find_import_in_module(mod, prefix, pref_len);
362 if (!prefix_mod) {
Michal Vasko6f6ac232015-06-18 11:11:46 +0200363 return NULL;
364 }
365
Radek Krejcia7f4a0e2015-07-02 19:13:35 +0200366 if (!sibling->module->type) {
367 if (prefix_mod != sibling->module) {
368 continue;
369 }
370 } else {
371 if (prefix_mod != ((struct ly_submodule *)sibling->module)->belongsto) {
372 continue;
373 }
Michal Vasko25880b42015-06-12 10:16:33 +0200374 }
375 }
376
377 /* the result node? */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200378 ptr = name+nam_len;
379 if (!ptr[0]) {
Michal Vasko25880b42015-06-12 10:16:33 +0200380 return sibling;
381 }
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200382 assert(ptr[0] == '/');
Michal Vasko25880b42015-06-12 10:16:33 +0200383
384 /* check for shorthand cases - then 'start' does not change */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200385 if (!sibling->parent || (sibling->parent->nodetype != LY_NODE_CHOICE)
386 || (sibling->nodetype == LY_NODE_CASE)) {
Michal Vasko25880b42015-06-12 10:16:33 +0200387 start = sibling->child;
388 }
389 break;
390 }
391 }
Radek Krejcif5be10f2015-06-16 13:29:36 +0200392
Michal Vasko6f6ac232015-06-18 11:11:46 +0200393 /* we did not find the case in direct siblings */
394 if (node_type == LY_NODE_CHOICE) {
395 return NULL;
396 }
397
Michal Vasko25880b42015-06-12 10:16:33 +0200398 /* no match */
399 if (!sibling) {
Michal Vasko6f6ac232015-06-18 11:11:46 +0200400 /* on augment search also RPCs and notifications, if we are in top-level */
Michal Vaskoaf989e62015-06-29 14:57:45 +0200401 if ((node_type == LY_NODE_AUGMENT) && (!start || !start->parent)) {
Michal Vasko6f6ac232015-06-18 11:11:46 +0200402 /* we have searched all the data nodes */
Michal Vaskoaf989e62015-06-29 14:57:45 +0200403 if (in_mod_part == 0) {
404 if (!in_submod) {
Michal Vaskodb7f2292015-07-02 11:52:13 +0200405 start = start_mod->rpc;
Michal Vaskoaf989e62015-06-29 14:57:45 +0200406 } else {
Michal Vaskodb7f2292015-07-02 11:52:13 +0200407 start = start_mod->inc[in_submod-1].submodule->rpc;
Michal Vasko6f6ac232015-06-18 11:11:46 +0200408 }
Michal Vaskoaf989e62015-06-29 14:57:45 +0200409 in_mod_part = 1;
410 continue;
Michal Vasko6f6ac232015-06-18 11:11:46 +0200411 }
412 /* we have searched all the RPCs */
Michal Vaskoaf989e62015-06-29 14:57:45 +0200413 if (in_mod_part == 1) {
414 if (!in_submod) {
Michal Vaskodb7f2292015-07-02 11:52:13 +0200415 start = start_mod->notif;
Michal Vaskoaf989e62015-06-29 14:57:45 +0200416 } else {
Michal Vaskodb7f2292015-07-02 11:52:13 +0200417 start = start_mod->inc[in_submod-1].submodule->notif;
Michal Vasko6f6ac232015-06-18 11:11:46 +0200418 }
Michal Vaskoaf989e62015-06-29 14:57:45 +0200419 in_mod_part = 2;
420 continue;
Michal Vasko6f6ac232015-06-18 11:11:46 +0200421 }
Michal Vaskoaf989e62015-06-29 14:57:45 +0200422 /* we have searched all the notifications, nothing else to search in this module */
423 }
424
425 /* are we done with the included submodules as well? */
Michal Vaskodb7f2292015-07-02 11:52:13 +0200426 if (in_submod == start_mod->inc_size) {
Michal Vasko86b84452015-06-22 10:54:05 +0200427 return NULL;
Michal Vasko6f6ac232015-06-18 11:11:46 +0200428 }
Michal Vaskoaf989e62015-06-29 14:57:45 +0200429
430 /* we aren't, check the next one */
431 ++in_submod;
432 in_mod_part = 0;
Michal Vaskodb7f2292015-07-02 11:52:13 +0200433 start = start_mod->inc[in_submod-1].submodule->data;
Michal Vaskoaf989e62015-06-29 14:57:45 +0200434 continue;
Michal Vasko25880b42015-06-12 10:16:33 +0200435 }
436 }
437
Michal Vasko3bf80ca2015-07-02 17:19:28 +0200438 /* we found our submodule */
439 if (in_submod) {
440 start_mod = (struct ly_module *)start_mod->inc[in_submod-1].submodule;
441 in_submod = 0;
442 }
Michal Vaskodb7f2292015-07-02 11:52:13 +0200443
Michal Vaskoa158c682015-06-17 09:25:38 +0200444 assert((*(name+nam_len) == '/') || (*(name+nam_len) == '\0'));
445
446 /* make prefix point to the next node name */
447 prefix = name+nam_len;
Michal Vaskoa158c682015-06-17 09:25:38 +0200448 ++prefix;
Michal Vasko92f4b2e2015-07-03 14:19:49 +0200449 assert(prefix[0]);
Michal Vaskoa158c682015-06-17 09:25:38 +0200450
451 /* parse prefix and node name */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200452 ptr = strchr(prefix, '/');
453 pref_len = (ptr ? (unsigned)(ptr-prefix) : strlen(prefix));
454 ptr = strnchr(prefix, ':', pref_len);
455
456 /* there is prefix */
457 if (ptr) {
Michal Vaskoa158c682015-06-17 09:25:38 +0200458 nam_len = (pref_len-(ptr-prefix))-1;
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200459 pref_len = ptr-prefix;
460 name = ptr+1;
461
462 /* no prefix used */
Michal Vasko25880b42015-06-12 10:16:33 +0200463 } else {
464 name = prefix;
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200465 nam_len = pref_len;
Michal Vasko25880b42015-06-12 10:16:33 +0200466 prefix = NULL;
467 }
Michal Vasko25880b42015-06-12 10:16:33 +0200468 }
469
470 /* cannot get here */
471 return NULL;
Radek Krejci3bde87f2015-06-05 16:51:58 +0200472}
473
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200474API struct ly_module *
475ly_module_read(struct ly_ctx *ctx, const char *data, LY_MINFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200476{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200477 if (!ctx || !data) {
478 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
479 return NULL;
480 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200481
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200482 switch (format) {
483 case LY_IN_YIN:
484 return yin_read_module(ctx, data);
485 case LY_IN_YANG:
486 default:
487 /* TODO */
488 return NULL;
489 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200490
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200491 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200492}
493
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200494struct ly_submodule *
495ly_submodule_read(struct ly_module *module, const char *data, LY_MINFORMAT format)
Radek Krejciefaeba32015-05-27 14:30:57 +0200496{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200497 assert(module);
498 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200499
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200500 switch (format) {
501 case LY_IN_YIN:
502 return yin_read_submodule(module, data);
503 case LY_IN_YANG:
504 default:
505 /* TODO */
506 return NULL;
507 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200508
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200509 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +0200510}
511
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200512API struct ly_module *
513ly_module_read_fd(struct ly_ctx *ctx, int fd, LY_MINFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200514{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200515 struct ly_module *module;
516 struct stat sb;
517 char *addr;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200518
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200519 if (!ctx || fd < 0) {
520 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
521 return NULL;
522 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200523
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200524 /*
525 * TODO
526 * This is just a temporary solution to make working automatic search for
527 * imported modules. This doesn't work e.g. for streams (stdin)
528 */
529 fstat(fd, &sb);
530 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
531 module = ly_module_read(ctx, addr, format);
532 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200533
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200534 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200535}
536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200537struct ly_submodule *
538ly_submodule_read_fd(struct ly_module *module, int fd, LY_MINFORMAT format)
Radek Krejciefaeba32015-05-27 14:30:57 +0200539{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200540 struct ly_submodule *submodule;
541 struct stat sb;
542 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +0200543
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200544 assert(module);
545 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +0200546
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200547 /*
548 * TODO
549 * This is just a temporary solution to make working automatic search for
550 * imported modules. This doesn't work e.g. for streams (stdin)
551 */
552 fstat(fd, &sb);
553 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
554 /* TODO addr error check */
555 submodule = ly_submodule_read(module, addr, format);
556 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +0200557
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200558 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +0200559
560}
561
Radek Krejci3733a802015-06-19 13:43:21 +0200562struct ly_restr *
563ly_restr_dup(struct ly_ctx *ctx, struct ly_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200564{
Radek Krejci3733a802015-06-19 13:43:21 +0200565 struct ly_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200566 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200567
Radek Krejci3733a802015-06-19 13:43:21 +0200568 if (!size) {
569 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200570 }
Radek Krejci3733a802015-06-19 13:43:21 +0200571
572 result = calloc(size, sizeof *result);
573 for (i = 0; i < size; i++) {
574 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
575 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
576 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
577 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
578 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
579 }
580
581 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200582}
583
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200584void
Radek Krejci0bd5db42015-06-19 13:30:07 +0200585ly_restr_free(struct ly_ctx *ctx, struct ly_restr *restr)
586{
587 assert(ctx);
588 if (!restr) {
589 return;
590 }
591
592 lydict_remove(ctx, restr->expr);
593 lydict_remove(ctx, restr->dsc);
594 lydict_remove(ctx, restr->ref);
595 lydict_remove(ctx, restr->eapptag);
596 lydict_remove(ctx, restr->emsg);
597}
598
599void
Radek Krejci3733a802015-06-19 13:43:21 +0200600ly_type_dup(struct ly_ctx *ctx, struct ly_type *new, struct ly_type *old)
601{
602 int i;
603
604 new->prefix = lydict_insert(ctx, old->prefix, 0);
605 new->base = old->base;
606 new->der = old->der;
607
608 switch (new->base) {
609 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +0200610 if (old->info.binary.length) {
611 new->info.binary.length = ly_restr_dup(ctx, old->info.binary.length, 1);
612 }
Radek Krejci3733a802015-06-19 13:43:21 +0200613 break;
614
615 case LY_TYPE_BITS:
616 new->info.bits.count = old->info.bits.count;
617 if (new->info.bits.count) {
618 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
619 for (i = 0; i < new->info.bits.count; i++) {
620 new->info.bits.bit[i].name = lydict_insert(ctx, old->info.bits.bit[i].name, 0);
621 new->info.bits.bit[i].dsc = lydict_insert(ctx, old->info.bits.bit[i].dsc, 0);
622 new->info.bits.bit[i].ref = lydict_insert(ctx, old->info.bits.bit[i].ref, 0);
623 new->info.bits.bit[i].status = old->info.bits.bit[i].status;
624 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
625 }
626 }
627 break;
628
Radek Krejcif9401c32015-06-26 16:47:36 +0200629 case LY_TYPE_DEC64:
630 new->info.dec64.dig = old->info.dec64.dig;
631 if (old->info.dec64.range) {
632 new->info.dec64.range = ly_restr_dup(ctx, old->info.dec64.range, 1);
633 }
634 break;
635
Radek Krejci3733a802015-06-19 13:43:21 +0200636 case LY_TYPE_ENUM:
637 new->info.enums.count = old->info.enums.count;
638 if (new->info.enums.count) {
639 new->info.enums.list = calloc(new->info.enums.count, sizeof *new->info.enums.list);
640 for (i = 0; i < new->info.enums.count; i++) {
641 new->info.enums.list[i].name = lydict_insert(ctx, old->info.enums.list[i].name, 0);
642 new->info.enums.list[i].dsc = lydict_insert(ctx, old->info.enums.list[i].dsc, 0);
643 new->info.enums.list[i].ref = lydict_insert(ctx, old->info.enums.list[i].ref, 0);
644 new->info.enums.list[i].status = old->info.enums.list[i].status;
645 new->info.enums.list[i].value = old->info.enums.list[i].value;
646 }
647 }
648 break;
649
Radek Krejci4a7b5ee2015-06-19 14:56:43 +0200650 case LY_TYPE_IDENT:
651 new->info.ident.ref = old->info.ident.ref;
652 break;
653
Radek Krejciaf351422015-06-19 14:49:38 +0200654 case LY_TYPE_INST:
655 new->info.inst.req = old->info.inst.req;
656 break;
657
Radek Krejcif2860132015-06-20 12:37:20 +0200658 case LY_TYPE_INT8:
659 case LY_TYPE_INT16:
660 case LY_TYPE_INT32:
661 case LY_TYPE_INT64:
662 case LY_TYPE_UINT8:
663 case LY_TYPE_UINT16:
664 case LY_TYPE_UINT32:
665 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +0200666 if (old->info.num.range) {
667 new->info.num.range = ly_restr_dup(ctx, old->info.num.range, 1);
668 }
Radek Krejcif2860132015-06-20 12:37:20 +0200669 break;
670
Radek Krejcidc4c1412015-06-19 15:39:54 +0200671 case LY_TYPE_LEAFREF:
672 new->info.lref.path = lydict_insert(ctx, old->info.lref.path, 0);
673 break;
674
Radek Krejci3733a802015-06-19 13:43:21 +0200675 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +0200676 if (old->info.str.length) {
677 new->info.str.length = ly_restr_dup(ctx, old->info.str.length, 1);
678 }
679 new->info.str.patterns = ly_restr_dup(ctx, old->info.str.patterns, old->info.str.pat_count);
Radek Krejci3733a802015-06-19 13:43:21 +0200680 break;
681
Radek Krejcie4c366b2015-07-02 10:11:31 +0200682 case LY_TYPE_UNION:
683 new->info.uni.count = old->info.uni.count;
684 if (new->info.uni.count) {
685 new->info.uni.type = calloc(new->info.uni.count, sizeof *new->info.uni.type);
686 for (i = 0; i < new->info.uni.count; i++) {
687 ly_type_dup(ctx, &(new->info.uni.type[i]), &(old->info.uni.type[i]));
688 }
689 }
690 break;
691
Radek Krejci3733a802015-06-19 13:43:21 +0200692 default:
Radek Krejcic7c85532015-07-02 10:16:54 +0200693 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +0200694 break;
695 }
696}
697
698void
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200699ly_type_free(struct ly_ctx *ctx, struct ly_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +0200700{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200701 int i;
Radek Krejci5a065542015-05-22 15:02:07 +0200702
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200703 assert(ctx);
704 if (!type) {
705 return;
706 }
Radek Krejci812b10a2015-05-28 16:48:25 +0200707
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200708 lydict_remove(ctx, type->prefix);
Radek Krejci5a065542015-05-22 15:02:07 +0200709
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200710 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +0200711 case LY_TYPE_BINARY:
712 ly_restr_free(ctx, type->info.binary.length);
713 free(type->info.binary.length);
714 break;
Radek Krejci994b6f62015-06-18 16:47:27 +0200715 case LY_TYPE_BITS:
716 for (i = 0; i < type->info.bits.count; i++) {
717 lydict_remove(ctx, type->info.bits.bit[i].name);
718 lydict_remove(ctx, type->info.bits.bit[i].dsc);
719 lydict_remove(ctx, type->info.bits.bit[i].ref);
720 }
721 free(type->info.bits.bit);
722 break;
Radek Krejcif9401c32015-06-26 16:47:36 +0200723
724 case LY_TYPE_DEC64:
725 ly_restr_free(ctx, type->info.dec64.range);
726 free(type->info.dec64.range);
727 break;
728
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200729 case LY_TYPE_ENUM:
730 for (i = 0; i < type->info.enums.count; i++) {
731 lydict_remove(ctx, type->info.enums.list[i].name);
732 lydict_remove(ctx, type->info.enums.list[i].dsc);
733 lydict_remove(ctx, type->info.enums.list[i].ref);
734 }
735 free(type->info.enums.list);
736 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +0200737
Radek Krejci6fcb9dd2015-06-22 10:16:37 +0200738 case LY_TYPE_INT8:
739 case LY_TYPE_INT16:
740 case LY_TYPE_INT32:
741 case LY_TYPE_INT64:
742 case LY_TYPE_UINT8:
743 case LY_TYPE_UINT16:
744 case LY_TYPE_UINT32:
745 case LY_TYPE_UINT64:
746 ly_restr_free(ctx, type->info.num.range);
747 free(type->info.num.range);
748 break;
749
Radek Krejcidc4c1412015-06-19 15:39:54 +0200750 case LY_TYPE_LEAFREF:
751 lydict_remove(ctx, type->info.lref.path);
752 break;
753
Radek Krejci3733a802015-06-19 13:43:21 +0200754 case LY_TYPE_STRING:
755 ly_restr_free(ctx, type->info.str.length);
756 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200757 for (i = 0; i < type->info.str.pat_count; i++) {
758 ly_restr_free(ctx, &type->info.str.patterns[i]);
759 }
760 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +0200761 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +0200762
Radek Krejcie4c366b2015-07-02 10:11:31 +0200763 case LY_TYPE_UNION:
764 for (i = 0; i < type->info.uni.count; i++) {
765 ly_type_free(ctx, &type->info.uni.type[i]);
766 }
767 free(type->info.uni.type);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +0200768 break;
769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200770 default:
Radek Krejcic7c85532015-07-02 10:16:54 +0200771 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200772 break;
773 }
Radek Krejci5a065542015-05-22 15:02:07 +0200774}
775
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200776struct ly_tpdf *
777ly_tpdf_dup(struct ly_ctx *ctx, struct ly_tpdf *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200778{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200779 struct ly_tpdf *result;
780 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200781
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200782 if (!size) {
783 return NULL;
784 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200785
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200786 result = calloc(size, sizeof *result);
787 for (i = 0; i < size; i++) {
788 result[i].name = lydict_insert(ctx, old[i].name, 0);
789 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
790 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
791 result[i].flags = old[i].flags;
792 result[i].module = old[i].module;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200793
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200794 ly_type_dup(ctx, &(result[i].type), &(old[i].type));
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200795
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200796 result[i].dflt = lydict_insert(ctx, old[i].dflt, 0);
797 result[i].units = lydict_insert(ctx, old[i].units, 0);
798 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200799
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200800 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200801}
802
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200803void
804ly_tpdf_free(struct ly_ctx *ctx, struct ly_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200805{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200806 assert(ctx);
807 if (!tpdf) {
808 return;
809 }
Radek Krejci812b10a2015-05-28 16:48:25 +0200810
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200811 lydict_remove(ctx, tpdf->name);
812 lydict_remove(ctx, tpdf->dsc);
813 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200814
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200815 ly_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200816
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200817 lydict_remove(ctx, tpdf->units);
818 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200819}
820
Radek Krejci00768f42015-06-18 17:04:04 +0200821struct ly_when *
822ly_when_dup(struct ly_ctx *ctx, struct ly_when *old)
823{
824 struct ly_when *new;
825
826 if (!old) {
827 return NULL;
828 }
829
830 new = calloc(1, sizeof *new);
831 new->cond = lydict_insert(ctx, old->cond, 0);
832 new->dsc = lydict_insert(ctx, old->dsc, 0);
833 new->ref = lydict_insert(ctx, old->ref, 0);
834
835 return new;
836}
837
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200838void
839ly_when_free(struct ly_ctx *ctx, struct ly_when *w)
840{
841 if (!w) {
842 return;
843 }
844
845 lydict_remove(ctx, w->cond);
846 lydict_remove(ctx, w->dsc);
847 lydict_remove(ctx, w->ref);
848
849 free(w);
850}
851
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200852struct ly_augment *
853ly_augment_dup(struct ly_module *module, struct ly_mnode *parent, struct ly_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +0200854{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200855 struct ly_augment *new = NULL;
856 int i = -1;
Radek Krejci106efc02015-06-10 14:36:27 +0200857
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200858 if (!size) {
859 return NULL;
860 }
Radek Krejci106efc02015-06-10 14:36:27 +0200861
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200862 new = calloc(size, sizeof *new);
863 for (i = 0; i < size; i++) {
864 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
865 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
866 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
867 new[i].flags = old[i].flags;
868 /* .target = NULL; .nodetype = 0 */
Radek Krejci106efc02015-06-10 14:36:27 +0200869
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200870 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +0200871
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200872 /* copy the definition of augment nodes */
873 if (old[i].child) {
874 new[i].child = (struct ly_mnode *)lyxml_dup_elem(module->ctx, (struct lyxml_elem *)old[i].child, NULL, 1);
875 }
876 }
Radek Krejci106efc02015-06-10 14:36:27 +0200877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200878 return new;
Radek Krejci106efc02015-06-10 14:36:27 +0200879}
880
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200881struct ly_refine *
882ly_refine_dup(struct ly_ctx *ctx, struct ly_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +0200883{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200884 struct ly_refine *result;
885 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +0200886
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200887 if (!size) {
888 return NULL;
889 }
Michal Vasko1982cad2015-06-08 15:49:30 +0200890
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200891 result = calloc(size, sizeof *result);
892 for (i = 0; i < size; i++) {
893 result[i].target = lydict_insert(ctx, old[i].target, 0);
894 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
895 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
896 result[i].flags = old[i].flags;
897 result[i].target_type = old[i].target_type;
898 result[i].must_size = old[i].must_size;
Radek Krejci0bd5db42015-06-19 13:30:07 +0200899 result[i].must = ly_restr_dup(ctx, old[i].must, old[i].must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200900 if (result[i].target_type & (LY_NODE_LEAF | LY_NODE_CHOICE)) {
901 result[i].mod.dflt = lydict_insert(ctx, old[i].mod.dflt, 0);
902 } else if (result[i].target_type == LY_NODE_CONTAINER) {
903 result[i].mod.presence = lydict_insert(ctx, old[i].mod.presence, 0);
904 } else if (result[i].target_type & (LY_NODE_LIST | LY_NODE_LEAFLIST)) {
905 result[i].mod.list = old[i].mod.list;
906 }
907 }
Michal Vasko1982cad2015-06-08 15:49:30 +0200908
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200909 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +0200910}
911
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200912void
913ly_ident_free(struct ly_ctx *ctx, struct ly_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +0200914{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200915 struct ly_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +0200916
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200917 assert(ctx);
918 if (!ident) {
919 return;
920 }
Radek Krejci812b10a2015-05-28 16:48:25 +0200921
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200922 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200923 * if caller free only a single data model which is used (its identity is
924 * reference from identity in another module), this silly freeing can lead
925 * to segmentation fault. But without noting if the module is used by some
926 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +0200927 *
928 * Possible solution is to not allow caller to remove particular schema
929 * from the context.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200930 */
931 while (ident->der) {
932 der = ident->der;
933 ident->der = der->next;
934 free(der);
935 }
Radek Krejci6793db02015-05-22 17:49:54 +0200936
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200937 lydict_remove(ctx, ident->name);
938 lydict_remove(ctx, ident->dsc);
939 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +0200940
941}
942
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200943void
944ly_grp_free(struct ly_ctx *ctx, struct ly_mnode_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200945{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200946 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200947
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200948 /* handle only specific parts for LY_NODE_GROUPING */
949 for (i = 0; i < grp->tpdf_size; i++) {
950 ly_tpdf_free(ctx, &grp->tpdf[i]);
951 }
952 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +0200953}
954
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200955void
956ly_anyxml_free(struct ly_ctx *ctx, struct ly_mnode_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +0200957{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200958 int i;
Radek Krejci537cf382015-06-04 11:07:01 +0200959
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200960 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci0bd5db42015-06-19 13:30:07 +0200961 ly_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200962 }
963 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200964
965 ly_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200966}
967
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200968void
969ly_leaf_free(struct ly_ctx *ctx, struct ly_mnode_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +0200970{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200971 int i;
Radek Krejci537cf382015-06-04 11:07:01 +0200972
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200973 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci0bd5db42015-06-19 13:30:07 +0200974 ly_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200975 }
976 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +0200977
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200978 ly_when_free(ctx, leaf->when);
979
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200980 ly_type_free(ctx, &leaf->type);
981 lydict_remove(ctx, leaf->units);
982 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +0200983}
984
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200985void
986ly_leaflist_free(struct ly_ctx *ctx, struct ly_mnode_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +0200987{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200988 int i;
Radek Krejci537cf382015-06-04 11:07:01 +0200989
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200990 for (i = 0; i < llist->must_size; i++) {
Radek Krejci0bd5db42015-06-19 13:30:07 +0200991 ly_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200992 }
993 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +0200994
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200995 ly_when_free(ctx, llist->when);
996
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200997 ly_type_free(ctx, &llist->type);
998 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +0200999}
1000
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001001void
1002ly_list_free(struct ly_ctx *ctx, struct ly_mnode_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001003{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001004 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001005
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001006 /* handle only specific parts for LY_NODE_LIST */
1007 for (i = 0; i < list->tpdf_size; i++) {
1008 ly_tpdf_free(ctx, &list->tpdf[i]);
1009 }
1010 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001011
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001012 for (i = 0; i < list->must_size; i++) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001013 ly_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001014 }
1015 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001016
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001017 ly_when_free(ctx, list->when);
1018
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001019 for (i = 0; i < list->unique_size; i++) {
1020 free(list->unique[i].leafs);
1021 }
1022 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001023
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001024 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001025}
1026
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001027void
1028ly_container_free(struct ly_ctx *ctx, struct ly_mnode_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001029{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001030 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001031
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001032 /* handle only specific parts for LY_NODE_CONTAINER */
1033 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001034
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001035 for (i = 0; i < cont->tpdf_size; i++) {
1036 ly_tpdf_free(ctx, &cont->tpdf[i]);
1037 }
1038 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001039
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001040 for (i = 0; i < cont->must_size; i++) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001041 ly_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001042 }
1043 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001044
1045 ly_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001046}
1047
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001048void
Radek Krejci3cf9e222015-06-18 11:37:50 +02001049ly_feature_free(struct ly_ctx *ctx, struct ly_feature *f)
1050{
1051 lydict_remove(ctx, f->name);
1052 lydict_remove(ctx, f->dsc);
1053 lydict_remove(ctx, f->ref);
1054 free(f->features);
1055}
1056
1057void
Radek Krejcieb00f512015-07-01 16:44:58 +02001058ly_deviation_free(struct ly_ctx *ctx, struct ly_deviation *dev)
1059{
1060 int i, j;
1061
1062 lydict_remove(ctx, dev->target_name);
1063 lydict_remove(ctx, dev->dsc);
1064 lydict_remove(ctx, dev->ref);
1065
1066 for (i = 0; i < dev->deviate_size; i++) {
1067 lydict_remove(ctx, dev->deviate[i].dflt);
1068 lydict_remove(ctx, dev->deviate[i].units);
1069
1070 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1071 for (j = 0; j < dev->deviate[i].must_size; j++) {
1072 ly_restr_free(ctx, &dev->deviate[i].must[j]);
1073 }
1074 free(dev->deviate[i].must);
1075
1076 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1077 free(dev->deviate[j].unique[j].leafs);
1078 }
1079 free(dev->deviate[i].unique);
1080 }
1081 }
1082 free(dev->deviate);
1083}
1084
1085void
Radek Krejcif5be10f2015-06-16 13:29:36 +02001086ly_augment_free(struct ly_ctx *ctx, struct ly_augment *aug)
1087{
1088 lydict_remove(ctx, aug->target_name);
1089 lydict_remove(ctx, aug->dsc);
1090 lydict_remove(ctx, aug->ref);
1091
Michal Vasko25b39612015-07-07 16:11:07 +02001092 free(aug->features);
1093
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001094 ly_when_free(ctx, aug->when);
1095
Radek Krejcif5be10f2015-06-16 13:29:36 +02001096 lyxml_free_elem(ctx, (struct lyxml_elem *)aug->child);
1097}
1098
1099void
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001100ly_uses_free(struct ly_ctx *ctx, struct ly_mnode_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +02001101{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001102 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001104 for (i = 0; i < uses->refine_size; i++) {
1105 lydict_remove(ctx, uses->refine[i].target);
1106 lydict_remove(ctx, uses->refine[i].dsc);
1107 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001108
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001109 for (j = 0; j < uses->refine[j].must_size; j++) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001110 ly_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001111 }
1112 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001113
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001114 if (uses->refine[i].target_type & (LY_NODE_LEAF | LY_NODE_CHOICE)) {
1115 lydict_remove(ctx, uses->refine[i].mod.dflt);
1116 } else if (uses->refine[i].target_type & LY_NODE_CONTAINER) {
1117 lydict_remove(ctx, uses->refine[i].mod.presence);
1118 }
1119 }
1120 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001121
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001122 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02001123 ly_augment_free(ctx, &uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001124 }
1125 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001126
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001127 ly_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001128}
1129
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001130void
1131ly_mnode_free(struct ly_mnode *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001132{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001133 struct ly_ctx *ctx;
1134 struct ly_mnode *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001135
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001136 if (!node) {
1137 return;
1138 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001139
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001140 assert(node->module);
1141 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001142
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001143 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001145 /* common part */
1146 LY_TREE_FOR_SAFE(node->child, next, sub) {
1147 ly_mnode_free(sub);
1148 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001149 free(node->features);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001150
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001151 lydict_remove(ctx, node->name);
1152 lydict_remove(ctx, node->dsc);
1153 lydict_remove(ctx, node->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001154
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001155 /* specific part */
1156 switch (node->nodetype) {
1157 case LY_NODE_CONTAINER:
1158 ly_container_free(ctx, (struct ly_mnode_container *)node);
1159 break;
1160 case LY_NODE_CHOICE:
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001161 ly_when_free(ctx, ((struct ly_mnode_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001162 break;
1163 case LY_NODE_LEAF:
1164 ly_leaf_free(ctx, (struct ly_mnode_leaf *)node);
1165 break;
1166 case LY_NODE_LEAFLIST:
1167 ly_leaflist_free(ctx, (struct ly_mnode_leaflist *)node);
1168 break;
1169 case LY_NODE_LIST:
1170 ly_list_free(ctx, (struct ly_mnode_list *)node);
1171 break;
1172 case LY_NODE_ANYXML:
1173 ly_anyxml_free(ctx, (struct ly_mnode_anyxml *)node);
1174 break;
1175 case LY_NODE_USES:
1176 ly_uses_free(ctx, (struct ly_mnode_uses *)node);
1177 break;
1178 case LY_NODE_CASE:
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001179 ly_when_free(ctx, ((struct ly_mnode_case *)node)->when);
1180 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001181 case LY_NODE_AUGMENT:
1182 /* do nothing */
1183 break;
Michal Vasko0ea41032015-06-16 08:53:55 +02001184 case LY_NODE_GROUPING:
1185 case LY_NODE_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001186 case LY_NODE_INPUT:
1187 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001188 case LY_NODE_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001189 ly_grp_free(ctx, (struct ly_mnode_grp *)node);
1190 break;
1191 }
Radek Krejci5a065542015-05-22 15:02:07 +02001192
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001193 /* again common part */
1194 ly_mnode_unlink(node);
1195 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001196}
1197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001198static void
1199module_free_common(struct ly_module *module)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001200{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001201 struct ly_ctx *ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001202 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001203 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001204
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001205 assert(module->ctx);
1206 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001207
Radek Krejcidce51452015-06-16 15:20:08 +02001208 /* as first step, free the imported modules */
1209 for (i = 0; i < module->imp_size; i++) {
1210 /* get the imported module from the context and then free,
1211 * this check is necessary because the imported module can
1212 * be already removed
1213 */
1214 l = ctx->models.used;
1215 for (j = 0; j < l; j++) {
1216 if (ctx->models.list[j] == module->imp[i].module) {
1217 ly_module_free(module->imp[i].module);
1218 break;
1219 }
1220 }
1221 }
1222 free(module->imp);
1223
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001224 while (module->data) {
Radek Krejci21181962015-06-30 14:11:00 +02001225 ly_mnode_free(module->data);
1226 }
1227 while (module->rpc) {
1228 ly_mnode_free(module->rpc);
1229 }
1230 while (module->notif) {
1231 ly_mnode_free(module->notif);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001232 }
Radek Krejci5a065542015-05-22 15:02:07 +02001233
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001234 lydict_remove(ctx, module->dsc);
1235 lydict_remove(ctx, module->ref);
1236 lydict_remove(ctx, module->org);
1237 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001238
Radek Krejcieb00f512015-07-01 16:44:58 +02001239 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001240 for (i = 0; i < module->rev_size; i++) {
1241 lydict_remove(ctx, module->rev[i].dsc);
1242 lydict_remove(ctx, module->rev[i].ref);
1243 }
1244 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001245
Radek Krejcieb00f512015-07-01 16:44:58 +02001246 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001247 for (i = 0; i < module->ident_size; i++) {
1248 ly_ident_free(ctx, &module->ident[i]);
1249 }
1250 module->ident_size = 0;
1251 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001252
Radek Krejcieb00f512015-07-01 16:44:58 +02001253 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001254 for (i = 0; i < module->tpdf_size; i++) {
1255 ly_tpdf_free(ctx, &module->tpdf[i]);
1256 }
1257 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001258
Radek Krejcieb00f512015-07-01 16:44:58 +02001259 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001260 for (i = 0; i < module->inc_size; i++) {
1261 ly_submodule_free(module->inc[i].submodule);
1262 }
1263 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001264
Radek Krejcieb00f512015-07-01 16:44:58 +02001265 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02001266 for (i = 0; i < module->augment_size; i++) {
1267 ly_augment_free(ctx, &module->augment[i]);
1268 }
1269 free(module->augment);
1270
Radek Krejcieb00f512015-07-01 16:44:58 +02001271 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001272 for (i = 0; i < module->features_size; i++) {
1273 ly_feature_free(ctx, &module->features[i]);
1274 }
1275 free(module->features);
1276
Radek Krejcieb00f512015-07-01 16:44:58 +02001277 /* deviations */
1278 for (i = 0; i < module->deviation_size; i++) {
1279 ly_deviation_free(ctx, &module->deviation[i]);
1280 }
1281 free(module->deviation);
1282
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001283 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02001284}
1285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001286void
1287ly_submodule_free(struct ly_submodule *submodule)
Radek Krejciefaeba32015-05-27 14:30:57 +02001288{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001289 if (!submodule) {
1290 return;
1291 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001292
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001293 submodule->inc_size = 0;
1294 free(submodule->inc);
1295 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02001296
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001297 /* common part with struct ly_module */
1298 module_free_common((struct ly_module *)submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001299
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001300 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02001301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001302 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001303}
1304
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001305struct ly_mnode *
1306ly_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 +02001307{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001308 struct ly_mnode *retval = NULL, *aux, *child;
1309 struct ly_ctx *ctx = module->ctx;
1310 int i, j;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001311
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001312 struct ly_mnode_container *cont;
1313 struct ly_mnode_container *cont_orig = (struct ly_mnode_container *)mnode;
1314 struct ly_mnode_choice *choice;
1315 struct ly_mnode_choice *choice_orig = (struct ly_mnode_choice *)mnode;
1316 struct ly_mnode_leaf *leaf;
1317 struct ly_mnode_leaf *leaf_orig = (struct ly_mnode_leaf *)mnode;
1318 struct ly_mnode_leaflist *llist;
1319 struct ly_mnode_leaflist *llist_orig = (struct ly_mnode_leaflist *)mnode;
1320 struct ly_mnode_list *list;
1321 struct ly_mnode_list *list_orig = (struct ly_mnode_list *)mnode;
1322 struct ly_mnode_anyxml *anyxml;
1323 struct ly_mnode_anyxml *anyxml_orig = (struct ly_mnode_anyxml *)mnode;
1324 struct ly_mnode_uses *uses;
1325 struct ly_mnode_uses *uses_orig = (struct ly_mnode_uses *)mnode;
1326 struct ly_mnode_grp *mix;
1327 struct ly_mnode_grp *mix_orig = (struct ly_mnode_grp *)mnode;
1328 struct ly_mnode_case *cs;
Radek Krejci00768f42015-06-18 17:04:04 +02001329 struct ly_mnode_case *cs_orig = (struct ly_mnode_case *)mnode;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001331 /* we cannot just duplicate memory since the strings are stored in
1332 * dictionary and we need to update dictionary counters.
1333 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001334
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001335 switch (mnode->nodetype) {
1336 case LY_NODE_CONTAINER:
1337 cont = calloc(1, sizeof *cont);
1338 retval = (struct ly_mnode *)cont;
1339 break;
1340
1341 case LY_NODE_CHOICE:
1342 choice = calloc(1, sizeof *choice);
1343 retval = (struct ly_mnode *)choice;
1344 break;
1345
1346 case LY_NODE_LEAF:
1347 leaf = calloc(1, sizeof *leaf);
1348 retval = (struct ly_mnode *)leaf;
1349 break;
1350
1351 case LY_NODE_LEAFLIST:
1352 llist = calloc(1, sizeof *llist);
1353 retval = (struct ly_mnode *)llist;
1354 break;
1355
1356 case LY_NODE_LIST:
1357 list = calloc(1, sizeof *list);
1358 retval = (struct ly_mnode *)list;
1359 break;
1360
1361 case LY_NODE_ANYXML:
1362 anyxml = calloc(1, sizeof *anyxml);
1363 retval = (struct ly_mnode *)anyxml;
1364 break;
1365
1366 case LY_NODE_USES:
1367 uses = calloc(1, sizeof *uses);
1368 retval = (struct ly_mnode *)uses;
1369 break;
1370
1371 case LY_NODE_CASE:
1372 cs = calloc(1, sizeof *cs);
1373 retval = (struct ly_mnode *)cs;
1374 break;
1375
1376 /* exact same structure */
Michal Vasko0ea41032015-06-16 08:53:55 +02001377 case LY_NODE_GROUPING:
Michal Vasko38d01f72015-06-15 09:41:06 +02001378 case LY_NODE_RPC:
Michal Vasko38d01f72015-06-15 09:41:06 +02001379 case LY_NODE_INPUT:
1380 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001381 case LY_NODE_NOTIF:
1382 mix = calloc(1, sizeof *mix);
1383 retval = (struct ly_mnode *)mix;
Michal Vasko38d01f72015-06-15 09:41:06 +02001384 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001385
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001386 default:
1387 goto error;
1388 }
Radek Krejcib388c152015-06-04 17:03:03 +02001389
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001390 /*
1391 * duplicate generic part of the structure
1392 */
1393 retval->name = lydict_insert(ctx, mnode->name, 0);
1394 retval->dsc = lydict_insert(ctx, mnode->dsc, 0);
1395 retval->ref = lydict_insert(ctx, mnode->ref, 0);
1396 retval->flags = mnode->flags;
1397 if (!(retval->flags & LY_NODE_CONFIG_MASK)) {
1398 /* set parent's config flag */
1399 retval->flags |= flags & LY_NODE_CONFIG_MASK;
1400 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001401
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001402 retval->module = module;
1403 retval->nodetype = mnode->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001404
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001405 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001406
Radek Krejci3cf9e222015-06-18 11:37:50 +02001407 retval->features_size = mnode->features_size;
1408 retval->features = calloc(retval->features_size, sizeof *retval->features);
1409 memcpy(retval->features, mnode->features, retval->features_size * sizeof *retval->features);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001410
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001411 if (recursive) {
1412 /* go recursively */
1413 LY_TREE_FOR(mnode->child, child) {
1414 aux = ly_mnode_dup(module, child, retval->flags, 1, line);
1415 if (!aux || ly_mnode_addchild(retval, aux)) {
1416 goto error;
1417 }
1418 }
1419 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001420
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001421 /*
1422 * duplicate specific part of the structure
1423 */
1424 switch (mnode->nodetype) {
1425 case LY_NODE_CONTAINER:
Radek Krejci00768f42015-06-18 17:04:04 +02001426 cont->when = ly_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001427 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001428
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001429 cont->must_size = cont_orig->must_size;
1430 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001431
Radek Krejci0bd5db42015-06-19 13:30:07 +02001432 cont->must = ly_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001433 cont->tpdf = ly_tpdf_dup(ctx, cont_orig->tpdf, cont->tpdf_size);
1434 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001435
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001436 case LY_NODE_CHOICE:
Radek Krejci00768f42015-06-18 17:04:04 +02001437 choice->when = ly_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001438 if (choice->dflt) {
1439 LY_TREE_FOR(choice->child, child) {
1440 if (child->name == choice_orig->dflt->name) {
1441 choice->dflt = child;
1442 break;
1443 }
1444 }
1445 }
1446 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001447
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001448 case LY_NODE_LEAF:
1449 ly_type_dup(ctx, &(leaf->type), &(leaf_orig->type));
1450 leaf->units = lydict_insert(ctx, leaf_orig->units, 0);
1451 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001452
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001453 leaf->must_size = leaf_orig->must_size;
Radek Krejci0bd5db42015-06-19 13:30:07 +02001454 leaf->must = ly_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02001455
1456 leaf->when = ly_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001457 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001458
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001459 case LY_NODE_LEAFLIST:
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001460
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001461 ly_type_dup(ctx, &(llist->type), &(llist_orig->type));
1462 llist->units = lydict_insert(ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001463
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001464 llist->min = llist_orig->min;
1465 llist->max = llist_orig->max;
1466
1467 llist->must_size = llist_orig->must_size;
Radek Krejci0bd5db42015-06-19 13:30:07 +02001468 llist->must = ly_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02001469
1470 llist->when = ly_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001471 break;
1472
1473 case LY_NODE_LIST:
1474 list->min = list_orig->min;
1475 list->max = list_orig->max;
1476
1477 list->must_size = list_orig->must_size;
1478 list->tpdf_size = list_orig->tpdf_size;
1479 list->keys_size = list_orig->keys_size;
1480 list->unique_size = list_orig->unique_size;
1481
Radek Krejci0bd5db42015-06-19 13:30:07 +02001482 list->must = ly_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001483 list->tpdf = ly_tpdf_dup(ctx, list_orig->tpdf, list->tpdf_size);
1484
1485 if (list->keys_size) {
1486 list->keys = calloc(list->keys_size, sizeof *list->keys);
1487 for (i = 0; i < list->keys_size; i++) {
1488 list->keys[i] = find_leaf(retval, list_orig->keys[i]->name, 0);
1489 }
1490 }
1491 if (list->unique_size) {
1492 list->unique = calloc(list->unique_size, sizeof *list->unique);
1493 for (i = 0; i < list->unique_size; i++) {
1494 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
1495 for (j = 0; j < list->unique[i].leafs_size; j++) {
1496 list->unique[i].leafs[j] = find_leaf(retval, list_orig->unique[i].leafs[j]->name, 0);
1497 }
1498 }
1499 }
Radek Krejci00768f42015-06-18 17:04:04 +02001500 list->when = ly_when_dup(ctx, list_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001501 break;
1502
1503 case LY_NODE_ANYXML:
1504 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci0bd5db42015-06-19 13:30:07 +02001505 anyxml->must = ly_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02001506 anyxml->when = ly_when_dup(ctx, anyxml_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001507 break;
1508
1509 case LY_NODE_USES:
1510 uses->grp = uses_orig->grp;
Radek Krejci00768f42015-06-18 17:04:04 +02001511 uses->when = ly_when_dup(ctx, uses_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001512 uses->refine_size = uses_orig->refine_size;
1513 uses->refine = ly_refine_dup(ctx, uses_orig->refine, uses_orig->refine_size);
1514 uses->augment_size = uses_orig->augment_size;
1515 uses->augment = ly_augment_dup(module, (struct ly_mnode *)uses, uses_orig->augment, uses_orig->augment_size);
1516 if (resolve_uses(uses, line)) {
1517 goto error;
1518 }
1519 break;
1520
1521 case LY_NODE_CASE:
Radek Krejci00768f42015-06-18 17:04:04 +02001522 cs->when = ly_when_dup(ctx, cs_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001523 break;
1524
Michal Vasko0ea41032015-06-16 08:53:55 +02001525 case LY_NODE_GROUPING:
Michal Vasko38d01f72015-06-15 09:41:06 +02001526 case LY_NODE_RPC:
Michal Vasko38d01f72015-06-15 09:41:06 +02001527 case LY_NODE_INPUT:
1528 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001529 case LY_NODE_NOTIF:
1530 mix->tpdf_size = mix_orig->tpdf_size;
1531 mix->tpdf = ly_tpdf_dup(ctx, mix_orig->tpdf, mix->tpdf_size);
Radek Krejcia01e5432015-06-16 10:35:25 +02001532 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001533
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001534 default:
Radek Krejci00768f42015-06-18 17:04:04 +02001535 /* LY_NODE_AUGMENT */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001536 goto error;
1537 }
1538
1539 return retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001540
1541error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001542 LOGDBG("error: %s:%d", __FILE__, __LINE__);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001543
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001544 ly_mnode_free(retval);
1545 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001546}
1547
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001548API void
1549ly_module_free(struct ly_module *module)
Radek Krejciefaeba32015-05-27 14:30:57 +02001550{
Radek Krejcidce51452015-06-16 15:20:08 +02001551 struct ly_ctx *ctx;
1552 int i;
1553
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001554 if (!module) {
1555 return;
1556 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001557
Radek Krejcidce51452015-06-16 15:20:08 +02001558 /* remove schema from the context */
1559 ctx = module->ctx;
1560 if (ctx->models.used) {
1561 for (i = 0; i < ctx->models.used; i++) {
1562 if (ctx->models.list[i] == module) {
1563 /* replace the position in the list by the last module in the list */
1564 ctx->models.used--;
1565 ctx->models.list[i] = ctx->models.list[ctx->models.used];
1566 ctx->models.list[ctx->models.used] = NULL;
1567 /* we are done */
1568 break;
1569 }
1570 }
1571 }
1572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001573 /* common part with struct ly_submodule */
1574 module_free_common(module);
Radek Krejciefaeba32015-05-27 14:30:57 +02001575
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001576 /* specific items to free */
1577 lydict_remove(module->ctx, module->ns);
1578 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02001579
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001580 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001581}
Radek Krejci7e97c352015-06-19 16:26:34 +02001582
1583/*
1584 * op: 1 - enable, 0 - disable
1585 */
1586static int
1587ly_features_change(struct ly_module *module, const char *name, int op)
1588{
1589 int all = 0;
1590 int i, j, k;
1591
1592 if (!module || !name || !strlen(name)) {
1593 return EXIT_FAILURE;
1594 }
1595
1596 if (!strcmp(name, "*")) {
1597 /* enable all */
1598 all = 1;
1599 }
1600
1601 /* module itself */
1602 for (i = 0; i < module->features_size; i++) {
1603 if (all || !strcmp(module->features[i].name, name)) {
1604 if (op) {
1605 module->features[i].flags |= LY_NODE_FENABLED;
1606 /* enable referenced features (recursion) */
1607 for (k = 0; k < module->features[i].features_size; k++) {
1608 ly_features_change(module->features[i].features[k]->module,
1609 module->features[i].features[k]->name, op);
1610 }
1611 } else {
1612 module->features[i].flags &= ~LY_NODE_FENABLED;
1613 }
1614 if (!all) {
1615 return EXIT_SUCCESS;
1616 }
1617 }
1618 }
1619
1620 /* submodules */
1621 for (j = 0; j < module->inc_size; j++) {
1622 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
1623 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
1624 if (op) {
1625 module->inc[j].submodule->features[i].flags |= LY_NODE_FENABLED;
1626 } else {
1627 module->inc[j].submodule->features[i].flags &= ~LY_NODE_FENABLED;
1628 }
1629 if (!all) {
1630 return EXIT_SUCCESS;
1631 }
1632 }
1633 }
1634 }
1635
1636 if (all) {
1637 return EXIT_SUCCESS;
1638 } else {
1639 return EXIT_FAILURE;
1640 }
1641}
1642
1643API int
1644ly_features_enable(struct ly_module *module, const char *name)
1645{
1646 return ly_features_change(module, name, 1);
1647}
1648
1649API int
1650ly_features_disable(struct ly_module *module, const char *name)
1651{
Michal Vasko4c5989d2015-07-07 11:32:55 +02001652 return ly_features_change(module, name, 0);
Radek Krejci7e97c352015-06-19 16:26:34 +02001653}
Michal Vasko2367e7c2015-07-07 11:33:44 +02001654
1655API char **
1656ly_get_features(struct ly_module *module, char ***enable_state)
1657{
1658 int i, j;
1659 char **result = NULL;
1660 unsigned int count;
1661
1662 if (!module) {
1663 return NULL;
1664 }
1665
1666 count = module->features_size;
1667 for (i = 0; i < module->inc_size; i++) {
1668 count += module->inc[i].submodule->features_size;
1669 }
1670 result = malloc((count+1) * sizeof *result);
1671 if (enable_state) {
1672 *enable_state = malloc((count+1) * sizeof **enable_state);
1673 }
1674
1675 count = 0;
1676
1677 /* module itself */
1678 for (i = 0; i < module->features_size; i++) {
1679 result[count] = strdup(module->features[i].name);
1680 if (enable_state) {
1681 if (module->features[i].flags & LY_NODE_FENABLED) {
1682 (*enable_state)[count] = strdup("on");
1683 } else {
1684 (*enable_state)[count] = strdup("off");
1685 }
1686 }
1687 ++count;
1688 }
1689
1690 /* submodules */
1691 for (j = 0; j < module->inc_size; j++) {
1692 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
1693 result[count] = strdup(module->inc[j].submodule->features[i].name);
1694 if (enable_state) {
1695 if (module->inc[j].submodule->features[i].flags & LY_NODE_FENABLED) {
1696 (*enable_state)[count] = strdup("on");
1697 } else {
1698 (*enable_state)[count] = strdup("off");
1699 }
1700 }
1701 ++count;
1702 }
1703 }
1704
1705 result[count] = NULL;
1706 if (enable_state) {
1707 (*enable_state)[count] = NULL;
1708 }
1709
1710 return result;
1711}
Radek Krejcib20c62d2015-07-07 17:07:14 +02001712
1713API struct lyd_node *
1714ly_data_read(struct ly_ctx *ctx, const char *data, LY_DFORMAT format)
1715{
1716 if (!ctx || !data) {
1717 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1718 return NULL;
1719 }
1720
1721 switch (format) {
1722 case LY_XML:
1723 return xml_read_data(ctx, data);
1724 case LY_JSON:
1725 default:
1726 /* TODO */
1727 return NULL;
1728 }
1729
1730 return NULL;
1731}
1732
1733API void
1734lyd_node_free(struct lyd_node *node)
1735{
1736 struct lyd_node *next, *child;
1737
Radek Krejcie4748472015-07-08 18:00:22 +02001738 if (!(node->schema->nodetype & (LY_NODE_LEAF | LY_NODE_LEAFLIST))) {
1739 /* free children */
1740 LY_TREE_FOR_SAFE(node->child, next, child) {
1741 lyd_node_free(child);
1742 }
1743 } else {
1744 /* free value */
1745 switch(((struct lyd_node_leaf *)node)->value_type) {
1746 case LY_TYPE_BINARY:
1747 case LY_TYPE_STRING:
1748 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf *)node)->value.string);
1749 break;
Radek Krejci3e3affe2015-07-09 15:38:40 +02001750 case LY_TYPE_BITS:
1751 if (((struct lyd_node_leaf *)node)->value.bit) {
1752 free(((struct lyd_node_leaf *)node)->value.bit);
1753 }
1754 break;
Radek Krejcie4748472015-07-08 18:00:22 +02001755 default:
1756 /* TODO */
1757 break;
1758 }
Radek Krejcib20c62d2015-07-07 17:07:14 +02001759 }
1760
1761 if (node->prev->next) {
1762 node->prev->next = node->next;
1763 } else if (node->parent) {
1764 /* first node */
1765 node->parent->child = node->next;
1766 }
1767 if (node->next) {
1768 node->next->prev = node->prev;
1769 }
1770
1771 free(node);
1772}