blob: 95ef8599c27d6cde42ff6371dc57bf07919e795b [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 */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020021#define _GNU_SOURCE
Radek Krejcida04f4a2015-05-21 12:54:09 +020022
Radek Krejci812b10a2015-05-28 16:48:25 +020023#include <assert.h>
Radek Krejci5a988152015-07-15 11:16:26 +020024#include <ctype.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020025#include <stdlib.h>
26#include <sys/mman.h>
27#include <sys/stat.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020028#include <string.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020029
30#include "common.h"
31#include "context.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020032#include "parse.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020033#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020034#include "resolve.h"
Radek Krejci106efc02015-06-10 14:36:27 +020035#include "xml.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020036#include "tree_internal.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020037
Radek Krejci48061fb2015-08-05 15:41:07 +020038API struct lys_feature *
39lys_is_disabled(struct lys_node *node, int recursive)
40{
41 int i;
42
43check:
44 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
45 /* input/output does not have if-feature, so skip them */
46
47 /* check local if-features */
48 for (i = 0; i < node->features_size; i++) {
49 if (!(node->features[i]->flags & LYS_FENABLED)) {
50 return node->features[i];
51 }
52 }
53 }
54
55 if (!recursive) {
56 return NULL;
57 }
58
59 /* go through parents */
60 if (node->nodetype == LYS_AUGMENT) {
61 /* go to parent actually means go to the target node */
62 node = ((struct lys_node_augment *)node)->target;
63 goto check;
64 } else if (node->parent) {
65 node = node->parent;
66 goto check;
67 }
68
69 return NULL;
70}
71
Radek Krejci7f40ce32015-08-12 20:38:46 +020072static struct lys_node *
73check_mand_getnext(struct lys_node *cur, struct lys_node *parent)
74{
75 struct lys_node *next;
76
77 if (!cur) {
78 next = parent->child;
79 } else {
80 next = cur->next;
81 }
82
83repeat:
84 while (next && (next->nodetype == LYS_AUGMENT || (next->nodetype & (LYS_AUGMENT | LYS_GROUPING | LYS_LEAFLIST)))) {
85 next = cur = next->next;
86 }
87
88 while (!next) {
89 if (cur->parent == parent) {
90 /* no next element */
91 return NULL;
92 }
93 cur = cur->parent;
94 next = cur->next;
95 goto repeat;
96 }
97
98 switch (next->nodetype) {
99 case LYS_CONTAINER:
100 if (((struct lys_node_container *)next)->presence) {
101 /* mandatory elements under the non-existing presence
102 * container are not mandatory - 7.6.5, rule 1 */
103 next = next->next;
104 goto repeat;
105 }
106 /* no break */
107 case LYS_LIST:
108 case LYS_USES:
109 case LYS_CASE:
110 /* go into */
111 next = next->child;
112 goto repeat;
113 case LYS_LEAF:
114 case LYS_CHOICE:
115 case LYS_ANYXML:
116 return next;
117 default:
118 /* we should not be here */
119 return NULL;
120 }
121}
122
123static struct lys_node *
124check_mand_check(struct lys_node *node, struct lys_node *stop, struct lyd_node *data)
125{
126 struct lys_node *siter = NULL, *parent;
127 struct lyd_node *diter = NULL;
128
129 if (node->flags & LYS_MAND_TRUE) {
130 switch (node->nodetype) {
131 case LYS_LEAF:
132 case LYS_ANYXML:
133 case LYS_CHOICE:
134 if (node->parent->nodetype == LYS_CASE) {
135 /* 7.6.5, rule 2 */
136 /* 7.9.4, rule 1 */
137 if (node->parent->parent->parent == data->schema) {
138 /* the only case the node's siblings can exist is that the
139 * data node passed originaly to ly_check_mandatory()
140 * had this choice as a child
141 */
142 /* try to find the node's siblings in data */
143 LY_TREE_FOR(data->child, diter) {
144 LY_TREE_FOR(node->parent->child, siter) {
145 if (siter == diter->schema) {
146 /* some sibling exists, rule applies */
147 break;
148 }
149 }
150 if (siter) {
151 break;
152 }
153 }
154 }
155 if (!siter) {
156 /* no sibling exists */
157 return NULL;
158 }
159 } else {
160 for(parent = node->parent; parent != stop; parent = parent->parent) {
161 if (parent->nodetype != LYS_CONTAINER) {
162 /* 7.6.5, rule 1, checking presence is not needed
163 * since it is done in check_mand_getnext()
164 */
165 return NULL;
166 }
167 }
168 }
169 /* 7.6.5, rule 3 (or 2) */
170 /* 7.9.4, rule 2 */
171 return node;
172 default:
173 /* error */
174 break;
175 }
176 }
177
178 return NULL;
179}
180
181struct lys_node *
182ly_check_mandatory(struct lyd_node *data)
183{
184 struct lys_node *siter, *saux = NULL, *result, *parent = NULL;
185 struct lyd_node *diter;
186 int found;
187
188 siter = data->schema->child;
189
190repeat:
191 while (siter) {
192 switch (siter->nodetype) {
193 case LYS_CONTAINER:
194 case LYS_LEAF:
195 case LYS_ANYXML:
196 /* search for instance */
197 LY_TREE_FOR(data->child, diter) {
198 if (diter->schema == siter) {
199 break;
200 }
201 }
202 if (diter) {
203 /* result has a child defined by siter, check another siter */
204 siter = siter->next;
205 break;
206 }
207
208 /* the siter has no instance under the result, check if there is
209 * some mandatory node; first the siter itself ... */
210 result = check_mand_check(siter, siter->parent, data);
211 if (result) {
212 return result;
213 }
214 /* ... and then the subtree */
215 if (siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
216 while ((saux = check_mand_getnext(saux, siter))) {
217 result = check_mand_check(saux, siter, data);
218 if (result) {
219 return result;
220 }
221 }
222 }
223 siter = siter->next;
224 break;
225 case LYS_CHOICE:
226 if (siter->flags & LYS_MAND_TRUE) {
227 /* search for instance */
228 saux = siter;
229 parent = NULL;
230 siter = siter->child;
231 found = 0;
232repeat_choice:
233 while (siter) {
234 switch(siter->nodetype) {
235 case LYS_CONTAINER:
236 case LYS_LEAF:
237 case LYS_LEAFLIST:
238 case LYS_LIST:
239 case LYS_ANYXML:
240 LY_TREE_FOR(data->child, diter) {
241 if (diter->schema == siter) {
242 break;
243 }
244 }
245 if (diter) {
246 /* got instance, done */
247 siter = parent = NULL;
248 found = 1;
249 break;
250 }
251 siter = siter->next;
252 break;
253 case LYS_CASE:
254 case LYS_CHOICE:
255 case LYS_USES:
256 /* go into */
257 parent = siter;
258 siter = siter->child;
259 break;
260 case LYS_AUGMENT:
261 case LYS_GROUPING:
262 /* skip */
263 siter = siter->next;
264 break;
265 default:
266 /* error */
267 break;
268 }
269 }
270
271 if (parent) {
272 siter = parent->next;
273 if (parent->parent == saux) {
274 parent = NULL;
275 } else {
276 parent = parent->parent;
277 }
278 goto repeat_choice;
279 }
280
281 if (!found) {
282 return saux;
283 }
284
285 siter = saux;
286 }
287
288 /* go into */
289 parent = siter;
290 siter = siter->child;
291 break;
292 case LYS_USES:
293 case LYS_CASE:
294 /* go into */
295 parent = siter;
296 siter = siter->child;
297 break;
298 default:
299 /* can ignore, go to next */
300 siter = siter->next;
301 break;
302 }
303 }
304
305 if (parent) {
306 siter = parent->next;
307 if (parent->parent == data->schema) {
308 parent = NULL;
309 } else {
310 parent = parent->parent;
311 }
312 goto repeat;
313 }
314
315 return NULL;
316}
317
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200318void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200319lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200320{
Radek Krejci76512572015-08-04 09:47:08 +0200321 struct lys_node *parent, *first;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200322
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200323 if (!node) {
324 return;
325 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200326
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200327 /* unlink from data model if necessary */
328 if (node->module) {
329 if (node->module->data == node) {
330 node->module->data = node->next;
Radek Krejci21181962015-06-30 14:11:00 +0200331 } else if (node->module->rpc == node) {
332 node->module->rpc = node->next;
333 } else if (node->module->notif == node) {
334 node->module->notif = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200335 }
336 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200337
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200338 /* store pointers to important nodes */
339 parent = node->parent;
340 if (parent && !parent->nodetype) {
341 /* handle augments - first, unlink it from the augment parent ... */
342 if (parent->child == node) {
343 parent->child = node->next;
344 }
345 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200346 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200347 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200348
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200349 /* unlink from parent */
350 if (parent) {
351 if (parent->child == node) {
352 parent->child = node->next;
353 }
354 node->parent = NULL;
355 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200357 /* unlink from siblings */
358 if (node->prev == node) {
359 /* there are no more siblings */
360 return;
361 }
362 if (node->next) {
363 node->next->prev = node->prev;
364 } else {
365 /* unlinking the last element */
366 if (parent) {
367 first = parent->child;
368 } else {
369 first = node;
370 while (node->prev->next) {
371 first = node->prev;
372 }
373 }
374 first->prev = node->prev;
375 }
376 if (node->prev->next) {
377 node->prev->next = node->next;
378 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200380 /* clean up the unlinked element */
381 node->next = NULL;
382 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200383}
384
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200385int
Radek Krejci1d82ef62015-08-07 14:44:40 +0200386lys_node_addchild(struct lys_node *parent, struct lys_node *child)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200387{
Radek Krejci76512572015-08-04 09:47:08 +0200388 struct lys_node *last;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200389
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200390 assert(parent);
391 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200392
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200393 /* checks */
394 switch (parent->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +0200395 case LYS_CONTAINER:
396 case LYS_LIST:
397 case LYS_GROUPING:
398 case LYS_USES:
399 case LYS_INPUT:
400 case LYS_OUTPUT:
401 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200402 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200403 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
404 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200405 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200406 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
407 return EXIT_FAILURE;
408 }
409 break;
Radek Krejci76512572015-08-04 09:47:08 +0200410 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200411 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200412 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200413 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"choice\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200414 strnodetype(child->nodetype), parent->name);
415 return EXIT_FAILURE;
416 }
417 break;
Radek Krejci76512572015-08-04 09:47:08 +0200418 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200419 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200420 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200421 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"case\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200422 strnodetype(child->nodetype), parent->name);
423 return EXIT_FAILURE;
424 }
425 break;
Radek Krejci76512572015-08-04 09:47:08 +0200426 case LYS_RPC:
427 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200428 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"rpc\" %s.",
Michal Vasko38d01f72015-06-15 09:41:06 +0200429 strnodetype(child->nodetype), parent->name);
430 return EXIT_FAILURE;
431 }
432 break;
Radek Krejci76512572015-08-04 09:47:08 +0200433 case LYS_LEAF:
434 case LYS_LEAFLIST:
435 case LYS_ANYXML:
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200436 LOGVAL(LYE_SPEC, 0, "The \"%s\" statement (%s) cannot have any substatement.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200437 strnodetype(parent->nodetype), parent->name);
438 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200439 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200440 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200441 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
442 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200443 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200444 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
445 return EXIT_FAILURE;
446 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200447 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200448
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200449 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200450 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200451 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200452
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200453 if (!parent->child) {
454 /* the only/first child of the parent */
455 parent->child = child;
456 child->parent = parent;
457 last = child;
458 } else {
459 /* add a new child at the end of parent's child list */
460 last = parent->child->prev;
461 last->next = child;
462 child->prev = last;
463 }
464 while (last->next) {
465 last = last->next;
466 last->parent = parent;
467 }
468 parent->child->prev = last;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200469
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200470 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200471}
472
Radek Krejcib8048692015-08-05 13:36:34 +0200473API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +0200474lys_parse(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200475{
Michal Vaskof02e3742015-08-05 16:27:02 +0200476 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200477 struct lys_module *mod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200478
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200479 if (!ctx || !data) {
480 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
481 return NULL;
482 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200483
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200484 unres = calloc(1, sizeof *unres);
485
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200486 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200487 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200488 mod = yin_read_module(ctx, data, 1, unres);
489 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200490 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200491 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +0200492 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200493 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200494 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200495
Radek Krejci0b5805d2015-08-13 09:38:02 +0200496 if (mod && unres->count && resolve_unres(mod, unres)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200497 lys_free(mod);
498 mod = NULL;
499 }
500 free(unres->item);
501 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +0200502 free(unres->str_snode);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200503 free(unres->line);
504 free(unres);
505
506 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200507}
508
Radek Krejcib8048692015-08-05 13:36:34 +0200509struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +0200510lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +0200511{
Michal Vaskof02e3742015-08-05 16:27:02 +0200512 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200513 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200514
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200515 assert(module);
516 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200517
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200518 unres = calloc(1, sizeof *unres);
519
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200520 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200521 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200522 submod = yin_read_submodule(module, data, implement, unres);
523 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200524 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200525 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +0200526 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200527 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200528 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200529
Radek Krejci0b5805d2015-08-13 09:38:02 +0200530 if (submod && unres->count && resolve_unres((struct lys_module *)submod, unres)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200531 lys_submodule_free(submod);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200532 submod = NULL;
533 }
534 free(unres->item);
535 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +0200536 free(unres->str_snode);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200537 free(unres->line);
538 free(unres);
539
540 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +0200541}
542
Radek Krejcib8048692015-08-05 13:36:34 +0200543API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +0200544lys_read(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +0200545{
Radek Krejcib8048692015-08-05 13:36:34 +0200546 struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +0200547 struct stat sb;
548 char *addr;
549
550 if (!ctx || fd < 0) {
551 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
552 return NULL;
553 }
554
555 /*
556 * TODO
557 * This is just a temporary solution to make working automatic search for
558 * imported modules. This doesn't work e.g. for streams (stdin)
559 */
560 fstat(fd, &sb);
561 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
562 module = lys_parse(ctx, addr, format);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200563 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200564
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200565 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200566}
567
Radek Krejcib8048692015-08-05 13:36:34 +0200568struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +0200569lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +0200570{
Radek Krejcib8048692015-08-05 13:36:34 +0200571 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200572 struct stat sb;
573 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +0200574
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200575 assert(module);
576 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +0200577
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200578 /*
579 * TODO
580 * This is just a temporary solution to make working automatic search for
581 * imported modules. This doesn't work e.g. for streams (stdin)
582 */
583 fstat(fd, &sb);
584 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
585 /* TODO addr error check */
Radek Krejci1d82ef62015-08-07 14:44:40 +0200586 submodule = lys_submodule_parse(module, addr, format, implement);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200587 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +0200588
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200589 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +0200590
591}
592
Radek Krejci1d82ef62015-08-07 14:44:40 +0200593static struct lys_restr *
594lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200595{
Radek Krejci1574a8d2015-08-03 14:16:52 +0200596 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200597 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200598
Radek Krejci3733a802015-06-19 13:43:21 +0200599 if (!size) {
600 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200601 }
Radek Krejci3733a802015-06-19 13:43:21 +0200602
603 result = calloc(size, sizeof *result);
604 for (i = 0; i < size; i++) {
605 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
606 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
607 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
608 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
609 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
610 }
611
612 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200613}
614
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200615void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200616lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +0200617{
618 assert(ctx);
619 if (!restr) {
620 return;
621 }
622
623 lydict_remove(ctx, restr->expr);
624 lydict_remove(ctx, restr->dsc);
625 lydict_remove(ctx, restr->ref);
626 lydict_remove(ctx, restr->eapptag);
627 lydict_remove(ctx, restr->emsg);
628}
629
Radek Krejci1d82ef62015-08-07 14:44:40 +0200630static void
631lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
Michal Vaskof02e3742015-08-05 16:27:02 +0200632 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +0200633{
634 int i;
635
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200636 new->prefix = lydict_insert(mod->ctx, old->prefix, 0);
Radek Krejci3733a802015-06-19 13:43:21 +0200637 new->base = old->base;
638 new->der = old->der;
639
Radek Krejci1d82ef62015-08-07 14:44:40 +0200640 i = unres_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200641 if (i != -1) {
642 /* HACK for unres */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200643 new->der = (struct lys_tpdf *)parent;
Radek Krejci1d82ef62015-08-07 14:44:40 +0200644 unres_add_str(mod, unres, new, UNRES_TYPE_DER, unres->str_snode[i], 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200645 return;
646 }
647
Radek Krejci3733a802015-06-19 13:43:21 +0200648 switch (new->base) {
649 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +0200650 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200651 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +0200652 }
Radek Krejci3733a802015-06-19 13:43:21 +0200653 break;
654
655 case LY_TYPE_BITS:
656 new->info.bits.count = old->info.bits.count;
657 if (new->info.bits.count) {
658 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
659 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200660 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
661 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
662 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Radek Krejci3733a802015-06-19 13:43:21 +0200663 new->info.bits.bit[i].status = old->info.bits.bit[i].status;
664 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
665 }
666 }
667 break;
668
Radek Krejcif9401c32015-06-26 16:47:36 +0200669 case LY_TYPE_DEC64:
670 new->info.dec64.dig = old->info.dec64.dig;
671 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200672 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +0200673 }
674 break;
675
Radek Krejci3733a802015-06-19 13:43:21 +0200676 case LY_TYPE_ENUM:
677 new->info.enums.count = old->info.enums.count;
678 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200679 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Radek Krejci3733a802015-06-19 13:43:21 +0200680 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200681 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
682 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
683 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
684 new->info.enums.enm[i].status = old->info.enums.enm[i].status;
685 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +0200686 }
687 }
688 break;
689
Radek Krejci4a7b5ee2015-06-19 14:56:43 +0200690 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200691 if (old->info.ident.ref) {
692 new->info.ident.ref = old->info.ident.ref;
693 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200694 i = unres_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200695 assert(i != -1);
Radek Krejci1d82ef62015-08-07 14:44:40 +0200696 unres_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i], 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200697 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +0200698 break;
699
Radek Krejciaf351422015-06-19 14:49:38 +0200700 case LY_TYPE_INST:
701 new->info.inst.req = old->info.inst.req;
702 break;
703
Radek Krejcif2860132015-06-20 12:37:20 +0200704 case LY_TYPE_INT8:
705 case LY_TYPE_INT16:
706 case LY_TYPE_INT32:
707 case LY_TYPE_INT64:
708 case LY_TYPE_UINT8:
709 case LY_TYPE_UINT16:
710 case LY_TYPE_UINT32:
711 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +0200712 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200713 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +0200714 }
Radek Krejcif2860132015-06-20 12:37:20 +0200715 break;
716
Radek Krejcidc4c1412015-06-19 15:39:54 +0200717 case LY_TYPE_LEAFREF:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200718 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Radek Krejci1d82ef62015-08-07 14:44:40 +0200719 unres_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200720 break;
721
Radek Krejci3733a802015-06-19 13:43:21 +0200722 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +0200723 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200724 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200725 }
Radek Krejci1d82ef62015-08-07 14:44:40 +0200726 new->info.str.patterns = lys_restr_dup(mod->ctx, old->info.str.patterns, old->info.str.pat_count);
Radek Krejci3733a802015-06-19 13:43:21 +0200727 break;
728
Radek Krejcie4c366b2015-07-02 10:11:31 +0200729 case LY_TYPE_UNION:
730 new->info.uni.count = old->info.uni.count;
731 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200732 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200733 for (i = 0; i < new->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200734 lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200735 }
736 }
737 break;
738
Radek Krejci3733a802015-06-19 13:43:21 +0200739 default:
Radek Krejcic7c85532015-07-02 10:16:54 +0200740 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +0200741 break;
742 }
743}
744
745void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200746lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +0200747{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200748 int i;
Radek Krejci5a065542015-05-22 15:02:07 +0200749
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200750 assert(ctx);
751 if (!type) {
752 return;
753 }
Radek Krejci812b10a2015-05-28 16:48:25 +0200754
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200755 lydict_remove(ctx, type->prefix);
Radek Krejci5a065542015-05-22 15:02:07 +0200756
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200757 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +0200758 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +0200759 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +0200760 free(type->info.binary.length);
761 break;
Radek Krejci994b6f62015-06-18 16:47:27 +0200762 case LY_TYPE_BITS:
763 for (i = 0; i < type->info.bits.count; i++) {
764 lydict_remove(ctx, type->info.bits.bit[i].name);
765 lydict_remove(ctx, type->info.bits.bit[i].dsc);
766 lydict_remove(ctx, type->info.bits.bit[i].ref);
767 }
768 free(type->info.bits.bit);
769 break;
Radek Krejcif9401c32015-06-26 16:47:36 +0200770
771 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +0200772 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +0200773 free(type->info.dec64.range);
774 break;
775
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200776 case LY_TYPE_ENUM:
777 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200778 lydict_remove(ctx, type->info.enums.enm[i].name);
779 lydict_remove(ctx, type->info.enums.enm[i].dsc);
780 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200781 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200782 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200783 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +0200784
Radek Krejci6fcb9dd2015-06-22 10:16:37 +0200785 case LY_TYPE_INT8:
786 case LY_TYPE_INT16:
787 case LY_TYPE_INT32:
788 case LY_TYPE_INT64:
789 case LY_TYPE_UINT8:
790 case LY_TYPE_UINT16:
791 case LY_TYPE_UINT32:
792 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +0200793 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +0200794 free(type->info.num.range);
795 break;
796
Radek Krejcidc4c1412015-06-19 15:39:54 +0200797 case LY_TYPE_LEAFREF:
798 lydict_remove(ctx, type->info.lref.path);
799 break;
800
Radek Krejci3733a802015-06-19 13:43:21 +0200801 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +0200802 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +0200803 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200804 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200805 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200806 }
807 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +0200808 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +0200809
Radek Krejcie4c366b2015-07-02 10:11:31 +0200810 case LY_TYPE_UNION:
811 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200812 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200813 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200814 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +0200815 break;
816
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200817 default:
Radek Krejcic7c85532015-07-02 10:16:54 +0200818 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200819 break;
820 }
Radek Krejci5a065542015-05-22 15:02:07 +0200821}
822
Radek Krejci1d82ef62015-08-07 14:44:40 +0200823static struct lys_tpdf *
824lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200825{
Radek Krejci1574a8d2015-08-03 14:16:52 +0200826 struct lys_tpdf *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200827 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200828
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200829 if (!size) {
830 return NULL;
831 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200832
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200833 result = calloc(size, sizeof *result);
834 for (i = 0; i < size; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200835 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
836 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
837 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200838 result[i].flags = old[i].flags;
839 result[i].module = old[i].module;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200840
Radek Krejci1d82ef62015-08-07 14:44:40 +0200841 lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres);
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200842
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200843 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
844 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200845 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200846
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200847 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200848}
849
Radek Krejci1d82ef62015-08-07 14:44:40 +0200850static void
851lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200852{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200853 assert(ctx);
854 if (!tpdf) {
855 return;
856 }
Radek Krejci812b10a2015-05-28 16:48:25 +0200857
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200858 lydict_remove(ctx, tpdf->name);
859 lydict_remove(ctx, tpdf->dsc);
860 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200861
Radek Krejci1d82ef62015-08-07 14:44:40 +0200862 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200863
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200864 lydict_remove(ctx, tpdf->units);
865 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200866}
867
Radek Krejci1d82ef62015-08-07 14:44:40 +0200868static struct lys_when *
869lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +0200870{
Radek Krejci76512572015-08-04 09:47:08 +0200871 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +0200872
873 if (!old) {
874 return NULL;
875 }
876
877 new = calloc(1, sizeof *new);
878 new->cond = lydict_insert(ctx, old->cond, 0);
879 new->dsc = lydict_insert(ctx, old->dsc, 0);
880 new->ref = lydict_insert(ctx, old->ref, 0);
881
882 return new;
883}
884
Radek Krejci1d82ef62015-08-07 14:44:40 +0200885static void
886lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200887{
888 if (!w) {
889 return;
890 }
891
892 lydict_remove(ctx, w->cond);
893 lydict_remove(ctx, w->dsc);
894 lydict_remove(ctx, w->ref);
895
896 free(w);
897}
898
Radek Krejcib7f5e412015-08-13 10:15:51 +0200899static void
900lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment aug)
901{
902 struct lys_node *child, *sub;
903
904 lydict_remove(ctx, aug.target_name);
905 lydict_remove(ctx, aug.dsc);
906 lydict_remove(ctx, aug.ref);
907
908 free(aug.features);
909
910 lys_when_free(ctx, aug.when);
911
912 LY_TREE_FOR_SAFE(aug.child, child, sub) {
913 lys_node_free(sub);
914 }
915}
916
Radek Krejci76512572015-08-04 09:47:08 +0200917static struct lys_node_augment *
Radek Krejci1d82ef62015-08-07 14:44:40 +0200918lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size,
Michal Vasko41de7352015-08-06 09:53:34 +0200919 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +0200920{
Radek Krejci76512572015-08-04 09:47:08 +0200921 struct lys_node_augment *new = NULL;
Michal Vasko41de7352015-08-06 09:53:34 +0200922 struct lys_node *snode;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200923 int i = -1;
Radek Krejci106efc02015-06-10 14:36:27 +0200924
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200925 if (!size) {
926 return NULL;
927 }
Radek Krejci106efc02015-06-10 14:36:27 +0200928
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200929 new = calloc(size, sizeof *new);
930 for (i = 0; i < size; i++) {
931 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
932 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
933 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
934 new[i].flags = old[i].flags;
935 /* .target = NULL; .nodetype = 0 */
Radek Krejci106efc02015-06-10 14:36:27 +0200936
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200937 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +0200938
Michal Vasko41de7352015-08-06 09:53:34 +0200939 /* copy the augment nodes */
940 assert(old[i].child);
941 LY_TREE_FOR(old[i].child, snode) {
Radek Krejcib7f5e412015-08-13 10:15:51 +0200942 if (lys_node_addchild((struct lys_node *)&new[i], lys_node_dup(module, snode, snode->flags, snode->nacm, 1, unres))) {
943 for ( ; i >= 0; i--) {
944 lys_augment_free(module->ctx, new[i]);
945 }
946 free(new);
947 return NULL;
948 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200949 }
950 }
Radek Krejci106efc02015-06-10 14:36:27 +0200951
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200952 return new;
Radek Krejci106efc02015-06-10 14:36:27 +0200953}
954
Radek Krejci76512572015-08-04 09:47:08 +0200955static struct lys_refine *
Radek Krejci1d82ef62015-08-07 14:44:40 +0200956lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size, struct lys_node_uses *uses,
Michal Vaskof02e3742015-08-05 16:27:02 +0200957 struct unres_schema *unres)
Michal Vasko1982cad2015-06-08 15:49:30 +0200958{
Radek Krejci76512572015-08-04 09:47:08 +0200959 struct lys_refine *result;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200960 int i, j;
Michal Vasko1982cad2015-06-08 15:49:30 +0200961
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200962 if (!size) {
963 return NULL;
964 }
Michal Vasko1982cad2015-06-08 15:49:30 +0200965
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200966 result = calloc(size, sizeof *result);
967 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +0200968 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200969 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
970 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200971 result[i].flags = old[i].flags;
972 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200973
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200974 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +0200975 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200976 for (j = 0; j < result[i].must_size; ++j) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200977 unres_add_node(mod, unres, &result[i].must[j], UNRES_MUST, (struct lys_node *)uses, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200978 }
979
Radek Krejci76512572015-08-04 09:47:08 +0200980 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200981 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +0200982 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200983 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +0200984 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200985 result[i].mod.list = old[i].mod.list;
986 }
987 }
Michal Vasko1982cad2015-06-08 15:49:30 +0200988
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200989 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +0200990}
991
Radek Krejci1d82ef62015-08-07 14:44:40 +0200992static void
993lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +0200994{
Radek Krejcia52656e2015-08-05 13:41:50 +0200995 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +0200996
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200997 assert(ctx);
998 if (!ident) {
999 return;
1000 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001001
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001002 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001003 * if caller free only a single data model which is used (its identity is
1004 * reference from identity in another module), this silly freeing can lead
1005 * to segmentation fault. But without noting if the module is used by some
1006 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001007 *
1008 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001009 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001010 */
1011 while (ident->der) {
1012 der = ident->der;
1013 ident->der = der->next;
1014 free(der);
1015 }
Radek Krejci6793db02015-05-22 17:49:54 +02001016
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001017 lydict_remove(ctx, ident->name);
1018 lydict_remove(ctx, ident->dsc);
1019 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001020
1021}
1022
Radek Krejci1d82ef62015-08-07 14:44:40 +02001023static void
1024lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001025{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001026 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001027
Radek Krejcid12f57b2015-08-06 10:43:39 +02001028 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001029 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001030 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001031 }
1032 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001033}
1034
Radek Krejci1d82ef62015-08-07 14:44:40 +02001035static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001036lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1037{
1038 int i;
1039
1040 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1041 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001042 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001043 }
1044 free(io->tpdf);
1045}
1046
Radek Krejci1d82ef62015-08-07 14:44:40 +02001047static void
1048lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001049{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001050 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001051
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001052 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001053 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001054 }
1055 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001056
Radek Krejci1d82ef62015-08-07 14:44:40 +02001057 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001058}
1059
Radek Krejci1d82ef62015-08-07 14:44:40 +02001060static void
1061lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001062{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001063 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001064
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001065 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001066 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001067 }
1068 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001069
Radek Krejci1d82ef62015-08-07 14:44:40 +02001070 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001071
Radek Krejci1d82ef62015-08-07 14:44:40 +02001072 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001073 lydict_remove(ctx, leaf->units);
1074 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001075}
1076
Radek Krejci1d82ef62015-08-07 14:44:40 +02001077static void
1078lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001079{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001080 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001081
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001082 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001083 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001084 }
1085 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001086
Radek Krejci1d82ef62015-08-07 14:44:40 +02001087 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001088
Radek Krejci1d82ef62015-08-07 14:44:40 +02001089 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001090 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001091}
1092
Radek Krejci1d82ef62015-08-07 14:44:40 +02001093static void
1094lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001095{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001096 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001097
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001098 /* handle only specific parts for LY_NODE_LIST */
1099 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001100 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001101 }
1102 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001104 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001105 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001106 }
1107 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001108
Radek Krejci1d82ef62015-08-07 14:44:40 +02001109 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001110
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001111 for (i = 0; i < list->unique_size; i++) {
1112 free(list->unique[i].leafs);
1113 }
1114 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001115
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001116 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001117}
1118
Radek Krejci1d82ef62015-08-07 14:44:40 +02001119static void
1120lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001121{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001122 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001123
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001124 /* handle only specific parts for LY_NODE_CONTAINER */
1125 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001126
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001127 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001128 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001129 }
1130 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001131
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001132 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001133 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001134 }
1135 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001136
Radek Krejci1d82ef62015-08-07 14:44:40 +02001137 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001138}
1139
Radek Krejci1d82ef62015-08-07 14:44:40 +02001140static void
1141lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001142{
1143 lydict_remove(ctx, f->name);
1144 lydict_remove(ctx, f->dsc);
1145 lydict_remove(ctx, f->ref);
1146 free(f->features);
1147}
1148
Radek Krejci1d82ef62015-08-07 14:44:40 +02001149static void
1150lys_deviation_free(struct ly_ctx *ctx, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001151{
1152 int i, j;
1153
1154 lydict_remove(ctx, dev->target_name);
1155 lydict_remove(ctx, dev->dsc);
1156 lydict_remove(ctx, dev->ref);
1157
1158 for (i = 0; i < dev->deviate_size; i++) {
1159 lydict_remove(ctx, dev->deviate[i].dflt);
1160 lydict_remove(ctx, dev->deviate[i].units);
1161
1162 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1163 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001164 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001165 }
1166 free(dev->deviate[i].must);
1167
1168 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1169 free(dev->deviate[j].unique[j].leafs);
1170 }
1171 free(dev->deviate[i].unique);
1172 }
1173 }
1174 free(dev->deviate);
1175}
1176
Radek Krejci1d82ef62015-08-07 14:44:40 +02001177static void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001178lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +02001179{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001180 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001181
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001182 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001183 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001184 lydict_remove(ctx, uses->refine[i].dsc);
1185 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001186
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001187 for (j = 0; j < uses->refine[j].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001188 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001189 }
1190 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001191
Radek Krejci76512572015-08-04 09:47:08 +02001192 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001193 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001194 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001195 lydict_remove(ctx, uses->refine[i].mod.presence);
1196 }
1197 }
1198 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001199
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001200 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001201 lys_augment_free(ctx, uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001202 }
1203 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001204
Radek Krejci1d82ef62015-08-07 14:44:40 +02001205 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001206}
1207
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001208void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001209lys_node_free(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001210{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001211 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001212 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001213
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001214 if (!node) {
1215 return;
1216 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001217
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001218 assert(node->module);
1219 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001220
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001221 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001222
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001223 /* common part */
1224 LY_TREE_FOR_SAFE(node->child, next, sub) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001225 lys_node_free(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001226 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001227
Radek Krejcid12f57b2015-08-06 10:43:39 +02001228 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1229 free(node->features);
1230 lydict_remove(ctx, node->name);
1231 lydict_remove(ctx, node->dsc);
1232 lydict_remove(ctx, node->ref);
1233 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001234
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001235 /* specific part */
1236 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001237 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001238 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001239 break;
Radek Krejci76512572015-08-04 09:47:08 +02001240 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001241 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001242 break;
Radek Krejci76512572015-08-04 09:47:08 +02001243 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001244 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001245 break;
Radek Krejci76512572015-08-04 09:47:08 +02001246 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001247 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001248 break;
Radek Krejci76512572015-08-04 09:47:08 +02001249 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001250 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001251 break;
Radek Krejci76512572015-08-04 09:47:08 +02001252 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001253 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001254 break;
Radek Krejci76512572015-08-04 09:47:08 +02001255 case LYS_USES:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001256 lys_uses_free(ctx, (struct lys_node_uses *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001257 break;
Radek Krejci76512572015-08-04 09:47:08 +02001258 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001259 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001260 break;
Radek Krejci76512572015-08-04 09:47:08 +02001261 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001262 /* do nothing */
1263 break;
Radek Krejci76512572015-08-04 09:47:08 +02001264 case LYS_GROUPING:
1265 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001266 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001267 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001268 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001269
1270 case LYS_INPUT:
1271 case LYS_OUTPUT:
1272 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1273 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001274 }
Radek Krejci5a065542015-05-22 15:02:07 +02001275
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001276 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001277 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001278 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001279}
1280
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001281static void
Radek Krejcib8048692015-08-05 13:36:34 +02001282module_free_common(struct lys_module *module)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001283{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001284 struct ly_ctx *ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001285 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001286 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001287
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001288 assert(module->ctx);
1289 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001290
Radek Krejcidce51452015-06-16 15:20:08 +02001291 /* as first step, free the imported modules */
1292 for (i = 0; i < module->imp_size; i++) {
1293 /* get the imported module from the context and then free,
1294 * this check is necessary because the imported module can
1295 * be already removed
1296 */
1297 l = ctx->models.used;
1298 for (j = 0; j < l; j++) {
1299 if (ctx->models.list[j] == module->imp[i].module) {
Radek Krejci912da452015-07-29 14:10:06 +02001300 lys_free(module->imp[i].module);
Radek Krejcidce51452015-06-16 15:20:08 +02001301 break;
1302 }
1303 }
1304 }
1305 free(module->imp);
1306
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001307 while (module->data) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001308 lys_node_free(module->data);
Radek Krejci21181962015-06-30 14:11:00 +02001309 }
1310 while (module->rpc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001311 lys_node_free(module->rpc);
Radek Krejci21181962015-06-30 14:11:00 +02001312 }
1313 while (module->notif) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001314 lys_node_free(module->notif);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001315 }
Radek Krejci5a065542015-05-22 15:02:07 +02001316
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001317 lydict_remove(ctx, module->dsc);
1318 lydict_remove(ctx, module->ref);
1319 lydict_remove(ctx, module->org);
1320 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001321
Radek Krejcieb00f512015-07-01 16:44:58 +02001322 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001323 for (i = 0; i < module->rev_size; i++) {
1324 lydict_remove(ctx, module->rev[i].dsc);
1325 lydict_remove(ctx, module->rev[i].ref);
1326 }
1327 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001328
Radek Krejcieb00f512015-07-01 16:44:58 +02001329 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001330 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001331 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001332 }
1333 module->ident_size = 0;
1334 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001335
Radek Krejcieb00f512015-07-01 16:44:58 +02001336 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001337 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001338 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001339 }
1340 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001341
Radek Krejcieb00f512015-07-01 16:44:58 +02001342 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001343 for (i = 0; i < module->inc_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001344 lys_submodule_free(module->inc[i].submodule);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001345 }
1346 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001347
Radek Krejcieb00f512015-07-01 16:44:58 +02001348 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02001349 for (i = 0; i < module->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001350 lys_augment_free(ctx, module->augment[i]);
Radek Krejcif5be10f2015-06-16 13:29:36 +02001351 }
1352 free(module->augment);
1353
Radek Krejcieb00f512015-07-01 16:44:58 +02001354 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001355 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001356 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001357 }
1358 free(module->features);
1359
Radek Krejcieb00f512015-07-01 16:44:58 +02001360 /* deviations */
1361 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001362 lys_deviation_free(ctx, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001363 }
1364 free(module->deviation);
1365
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001366 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02001367}
1368
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001369void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001370lys_submodule_free(struct lys_submodule *submodule)
Radek Krejciefaeba32015-05-27 14:30:57 +02001371{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001372 if (!submodule) {
1373 return;
1374 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001375
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001376 submodule->inc_size = 0;
1377 free(submodule->inc);
1378 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02001379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001380 /* common part with struct ly_module */
Radek Krejcib8048692015-08-05 13:36:34 +02001381 module_free_common((struct lys_module *)submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001382
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001383 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02001384
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001385 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001386}
1387
Radek Krejcib8048692015-08-05 13:36:34 +02001388static struct lys_node_leaf *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001389lys_uniq_find(struct lys_node_list *list, struct lys_node_leaf *orig_leaf)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001390{
Radek Krejci1d82ef62015-08-07 14:44:40 +02001391 struct lys_node *node, *node2, *ret = NULL, *parent1, *parent2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001392 int depth = 1, i;
1393
1394 /* find the correct direct descendant of list in orig_leaf */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001395 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001396 while (1) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001397 if (!node->parent) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001398 return NULL;
1399 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001400 if (!strcmp(node->parent->name, list->name)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001401 break;
1402 }
1403
Radek Krejci1d82ef62015-08-07 14:44:40 +02001404 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001405 ++depth;
1406 }
1407
1408 /* make sure the nodes are equal */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001409 parent1 = node->parent->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001410 parent2 = list->parent;
1411 while (1) {
1412 if ((parent1 && !parent2) || (!parent1 && parent2)) {
1413 return NULL;
1414 }
1415
1416 if (parent1 == parent2) {
1417 break;
1418 }
1419
1420 parent1 = parent1->parent;
1421 parent2 = parent2->parent;
1422 }
1423
1424 /* find the descendant in the list */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001425 LY_TREE_FOR(list->child, node2) {
1426 if (!strcmp(node2->name, node->name)) {
1427 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001428 break;
1429 }
1430 }
1431
1432 if (!ret) {
1433 return NULL;
1434 }
1435
1436 /* continue traversing both trees, the nodes are always truly equal */
1437 while (1) {
1438 --depth;
1439 if (!depth) {
Radek Krejci76512572015-08-04 09:47:08 +02001440 if (ret->nodetype != LYS_LEAF) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001441 return NULL;
1442 }
Radek Krejcib8048692015-08-05 13:36:34 +02001443 return (struct lys_node_leaf *)ret;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001444 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001445 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001446 for (i = 0; i < depth-1; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001447 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001448 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001449 LY_TREE_FOR(ret->child, node2) {
1450 if (!strcmp(node2->name, node->name)) {
1451 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001452 break;
1453 }
1454 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001455 if (!node2) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001456 return NULL;
1457 }
1458 }
1459}
1460
Radek Krejci76512572015-08-04 09:47:08 +02001461struct lys_node *
Michal Vasko71e1aa82015-08-12 12:17:51 +02001462lys_node_dup(struct lys_module *module, struct lys_node *node, uint8_t flags, uint8_t nacm, int recursive,
Michal Vaskof02e3742015-08-05 16:27:02 +02001463 struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001464{
Radek Krejci76512572015-08-04 09:47:08 +02001465 struct lys_node *retval = NULL, *aux, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001466 struct ly_ctx *ctx = module->ctx;
1467 int i, j;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001468
Radek Krejcib8048692015-08-05 13:36:34 +02001469 struct lys_node_container *cont;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001470 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Radek Krejcib8048692015-08-05 13:36:34 +02001471 struct lys_node_choice *choice;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001472 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Radek Krejcib8048692015-08-05 13:36:34 +02001473 struct lys_node_leaf *leaf;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001474 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Radek Krejcib8048692015-08-05 13:36:34 +02001475 struct lys_node_leaflist *llist;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001476 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Radek Krejcib8048692015-08-05 13:36:34 +02001477 struct lys_node_list *list;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001478 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Radek Krejcib8048692015-08-05 13:36:34 +02001479 struct lys_node_anyxml *anyxml;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001480 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Radek Krejcib8048692015-08-05 13:36:34 +02001481 struct lys_node_uses *uses;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001482 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001483 struct lys_node_grp *grp;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001484 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001485 struct lys_node_rpc *rpc;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001486 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001487 struct lys_node_rpc_inout *io;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001488 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001489 struct lys_node_rpc *ntf;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001490 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Radek Krejcib8048692015-08-05 13:36:34 +02001491 struct lys_node_case *cs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001492 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001493
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001494 /* we cannot just duplicate memory since the strings are stored in
1495 * dictionary and we need to update dictionary counters.
1496 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001497
Radek Krejci1d82ef62015-08-07 14:44:40 +02001498 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001499 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001500 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02001501 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001502 break;
1503
Radek Krejci76512572015-08-04 09:47:08 +02001504 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001505 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02001506 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001507 break;
1508
Radek Krejci76512572015-08-04 09:47:08 +02001509 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001510 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02001511 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001512 break;
1513
Radek Krejci76512572015-08-04 09:47:08 +02001514 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001515 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02001516 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001517 break;
1518
Radek Krejci76512572015-08-04 09:47:08 +02001519 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001520 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02001521 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001522 break;
1523
Radek Krejci76512572015-08-04 09:47:08 +02001524 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001525 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02001526 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001527 break;
1528
Radek Krejci76512572015-08-04 09:47:08 +02001529 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001530 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02001531 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001532 break;
1533
Radek Krejci76512572015-08-04 09:47:08 +02001534 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001535 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02001536 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001537 break;
1538
Radek Krejci76512572015-08-04 09:47:08 +02001539 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001540 grp = calloc(1, sizeof *grp);
1541 retval = (struct lys_node *)grp;
1542 break;
1543
Radek Krejci76512572015-08-04 09:47:08 +02001544 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001545 rpc = calloc(1, sizeof *rpc);
1546 retval = (struct lys_node *)rpc;
1547 break;
1548
Radek Krejci76512572015-08-04 09:47:08 +02001549 case LYS_INPUT:
1550 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001551 io = calloc(1, sizeof *io);
1552 retval = (struct lys_node *)io;
1553 break;
1554
Radek Krejci76512572015-08-04 09:47:08 +02001555 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001556 ntf = calloc(1, sizeof *ntf);
1557 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02001558 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001559
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001560 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02001561 LOGINT;
1562 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001563 }
Radek Krejcib388c152015-06-04 17:03:03 +02001564
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001565 /*
1566 * duplicate generic part of the structure
1567 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001568 retval->name = lydict_insert(ctx, node->name, 0);
1569 retval->dsc = lydict_insert(ctx, node->dsc, 0);
1570 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02001571 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001572 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001573 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001574 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001575 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001576 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001577
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001578 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001579 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001580
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001581 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001582
Radek Krejci1d82ef62015-08-07 14:44:40 +02001583 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001584 retval->features = calloc(retval->features_size, sizeof *retval->features);
Radek Krejci1d82ef62015-08-07 14:44:40 +02001585 for (i = 0; i < node->features_size; ++i) {
1586 if (unres_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
1587 retval->features[i] = node->features[i];
Michal Vaskod23ce592015-08-06 09:55:37 +02001588 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001589 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001590
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001591 if (recursive) {
1592 /* go recursively */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001593 LY_TREE_FOR(node->child, child) {
Michal Vasko71e1aa82015-08-12 12:17:51 +02001594 aux = lys_node_dup(module, child, retval->flags, retval->nacm, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02001595 if (!aux || lys_node_addchild(retval, aux)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02001596 LOGINT;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001597 lys_node_free(retval);
Michal Vaskod23ce592015-08-06 09:55:37 +02001598 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001599 }
1600 }
1601 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001602
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001603 /*
1604 * duplicate specific part of the structure
1605 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001606 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001607 case LYS_CONTAINER:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001608 if (cont_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001609 cont->when = lys_when_dup(ctx, cont_orig->when);
1610 unres_add_node(module, unres, cont->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001611 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001612 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001613
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001614 cont->must_size = cont_orig->must_size;
1615 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001616
Radek Krejci1d82ef62015-08-07 14:44:40 +02001617 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001618 for (i = 0; i < cont->must_size; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001619 unres_add_node(module, unres, &cont->must[i], UNRES_MUST, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001620 }
1621
Radek Krejci1d82ef62015-08-07 14:44:40 +02001622 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001623 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001624
Radek Krejci76512572015-08-04 09:47:08 +02001625 case LYS_CHOICE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001626 if (choice_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001627 choice->when = lys_when_dup(ctx, choice_orig->when);
1628 unres_add_node(module, unres, choice->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001629 }
1630
1631 if (choice_orig->dflt) {
Radek Krejci76512572015-08-04 09:47:08 +02001632 choice->dflt = resolve_child((struct lys_node *)choice, choice_orig->dflt->name, 0, LYS_ANYXML
1633 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
1634 | LYS_LIST);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001635 assert(choice->dflt);
1636 } else {
Michal Vaskoc68a2a22015-08-06 09:57:24 +02001637 /* useless to check return value, we don't know whether
1638 * there really wasn't any default defined or it just hasn't
1639 * been resolved, we just hope for the best :)
1640 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001641 unres_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001642 }
1643 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001644
Radek Krejci76512572015-08-04 09:47:08 +02001645 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001646 lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001647 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
1648
1649 if (leaf_orig->dflt) {
1650 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Radek Krejci1d82ef62015-08-07 14:44:40 +02001651 unres_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001652 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001653
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001654 leaf->must_size = leaf_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001655 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001656 for (i = 0; i < leaf->must_size; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001657 unres_add_node(module, unres, &leaf->must[i], UNRES_MUST, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001658 }
Radek Krejci00768f42015-06-18 17:04:04 +02001659
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001660 if (leaf_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001661 leaf->when = lys_when_dup(ctx, leaf_orig->when);
1662 unres_add_node(module, unres, leaf->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001663 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001664 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001665
Radek Krejci76512572015-08-04 09:47:08 +02001666 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001667 lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001668 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001669
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001670 llist->min = llist_orig->min;
1671 llist->max = llist_orig->max;
1672
1673 llist->must_size = llist_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001674 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001675 for (i = 0; i < llist->must_size; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001676 unres_add_node(module, unres, &llist->must[i], UNRES_MUST, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001677 }
Radek Krejci00768f42015-06-18 17:04:04 +02001678
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001679 if (llist_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001680 llist->when = lys_when_dup(ctx, llist_orig->when);
1681 unres_add_node(module, unres, llist->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001682 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001683 break;
1684
Radek Krejci76512572015-08-04 09:47:08 +02001685 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001686 list->min = list_orig->min;
1687 list->max = list_orig->max;
1688
1689 list->must_size = list_orig->must_size;
1690 list->tpdf_size = list_orig->tpdf_size;
1691 list->keys_size = list_orig->keys_size;
1692 list->unique_size = list_orig->unique_size;
1693
Radek Krejci1d82ef62015-08-07 14:44:40 +02001694 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001695 for (i = 0; i < list->must_size; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001696 unres_add_node(module, unres, &list->must[i], UNRES_MUST, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001697 }
1698
Radek Krejci1d82ef62015-08-07 14:44:40 +02001699 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001700
1701 if (list->keys_size) {
1702 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001703
1704 /* we managed to resolve it before, resolve it again manually */
1705 if (list_orig->keys[0]) {
1706 for (i = 0; i < list->keys_size; ++i) {
Radek Krejcib8048692015-08-05 13:36:34 +02001707 list->keys[i] = (struct lys_node_leaf *)resolve_child((struct lys_node *)list,
Radek Krejci76512572015-08-04 09:47:08 +02001708 list_orig->keys[i]->name, 0, LYS_LEAF);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001709 assert(list->keys[i]);
1710 }
1711 /* it was not resolved yet, add unres copy */
1712 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001713 if (unres_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02001714 LOGINT;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001715 lys_node_free(retval);
Michal Vaskod23ce592015-08-06 09:55:37 +02001716 return NULL;
1717 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001718 }
1719 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001720
1721 list->unique = calloc(list->unique_size, sizeof *list->unique);
1722 if (list_orig->unique) {
1723 for (i = 0; i < list->unique_size; ++i) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001724 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
1725 for (j = 0; j < list->unique[i].leafs_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001726 list->unique[i].leafs[j] = lys_uniq_find(list, list_orig->unique[i].leafs[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001727 }
1728 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001729 } else {
1730 for (i = 0; i < list->unique_size; ++i) {
1731 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02001732 list->unique[i].leafs = (struct lys_node_leaf **)list;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001733 unres_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001734 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001735 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001736
1737 if (list_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001738 list->when = lys_when_dup(ctx, list_orig->when);
1739 unres_add_node(module, unres, list->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001740 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001741 break;
1742
Radek Krejci76512572015-08-04 09:47:08 +02001743 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001744 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001745 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001746 for (i = 0; i < anyxml->must_size; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001747 unres_add_node(module, unres, &anyxml->must[i], UNRES_MUST, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001748 }
1749
1750 if (anyxml_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001751 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
1752 unres_add_node(module, unres, anyxml->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001753 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001754 break;
1755
Radek Krejci76512572015-08-04 09:47:08 +02001756 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001757 uses->grp = uses_orig->grp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001758
1759 if (uses_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001760 uses->when = lys_when_dup(ctx, uses_orig->when);
1761 unres_add_node(module, unres, uses->when, UNRES_WHEN, (struct lys_node *)uses, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001762 }
1763
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001764 uses->refine_size = uses_orig->refine_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001765 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size, uses, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001766 uses->augment_size = uses_orig->augment_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001767 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size, unres);
Michal Vaskof8c128d2015-08-06 15:25:28 +02001768 if (!uses->child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001769 unres_add_node(module, unres, uses, UNRES_USES, NULL, 0);
Michal Vaskof8c128d2015-08-06 15:25:28 +02001770 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001771 break;
1772
Radek Krejci76512572015-08-04 09:47:08 +02001773 case LYS_CASE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001774 if (cs_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001775 cs->when = lys_when_dup(ctx, cs_orig->when);
1776 unres_add_node(module, unres, cs->when, UNRES_WHEN, retval, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001777 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001778 break;
1779
Radek Krejci76512572015-08-04 09:47:08 +02001780 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001781 grp->tpdf_size = grp_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001782 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001783 break;
1784
Radek Krejci76512572015-08-04 09:47:08 +02001785 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001786 rpc->tpdf_size = rpc_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001787 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001788 break;
1789
Radek Krejci76512572015-08-04 09:47:08 +02001790 case LYS_INPUT:
1791 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001792 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001793 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001794 break;
1795
Radek Krejci76512572015-08-04 09:47:08 +02001796 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001797 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001798 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcia01e5432015-06-16 10:35:25 +02001799 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001800
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001801 default:
Radek Krejci00768f42015-06-18 17:04:04 +02001802 /* LY_NODE_AUGMENT */
Michal Vaskod23ce592015-08-06 09:55:37 +02001803 LOGINT;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001804 lys_node_free(retval);
Michal Vaskod23ce592015-08-06 09:55:37 +02001805 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001806 }
1807
1808 return retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001809}
1810
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001811API void
Radek Krejcib8048692015-08-05 13:36:34 +02001812lys_free(struct lys_module *module)
Radek Krejciefaeba32015-05-27 14:30:57 +02001813{
Radek Krejcidce51452015-06-16 15:20:08 +02001814 struct ly_ctx *ctx;
1815 int i;
1816
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001817 if (!module) {
1818 return;
1819 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001820
Radek Krejcidce51452015-06-16 15:20:08 +02001821 /* remove schema from the context */
1822 ctx = module->ctx;
1823 if (ctx->models.used) {
1824 for (i = 0; i < ctx->models.used; i++) {
1825 if (ctx->models.list[i] == module) {
1826 /* replace the position in the list by the last module in the list */
1827 ctx->models.used--;
1828 ctx->models.list[i] = ctx->models.list[ctx->models.used];
1829 ctx->models.list[ctx->models.used] = NULL;
1830 /* we are done */
1831 break;
1832 }
1833 }
1834 }
1835
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001836 /* common part with struct ly_submodule */
1837 module_free_common(module);
Radek Krejciefaeba32015-05-27 14:30:57 +02001838
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001839 /* specific items to free */
1840 lydict_remove(module->ctx, module->ns);
1841 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02001842
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001843 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001844}
Radek Krejci7e97c352015-06-19 16:26:34 +02001845
1846/*
1847 * op: 1 - enable, 0 - disable
1848 */
1849static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001850lys_features_change(struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02001851{
1852 int all = 0;
1853 int i, j, k;
1854
1855 if (!module || !name || !strlen(name)) {
1856 return EXIT_FAILURE;
1857 }
1858
1859 if (!strcmp(name, "*")) {
1860 /* enable all */
1861 all = 1;
1862 }
1863
1864 /* module itself */
1865 for (i = 0; i < module->features_size; i++) {
1866 if (all || !strcmp(module->features[i].name, name)) {
1867 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001868 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02001869 /* enable referenced features (recursion) */
1870 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001871 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02001872 module->features[i].features[k]->name, op);
1873 }
1874 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001875 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02001876 }
1877 if (!all) {
1878 return EXIT_SUCCESS;
1879 }
1880 }
1881 }
1882
1883 /* submodules */
1884 for (j = 0; j < module->inc_size; j++) {
1885 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
1886 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
1887 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001888 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02001889 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001890 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02001891 }
1892 if (!all) {
1893 return EXIT_SUCCESS;
1894 }
1895 }
1896 }
1897 }
1898
Radek Krejcie98bb4b2015-07-30 14:21:41 +02001899 /* TODO submodules of submodules ... */
1900
Radek Krejci7e97c352015-06-19 16:26:34 +02001901 if (all) {
1902 return EXIT_SUCCESS;
1903 } else {
1904 return EXIT_FAILURE;
1905 }
1906}
1907
1908API int
Radek Krejcib8048692015-08-05 13:36:34 +02001909lys_features_enable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02001910{
Radek Krejci1d82ef62015-08-07 14:44:40 +02001911 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02001912}
1913
1914API int
Radek Krejcib8048692015-08-05 13:36:34 +02001915lys_features_disable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02001916{
Radek Krejci1d82ef62015-08-07 14:44:40 +02001917 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02001918}
1919
1920API int
Radek Krejcib8048692015-08-05 13:36:34 +02001921lys_features_state(struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02001922{
1923 int i, j;
1924
1925 if (!module || !feature) {
1926 return -1;
1927 }
1928
1929 /* search for the specified feature */
1930 /* module itself */
1931 for (i = 0; i < module->features_size; i++) {
1932 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001933 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02001934 return 1;
1935 } else {
1936 return 0;
1937 }
1938 }
1939 }
1940
1941 /* submodules */
1942 for (j = 0; j < module->inc_size; j++) {
1943 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
1944 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001945 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02001946 return 1;
1947 } else {
1948 return 0;
1949 }
1950 }
1951 }
1952 }
1953
1954 /* TODO submodules of submodules ... */
1955
1956 /* feature definition not found */
1957 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02001958}
Michal Vasko2367e7c2015-07-07 11:33:44 +02001959
Radek Krejci96a10da2015-07-30 11:00:14 +02001960API const char **
Radek Krejcib8048692015-08-05 13:36:34 +02001961lys_features_list(struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02001962{
Radek Krejci96a10da2015-07-30 11:00:14 +02001963 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02001964 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02001965 unsigned int count;
1966
1967 if (!module) {
1968 return NULL;
1969 }
1970
1971 count = module->features_size;
1972 for (i = 0; i < module->inc_size; i++) {
1973 count += module->inc[i].submodule->features_size;
1974 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02001975 result = malloc((count + 1) * sizeof *result);
1976 if (states) {
1977 *states = malloc((count + 1) * sizeof **states);
Michal Vasko2367e7c2015-07-07 11:33:44 +02001978 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02001979 count = 0;
1980
1981 /* module itself */
1982 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02001983 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02001984 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001985 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02001986 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02001987 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02001988 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02001989 }
1990 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02001991 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02001992 }
1993
1994 /* submodules */
1995 for (j = 0; j < module->inc_size; j++) {
1996 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02001997 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02001998 if (states) {
1999 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2000 (*states)[count] = 1;
2001 } else {
2002 (*states)[count] = 0;
2003 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002004 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002005 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002006 }
2007 }
2008
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002009 /* TODO submodules of submodules ... */
2010
2011 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002012 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002013
2014 return result;
2015}
Radek Krejcib20c62d2015-07-07 17:07:14 +02002016
2017API struct lyd_node *
Radek Krejci25b9fd32015-08-10 15:06:07 +02002018lyd_parse(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
Radek Krejcib20c62d2015-07-07 17:07:14 +02002019{
2020 if (!ctx || !data) {
2021 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2022 return NULL;
2023 }
2024
2025 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02002026 case LYD_XML:
Radek Krejci25b9fd32015-08-10 15:06:07 +02002027 return xml_read_data(ctx, data, options);
Radek Krejcia9167ef2015-08-03 11:01:11 +02002028 case LYD_JSON:
Radek Krejcib20c62d2015-07-07 17:07:14 +02002029 default:
2030 /* TODO */
2031 return NULL;
2032 }
2033
2034 return NULL;
2035}
2036
Radek Krejci0e1d1a62015-07-31 11:17:01 +02002037API void
Radek Krejci912da452015-07-29 14:10:06 +02002038lyd_free(struct lyd_node *node)
Radek Krejcib20c62d2015-07-07 17:07:14 +02002039{
2040 struct lyd_node *next, *child;
2041
Radek Krejci52f791c2015-07-15 11:14:17 +02002042 if (!node) {
2043 return;
2044 }
2045
Radek Krejci76512572015-08-04 09:47:08 +02002046 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
Radek Krejcie4748472015-07-08 18:00:22 +02002047 /* free children */
2048 LY_TREE_FOR_SAFE(node->child, next, child) {
Radek Krejci912da452015-07-29 14:10:06 +02002049 lyd_free(child);
Radek Krejcie4748472015-07-08 18:00:22 +02002050 }
Radek Krejci76512572015-08-04 09:47:08 +02002051 } else if (node->schema->nodetype == LYS_ANYXML) {
Radek Krejci9566b092015-07-31 11:18:15 +02002052 lyxml_free_elem(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
Radek Krejcie4748472015-07-08 18:00:22 +02002053 } else {
2054 /* free value */
2055 switch(((struct lyd_node_leaf *)node)->value_type) {
2056 case LY_TYPE_BINARY:
2057 case LY_TYPE_STRING:
2058 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf *)node)->value.string);
2059 break;
Radek Krejci3e3affe2015-07-09 15:38:40 +02002060 case LY_TYPE_BITS:
2061 if (((struct lyd_node_leaf *)node)->value.bit) {
2062 free(((struct lyd_node_leaf *)node)->value.bit);
2063 }
2064 break;
Radek Krejcie4748472015-07-08 18:00:22 +02002065 default:
Radek Krejci7511f402015-07-10 09:56:30 +02002066 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
Radek Krejcie4748472015-07-08 18:00:22 +02002067 break;
2068 }
Radek Krejcib20c62d2015-07-07 17:07:14 +02002069 }
2070
2071 if (node->prev->next) {
2072 node->prev->next = node->next;
2073 } else if (node->parent) {
2074 /* first node */
2075 node->parent->child = node->next;
2076 }
2077 if (node->next) {
2078 node->next->prev = node->prev;
2079 }
2080
2081 free(node);
2082}
Michal Vaskof54f2f82015-07-17 13:12:05 +02002083
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002084API int
Radek Krejci9566b092015-07-31 11:18:15 +02002085lyd_is_last(struct lyd_node *node)
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002086{
2087 struct lyd_node *n;
2088
2089 if (!node->next) {
2090 return 1;
2091 }
2092
2093 for (n = node->next; n; n = n->next) {
2094 switch (n->schema->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002095 case LYS_LIST:
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002096 if (!((struct lyd_node_list *)n)->lprev) {
2097 return 0;
2098 }
2099 break;
Radek Krejci76512572015-08-04 09:47:08 +02002100 case LYS_LEAFLIST:
Radek Krejci2dbed4c2015-07-20 13:02:04 +02002101 if (!((struct lyd_node_leaflist *)n)->lprev) {
2102 return 0;
2103 }
2104 break;
2105 default:
2106 return 0;
2107 }
2108 }
2109 return 1;
2110}