blob: b2b45558fc26cb3bc279d1cf0172fa8c27023831 [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 Krejci5a988152015-07-15 11:16:26 +020023#include <ctype.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020024#include <stdlib.h>
25#include <sys/mman.h>
26#include <sys/stat.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020027#include <string.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020028
29#include "common.h"
30#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020031#include "parser.h"
Radek Krejci106efc02015-06-10 14:36:27 +020032#include "xml.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020033#include "tree_internal.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020034
35void ly_submodule_free(struct ly_submodule *submodule);
36
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020037struct ly_mnode_leaf *
38find_leaf(struct ly_mnode *parent, const char *name, int len)
Radek Krejci8bc9ca02015-06-04 15:52:46 +020039{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020040 struct ly_mnode *child;
41 struct ly_mnode_leaf *result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +020042
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020043 if (!len) {
44 len = strlen(name);
45 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +020046
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020047 LY_TREE_FOR(parent->child, child) {
48 switch (child->nodetype) {
49 case LY_NODE_LEAF:
50 /* direct check */
51 if (child->name == name || (!strncmp(child->name, name, len) && !child->name[len])) {
52 return (struct ly_mnode_leaf *)child;
53 }
54 break;
55 case LY_NODE_USES:
56 /* search recursively */
57 result = find_leaf(child, name, len);
58 if (result) {
59 return result;
60 }
61 break;
62 default:
63 /* ignore */
64 break;
65 }
66 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +020067
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020068 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +020069}
Radek Krejcida04f4a2015-05-21 12:54:09 +020070
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020071void
72ly_mnode_unlink(struct ly_mnode *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +020073{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020074 struct ly_mnode *parent, *first;
Radek Krejcida04f4a2015-05-21 12:54:09 +020075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020076 if (!node) {
77 return;
78 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020079
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020080 /* unlink from data model if necessary */
81 if (node->module) {
82 if (node->module->data == node) {
83 node->module->data = node->next;
Radek Krejci21181962015-06-30 14:11:00 +020084 } else if (node->module->rpc == node) {
85 node->module->rpc = node->next;
86 } else if (node->module->notif == node) {
87 node->module->notif = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020088 }
89 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020090
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020091 /* store pointers to important nodes */
92 parent = node->parent;
93 if (parent && !parent->nodetype) {
94 /* handle augments - first, unlink it from the augment parent ... */
95 if (parent->child == node) {
96 parent->child = node->next;
97 }
98 /* and then continue with the target parent */
99 parent = ((struct ly_augment *)parent)->target;
100 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200101
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200102 /* unlink from parent */
103 if (parent) {
104 if (parent->child == node) {
105 parent->child = node->next;
106 }
107 node->parent = NULL;
108 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200109
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200110 /* unlink from siblings */
111 if (node->prev == node) {
112 /* there are no more siblings */
113 return;
114 }
115 if (node->next) {
116 node->next->prev = node->prev;
117 } else {
118 /* unlinking the last element */
119 if (parent) {
120 first = parent->child;
121 } else {
122 first = node;
123 while (node->prev->next) {
124 first = node->prev;
125 }
126 }
127 first->prev = node->prev;
128 }
129 if (node->prev->next) {
130 node->prev->next = node->next;
131 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200132
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200133 /* clean up the unlinked element */
134 node->next = NULL;
135 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200136}
137
138/*
139 * Add child model node at the end of the parent's child list.
140 * If the child is connected somewhere (has a parent), it is completely
141 * unlinked and none of the following conditions applies.
142 * If the child has prev sibling(s), they are ignored (child is added at the
143 * end of the child list).
144 * If the child has next sibling(s), all of them are connected with the parent.
145 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200146int
147ly_mnode_addchild(struct ly_mnode *parent, struct ly_mnode *child)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200148{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200149 struct ly_mnode *last;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200150
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200151 assert(parent);
152 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200154 /* checks */
155 switch (parent->nodetype) {
156 case LY_NODE_CONTAINER:
157 case LY_NODE_LIST:
158 case LY_NODE_GROUPING:
159 case LY_NODE_USES:
Michal Vasko38d01f72015-06-15 09:41:06 +0200160 case LY_NODE_INPUT:
161 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +0200162 case LY_NODE_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200163 if (!(child->nodetype &
164 (LY_NODE_ANYXML | LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_GROUPING | LY_NODE_LEAF |
165 LY_NODE_LEAFLIST | LY_NODE_LIST | LY_NODE_USES))) {
166 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
167 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
168 return EXIT_FAILURE;
169 }
170 break;
171 case LY_NODE_CHOICE:
172 if (!(child->nodetype &
173 (LY_NODE_ANYXML | LY_NODE_CASE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST))) {
174 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"choice\" %s.",
175 strnodetype(child->nodetype), parent->name);
176 return EXIT_FAILURE;
177 }
178 break;
179 case LY_NODE_CASE:
180 if (!(child->nodetype &
181 (LY_NODE_ANYXML | LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST | LY_NODE_USES))) {
182 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"case\" %s.",
183 strnodetype(child->nodetype), parent->name);
184 return EXIT_FAILURE;
185 }
186 break;
Michal Vasko38d01f72015-06-15 09:41:06 +0200187 case LY_NODE_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200188 if (!(child->nodetype & (LY_NODE_INPUT | LY_NODE_OUTPUT | LY_NODE_GROUPING))) {
Michal Vasko38d01f72015-06-15 09:41:06 +0200189 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"rpc\" %s.",
190 strnodetype(child->nodetype), parent->name);
191 return EXIT_FAILURE;
192 }
193 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200194 case LY_NODE_LEAF:
195 case LY_NODE_LEAFLIST:
196 case LY_NODE_ANYXML:
197 LOGVAL(VE_SPEC, 0, "The \"%s\" statement (%s) cannot have any substatement.",
198 strnodetype(parent->nodetype), parent->name);
199 return EXIT_FAILURE;
200 case LY_NODE_AUGMENT:
201 LOGVAL(VE_SPEC, 0, "Internal error (%s:%d)", __FILE__, __LINE__);
202 return EXIT_FAILURE;
203 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200204
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200205 if (child->parent) {
206 ly_mnode_unlink(child);
207 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200208
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200209 if (!parent->child) {
210 /* the only/first child of the parent */
211 parent->child = child;
212 child->parent = parent;
213 last = child;
214 } else {
215 /* add a new child at the end of parent's child list */
216 last = parent->child->prev;
217 last->next = child;
218 child->prev = last;
219 }
220 while (last->next) {
221 last = last->next;
222 last->parent = parent;
223 }
224 parent->child->prev = last;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200225
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200226 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200227}
228
Michal Vaskodb7f2292015-07-02 11:52:13 +0200229static struct ly_module *
230find_import_in_includes_recursive(struct ly_module *mod, const char *prefix, uint32_t pref_len)
231{
232 int i, j;
233 struct ly_submodule *sub_mod;
234 struct ly_module *ret;
235
236 for (i = 0; i < mod->inc_size; i++) {
237 sub_mod = mod->inc[i].submodule;
238 for (j = 0; j < sub_mod->imp_size; j++) {
239 if ((pref_len == strlen(sub_mod->imp[j].prefix))
240 && !strncmp(sub_mod->imp[j].prefix, prefix, pref_len)) {
241 return sub_mod->imp[j].module;
242 }
243 }
244 }
245
246 for (i = 0; i < mod->inc_size; i++) {
247 ret = find_import_in_includes_recursive((struct ly_module *)mod->inc[i].submodule, prefix, pref_len);
248 if (ret) {
249 return ret;
250 }
251 }
252
253 return NULL;
254}
255
256static struct ly_module *
Radek Krejci5a988152015-07-15 11:16:26 +0200257find_prefixed_module(struct ly_module *mod, const char *prefix, uint32_t pref_len)
Michal Vaskodb7f2292015-07-02 11:52:13 +0200258{
259 int i;
260
Radek Krejci5a988152015-07-15 11:16:26 +0200261 /* module itself */
262 if (!strncmp(mod->prefix, prefix, pref_len) && mod->prefix[pref_len] == '\0') {
263 return mod;
264 }
265
266 /* imported modules */
Michal Vaskodb7f2292015-07-02 11:52:13 +0200267 for (i = 0; i < mod->imp_size; i++) {
Radek Krejci5a988152015-07-15 11:16:26 +0200268 if (!strncmp(mod->imp[i].prefix, prefix, pref_len) && mod->imp[i].prefix[pref_len] == '\0') {
Michal Vaskodb7f2292015-07-02 11:52:13 +0200269 return mod->imp[i].module;
270 }
271 }
272
Radek Krejci5a988152015-07-15 11:16:26 +0200273 /* imports in includes */
Michal Vaskodb7f2292015-07-02 11:52:13 +0200274 return find_import_in_includes_recursive(mod, prefix, pref_len);
275}
276
Radek Krejci3bde87f2015-06-05 16:51:58 +0200277/*
Michal Vasko25880b42015-06-12 10:16:33 +0200278 * id - schema-nodeid
Michal Vasko6f6ac232015-06-18 11:11:46 +0200279 *
280 * node_type - LY_NODE_AUGMENT (searches also RPCs and notifications)
Michal Vaskodb7f2292015-07-02 11:52:13 +0200281 * - LY_NODE_USES (only descendant-schema-nodeid allowed, ".." not allowed)
Michal Vasko6f6ac232015-06-18 11:11:46 +0200282 * - LY_NODE_CHOICE (search only start->child, only descendant-schema-nodeid allowed)
Radek Krejci3bde87f2015-06-05 16:51:58 +0200283 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200284struct ly_mnode *
Michal Vasko6f6ac232015-06-18 11:11:46 +0200285resolve_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 +0200286{
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200287 const char *name, *prefix, *ptr;
Michal Vaskoaf989e62015-06-29 14:57:45 +0200288 struct ly_mnode *sibling;
Michal Vaskodb7f2292015-07-02 11:52:13 +0200289 uint32_t nam_len, pref_len;
290 struct ly_module *prefix_mod, *start_mod;
291 /* 0 - in module, 1 - in 1st submodule, 2 - in 2nd submodule, ... */
292 uint8_t in_submod = 0;
293 /* 0 - in data, 1 - in RPCs, 2 - in notifications (relevant only with LY_NODE_AUGMENT) */
294 uint8_t in_mod_part = 0;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200295
Radek Krejcif5be10f2015-06-16 13:29:36 +0200296 assert(mod);
297 assert(id);
298
Michal Vasko92f4b2e2015-07-03 14:19:49 +0200299 if (id[strlen(id)-1] == '/') {
300 LOGERR(LY_EINVAL, "%s: Path ending with '/' is not valid.", __func__);
301 return NULL;
302 }
303
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200304 if (id[0] == '/') {
Michal Vasko6f6ac232015-06-18 11:11:46 +0200305 if (node_type & (LY_NODE_USES | LY_NODE_CHOICE)) {
306 return NULL;
307 }
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200308 ptr = strchr(id+1, '/');
309 prefix = id+1;
310 } else {
311 ptr = strchr(id, '/');
312 prefix = id;
313 }
314 pref_len = (ptr ? (unsigned)(ptr-prefix) : strlen(prefix));
Radek Krejci3bde87f2015-06-05 16:51:58 +0200315
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200316 ptr = strnchr(prefix, ':', pref_len);
Michal Vaskodb7f2292015-07-02 11:52:13 +0200317 /* there is a prefix */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200318 if (ptr) {
319 nam_len = (pref_len-(ptr-prefix))-1;
320 pref_len = ptr-prefix;
321 name = ptr+1;
322
323 /* no prefix used */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200324 } else {
325 name = prefix;
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200326 nam_len = pref_len;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200327 prefix = NULL;
328 }
Michal Vasko25880b42015-06-12 10:16:33 +0200329
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200330 /* absolute-schema-nodeid */
331 if (id[0] == '/') {
Michal Vaskodb7f2292015-07-02 11:52:13 +0200332 if (prefix) {
Radek Krejci5a988152015-07-15 11:16:26 +0200333 start_mod = find_prefixed_module(mod, prefix, pref_len);
Michal Vaskodb7f2292015-07-02 11:52:13 +0200334 if (!start_mod) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200335 return NULL;
336 }
Michal Vaskodb7f2292015-07-02 11:52:13 +0200337 start = start_mod->data;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200338 } else {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200339 start = mod->data;
Michal Vaskodb7f2292015-07-02 11:52:13 +0200340 start_mod = mod;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200341 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200342 /* descendant-schema-nodeid */
Radek Krejcif5be10f2015-06-16 13:29:36 +0200343 } else {
344 assert(start);
345 start = start->child;
Michal Vaskodb7f2292015-07-02 11:52:13 +0200346 start_mod = start->module;
Radek Krejcif5be10f2015-06-16 13:29:36 +0200347 }
348
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200349 while (1) {
350 if (!strcmp(name, ".")) {
351 /* this node - start does not change */
352 } else if (!strcmp(name, "..")) {
Michal Vaskoaf989e62015-06-29 14:57:45 +0200353 /* ".." is not allowed in refines and augments in uses, there is no need for it there */
Michal Vasko6f6ac232015-06-18 11:11:46 +0200354 if (!start || (node_type == LY_NODE_USES)) {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200355 return NULL;
356 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200357 start = start->parent;
358 } else {
Radek Krejcif5be10f2015-06-16 13:29:36 +0200359 sibling = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200360 LY_TREE_FOR(start, sibling) {
Michal Vaskodb7f2292015-07-02 11:52:13 +0200361 /* name match */
Michal Vasko69b42912015-07-03 13:43:15 +0200362 if ((sibling->name && !strncmp(name, sibling->name, nam_len) && (strlen(sibling->name) == nam_len))
363 || (!strncmp(name, "input", 5) && (nam_len == 5) && (sibling->nodetype == LY_NODE_INPUT))
364 || (!strncmp(name, "output", 6) && (nam_len == 6) && (sibling->nodetype == LY_NODE_OUTPUT))) {
Michal Vasko25880b42015-06-12 10:16:33 +0200365
Michal Vaskodb7f2292015-07-02 11:52:13 +0200366 /* prefix match check */
367 if (prefix) {
368
Radek Krejci5a988152015-07-15 11:16:26 +0200369 prefix_mod = find_prefixed_module(mod, prefix, pref_len);
Michal Vaskodb7f2292015-07-02 11:52:13 +0200370 if (!prefix_mod) {
Michal Vasko6f6ac232015-06-18 11:11:46 +0200371 return NULL;
372 }
373
Radek Krejcia7f4a0e2015-07-02 19:13:35 +0200374 if (!sibling->module->type) {
375 if (prefix_mod != sibling->module) {
376 continue;
377 }
378 } else {
379 if (prefix_mod != ((struct ly_submodule *)sibling->module)->belongsto) {
380 continue;
381 }
Michal Vasko25880b42015-06-12 10:16:33 +0200382 }
383 }
384
385 /* the result node? */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200386 ptr = name+nam_len;
387 if (!ptr[0]) {
Michal Vasko25880b42015-06-12 10:16:33 +0200388 return sibling;
389 }
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200390 assert(ptr[0] == '/');
Michal Vasko25880b42015-06-12 10:16:33 +0200391
392 /* check for shorthand cases - then 'start' does not change */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200393 if (!sibling->parent || (sibling->parent->nodetype != LY_NODE_CHOICE)
394 || (sibling->nodetype == LY_NODE_CASE)) {
Michal Vasko25880b42015-06-12 10:16:33 +0200395 start = sibling->child;
396 }
397 break;
398 }
399 }
Radek Krejcif5be10f2015-06-16 13:29:36 +0200400
Michal Vasko6f6ac232015-06-18 11:11:46 +0200401 /* we did not find the case in direct siblings */
402 if (node_type == LY_NODE_CHOICE) {
403 return NULL;
404 }
405
Michal Vasko25880b42015-06-12 10:16:33 +0200406 /* no match */
407 if (!sibling) {
Michal Vasko6f6ac232015-06-18 11:11:46 +0200408 /* on augment search also RPCs and notifications, if we are in top-level */
Michal Vaskoaf989e62015-06-29 14:57:45 +0200409 if ((node_type == LY_NODE_AUGMENT) && (!start || !start->parent)) {
Michal Vasko6f6ac232015-06-18 11:11:46 +0200410 /* we have searched all the data nodes */
Michal Vaskoaf989e62015-06-29 14:57:45 +0200411 if (in_mod_part == 0) {
412 if (!in_submod) {
Michal Vaskodb7f2292015-07-02 11:52:13 +0200413 start = start_mod->rpc;
Michal Vaskoaf989e62015-06-29 14:57:45 +0200414 } else {
Michal Vaskodb7f2292015-07-02 11:52:13 +0200415 start = start_mod->inc[in_submod-1].submodule->rpc;
Michal Vasko6f6ac232015-06-18 11:11:46 +0200416 }
Michal Vaskoaf989e62015-06-29 14:57:45 +0200417 in_mod_part = 1;
418 continue;
Michal Vasko6f6ac232015-06-18 11:11:46 +0200419 }
420 /* we have searched all the RPCs */
Michal Vaskoaf989e62015-06-29 14:57:45 +0200421 if (in_mod_part == 1) {
422 if (!in_submod) {
Michal Vaskodb7f2292015-07-02 11:52:13 +0200423 start = start_mod->notif;
Michal Vaskoaf989e62015-06-29 14:57:45 +0200424 } else {
Michal Vaskodb7f2292015-07-02 11:52:13 +0200425 start = start_mod->inc[in_submod-1].submodule->notif;
Michal Vasko6f6ac232015-06-18 11:11:46 +0200426 }
Michal Vaskoaf989e62015-06-29 14:57:45 +0200427 in_mod_part = 2;
428 continue;
Michal Vasko6f6ac232015-06-18 11:11:46 +0200429 }
Michal Vaskoaf989e62015-06-29 14:57:45 +0200430 /* we have searched all the notifications, nothing else to search in this module */
431 }
432
433 /* are we done with the included submodules as well? */
Michal Vaskodb7f2292015-07-02 11:52:13 +0200434 if (in_submod == start_mod->inc_size) {
Michal Vasko86b84452015-06-22 10:54:05 +0200435 return NULL;
Michal Vasko6f6ac232015-06-18 11:11:46 +0200436 }
Michal Vaskoaf989e62015-06-29 14:57:45 +0200437
438 /* we aren't, check the next one */
439 ++in_submod;
440 in_mod_part = 0;
Michal Vaskodb7f2292015-07-02 11:52:13 +0200441 start = start_mod->inc[in_submod-1].submodule->data;
Michal Vaskoaf989e62015-06-29 14:57:45 +0200442 continue;
Michal Vasko25880b42015-06-12 10:16:33 +0200443 }
444 }
445
Michal Vasko3bf80ca2015-07-02 17:19:28 +0200446 /* we found our submodule */
447 if (in_submod) {
448 start_mod = (struct ly_module *)start_mod->inc[in_submod-1].submodule;
449 in_submod = 0;
450 }
Michal Vaskodb7f2292015-07-02 11:52:13 +0200451
Michal Vaskoa158c682015-06-17 09:25:38 +0200452 assert((*(name+nam_len) == '/') || (*(name+nam_len) == '\0'));
453
454 /* make prefix point to the next node name */
455 prefix = name+nam_len;
Michal Vaskoa158c682015-06-17 09:25:38 +0200456 ++prefix;
Michal Vasko92f4b2e2015-07-03 14:19:49 +0200457 assert(prefix[0]);
Michal Vaskoa158c682015-06-17 09:25:38 +0200458
459 /* parse prefix and node name */
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200460 ptr = strchr(prefix, '/');
461 pref_len = (ptr ? (unsigned)(ptr-prefix) : strlen(prefix));
462 ptr = strnchr(prefix, ':', pref_len);
463
464 /* there is prefix */
465 if (ptr) {
Michal Vaskoa158c682015-06-17 09:25:38 +0200466 nam_len = (pref_len-(ptr-prefix))-1;
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200467 pref_len = ptr-prefix;
468 name = ptr+1;
469
470 /* no prefix used */
Michal Vasko25880b42015-06-12 10:16:33 +0200471 } else {
472 name = prefix;
Michal Vaskoa7d0be62015-06-16 10:43:49 +0200473 nam_len = pref_len;
Michal Vasko25880b42015-06-12 10:16:33 +0200474 prefix = NULL;
475 }
Michal Vasko25880b42015-06-12 10:16:33 +0200476 }
477
478 /* cannot get here */
479 return NULL;
Radek Krejci3bde87f2015-06-05 16:51:58 +0200480}
481
Radek Krejci5a988152015-07-15 11:16:26 +0200482static int
483is_identifier(char start, char c)
484{
485 if (start == c) {
486 /* first letter */
487 if (isalpha(start) || c == '_') {
488 return 1;
489 }
490 } else {
491 /* checking inner letter */
492 if (isalnum(c) || c == '_' || c == '-' || c == '.') {
493 return 1;
494 }
495 }
496 return 0;
497}
498
499static int
500match_data_nodeid(const char *id, struct lyd_node *data, struct lyd_node *parent, struct lyd_node **result)
501{
502 int i = 0, j;
503 const char *name;
504 struct ly_module *mod;
505 struct lyd_node *node, *start;
506
507 *result = NULL;
508
509 /* [prefix:]identifier */
510 name = id;
511 while(is_identifier(name[0], name[i])) {
512 i++;
513 }
514 if (name[i] == ':') {
515 /* we have prefix, find appropriate module */
516 if (!i) {
517 /* syntax error */
518 return 0;
519 }
520
521 mod = find_prefixed_module(data->schema->module, name, i);
522 if (!mod) {
523 /* invalid prefix */
524 return 0;
525 }
526
527 /* now get the identifier */
528 name = &id[i + 1];
529 j = 0;
530 while(is_identifier(name[0], name[j])) {
531 j++;
532 }
533 if (!j) {
534 i = 0;
535 }
536 } else {
537 /* no prefix, module is the same as of current node */
538 mod = data->schema->module;
539 j = i;
540 }
541 if (!i) {
542 /* syntax error */
543 return 0;
544 }
545
546 if (parent) {
547 start = parent->child;
548 } else {
549 /* get data root */
550 for (start = data; start->parent; start = start->parent);
551 }
552 LY_TREE_FOR(start, node) {
553 if (node->schema->module == mod && !strncmp(node->schema->name, name, j)) {
554 /* matching target */
555 *result = node;
556 break;
557 }
558 }
559
560 if (!*result) {
561 return 0;
562 }
563
564 return i;
565}
566
567/* return number of processed bytes in id */
568static int
Michal Vasko493bea72015-07-16 16:08:12 +0200569resolve_data_nodeid(const char *id, struct lyd_node *data, struct leafref_instid **parents)
Radek Krejci5a988152015-07-15 11:16:26 +0200570{
571 int i = 0, j, flag;
572 struct ly_module *mod;
573 const char *name;
Michal Vasko493bea72015-07-16 16:08:12 +0200574 struct leafref_instid *item, *par_iter;
Radek Krejci5a988152015-07-15 11:16:26 +0200575 struct lyd_node *node, *root = NULL;
576
577 /* [prefix:]identifier */
578 name = id;
579 while(is_identifier(name[0], name[i])) {
580 i++;
581 }
582 if (name[i] == ':') {
583 /* we have prefix, find appropriate module */
584 if (!i) {
585 /* syntax error */
586 return 0;
587 }
588
589 mod = find_prefixed_module(data->schema->module, name, i);
590 if (!mod) {
591 /* invalid prefix */
592 return 0;
593 }
594
595 /* now get the identifier */
596 name = &id[++i];
597 j = 0;
598 while(is_identifier(name[0], name[j])) {
599 j++;
600 }
601 if (!j) {
602 i = 0;
603 } else {
604 i += j;
605 }
606 } else {
607 /* no prefix, module is the same as of current node */
608 mod = data->schema->module;
609 j = i;
610 }
611 if (!i) {
612 /* syntax error */
613 return 0;
614 }
615
616 if (!*parents) {
617 *parents = malloc(sizeof **parents);
Michal Vasko493bea72015-07-16 16:08:12 +0200618 (*parents)->dnode = NULL;
Radek Krejci5a988152015-07-15 11:16:26 +0200619 (*parents)->next = NULL;
620
621 /* find root data element */
622 for (root = data; root->parent; root = root->parent);
Michal Vasko493bea72015-07-16 16:08:12 +0200623 /* make sure it's first */
624 for (; root->prev->next; root = root->prev);
Radek Krejci5a988152015-07-15 11:16:26 +0200625 }
626 for (par_iter = *parents; par_iter; par_iter = par_iter->next) {
Michal Vasko493bea72015-07-16 16:08:12 +0200627 if (par_iter->dnode && (par_iter->dnode->schema->nodetype & (LY_NODE_LEAF | LY_NODE_LEAFLIST))) {
Radek Krejci5a988152015-07-15 11:16:26 +0200628 /* skip */
629 continue;
630 }
631 flag = 0;
Michal Vasko493bea72015-07-16 16:08:12 +0200632 LY_TREE_FOR(par_iter->dnode ? par_iter->dnode->child : root, node) {
Radek Krejci5a988152015-07-15 11:16:26 +0200633 if (node->schema->module == mod && !strncmp(node->schema->name, name, j)) {
634 /* matching target */
635 if (!flag) {
636 /* replace leafref instead of the current parent */
Michal Vasko493bea72015-07-16 16:08:12 +0200637 par_iter->dnode = node;
Radek Krejci5a988152015-07-15 11:16:26 +0200638 flag = 1;
639 } else {
640 /* multiple matching, so create new leafref structure */
641 item = malloc(sizeof *item);
Michal Vasko493bea72015-07-16 16:08:12 +0200642 item->dnode = node;
Michal Vasko63ee3d42015-07-17 10:30:50 +0200643 item->next = par_iter->next;
644 par_iter->next = item;
645 par_iter = par_iter->next;
Radek Krejci5a988152015-07-15 11:16:26 +0200646 }
647 }
648 }
649 }
650
651 return i;
652}
653
Michal Vasko3f1098b2015-07-20 15:16:43 +0200654int
655resolve_path(struct lyd_node *data, const char *path, struct leafref_instid **ret)
Radek Krejci5a988152015-07-15 11:16:26 +0200656{
Michal Vasko3f1098b2015-07-20 15:16:43 +0200657 struct leafref_instid *riter = NULL, *raux;
Radek Krejci5a988152015-07-15 11:16:26 +0200658 struct ly_mnode_leaf *schema = (struct ly_mnode_leaf *)data->schema;
659 struct lyd_node *pathnode = NULL;
660 int i, j;
661 char *p = strdup(path);
662 char *name;
663 struct lyd_node *pred_source, *pred_target;
Michal Vasko3f1098b2015-07-20 15:16:43 +0200664 *ret = NULL;
Radek Krejci5a988152015-07-15 11:16:26 +0200665
666 i = 0;
667 if (p[0] == '/') {
668 /* absolute path, start with '/' */
669 i = 0;
670
671 } else {
Michal Vasko3f1098b2015-07-20 15:16:43 +0200672 *ret = calloc(1, sizeof **ret);
Radek Krejci5a988152015-07-15 11:16:26 +0200673 while(!strncmp(&p[i], "../", 3)) {
674 /* relative path */
675 i += 3;
Michal Vasko3f1098b2015-07-20 15:16:43 +0200676 if (!*ret) {
Radek Krejci5a988152015-07-15 11:16:26 +0200677 /* error, too many .. */
678 LOGVAL(DE_INVAL, 0, p, schema->name);
679 goto error;
Michal Vasko3f1098b2015-07-20 15:16:43 +0200680 } else if (!(*ret)->dnode) {
Radek Krejci5a988152015-07-15 11:16:26 +0200681 /* first .. */
Michal Vasko3f1098b2015-07-20 15:16:43 +0200682 (*ret)->dnode = data->parent;
683 } else if (!(*ret)->dnode->parent) {
Radek Krejci5a988152015-07-15 11:16:26 +0200684 /* we are in root */
Michal Vasko3f1098b2015-07-20 15:16:43 +0200685 free(*ret);
686 *ret = NULL;
Radek Krejci5a988152015-07-15 11:16:26 +0200687 } else {
688 /* multiple .. */
Michal Vasko3f1098b2015-07-20 15:16:43 +0200689 (*ret)->dnode = (*ret)->dnode->parent;
Radek Krejci5a988152015-07-15 11:16:26 +0200690 }
691 }
692 if (!i) {
693 /* neither absolute or relative p */
694 LOGVAL(DE_INVAL, 0, p, schema->name);
695 goto error;
696 }
697 /* start with '/' */
698 i--;
699 }
700
701 /* searching for nodeset */
702 for (; p[i]; ) {
703 if (p[i] == '/') {
704 i++;
705
706 /* node identifier */
Michal Vasko3f1098b2015-07-20 15:16:43 +0200707 j = resolve_data_nodeid(&p[i], data, ret);
708 if (!j || !*ret) {
Radek Krejci5a988152015-07-15 11:16:26 +0200709 goto error;
710 }
711
712 i += j;
713 if (p[i] == '[') {
714 /* we have predicate, so the current results must be lists */
Michal Vasko3f1098b2015-07-20 15:16:43 +0200715 for (raux = NULL, riter = *ret; riter; ) {
Michal Vasko493bea72015-07-16 16:08:12 +0200716 if (riter->dnode->schema->nodetype == LY_NODE_LIST &&
717 ((struct ly_mnode_list *)riter->dnode->schema)->keys) {
Radek Krejci5a988152015-07-15 11:16:26 +0200718 /* leafref is ok, continue check with next leafref */
719 raux = riter;
720 riter = riter->next;
721 continue;
722 }
723
724 /* does not fulfill conditions, remove leafref record */
725 if (raux) {
726 raux->next = riter->next;
727 free(riter);
728 riter = raux->next;
729 } else {
Michal Vasko3f1098b2015-07-20 15:16:43 +0200730 *ret = riter->next;
Radek Krejci5a988152015-07-15 11:16:26 +0200731 free(riter);
Michal Vasko3f1098b2015-07-20 15:16:43 +0200732 riter = *ret;
Radek Krejci5a988152015-07-15 11:16:26 +0200733 }
734 }
Michal Vasko3f1098b2015-07-20 15:16:43 +0200735 if (!*ret) {
Radek Krejci5a988152015-07-15 11:16:26 +0200736 /* no matching node */
737 }
738 }
739 } else if (p[i] == '[') {
740 /* predicate */
741 i++;
742 while(isspace(p[i])) {
743 i++;
744 }
745
746 /* [prefix:]identifier */
747 name = &p[i]; /* use name later */
748 while (isalnum(p[i]) || p[i] == '_' || p[i] == '-' || p[i] == '.' || p[i] == ':') {
749 i++;
750 }
751
752 /* *WSP "=" *WSP */
753 while (isspace(p[i])) {
754 p[i] = '\0';
755 i++;
756 }
757 if (p[i] != '=') {
758 /* error */
759 }
760 p[i] = '\0';
761 i++;
762 while (isspace(p[i])) {
763 i++;
764 }
765
766 /* path-key-expr (pred_source) */
767 /* current-function-invocation */
768 if (strncmp(&p[i], "current()", 9)) {
769 /* error */
770 }
771 pred_source = data;
772 i += 9;
773 /* *WSP */
774 while (isspace(p[i])) {
775 i++;
776 }
777 /* rel-path-keyexpr */
778 while(p[i] != ']') {
779 /* "/" *WSP */
780 if (p[i] != '/') {
781 /* error */
782 }
783 i++;
784 while (isspace(p[i])) {
785 i++;
786 }
787
788 if (!strncmp("..", &p[i], 2)) {
789 /* 1*(".." *WSP */
790 i += 2;
791 while (isspace(p[i])) {
792 i++;
793 }
794 pred_source = pred_source->parent;
795 } else {
796 /* node-identifier *WSP */
797 j = match_data_nodeid(&p[i], data, pred_source, &pred_source);
798 if (!j) {
799 /* error */
800 }
801 i += j;
802 while (isspace(p[i])) {
803 i++;
804 }
805 }
806 }
807 i++;
808
809 if (pred_source == data) {
810 /* something is wrong */
811 }
812
813 /* find match between target and source nodes */
Michal Vasko3f1098b2015-07-20 15:16:43 +0200814 for (raux = NULL, riter = *ret; riter; ) {
Michal Vasko493bea72015-07-16 16:08:12 +0200815 pathnode = riter->dnode;
Radek Krejci5a988152015-07-15 11:16:26 +0200816
817 /* get target */
818 if (!match_data_nodeid(name, data, pathnode, &pred_target)) {
819 /* error */
820 }
821
822 if (pred_target->schema->nodetype != pred_source->schema->nodetype) {
823 goto remove_leafref;
824 }
825
826 if (((struct ly_mnode_leaf *)pred_target->schema)->type.base != ((struct ly_mnode_leaf *)pred_source->schema)->type.base) {
827 goto remove_leafref;
828 }
829
830 if (((struct lyd_node_leaf *)pred_target)->value_str != ((struct lyd_node_leaf *)pred_source)->value_str) {
831 goto remove_leafref;
832 }
833
834 /* leafref is ok, continue check with next leafref */
835 raux = riter;
836 riter = riter->next;
837 continue;
838
839remove_leafref:
840
841 /* does not fulfill conditions, remove leafref record */
842 if (raux) {
843 raux->next = riter->next;
844 free(riter);
845 riter = raux->next;
846 } else {
Michal Vasko3f1098b2015-07-20 15:16:43 +0200847 *ret = riter->next;
Radek Krejci5a988152015-07-15 11:16:26 +0200848 free(riter);
Michal Vasko3f1098b2015-07-20 15:16:43 +0200849 riter = *ret;
Radek Krejci5a988152015-07-15 11:16:26 +0200850 }
851 }
852 } else {
853 /* syntax error */
854 goto error;
855 }
856 }
857
858 free(p);
Michal Vasko3f1098b2015-07-20 15:16:43 +0200859 return 0;
Radek Krejci5a988152015-07-15 11:16:26 +0200860
861error:
862
863 free(p);
Michal Vasko3f1098b2015-07-20 15:16:43 +0200864 while (*ret) {
865 raux = (*ret)->next;
866 free(*ret);
867 *ret = raux;
Radek Krejci5a988152015-07-15 11:16:26 +0200868 }
869
Michal Vasko3f1098b2015-07-20 15:16:43 +0200870 return 1;
Radek Krejci5a988152015-07-15 11:16:26 +0200871}
Michal Vasko5d34dea2015-07-16 12:08:24 +0200872
Michal Vasko3f1098b2015-07-20 15:16:43 +0200873int
874resolve_instid(struct lyd_node *data, const char *path, int path_len, struct leafref_instid **ret)
Michal Vasko493bea72015-07-16 16:08:12 +0200875{
Michal Vasko3f1098b2015-07-20 15:16:43 +0200876 struct leafref_instid *riter = NULL, *raux;
Michal Vasko493bea72015-07-16 16:08:12 +0200877 struct lyd_node *pathnode = NULL;
Michal Vaskof1b9c362015-07-17 10:32:02 +0200878 int i, j, cur_idx, idx = -1;
Michal Vaskoc82396e2015-07-17 15:31:25 +0200879 char *p = strndup(path, path_len);
Michal Vaskof1b9c362015-07-17 10:32:02 +0200880 char *name, *value = NULL;
Michal Vasko493bea72015-07-16 16:08:12 +0200881 struct lyd_node *pred_target;
882
883 i = 0;
884 if (p[0] != '/') {
885 /* error */
886 }
887
888 /* searching for nodeset */
889 while (p[i]) {
890 if (p[i] == '/') {
891 i++;
892
893 /* node identifier */
Michal Vasko3f1098b2015-07-20 15:16:43 +0200894 j = resolve_data_nodeid(&p[i], data, ret);
895 if (!j || !*ret) {
Michal Vasko493bea72015-07-16 16:08:12 +0200896 goto error;
897 }
898
899 i += j;
900 if (p[i] == '[') {
Michal Vaskof1b9c362015-07-17 10:32:02 +0200901 /* we have predicate, so the current results must be list or leaf-list */
Michal Vasko3f1098b2015-07-20 15:16:43 +0200902 for (raux = NULL, riter = *ret; riter; ) {
Michal Vasko493bea72015-07-16 16:08:12 +0200903 if ((riter->dnode->schema->nodetype == LY_NODE_LIST &&
904 ((struct ly_mnode_list *)riter->dnode->schema)->keys)
905 || (riter->dnode->schema->nodetype == LY_NODE_LEAFLIST)) {
906 /* instid is ok, continue check with next instid */
907 raux = riter;
908 riter = riter->next;
909 continue;
910 }
911
912 /* does not fulfill conditions, remove inst record */
913 if (raux) {
914 raux->next = riter->next;
915 free(riter);
916 riter = raux->next;
917 } else {
Michal Vasko3f1098b2015-07-20 15:16:43 +0200918 *ret = riter->next;
Michal Vasko493bea72015-07-16 16:08:12 +0200919 free(riter);
Michal Vasko3f1098b2015-07-20 15:16:43 +0200920 riter = *ret;
Michal Vasko493bea72015-07-16 16:08:12 +0200921 }
922 }
Michal Vasko3f1098b2015-07-20 15:16:43 +0200923 if (!*ret) {
Michal Vasko493bea72015-07-16 16:08:12 +0200924 /* no matching node */
925 }
926 }
927 } else if (p[i] == '[') {
928 /* predicate */
929 i++;
930 while(isspace(p[i])) {
931 i++;
932 }
933
934 /* [prefix:]identifier */
935 name = &p[i]; /* use name later */
936 while (isalnum(p[i]) || p[i] == '_' || p[i] == '-' || p[i] == '.' || p[i] == ':') {
937 i++;
938 }
939
Michal Vaskof1b9c362015-07-17 10:32:02 +0200940 /* *WSP */
Michal Vasko493bea72015-07-16 16:08:12 +0200941 while (isspace(p[i])) {
942 p[i] = '\0';
943 i++;
944 }
Michal Vaskof1b9c362015-07-17 10:32:02 +0200945
946 /* name is position */
947 if (isdigit(name[0])) {
948 if (p[i] != ']') {
949 /* error */
950 }
951 p[i] = '\0';
952 ++i;
953 idx = atoi(name);
954 goto resolve_predicate;
955 }
956
957 /* "=" *WSP */
Michal Vasko493bea72015-07-16 16:08:12 +0200958 if (p[i] != '=') {
959 /* error */
960 }
961 p[i] = '\0';
962 i++;
963 while (isspace(p[i])) {
964 i++;
965 }
966
967 /* (DQUOTE/SQUOTE) string (DQUOTE/SQUOTE) */
968 if ((p[i] != '\"') && (p[i] != '\'')) {
969 /* error */
970 }
971
972 value = &p[i+1];
Michal Vasko8ed75302015-07-17 11:05:14 +0200973 if (!value[0]) {
974 /* error */
975 }
976
Michal Vasko493bea72015-07-16 16:08:12 +0200977 j = i;
978 i++;
979
980 while (p[j] != p[i]) {
981 if (p[i] == '\0') {
982 /* error */
983 }
984 i++;
985 }
986
987 p[i] = '\0';
988 i++;
989
990 /* *WSP */
991 while (isspace(p[i])) {
992 i++;
993 }
994
995 if (p[i] != ']') {
996 /* error */
997 }
998 i++;
999
Michal Vaskof1b9c362015-07-17 10:32:02 +02001000resolve_predicate:
1001
Michal Vasko493bea72015-07-16 16:08:12 +02001002 /* find match between target and source nodes */
Michal Vasko3f1098b2015-07-20 15:16:43 +02001003 for (cur_idx = 0, raux = NULL, riter = *ret; riter; ++cur_idx) {
Michal Vasko493bea72015-07-16 16:08:12 +02001004 pathnode = riter->dnode;
1005
1006 /* get target */
Michal Vaskof1b9c362015-07-17 10:32:02 +02001007 if (!strcmp(name, ".") || !value) {
Michal Vasko493bea72015-07-16 16:08:12 +02001008 pred_target = pathnode;
1009 } else if (!match_data_nodeid(name, data, pathnode, &pred_target)) {
1010 /* error */
1011 }
1012
1013 /* check that we have the correct type */
1014 if (!strcmp(name, ".")) {
1015 if (pathnode->schema->nodetype != LY_NODE_LEAFLIST) {
1016 goto remove_leafref;
1017 }
Michal Vaskof1b9c362015-07-17 10:32:02 +02001018 } else if (value) {
Michal Vasko493bea72015-07-16 16:08:12 +02001019 if (pathnode->schema->nodetype != LY_NODE_LIST) {
1020 goto remove_leafref;
1021 }
1022 }
1023
Michal Vaskof1b9c362015-07-17 10:32:02 +02001024 if ((value && strcmp(((struct lyd_node_leaf *)pred_target)->value_str, value)) || (!value && (idx != cur_idx))) {
Michal Vasko493bea72015-07-16 16:08:12 +02001025 goto remove_leafref;
1026 }
1027
1028 /* leafref is ok, continue check with next leafref */
1029 raux = riter;
1030 riter = riter->next;
1031 continue;
1032
1033remove_leafref:
1034
1035 /* does not fulfill conditions, remove leafref record */
1036 if (raux) {
1037 raux->next = riter->next;
1038 free(riter);
1039 riter = raux->next;
1040 } else {
Michal Vasko3f1098b2015-07-20 15:16:43 +02001041 *ret = riter->next;
Michal Vasko493bea72015-07-16 16:08:12 +02001042 free(riter);
Michal Vasko3f1098b2015-07-20 15:16:43 +02001043 riter = *ret;
Michal Vasko493bea72015-07-16 16:08:12 +02001044 }
1045 }
1046 } else {
1047 /* syntax error */
1048 goto error;
1049 }
1050 }
1051
1052 free(p);
Michal Vasko3f1098b2015-07-20 15:16:43 +02001053 return 0;
Michal Vasko493bea72015-07-16 16:08:12 +02001054
1055error:
1056
1057 free(p);
Michal Vasko3f1098b2015-07-20 15:16:43 +02001058 while (*ret) {
1059 raux = (*ret)->next;
1060 free(*ret);
1061 *ret = raux;
Michal Vasko493bea72015-07-16 16:08:12 +02001062 }
1063
Michal Vasko3f1098b2015-07-20 15:16:43 +02001064 return 1;
Michal Vasko493bea72015-07-16 16:08:12 +02001065}
1066
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001067API struct ly_module *
Radek Krejci63a91a92015-07-29 13:31:04 +02001068lys_parse(struct ly_ctx *ctx, const char *data, LY_MINFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001069{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001070 if (!ctx || !data) {
1071 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1072 return NULL;
1073 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001074
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001075 switch (format) {
1076 case LY_IN_YIN:
Radek Krejci63a91a92015-07-29 13:31:04 +02001077 return yin_read_module(ctx, data, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001078 case LY_IN_YANG:
1079 default:
1080 /* TODO */
1081 return NULL;
1082 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001083
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001084 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001085}
1086
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001087struct ly_submodule *
Michal Vaskod8aa32d2015-07-24 11:50:01 +02001088ly_submodule_read(struct ly_module *module, const char *data, LY_MINFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02001089{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001090 assert(module);
1091 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +02001092
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001093 switch (format) {
1094 case LY_IN_YIN:
Michal Vaskod8aa32d2015-07-24 11:50:01 +02001095 return yin_read_submodule(module, data, implement);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001096 case LY_IN_YANG:
1097 default:
1098 /* TODO */
1099 return NULL;
1100 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001101
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001102 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02001103}
1104
Radek Krejci63a91a92015-07-29 13:31:04 +02001105struct ly_module *
1106lys_read_import(struct ly_ctx *ctx, int fd, LY_MINFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001107{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001108 struct ly_module *module;
1109 struct stat sb;
1110 char *addr;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001111
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001112 if (!ctx || fd < 0) {
1113 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1114 return NULL;
1115 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001116
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001117 /*
1118 * TODO
1119 * This is just a temporary solution to make working automatic search for
1120 * imported modules. This doesn't work e.g. for streams (stdin)
1121 */
1122 fstat(fd, &sb);
1123 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Radek Krejci63a91a92015-07-29 13:31:04 +02001124
1125 switch (format) {
1126 case LY_IN_YIN:
1127 module = yin_read_module(ctx, addr, 0);
1128 break;
1129 case LY_IN_YANG:
1130 default:
1131 /* TODO */
1132 munmap(addr, sb.st_size);
1133 return NULL;
1134 }
1135 munmap(addr, sb.st_size);
1136
1137 return module;
1138}
1139
1140API struct ly_module *
1141lys_read(struct ly_ctx *ctx, int fd, LY_MINFORMAT format)
1142{
1143 struct ly_module *module;
1144 struct stat sb;
1145 char *addr;
1146
1147 if (!ctx || fd < 0) {
1148 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1149 return NULL;
1150 }
1151
1152 /*
1153 * TODO
1154 * This is just a temporary solution to make working automatic search for
1155 * imported modules. This doesn't work e.g. for streams (stdin)
1156 */
1157 fstat(fd, &sb);
1158 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
1159 module = lys_parse(ctx, addr, format);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001160 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001162 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001163}
1164
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001165struct ly_submodule *
Michal Vaskod8aa32d2015-07-24 11:50:01 +02001166ly_submodule_read_fd(struct ly_module *module, int fd, LY_MINFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02001167{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001168 struct ly_submodule *submodule;
1169 struct stat sb;
1170 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +02001171
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001172 assert(module);
1173 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02001174
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001175 /*
1176 * TODO
1177 * This is just a temporary solution to make working automatic search for
1178 * imported modules. This doesn't work e.g. for streams (stdin)
1179 */
1180 fstat(fd, &sb);
1181 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
1182 /* TODO addr error check */
Michal Vaskod8aa32d2015-07-24 11:50:01 +02001183 submodule = ly_submodule_read(module, addr, format, implement);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001184 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +02001185
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001186 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02001187
1188}
1189
Radek Krejci3733a802015-06-19 13:43:21 +02001190struct ly_restr *
1191ly_restr_dup(struct ly_ctx *ctx, struct ly_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001192{
Radek Krejci3733a802015-06-19 13:43:21 +02001193 struct ly_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001194 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001195
Radek Krejci3733a802015-06-19 13:43:21 +02001196 if (!size) {
1197 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001198 }
Radek Krejci3733a802015-06-19 13:43:21 +02001199
1200 result = calloc(size, sizeof *result);
1201 for (i = 0; i < size; i++) {
1202 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1203 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1204 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1205 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1206 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1207 }
1208
1209 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001210}
1211
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001212void
Radek Krejci0bd5db42015-06-19 13:30:07 +02001213ly_restr_free(struct ly_ctx *ctx, struct ly_restr *restr)
1214{
1215 assert(ctx);
1216 if (!restr) {
1217 return;
1218 }
1219
1220 lydict_remove(ctx, restr->expr);
1221 lydict_remove(ctx, restr->dsc);
1222 lydict_remove(ctx, restr->ref);
1223 lydict_remove(ctx, restr->eapptag);
1224 lydict_remove(ctx, restr->emsg);
1225}
1226
1227void
Radek Krejci3733a802015-06-19 13:43:21 +02001228ly_type_dup(struct ly_ctx *ctx, struct ly_type *new, struct ly_type *old)
1229{
1230 int i;
1231
1232 new->prefix = lydict_insert(ctx, old->prefix, 0);
1233 new->base = old->base;
1234 new->der = old->der;
1235
1236 switch (new->base) {
1237 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +02001238 if (old->info.binary.length) {
1239 new->info.binary.length = ly_restr_dup(ctx, old->info.binary.length, 1);
1240 }
Radek Krejci3733a802015-06-19 13:43:21 +02001241 break;
1242
1243 case LY_TYPE_BITS:
1244 new->info.bits.count = old->info.bits.count;
1245 if (new->info.bits.count) {
1246 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1247 for (i = 0; i < new->info.bits.count; i++) {
1248 new->info.bits.bit[i].name = lydict_insert(ctx, old->info.bits.bit[i].name, 0);
1249 new->info.bits.bit[i].dsc = lydict_insert(ctx, old->info.bits.bit[i].dsc, 0);
1250 new->info.bits.bit[i].ref = lydict_insert(ctx, old->info.bits.bit[i].ref, 0);
1251 new->info.bits.bit[i].status = old->info.bits.bit[i].status;
1252 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1253 }
1254 }
1255 break;
1256
Radek Krejcif9401c32015-06-26 16:47:36 +02001257 case LY_TYPE_DEC64:
1258 new->info.dec64.dig = old->info.dec64.dig;
1259 if (old->info.dec64.range) {
1260 new->info.dec64.range = ly_restr_dup(ctx, old->info.dec64.range, 1);
1261 }
1262 break;
1263
Radek Krejci3733a802015-06-19 13:43:21 +02001264 case LY_TYPE_ENUM:
1265 new->info.enums.count = old->info.enums.count;
1266 if (new->info.enums.count) {
1267 new->info.enums.list = calloc(new->info.enums.count, sizeof *new->info.enums.list);
1268 for (i = 0; i < new->info.enums.count; i++) {
1269 new->info.enums.list[i].name = lydict_insert(ctx, old->info.enums.list[i].name, 0);
1270 new->info.enums.list[i].dsc = lydict_insert(ctx, old->info.enums.list[i].dsc, 0);
1271 new->info.enums.list[i].ref = lydict_insert(ctx, old->info.enums.list[i].ref, 0);
1272 new->info.enums.list[i].status = old->info.enums.list[i].status;
1273 new->info.enums.list[i].value = old->info.enums.list[i].value;
1274 }
1275 }
1276 break;
1277
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001278 case LY_TYPE_IDENT:
1279 new->info.ident.ref = old->info.ident.ref;
1280 break;
1281
Radek Krejciaf351422015-06-19 14:49:38 +02001282 case LY_TYPE_INST:
1283 new->info.inst.req = old->info.inst.req;
1284 break;
1285
Radek Krejcif2860132015-06-20 12:37:20 +02001286 case LY_TYPE_INT8:
1287 case LY_TYPE_INT16:
1288 case LY_TYPE_INT32:
1289 case LY_TYPE_INT64:
1290 case LY_TYPE_UINT8:
1291 case LY_TYPE_UINT16:
1292 case LY_TYPE_UINT32:
1293 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +02001294 if (old->info.num.range) {
1295 new->info.num.range = ly_restr_dup(ctx, old->info.num.range, 1);
1296 }
Radek Krejcif2860132015-06-20 12:37:20 +02001297 break;
1298
Radek Krejcidc4c1412015-06-19 15:39:54 +02001299 case LY_TYPE_LEAFREF:
1300 new->info.lref.path = lydict_insert(ctx, old->info.lref.path, 0);
1301 break;
1302
Radek Krejci3733a802015-06-19 13:43:21 +02001303 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +02001304 if (old->info.str.length) {
1305 new->info.str.length = ly_restr_dup(ctx, old->info.str.length, 1);
1306 }
1307 new->info.str.patterns = ly_restr_dup(ctx, old->info.str.patterns, old->info.str.pat_count);
Radek Krejci3733a802015-06-19 13:43:21 +02001308 break;
1309
Radek Krejcie4c366b2015-07-02 10:11:31 +02001310 case LY_TYPE_UNION:
1311 new->info.uni.count = old->info.uni.count;
1312 if (new->info.uni.count) {
1313 new->info.uni.type = calloc(new->info.uni.count, sizeof *new->info.uni.type);
1314 for (i = 0; i < new->info.uni.count; i++) {
1315 ly_type_dup(ctx, &(new->info.uni.type[i]), &(old->info.uni.type[i]));
1316 }
1317 }
1318 break;
1319
Radek Krejci3733a802015-06-19 13:43:21 +02001320 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001321 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001322 break;
1323 }
1324}
1325
1326void
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001327ly_type_free(struct ly_ctx *ctx, struct ly_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001328{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001329 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001331 assert(ctx);
1332 if (!type) {
1333 return;
1334 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001335
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001336 lydict_remove(ctx, type->prefix);
Radek Krejci5a065542015-05-22 15:02:07 +02001337
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001338 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001339 case LY_TYPE_BINARY:
1340 ly_restr_free(ctx, type->info.binary.length);
1341 free(type->info.binary.length);
1342 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001343 case LY_TYPE_BITS:
1344 for (i = 0; i < type->info.bits.count; i++) {
1345 lydict_remove(ctx, type->info.bits.bit[i].name);
1346 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1347 lydict_remove(ctx, type->info.bits.bit[i].ref);
1348 }
1349 free(type->info.bits.bit);
1350 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001351
1352 case LY_TYPE_DEC64:
1353 ly_restr_free(ctx, type->info.dec64.range);
1354 free(type->info.dec64.range);
1355 break;
1356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001357 case LY_TYPE_ENUM:
1358 for (i = 0; i < type->info.enums.count; i++) {
1359 lydict_remove(ctx, type->info.enums.list[i].name);
1360 lydict_remove(ctx, type->info.enums.list[i].dsc);
1361 lydict_remove(ctx, type->info.enums.list[i].ref);
1362 }
1363 free(type->info.enums.list);
1364 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001365
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001366 case LY_TYPE_INT8:
1367 case LY_TYPE_INT16:
1368 case LY_TYPE_INT32:
1369 case LY_TYPE_INT64:
1370 case LY_TYPE_UINT8:
1371 case LY_TYPE_UINT16:
1372 case LY_TYPE_UINT32:
1373 case LY_TYPE_UINT64:
1374 ly_restr_free(ctx, type->info.num.range);
1375 free(type->info.num.range);
1376 break;
1377
Radek Krejcidc4c1412015-06-19 15:39:54 +02001378 case LY_TYPE_LEAFREF:
1379 lydict_remove(ctx, type->info.lref.path);
1380 break;
1381
Radek Krejci3733a802015-06-19 13:43:21 +02001382 case LY_TYPE_STRING:
1383 ly_restr_free(ctx, type->info.str.length);
1384 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001385 for (i = 0; i < type->info.str.pat_count; i++) {
1386 ly_restr_free(ctx, &type->info.str.patterns[i]);
1387 }
1388 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001389 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001390
Radek Krejcie4c366b2015-07-02 10:11:31 +02001391 case LY_TYPE_UNION:
1392 for (i = 0; i < type->info.uni.count; i++) {
1393 ly_type_free(ctx, &type->info.uni.type[i]);
1394 }
1395 free(type->info.uni.type);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001396 break;
1397
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001398 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001399 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001400 break;
1401 }
Radek Krejci5a065542015-05-22 15:02:07 +02001402}
1403
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001404struct ly_tpdf *
1405ly_tpdf_dup(struct ly_ctx *ctx, struct ly_tpdf *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001406{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001407 struct ly_tpdf *result;
1408 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001409
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001410 if (!size) {
1411 return NULL;
1412 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001413
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001414 result = calloc(size, sizeof *result);
1415 for (i = 0; i < size; i++) {
1416 result[i].name = lydict_insert(ctx, old[i].name, 0);
1417 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1418 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1419 result[i].flags = old[i].flags;
1420 result[i].module = old[i].module;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001421
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001422 ly_type_dup(ctx, &(result[i].type), &(old[i].type));
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001423
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001424 result[i].dflt = lydict_insert(ctx, old[i].dflt, 0);
1425 result[i].units = lydict_insert(ctx, old[i].units, 0);
1426 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001427
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001428 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001429}
1430
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001431void
1432ly_tpdf_free(struct ly_ctx *ctx, struct ly_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001433{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001434 assert(ctx);
1435 if (!tpdf) {
1436 return;
1437 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001438
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001439 lydict_remove(ctx, tpdf->name);
1440 lydict_remove(ctx, tpdf->dsc);
1441 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001442
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001443 ly_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001444
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001445 lydict_remove(ctx, tpdf->units);
1446 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001447}
1448
Radek Krejci00768f42015-06-18 17:04:04 +02001449struct ly_when *
1450ly_when_dup(struct ly_ctx *ctx, struct ly_when *old)
1451{
1452 struct ly_when *new;
1453
1454 if (!old) {
1455 return NULL;
1456 }
1457
1458 new = calloc(1, sizeof *new);
1459 new->cond = lydict_insert(ctx, old->cond, 0);
1460 new->dsc = lydict_insert(ctx, old->dsc, 0);
1461 new->ref = lydict_insert(ctx, old->ref, 0);
1462
1463 return new;
1464}
1465
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001466void
1467ly_when_free(struct ly_ctx *ctx, struct ly_when *w)
1468{
1469 if (!w) {
1470 return;
1471 }
1472
1473 lydict_remove(ctx, w->cond);
1474 lydict_remove(ctx, w->dsc);
1475 lydict_remove(ctx, w->ref);
1476
1477 free(w);
1478}
1479
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001480struct ly_augment *
1481ly_augment_dup(struct ly_module *module, struct ly_mnode *parent, struct ly_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001482{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001483 struct ly_augment *new = NULL;
1484 int i = -1;
Radek Krejci106efc02015-06-10 14:36:27 +02001485
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001486 if (!size) {
1487 return NULL;
1488 }
Radek Krejci106efc02015-06-10 14:36:27 +02001489
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001490 new = calloc(size, sizeof *new);
1491 for (i = 0; i < size; i++) {
1492 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1493 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1494 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1495 new[i].flags = old[i].flags;
1496 /* .target = NULL; .nodetype = 0 */
Radek Krejci106efc02015-06-10 14:36:27 +02001497
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001498 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001499
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001500 /* copy the definition of augment nodes */
1501 if (old[i].child) {
1502 new[i].child = (struct ly_mnode *)lyxml_dup_elem(module->ctx, (struct lyxml_elem *)old[i].child, NULL, 1);
1503 }
1504 }
Radek Krejci106efc02015-06-10 14:36:27 +02001505
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001506 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001507}
1508
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001509struct ly_refine *
1510ly_refine_dup(struct ly_ctx *ctx, struct ly_refine *old, int size)
Michal Vasko1982cad2015-06-08 15:49:30 +02001511{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001512 struct ly_refine *result;
1513 int i;
Michal Vasko1982cad2015-06-08 15:49:30 +02001514
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001515 if (!size) {
1516 return NULL;
1517 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001518
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001519 result = calloc(size, sizeof *result);
1520 for (i = 0; i < size; i++) {
1521 result[i].target = lydict_insert(ctx, old[i].target, 0);
1522 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1523 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1524 result[i].flags = old[i].flags;
1525 result[i].target_type = old[i].target_type;
1526 result[i].must_size = old[i].must_size;
Radek Krejci0bd5db42015-06-19 13:30:07 +02001527 result[i].must = ly_restr_dup(ctx, old[i].must, old[i].must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001528 if (result[i].target_type & (LY_NODE_LEAF | LY_NODE_CHOICE)) {
1529 result[i].mod.dflt = lydict_insert(ctx, old[i].mod.dflt, 0);
1530 } else if (result[i].target_type == LY_NODE_CONTAINER) {
1531 result[i].mod.presence = lydict_insert(ctx, old[i].mod.presence, 0);
1532 } else if (result[i].target_type & (LY_NODE_LIST | LY_NODE_LEAFLIST)) {
1533 result[i].mod.list = old[i].mod.list;
1534 }
1535 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001537 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001538}
1539
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001540void
1541ly_ident_free(struct ly_ctx *ctx, struct ly_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001542{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001543 struct ly_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001544
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001545 assert(ctx);
1546 if (!ident) {
1547 return;
1548 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001549
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001550 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001551 * if caller free only a single data model which is used (its identity is
1552 * reference from identity in another module), this silly freeing can lead
1553 * to segmentation fault. But without noting if the module is used by some
1554 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001555 *
1556 * Possible solution is to not allow caller to remove particular schema
1557 * from the context.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001558 */
1559 while (ident->der) {
1560 der = ident->der;
1561 ident->der = der->next;
1562 free(der);
1563 }
Radek Krejci6793db02015-05-22 17:49:54 +02001564
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001565 lydict_remove(ctx, ident->name);
1566 lydict_remove(ctx, ident->dsc);
1567 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001568
1569}
1570
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001571void
1572ly_grp_free(struct ly_ctx *ctx, struct ly_mnode_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001573{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001574 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001575
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001576 /* handle only specific parts for LY_NODE_GROUPING */
1577 for (i = 0; i < grp->tpdf_size; i++) {
1578 ly_tpdf_free(ctx, &grp->tpdf[i]);
1579 }
1580 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001581}
1582
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001583void
1584ly_anyxml_free(struct ly_ctx *ctx, struct ly_mnode_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001585{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001586 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001587
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001588 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001589 ly_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001590 }
1591 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001592
1593 ly_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001594}
1595
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001596void
1597ly_leaf_free(struct ly_ctx *ctx, struct ly_mnode_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001598{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001599 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001600
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001601 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001602 ly_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001603 }
1604 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001605
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001606 ly_when_free(ctx, leaf->when);
1607
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001608 ly_type_free(ctx, &leaf->type);
1609 lydict_remove(ctx, leaf->units);
1610 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001611}
1612
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001613void
1614ly_leaflist_free(struct ly_ctx *ctx, struct ly_mnode_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001615{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001616 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001617
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001618 for (i = 0; i < llist->must_size; i++) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001619 ly_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001620 }
1621 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001622
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001623 ly_when_free(ctx, llist->when);
1624
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001625 ly_type_free(ctx, &llist->type);
1626 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001627}
1628
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001629void
1630ly_list_free(struct ly_ctx *ctx, struct ly_mnode_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001631{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001632 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001633
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001634 /* handle only specific parts for LY_NODE_LIST */
1635 for (i = 0; i < list->tpdf_size; i++) {
1636 ly_tpdf_free(ctx, &list->tpdf[i]);
1637 }
1638 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001639
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001640 for (i = 0; i < list->must_size; i++) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001641 ly_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001642 }
1643 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001644
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001645 ly_when_free(ctx, list->when);
1646
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001647 for (i = 0; i < list->unique_size; i++) {
1648 free(list->unique[i].leafs);
1649 }
1650 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001651
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001652 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001653}
1654
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001655void
1656ly_container_free(struct ly_ctx *ctx, struct ly_mnode_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001657{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001658 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001659
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001660 /* handle only specific parts for LY_NODE_CONTAINER */
1661 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001662
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001663 for (i = 0; i < cont->tpdf_size; i++) {
1664 ly_tpdf_free(ctx, &cont->tpdf[i]);
1665 }
1666 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001667
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001668 for (i = 0; i < cont->must_size; i++) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001669 ly_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001670 }
1671 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001672
1673 ly_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001674}
1675
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001676void
Radek Krejci3cf9e222015-06-18 11:37:50 +02001677ly_feature_free(struct ly_ctx *ctx, struct ly_feature *f)
1678{
1679 lydict_remove(ctx, f->name);
1680 lydict_remove(ctx, f->dsc);
1681 lydict_remove(ctx, f->ref);
1682 free(f->features);
1683}
1684
1685void
Radek Krejcieb00f512015-07-01 16:44:58 +02001686ly_deviation_free(struct ly_ctx *ctx, struct ly_deviation *dev)
1687{
1688 int i, j;
1689
1690 lydict_remove(ctx, dev->target_name);
1691 lydict_remove(ctx, dev->dsc);
1692 lydict_remove(ctx, dev->ref);
1693
1694 for (i = 0; i < dev->deviate_size; i++) {
1695 lydict_remove(ctx, dev->deviate[i].dflt);
1696 lydict_remove(ctx, dev->deviate[i].units);
1697
1698 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1699 for (j = 0; j < dev->deviate[i].must_size; j++) {
1700 ly_restr_free(ctx, &dev->deviate[i].must[j]);
1701 }
1702 free(dev->deviate[i].must);
1703
1704 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1705 free(dev->deviate[j].unique[j].leafs);
1706 }
1707 free(dev->deviate[i].unique);
1708 }
1709 }
1710 free(dev->deviate);
1711}
1712
1713void
Radek Krejcif5be10f2015-06-16 13:29:36 +02001714ly_augment_free(struct ly_ctx *ctx, struct ly_augment *aug)
1715{
1716 lydict_remove(ctx, aug->target_name);
1717 lydict_remove(ctx, aug->dsc);
1718 lydict_remove(ctx, aug->ref);
1719
Michal Vasko25b39612015-07-07 16:11:07 +02001720 free(aug->features);
1721
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001722 ly_when_free(ctx, aug->when);
1723
Radek Krejcif5be10f2015-06-16 13:29:36 +02001724 lyxml_free_elem(ctx, (struct lyxml_elem *)aug->child);
1725}
1726
1727void
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001728ly_uses_free(struct ly_ctx *ctx, struct ly_mnode_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +02001729{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001730 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001731
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001732 for (i = 0; i < uses->refine_size; i++) {
1733 lydict_remove(ctx, uses->refine[i].target);
1734 lydict_remove(ctx, uses->refine[i].dsc);
1735 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001736
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001737 for (j = 0; j < uses->refine[j].must_size; j++) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001738 ly_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001739 }
1740 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001741
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001742 if (uses->refine[i].target_type & (LY_NODE_LEAF | LY_NODE_CHOICE)) {
1743 lydict_remove(ctx, uses->refine[i].mod.dflt);
1744 } else if (uses->refine[i].target_type & LY_NODE_CONTAINER) {
1745 lydict_remove(ctx, uses->refine[i].mod.presence);
1746 }
1747 }
1748 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001749
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001750 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02001751 ly_augment_free(ctx, &uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001752 }
1753 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001754
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001755 ly_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001756}
1757
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001758void
1759ly_mnode_free(struct ly_mnode *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001760{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001761 struct ly_ctx *ctx;
1762 struct ly_mnode *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001763
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001764 if (!node) {
1765 return;
1766 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001767
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001768 assert(node->module);
1769 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001770
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001771 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001772
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001773 /* common part */
1774 LY_TREE_FOR_SAFE(node->child, next, sub) {
1775 ly_mnode_free(sub);
1776 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001777 free(node->features);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001778
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001779 lydict_remove(ctx, node->name);
1780 lydict_remove(ctx, node->dsc);
1781 lydict_remove(ctx, node->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001782
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001783 /* specific part */
1784 switch (node->nodetype) {
1785 case LY_NODE_CONTAINER:
1786 ly_container_free(ctx, (struct ly_mnode_container *)node);
1787 break;
1788 case LY_NODE_CHOICE:
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001789 ly_when_free(ctx, ((struct ly_mnode_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001790 break;
1791 case LY_NODE_LEAF:
1792 ly_leaf_free(ctx, (struct ly_mnode_leaf *)node);
1793 break;
1794 case LY_NODE_LEAFLIST:
1795 ly_leaflist_free(ctx, (struct ly_mnode_leaflist *)node);
1796 break;
1797 case LY_NODE_LIST:
1798 ly_list_free(ctx, (struct ly_mnode_list *)node);
1799 break;
1800 case LY_NODE_ANYXML:
1801 ly_anyxml_free(ctx, (struct ly_mnode_anyxml *)node);
1802 break;
1803 case LY_NODE_USES:
1804 ly_uses_free(ctx, (struct ly_mnode_uses *)node);
1805 break;
1806 case LY_NODE_CASE:
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001807 ly_when_free(ctx, ((struct ly_mnode_case *)node)->when);
1808 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001809 case LY_NODE_AUGMENT:
1810 /* do nothing */
1811 break;
Michal Vasko0ea41032015-06-16 08:53:55 +02001812 case LY_NODE_GROUPING:
1813 case LY_NODE_RPC:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001814 case LY_NODE_INPUT:
1815 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02001816 case LY_NODE_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001817 ly_grp_free(ctx, (struct ly_mnode_grp *)node);
1818 break;
1819 }
Radek Krejci5a065542015-05-22 15:02:07 +02001820
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001821 /* again common part */
1822 ly_mnode_unlink(node);
1823 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001824}
1825
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001826static void
1827module_free_common(struct ly_module *module)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001828{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001829 struct ly_ctx *ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001830 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001831 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001832
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001833 assert(module->ctx);
1834 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001835
Radek Krejcidce51452015-06-16 15:20:08 +02001836 /* as first step, free the imported modules */
1837 for (i = 0; i < module->imp_size; i++) {
1838 /* get the imported module from the context and then free,
1839 * this check is necessary because the imported module can
1840 * be already removed
1841 */
1842 l = ctx->models.used;
1843 for (j = 0; j < l; j++) {
1844 if (ctx->models.list[j] == module->imp[i].module) {
Radek Krejci912da452015-07-29 14:10:06 +02001845 lys_free(module->imp[i].module);
Radek Krejcidce51452015-06-16 15:20:08 +02001846 break;
1847 }
1848 }
1849 }
1850 free(module->imp);
1851
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001852 while (module->data) {
Radek Krejci21181962015-06-30 14:11:00 +02001853 ly_mnode_free(module->data);
1854 }
1855 while (module->rpc) {
1856 ly_mnode_free(module->rpc);
1857 }
1858 while (module->notif) {
1859 ly_mnode_free(module->notif);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001860 }
Radek Krejci5a065542015-05-22 15:02:07 +02001861
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001862 lydict_remove(ctx, module->dsc);
1863 lydict_remove(ctx, module->ref);
1864 lydict_remove(ctx, module->org);
1865 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001866
Radek Krejcieb00f512015-07-01 16:44:58 +02001867 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001868 for (i = 0; i < module->rev_size; i++) {
1869 lydict_remove(ctx, module->rev[i].dsc);
1870 lydict_remove(ctx, module->rev[i].ref);
1871 }
1872 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001873
Radek Krejcieb00f512015-07-01 16:44:58 +02001874 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001875 for (i = 0; i < module->ident_size; i++) {
1876 ly_ident_free(ctx, &module->ident[i]);
1877 }
1878 module->ident_size = 0;
1879 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001880
Radek Krejcieb00f512015-07-01 16:44:58 +02001881 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001882 for (i = 0; i < module->tpdf_size; i++) {
1883 ly_tpdf_free(ctx, &module->tpdf[i]);
1884 }
1885 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001886
Radek Krejcieb00f512015-07-01 16:44:58 +02001887 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001888 for (i = 0; i < module->inc_size; i++) {
1889 ly_submodule_free(module->inc[i].submodule);
1890 }
1891 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001892
Radek Krejcieb00f512015-07-01 16:44:58 +02001893 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02001894 for (i = 0; i < module->augment_size; i++) {
1895 ly_augment_free(ctx, &module->augment[i]);
1896 }
1897 free(module->augment);
1898
Radek Krejcieb00f512015-07-01 16:44:58 +02001899 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001900 for (i = 0; i < module->features_size; i++) {
1901 ly_feature_free(ctx, &module->features[i]);
1902 }
1903 free(module->features);
1904
Radek Krejcieb00f512015-07-01 16:44:58 +02001905 /* deviations */
1906 for (i = 0; i < module->deviation_size; i++) {
1907 ly_deviation_free(ctx, &module->deviation[i]);
1908 }
1909 free(module->deviation);
1910
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001911 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02001912}
1913
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001914void
1915ly_submodule_free(struct ly_submodule *submodule)
Radek Krejciefaeba32015-05-27 14:30:57 +02001916{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001917 if (!submodule) {
1918 return;
1919 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001920
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001921 submodule->inc_size = 0;
1922 free(submodule->inc);
1923 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02001924
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001925 /* common part with struct ly_module */
1926 module_free_common((struct ly_module *)submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001927
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001928 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02001929
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001930 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001931}
1932
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001933struct ly_mnode *
1934ly_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 +02001935{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001936 struct ly_mnode *retval = NULL, *aux, *child;
1937 struct ly_ctx *ctx = module->ctx;
1938 int i, j;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001939
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001940 struct ly_mnode_container *cont;
1941 struct ly_mnode_container *cont_orig = (struct ly_mnode_container *)mnode;
1942 struct ly_mnode_choice *choice;
1943 struct ly_mnode_choice *choice_orig = (struct ly_mnode_choice *)mnode;
1944 struct ly_mnode_leaf *leaf;
1945 struct ly_mnode_leaf *leaf_orig = (struct ly_mnode_leaf *)mnode;
1946 struct ly_mnode_leaflist *llist;
1947 struct ly_mnode_leaflist *llist_orig = (struct ly_mnode_leaflist *)mnode;
1948 struct ly_mnode_list *list;
1949 struct ly_mnode_list *list_orig = (struct ly_mnode_list *)mnode;
1950 struct ly_mnode_anyxml *anyxml;
1951 struct ly_mnode_anyxml *anyxml_orig = (struct ly_mnode_anyxml *)mnode;
1952 struct ly_mnode_uses *uses;
1953 struct ly_mnode_uses *uses_orig = (struct ly_mnode_uses *)mnode;
1954 struct ly_mnode_grp *mix;
1955 struct ly_mnode_grp *mix_orig = (struct ly_mnode_grp *)mnode;
1956 struct ly_mnode_case *cs;
Radek Krejci00768f42015-06-18 17:04:04 +02001957 struct ly_mnode_case *cs_orig = (struct ly_mnode_case *)mnode;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001958
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001959 /* we cannot just duplicate memory since the strings are stored in
1960 * dictionary and we need to update dictionary counters.
1961 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001962
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001963 switch (mnode->nodetype) {
1964 case LY_NODE_CONTAINER:
1965 cont = calloc(1, sizeof *cont);
1966 retval = (struct ly_mnode *)cont;
1967 break;
1968
1969 case LY_NODE_CHOICE:
1970 choice = calloc(1, sizeof *choice);
1971 retval = (struct ly_mnode *)choice;
1972 break;
1973
1974 case LY_NODE_LEAF:
1975 leaf = calloc(1, sizeof *leaf);
1976 retval = (struct ly_mnode *)leaf;
1977 break;
1978
1979 case LY_NODE_LEAFLIST:
1980 llist = calloc(1, sizeof *llist);
1981 retval = (struct ly_mnode *)llist;
1982 break;
1983
1984 case LY_NODE_LIST:
1985 list = calloc(1, sizeof *list);
1986 retval = (struct ly_mnode *)list;
1987 break;
1988
1989 case LY_NODE_ANYXML:
1990 anyxml = calloc(1, sizeof *anyxml);
1991 retval = (struct ly_mnode *)anyxml;
1992 break;
1993
1994 case LY_NODE_USES:
1995 uses = calloc(1, sizeof *uses);
1996 retval = (struct ly_mnode *)uses;
1997 break;
1998
1999 case LY_NODE_CASE:
2000 cs = calloc(1, sizeof *cs);
2001 retval = (struct ly_mnode *)cs;
2002 break;
2003
2004 /* exact same structure */
Michal Vasko0ea41032015-06-16 08:53:55 +02002005 case LY_NODE_GROUPING:
Michal Vasko38d01f72015-06-15 09:41:06 +02002006 case LY_NODE_RPC:
Michal Vasko38d01f72015-06-15 09:41:06 +02002007 case LY_NODE_INPUT:
2008 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02002009 case LY_NODE_NOTIF:
2010 mix = calloc(1, sizeof *mix);
2011 retval = (struct ly_mnode *)mix;
Michal Vasko38d01f72015-06-15 09:41:06 +02002012 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002013
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002014 default:
2015 goto error;
2016 }
Radek Krejcib388c152015-06-04 17:03:03 +02002017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002018 /*
2019 * duplicate generic part of the structure
2020 */
2021 retval->name = lydict_insert(ctx, mnode->name, 0);
2022 retval->dsc = lydict_insert(ctx, mnode->dsc, 0);
2023 retval->ref = lydict_insert(ctx, mnode->ref, 0);
2024 retval->flags = mnode->flags;
2025 if (!(retval->flags & LY_NODE_CONFIG_MASK)) {
2026 /* set parent's config flag */
2027 retval->flags |= flags & LY_NODE_CONFIG_MASK;
2028 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002029
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002030 retval->module = module;
2031 retval->nodetype = mnode->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002032
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002033 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002034
Radek Krejci3cf9e222015-06-18 11:37:50 +02002035 retval->features_size = mnode->features_size;
2036 retval->features = calloc(retval->features_size, sizeof *retval->features);
2037 memcpy(retval->features, mnode->features, retval->features_size * sizeof *retval->features);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002038
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002039 if (recursive) {
2040 /* go recursively */
2041 LY_TREE_FOR(mnode->child, child) {
2042 aux = ly_mnode_dup(module, child, retval->flags, 1, line);
2043 if (!aux || ly_mnode_addchild(retval, aux)) {
2044 goto error;
2045 }
2046 }
2047 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002048
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002049 /*
2050 * duplicate specific part of the structure
2051 */
2052 switch (mnode->nodetype) {
2053 case LY_NODE_CONTAINER:
Radek Krejci00768f42015-06-18 17:04:04 +02002054 cont->when = ly_when_dup(ctx, cont_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002055 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002056
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002057 cont->must_size = cont_orig->must_size;
2058 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002059
Radek Krejci0bd5db42015-06-19 13:30:07 +02002060 cont->must = ly_restr_dup(ctx, cont_orig->must, cont->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002061 cont->tpdf = ly_tpdf_dup(ctx, cont_orig->tpdf, cont->tpdf_size);
2062 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002063
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002064 case LY_NODE_CHOICE:
Radek Krejci00768f42015-06-18 17:04:04 +02002065 choice->when = ly_when_dup(ctx, choice_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002066 if (choice->dflt) {
2067 LY_TREE_FOR(choice->child, child) {
2068 if (child->name == choice_orig->dflt->name) {
2069 choice->dflt = child;
2070 break;
2071 }
2072 }
2073 }
2074 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002076 case LY_NODE_LEAF:
2077 ly_type_dup(ctx, &(leaf->type), &(leaf_orig->type));
2078 leaf->units = lydict_insert(ctx, leaf_orig->units, 0);
2079 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002080
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002081 leaf->must_size = leaf_orig->must_size;
Radek Krejci0bd5db42015-06-19 13:30:07 +02002082 leaf->must = ly_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002083
2084 leaf->when = ly_when_dup(ctx, leaf_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002085 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002086
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002087 case LY_NODE_LEAFLIST:
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002088
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002089 ly_type_dup(ctx, &(llist->type), &(llist_orig->type));
2090 llist->units = lydict_insert(ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002091
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002092 llist->min = llist_orig->min;
2093 llist->max = llist_orig->max;
2094
2095 llist->must_size = llist_orig->must_size;
Radek Krejci0bd5db42015-06-19 13:30:07 +02002096 llist->must = ly_restr_dup(ctx, llist_orig->must, llist->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002097
2098 llist->when = ly_when_dup(ctx, llist_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002099 break;
2100
2101 case LY_NODE_LIST:
2102 list->min = list_orig->min;
2103 list->max = list_orig->max;
2104
2105 list->must_size = list_orig->must_size;
2106 list->tpdf_size = list_orig->tpdf_size;
2107 list->keys_size = list_orig->keys_size;
2108 list->unique_size = list_orig->unique_size;
2109
Radek Krejci0bd5db42015-06-19 13:30:07 +02002110 list->must = ly_restr_dup(ctx, list_orig->must, list->must_size);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002111 list->tpdf = ly_tpdf_dup(ctx, list_orig->tpdf, list->tpdf_size);
2112
2113 if (list->keys_size) {
2114 list->keys = calloc(list->keys_size, sizeof *list->keys);
2115 for (i = 0; i < list->keys_size; i++) {
2116 list->keys[i] = find_leaf(retval, list_orig->keys[i]->name, 0);
2117 }
2118 }
2119 if (list->unique_size) {
2120 list->unique = calloc(list->unique_size, sizeof *list->unique);
2121 for (i = 0; i < list->unique_size; i++) {
2122 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
2123 for (j = 0; j < list->unique[i].leafs_size; j++) {
2124 list->unique[i].leafs[j] = find_leaf(retval, list_orig->unique[i].leafs[j]->name, 0);
2125 }
2126 }
2127 }
Radek Krejci00768f42015-06-18 17:04:04 +02002128 list->when = ly_when_dup(ctx, list_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002129 break;
2130
2131 case LY_NODE_ANYXML:
2132 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci0bd5db42015-06-19 13:30:07 +02002133 anyxml->must = ly_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Radek Krejci00768f42015-06-18 17:04:04 +02002134 anyxml->when = ly_when_dup(ctx, anyxml_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002135 break;
2136
2137 case LY_NODE_USES:
2138 uses->grp = uses_orig->grp;
Radek Krejci00768f42015-06-18 17:04:04 +02002139 uses->when = ly_when_dup(ctx, uses_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002140 uses->refine_size = uses_orig->refine_size;
2141 uses->refine = ly_refine_dup(ctx, uses_orig->refine, uses_orig->refine_size);
2142 uses->augment_size = uses_orig->augment_size;
2143 uses->augment = ly_augment_dup(module, (struct ly_mnode *)uses, uses_orig->augment, uses_orig->augment_size);
2144 if (resolve_uses(uses, line)) {
2145 goto error;
2146 }
2147 break;
2148
2149 case LY_NODE_CASE:
Radek Krejci00768f42015-06-18 17:04:04 +02002150 cs->when = ly_when_dup(ctx, cs_orig->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002151 break;
2152
Michal Vasko0ea41032015-06-16 08:53:55 +02002153 case LY_NODE_GROUPING:
Michal Vasko38d01f72015-06-15 09:41:06 +02002154 case LY_NODE_RPC:
Michal Vasko38d01f72015-06-15 09:41:06 +02002155 case LY_NODE_INPUT:
2156 case LY_NODE_OUTPUT:
Michal Vasko0ea41032015-06-16 08:53:55 +02002157 case LY_NODE_NOTIF:
2158 mix->tpdf_size = mix_orig->tpdf_size;
2159 mix->tpdf = ly_tpdf_dup(ctx, mix_orig->tpdf, mix->tpdf_size);
Radek Krejcia01e5432015-06-16 10:35:25 +02002160 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002162 default:
Radek Krejci00768f42015-06-18 17:04:04 +02002163 /* LY_NODE_AUGMENT */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002164 goto error;
2165 }
2166
2167 return retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002168
2169error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002170 LOGDBG("error: %s:%d", __FILE__, __LINE__);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002171
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002172 ly_mnode_free(retval);
2173 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002174}
2175
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002176API void
Radek Krejci912da452015-07-29 14:10:06 +02002177lys_free(struct ly_module *module)
Radek Krejciefaeba32015-05-27 14:30:57 +02002178{
Radek Krejcidce51452015-06-16 15:20:08 +02002179 struct ly_ctx *ctx;
2180 int i;
2181
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002182 if (!module) {
2183 return;
2184 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002185
Radek Krejcidce51452015-06-16 15:20:08 +02002186 /* remove schema from the context */
2187 ctx = module->ctx;
2188 if (ctx->models.used) {
2189 for (i = 0; i < ctx->models.used; i++) {
2190 if (ctx->models.list[i] == module) {
2191 /* replace the position in the list by the last module in the list */
2192 ctx->models.used--;
2193 ctx->models.list[i] = ctx->models.list[ctx->models.used];
2194 ctx->models.list[ctx->models.used] = NULL;
2195 /* we are done */
2196 break;
2197 }
2198 }
2199 }
2200
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002201 /* common part with struct ly_submodule */
2202 module_free_common(module);
Radek Krejciefaeba32015-05-27 14:30:57 +02002203
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002204 /* specific items to free */
2205 lydict_remove(module->ctx, module->ns);
2206 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02002207
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002208 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002209}
Radek Krejci7e97c352015-06-19 16:26:34 +02002210
2211/*
2212 * op: 1 - enable, 0 - disable
2213 */
2214static int
2215ly_features_change(struct ly_module *module, const char *name, int op)
2216{
2217 int all = 0;
2218 int i, j, k;
2219
2220 if (!module || !name || !strlen(name)) {
2221 return EXIT_FAILURE;
2222 }
2223
2224 if (!strcmp(name, "*")) {
2225 /* enable all */
2226 all = 1;
2227 }
2228
2229 /* module itself */
2230 for (i = 0; i < module->features_size; i++) {
2231 if (all || !strcmp(module->features[i].name, name)) {
2232 if (op) {
2233 module->features[i].flags |= LY_NODE_FENABLED;
2234 /* enable referenced features (recursion) */
2235 for (k = 0; k < module->features[i].features_size; k++) {
2236 ly_features_change(module->features[i].features[k]->module,
2237 module->features[i].features[k]->name, op);
2238 }
2239 } else {
2240 module->features[i].flags &= ~LY_NODE_FENABLED;
2241 }
2242 if (!all) {
2243 return EXIT_SUCCESS;
2244 }
2245 }
2246 }
2247
2248 /* submodules */
2249 for (j = 0; j < module->inc_size; j++) {
2250 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2251 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2252 if (op) {
2253 module->inc[j].submodule->features[i].flags |= LY_NODE_FENABLED;
2254 } else {
2255 module->inc[j].submodule->features[i].flags &= ~LY_NODE_FENABLED;
2256 }
2257 if (!all) {
2258 return EXIT_SUCCESS;
2259 }
2260 }
2261 }
2262 }
2263
2264 if (all) {
2265 return EXIT_SUCCESS;
2266 } else {
2267 return EXIT_FAILURE;
2268 }
2269}
2270
2271API int
2272ly_features_enable(struct ly_module *module, const char *name)
2273{
2274 return ly_features_change(module, name, 1);
2275}
2276
2277API int
2278ly_features_disable(struct ly_module *module, const char *name)
2279{
Michal Vasko4c5989d2015-07-07 11:32:55 +02002280 return ly_features_change(module, name, 0);
Radek Krejci7e97c352015-06-19 16:26:34 +02002281}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002282
2283API char **
2284ly_get_features(struct ly_module *module, char ***enable_state)
2285{
2286 int i, j;
2287 char **result = NULL;
2288 unsigned int count;
2289
2290 if (!module) {
2291 return NULL;
2292 }
2293
2294 count = module->features_size;
2295 for (i = 0; i < module->inc_size; i++) {
2296 count += module->inc[i].submodule->features_size;
2297 }
2298 result = malloc((count+1) * sizeof *result);
2299 if (enable_state) {
2300 *enable_state = malloc((count+1) * sizeof **enable_state);
2301 }
2302
2303 count = 0;
2304
2305 /* module itself */
2306 for (i = 0; i < module->features_size; i++) {
2307 result[count] = strdup(module->features[i].name);
2308 if (enable_state) {
2309 if (module->features[i].flags & LY_NODE_FENABLED) {
2310 (*enable_state)[count] = strdup("on");
2311 } else {
2312 (*enable_state)[count] = strdup("off");
2313 }
2314 }
2315 ++count;
2316 }
2317
2318 /* submodules */
2319 for (j = 0; j < module->inc_size; j++) {
2320 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2321 result[count] = strdup(module->inc[j].submodule->features[i].name);
2322 if (enable_state) {
2323 if (module->inc[j].submodule->features[i].flags & LY_NODE_FENABLED) {
2324 (*enable_state)[count] = strdup("on");
2325 } else {
2326 (*enable_state)[count] = strdup("off");
2327 }
2328 }
2329 ++count;
2330 }
2331 }
2332
2333 result[count] = NULL;
2334 if (enable_state) {
2335 (*enable_state)[count] = NULL;
2336 }
2337
2338 return result;
2339}
Radek Krejcib20c62d2015-07-07 17:07:14 +02002340
Radek Krejcie3d724f2015-07-10 15:32:42 +02002341static struct ly_ident *
2342find_base_ident_sub(struct ly_module *module, struct ly_ident *ident, const char *basename)
2343{
2344 unsigned int i, j;
2345 struct ly_ident *base_iter = NULL;
2346 struct ly_ident_der *der;
2347
2348 /* search module */
2349 for (i = 0; i < module->ident_size; i++) {
2350 if (!strcmp(basename, module->ident[i].name)) {
2351
2352 if (!ident) {
2353 /* just search for type, so do not modify anything, just return
2354 * the base identity pointer
2355 */
2356 return &module->ident[i];
2357 }
2358
2359 /* we are resolving identity definition, so now update structures */
2360 ident->base = base_iter = &module->ident[i];
2361
2362 break;
2363 }
2364 }
2365
2366 /* search submodules */
2367 if (!base_iter) {
2368 for (j = 0; j < module->inc_size; j++) {
2369 for (i = 0; i < module->inc[j].submodule->ident_size; i++) {
2370 if (!strcmp(basename, module->inc[j].submodule->ident[i].name)) {
2371
2372 if (!ident) {
2373 return &module->inc[j].submodule->ident[i];
2374 }
2375
2376 ident->base = base_iter = &module->inc[j].submodule->ident[i];
2377 break;
2378 }
2379 }
2380 }
2381 }
2382
2383 /* we found it somewhere */
2384 if (base_iter) {
2385 while (base_iter) {
2386 for (der = base_iter->der; der && der->next; der = der->next);
2387 if (der) {
2388 der->next = malloc(sizeof *der);
2389 der = der->next;
2390 } else {
2391 ident->base->der = der = malloc(sizeof *der);
2392 }
2393 der->next = NULL;
2394 der->ident = ident;
2395
2396 base_iter = base_iter->base;
2397 }
2398 return ident->base;
2399 }
2400
2401 return NULL;
2402}
2403
2404struct ly_ident *
2405find_base_ident(struct ly_module *module, struct ly_ident *ident, const char *basename, int line, const char* parent)
2406{
2407 const char *name;
2408 int prefix_len = 0;
2409 int i, found = 0;
2410 struct ly_ident *result;
2411
2412 /* search for the base identity */
2413 name = strchr(basename, ':');
2414 if (name) {
2415 /* set name to correct position after colon */
2416 prefix_len = name - basename;
2417 name++;
2418
2419 if (!strncmp(basename, module->prefix, prefix_len) && !module->prefix[prefix_len]) {
2420 /* prefix refers to the current module, ignore it */
2421 prefix_len = 0;
2422 }
2423 } else {
2424 name = basename;
2425 }
2426
2427 if (prefix_len) {
2428 /* get module where to search */
2429 for (i = 0; i < module->imp_size; i++) {
2430 if (!strncmp(module->imp[i].prefix, basename, prefix_len)
2431 && !module->imp[i].prefix[prefix_len]) {
2432 module = module->imp[i].module;
2433 found = 1;
2434 break;
2435 }
2436 }
2437 if (!found) {
2438 /* identity refers unknown data model */
2439 LOGVAL(VE_INPREFIX, line, basename);
2440 return NULL;
2441 }
2442 } else {
2443 /* search in submodules */
2444 for (i = 0; i < module->inc_size; i++) {
2445 result = find_base_ident_sub((struct ly_module *)module->inc[i].submodule, ident, name);
2446 if (result) {
2447 return result;
2448 }
2449 }
2450 }
2451
2452 /* search in the identified module */
2453 result = find_base_ident_sub(module, ident, name);
2454 if (!result) {
2455 LOGVAL(VE_INARG, line, basename, parent);
2456 }
2457
2458 return result;
2459}
2460
2461struct ly_ident *
2462find_identityref(struct ly_ident *base, const char *name, const char *ns)
2463{
2464 struct ly_ident_der *der;
2465
2466 if (!base || !name || !ns) {
2467 return NULL;
2468 }
2469
2470 for(der = base->der; der; der = der->next) {
2471 if (!strcmp(der->ident->name, name) && ns == der->ident->module->ns) {
2472 /* we have match */
2473 return der->ident;
2474 }
2475 }
2476
2477 /* not found */
2478 return NULL;
2479}
2480
Radek Krejcib20c62d2015-07-07 17:07:14 +02002481API struct lyd_node *
Radek Krejci912da452015-07-29 14:10:06 +02002482lyd_parse(struct ly_ctx *ctx, const char *data, LY_DFORMAT format)
Radek Krejcib20c62d2015-07-07 17:07:14 +02002483{
2484 if (!ctx || !data) {
2485 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2486 return NULL;
2487 }
2488
2489 switch (format) {
Michal Vasko520d4732015-07-13 15:53:33 +02002490 case LY_DATA_XML:
Radek Krejcib20c62d2015-07-07 17:07:14 +02002491 return xml_read_data(ctx, data);
Michal Vasko520d4732015-07-13 15:53:33 +02002492 case LY_DATA_JSON:
Radek Krejcib20c62d2015-07-07 17:07:14 +02002493 default:
2494 /* TODO */
2495 return NULL;
2496 }
2497
2498 return NULL;
2499}
2500
2501API void
Radek Krejci912da452015-07-29 14:10:06 +02002502lyd_free(struct lyd_node *node)
Radek Krejcib20c62d2015-07-07 17:07:14 +02002503{
2504 struct lyd_node *next, *child;
2505
Radek Krejci52f791c2015-07-15 11:14:17 +02002506 if (!node) {
2507 return;
2508 }
2509
Michal Vaskoab8e4402015-07-17 12:54:28 +02002510 if (!(node->schema->nodetype & (LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_ANYXML))) {
Radek Krejcie4748472015-07-08 18:00:22 +02002511 /* free children */
2512 LY_TREE_FOR_SAFE(node->child, next, child) {
Radek Krejci912da452015-07-29 14:10:06 +02002513 lyd_free(child);
Radek Krejcie4748472015-07-08 18:00:22 +02002514 }
Michal Vaskoab8e4402015-07-17 12:54:28 +02002515 } else if (node->schema->nodetype == LY_NODE_ANYXML) {
2516 lyxml_free_elem(((struct lyd_node_anyxml *)node)->ctx, ((struct lyd_node_anyxml *)node)->value);
Radek Krejcie4748472015-07-08 18:00:22 +02002517 } else {
2518 /* free value */
2519 switch(((struct lyd_node_leaf *)node)->value_type) {
2520 case LY_TYPE_BINARY:
2521 case LY_TYPE_STRING:
2522 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf *)node)->value.string);
2523 break;
Radek Krejci3e3affe2015-07-09 15:38:40 +02002524 case LY_TYPE_BITS:
2525 if (((struct lyd_node_leaf *)node)->value.bit) {
2526 free(((struct lyd_node_leaf *)node)->value.bit);
2527 }
2528 break;
Radek Krejcie4748472015-07-08 18:00:22 +02002529 default:
Radek Krejci7511f402015-07-10 09:56:30 +02002530 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
Radek Krejcie4748472015-07-08 18:00:22 +02002531 break;
2532 }
Radek Krejcib20c62d2015-07-07 17:07:14 +02002533 }
2534
2535 if (node->prev->next) {
2536 node->prev->next = node->next;
2537 } else if (node->parent) {
2538 /* first node */
2539 node->parent->child = node->next;
2540 }
2541 if (node->next) {
2542 node->next->prev = node->prev;
2543 }
2544
2545 free(node);
2546}
Michal Vaskof54f2f82015-07-17 13:12:05 +02002547
2548API void
2549lyd_node_siblings_free(struct lyd_node *node)
2550{
2551 struct lyd_node *next, *sibling;
2552
2553 if (!node) {
2554 return;
2555 }
2556
2557 if (node->schema->nodetype & (LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_ANYXML)) {
Radek Krejci912da452015-07-29 14:10:06 +02002558 lyd_free(node);
Michal Vaskof54f2f82015-07-17 13:12:05 +02002559 } else {
2560 LY_TREE_FOR_SAFE(node, next, sibling) {
Radek Krejci912da452015-07-29 14:10:06 +02002561 lyd_free(sibling);
Michal Vaskof54f2f82015-07-17 13:12:05 +02002562 }
2563 }
2564}
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002565
2566API int
2567lyd_islast(struct lyd_node *node)
2568{
2569 struct lyd_node *n;
2570
2571 if (!node->next) {
2572 return 1;
2573 }
2574
2575 for (n = node->next; n; n = n->next) {
2576 switch (n->schema->nodetype) {
2577 case LY_NODE_LIST:
2578 if (!((struct lyd_node_list *)n)->lprev) {
2579 return 0;
2580 }
2581 break;
2582 case LY_NODE_LEAFLIST:
2583 if (!((struct lyd_node_leaflist *)n)->lprev) {
2584 return 0;
2585 }
2586 break;
2587 default:
2588 return 0;
2589 }
2590 }
2591 return 1;
2592}