blob: 9779ce6a34bf93af4f1aad51acfeb6d6b023326b [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"
Radek Krejci3045cf32015-05-28 10:58:52 +020032#include "parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020033#include "resolve.h"
Radek Krejci106efc02015-06-10 14:36:27 +020034#include "xml.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020035#include "tree_internal.h"
Radek Krejcieab784a2015-08-27 09:56:53 +020036#include "validation.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020037
Michal Vaskoa76ee152015-08-17 15:38:22 +020038static const struct internal_modules int_mods = {
39 .modules = {
40 {"ietf-yang-types", "2013-07-15"},
41 {"ietf-inet-types", "2013-07-15"},
42 {"ietf-yang-library", "2015-07-03"}
43 },
44 .count = LY_INTERNAL_MODULE_COUNT
45};
46
Radek Krejci48061fb2015-08-05 15:41:07 +020047API struct lys_feature *
48lys_is_disabled(struct lys_node *node, int recursive)
49{
50 int i;
51
52check:
53 if (node->nodetype != LYS_INPUT && node->nodetype != LYS_OUTPUT) {
54 /* input/output does not have if-feature, so skip them */
55
56 /* check local if-features */
57 for (i = 0; i < node->features_size; i++) {
58 if (!(node->features[i]->flags & LYS_FENABLED)) {
59 return node->features[i];
60 }
61 }
62 }
63
64 if (!recursive) {
65 return NULL;
66 }
67
68 /* go through parents */
69 if (node->nodetype == LYS_AUGMENT) {
70 /* go to parent actually means go to the target node */
71 node = ((struct lys_node_augment *)node)->target;
Radek Krejci48061fb2015-08-05 15:41:07 +020072 } else if (node->parent) {
73 node = node->parent;
Radek Krejci074bf852015-08-19 14:22:16 +020074 } else {
75 return NULL;
Radek Krejci48061fb2015-08-05 15:41:07 +020076 }
77
Radek Krejci074bf852015-08-19 14:22:16 +020078 if (recursive == 2) {
79 /* continue only if the node cannot have a data instance */
80 if (node->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST)) {
81 return NULL;
82 }
83 }
84 goto check;
Radek Krejci48061fb2015-08-05 15:41:07 +020085}
86
Radek Krejci8bc87f62015-09-02 16:19:05 +020087struct lys_node *
88lys_getnext(struct lys_node *last, struct lys_node *parent, struct lys_module *module, int options)
Radek Krejci7f40ce32015-08-12 20:38:46 +020089{
90 struct lys_node *next;
91
Radek Krejci8bc87f62015-09-02 16:19:05 +020092 if (!last) {
93 /* first call */
94
95 /* get know where to start */
96 if (parent) {
97 /* schema subtree */
98 next = last = parent->child;
99 } else {
100 /* top level data */
101 assert(module);
102 next = last = module->data;
103 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200104 } else {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200105 /* continue after the last returned value */
106 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200107 }
108
109repeat:
Radek Krejci14a11a62015-08-17 17:27:38 +0200110 while (next && (next->nodetype & (LYS_AUGMENT | LYS_GROUPING))) {
111 next = next->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200112 }
113
114 while (!next) {
Radek Krejci8bc87f62015-09-02 16:19:05 +0200115 if (last->parent == parent) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200116 /* no next element */
117 return NULL;
118 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200119 last = last->parent;
120 next = last->next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200121 goto repeat;
122 }
123
124 switch (next->nodetype) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200125 case LYS_USES:
126 case LYS_CASE:
127 /* go into */
128 next = next->child;
129 goto repeat;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200130
131 case LYS_CONTAINER:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200132 case LYS_LEAF:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200133 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200134 case LYS_LIST:
135 case LYS_LEAFLIST:
Radek Krejci7f40ce32015-08-12 20:38:46 +0200136 return next;
Radek Krejci8bc87f62015-09-02 16:19:05 +0200137
138 case LYS_CHOICE:
139 if (options & LYS_GETNEXT_WITHCHOICE) {
140 return next;
141 } else {
142 /* go into */
143 next = next->child;
144 goto repeat;
145 }
146 break;
147
Radek Krejci7f40ce32015-08-12 20:38:46 +0200148 default:
149 /* we should not be here */
150 return NULL;
151 }
Radek Krejci8bc87f62015-09-02 16:19:05 +0200152
153
154}
155
156static struct lys_node *
157check_mand_getnext(struct lys_node *last, struct lys_node *parent)
158{
159 struct lys_node *next;
160
161repeat:
162 next = lys_getnext(last, parent, NULL, LYS_GETNEXT_WITHCHOICE);
163
164 if (next && next->nodetype == LYS_CONTAINER) {
165 if (((struct lys_node_container *)next)->presence) {
166 /* mandatory elements under the non-existing presence
167 * container are not mandatory - 7.6.5, rule 1 */
168 next = next->next;
169 } else {
170 /* go into */
171 next = next->child;
172 }
173 goto repeat;
174 }
175
176 return next;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200177}
178
179static struct lys_node *
180check_mand_check(struct lys_node *node, struct lys_node *stop, struct lyd_node *data)
181{
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200182 struct lys_node *siter = NULL, *parent = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200183 struct lyd_node *diter = NULL;
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200184 struct lyd_set *set = NULL;
185 unsigned int i;
Radek Krejci14a11a62015-08-17 17:27:38 +0200186 uint32_t minmax;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200187
188 if (node->flags & LYS_MAND_TRUE) {
189 switch (node->nodetype) {
190 case LYS_LEAF:
191 case LYS_ANYXML:
192 case LYS_CHOICE:
193 if (node->parent->nodetype == LYS_CASE) {
194 /* 7.6.5, rule 2 */
195 /* 7.9.4, rule 1 */
196 if (node->parent->parent->parent == data->schema) {
197 /* the only case the node's siblings can exist is that the
198 * data node passed originaly to ly_check_mandatory()
199 * had this choice as a child
200 */
201 /* try to find the node's siblings in data */
202 LY_TREE_FOR(data->child, diter) {
203 LY_TREE_FOR(node->parent->child, siter) {
204 if (siter == diter->schema) {
205 /* some sibling exists, rule applies */
206 break;
207 }
208 }
209 if (siter) {
210 break;
211 }
212 }
213 }
214 if (!siter) {
215 /* no sibling exists */
216 return NULL;
217 }
218 } else {
219 for(parent = node->parent; parent != stop; parent = parent->parent) {
220 if (parent->nodetype != LYS_CONTAINER) {
221 /* 7.6.5, rule 1, checking presence is not needed
222 * since it is done in check_mand_getnext()
223 */
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200224 lyd_set_free(set);
Radek Krejci7f40ce32015-08-12 20:38:46 +0200225 return NULL;
226 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200227 /* add the parent to the list for searching in data tree */
228 if (!set) {
229 set = lyd_set_new();
230 }
231 lyd_set_add(set, (struct lyd_node *)parent);
Radek Krejci7f40ce32015-08-12 20:38:46 +0200232 }
233 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200234
235 /* search for instance */
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200236 if (set) {
237 for (i = 0; i < set->number; i++) {
238 LY_TREE_FOR(data->child, diter) {
239 if (diter->schema == (struct lys_node *)(set->set[i])) {
240 break;
241 }
242 }
243 if (!diter) {
244 /* instance not found */
245 node = (struct lys_node *)(set->set[i]);
246 lyd_set_free(set);
247 return node;
248 }
249 data = diter;
250 }
251 lyd_set_free(set);
252 }
253
Radek Krejci14a11a62015-08-17 17:27:38 +0200254 LY_TREE_FOR(data->child, diter) {
255 if (diter->schema == node) {
256 return NULL;
257 }
258 }
Radek Krejci50c5b0e2015-08-21 15:43:45 +0200259
Radek Krejci14a11a62015-08-17 17:27:38 +0200260 /* instance not found */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200261 /* 7.6.5, rule 3 (or 2) */
262 /* 7.9.4, rule 2 */
263 return node;
264 default:
265 /* error */
266 break;
267 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200268 } else if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
269 /* search for number of instances */
270 minmax = 0;
271 LY_TREE_FOR(data->child, diter) {
272 if (diter->schema == node) {
273 minmax++;
274 }
275 }
276
277 /* check the specified constraints */
278 if (node->nodetype == LYS_LIST) {
279 if (((struct lys_node_list *)node)->min && minmax < ((struct lys_node_list *)node)->min) {
280 return node;
281 }
282
283 if (((struct lys_node_list *)node)->max && minmax > ((struct lys_node_list *)node)->max) {
284 return node;
285 }
286 } else if (node->nodetype == LYS_LEAFLIST) {
287 if (((struct lys_node_leaflist *)node)->min && minmax < ((struct lys_node_leaflist *)node)->min) {
288 return node;
289 }
290
291 if (((struct lys_node_leaflist *)node)->max && minmax > ((struct lys_node_leaflist *)node)->max) {
292 return node;
293 }
294 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200295 }
296
297 return NULL;
298}
299
300struct lys_node *
301ly_check_mandatory(struct lyd_node *data)
302{
Radek Krejci14a11a62015-08-17 17:27:38 +0200303 struct lys_node *siter, *saux, *saux2, *result, *parent = NULL, *parent2;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200304 struct lyd_node *diter;
305 int found;
306
307 siter = data->schema->child;
308
309repeat:
310 while (siter) {
Radek Krejci074bf852015-08-19 14:22:16 +0200311 if (lys_is_disabled(siter, 2)) {
312 siter = siter->next;
313 continue;
314 }
315
Radek Krejci7f40ce32015-08-12 20:38:46 +0200316 switch (siter->nodetype) {
317 case LYS_CONTAINER:
318 case LYS_LEAF:
319 case LYS_ANYXML:
Radek Krejci14a11a62015-08-17 17:27:38 +0200320 case LYS_LIST:
321 case LYS_LEAFLIST:
322 /* check if there is some mandatory node; first test the siter itself ... */
Radek Krejci7f40ce32015-08-12 20:38:46 +0200323 result = check_mand_check(siter, siter->parent, data);
324 if (result) {
325 return result;
326 }
327 /* ... and then the subtree */
Radek Krejci14a11a62015-08-17 17:27:38 +0200328 if (parent && siter->nodetype == LYS_CONTAINER && !((struct lys_node_container *)siter)->presence) {
329 saux = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200330 while ((saux = check_mand_getnext(saux, siter))) {
331 result = check_mand_check(saux, siter, data);
332 if (result) {
333 return result;
334 }
335 }
336 }
337 siter = siter->next;
338 break;
339 case LYS_CHOICE:
Radek Krejci14a11a62015-08-17 17:27:38 +0200340 /* search for instance */
341 saux = siter;
342 siter = siter->child;
343 found = 0;
344 parent2 = NULL;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200345repeat_choice:
Radek Krejci074bf852015-08-19 14:22:16 +0200346 while (siter) {
347 if (lys_is_disabled(siter, 2)) {
348 siter = siter->next;
349 continue;
350 }
351
Radek Krejci14a11a62015-08-17 17:27:38 +0200352 switch (siter->nodetype) {
353 case LYS_CONTAINER:
354 case LYS_LEAF:
355 case LYS_LEAFLIST:
356 case LYS_LIST:
357 case LYS_ANYXML:
358 LY_TREE_FOR(data->child, diter) {
359 if (diter->schema == siter) {
Radek Krejci7f40ce32015-08-12 20:38:46 +0200360 break;
361 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200362 }
363 if (diter) {
364 /* got instance */
365 /* check presence of mandatory siblings */
Radek Krejci65d0a652015-08-27 13:09:42 +0200366 if (parent2 && parent2->nodetype == LYS_CASE) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200367 saux2 = NULL;
Radek Krejci37bda002015-08-27 11:23:56 +0200368 while ((saux2 = check_mand_getnext(saux2, parent2))) {
369 result = check_mand_check(saux2, parent2, data);
Radek Krejci14a11a62015-08-17 17:27:38 +0200370 if (result) {
371 return result;
372 }
373 }
374 }
375 siter = parent2 = NULL;
376 found = 1;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200377 break;
378 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200379 siter = siter->next;
380 break;
381 case LYS_CASE:
382 case LYS_CHOICE:
383 case LYS_USES:
384 /* go into */
Radek Krejci37bda002015-08-27 11:23:56 +0200385 if (!parent2) {
386 parent2 = siter;
387 }
Radek Krejci14a11a62015-08-17 17:27:38 +0200388 siter = siter->child;
389 break;
390 case LYS_AUGMENT:
391 case LYS_GROUPING:
392 /* skip */
393 siter = siter->next;
394 break;
395 default:
396 /* error */
397 break;
Radek Krejci7f40ce32015-08-12 20:38:46 +0200398 }
Radek Krejci7f40ce32015-08-12 20:38:46 +0200399 }
400
Radek Krejci14a11a62015-08-17 17:27:38 +0200401 if (parent2) {
402 siter = parent2->next;
403 if (parent2->parent == saux) {
404 parent2 = NULL;
405 } else {
406 parent2 = parent2->parent;
407 }
408 goto repeat_choice;
409 }
410
Radek Krejci074bf852015-08-19 14:22:16 +0200411 if (!found && (saux->flags & LYS_MAND_TRUE)) {
Radek Krejci14a11a62015-08-17 17:27:38 +0200412 return saux;
413 }
414
415 /* go to next */
416 siter = saux->next;
417
Radek Krejci7f40ce32015-08-12 20:38:46 +0200418 break;
419 case LYS_USES:
420 case LYS_CASE:
421 /* go into */
422 parent = siter;
423 siter = siter->child;
424 break;
425 default:
426 /* can ignore, go to next */
427 siter = siter->next;
428 break;
429 }
430 }
431
432 if (parent) {
433 siter = parent->next;
434 if (parent->parent == data->schema) {
435 parent = NULL;
436 } else {
437 parent = parent->parent;
438 }
439 goto repeat;
440 }
441
442 return NULL;
443}
444
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200445void
Radek Krejci1d82ef62015-08-07 14:44:40 +0200446lys_node_unlink(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200447{
Radek Krejci76512572015-08-04 09:47:08 +0200448 struct lys_node *parent, *first;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200449
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200450 if (!node) {
451 return;
452 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200453
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200454 /* unlink from data model if necessary */
455 if (node->module) {
456 if (node->module->data == node) {
457 node->module->data = node->next;
Radek Krejci21181962015-06-30 14:11:00 +0200458 } else if (node->module->rpc == node) {
459 node->module->rpc = node->next;
460 } else if (node->module->notif == node) {
461 node->module->notif = node->next;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200462 }
463 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200464
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200465 /* store pointers to important nodes */
466 parent = node->parent;
Michal Vasko3a9943b2015-09-23 11:33:50 +0200467 if (parent && (parent->nodetype == LYS_AUGMENT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200468 /* handle augments - first, unlink it from the augment parent ... */
469 if (parent->child == node) {
470 parent->child = node->next;
471 }
472 /* and then continue with the target parent */
Radek Krejci76512572015-08-04 09:47:08 +0200473 parent = ((struct lys_node_augment *)parent)->target;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200474 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200475
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200476 /* unlink from parent */
477 if (parent) {
478 if (parent->child == node) {
479 parent->child = node->next;
480 }
481 node->parent = NULL;
482 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200484 /* unlink from siblings */
485 if (node->prev == node) {
486 /* there are no more siblings */
487 return;
488 }
489 if (node->next) {
490 node->next->prev = node->prev;
491 } else {
492 /* unlinking the last element */
493 if (parent) {
494 first = parent->child;
495 } else {
496 first = node;
Radek Krejci10c760e2015-08-14 14:45:43 +0200497 while (first->prev->next) {
Michal Vasko276f96b2015-09-23 11:34:28 +0200498 first = first->prev;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200499 }
500 }
501 first->prev = node->prev;
502 }
503 if (node->prev->next) {
504 node->prev->next = node->next;
505 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200506
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200507 /* clean up the unlinked element */
508 node->next = NULL;
509 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200510}
511
Michal Vasko563ef092015-09-04 13:17:23 +0200512struct lys_node_grp *
513lys_find_grouping_up(const char *name, struct lys_node *start, int in_submodules)
514{
515 struct lys_node *par_iter, *iter, *stop;
516 int i;
517
518 for (par_iter = start; par_iter; par_iter = par_iter->parent) {
519 if (par_iter->nodetype & (LYS_CHOICE | LYS_CASE | LYS_AUGMENT | LYS_USES)) {
520 continue;
521 }
522
523 for (iter = par_iter, stop = NULL; iter; iter = iter->prev) {
524 if (!stop) {
525 stop = par_iter;
526 } else if (iter == stop) {
527 break;
528 }
529 if (iter->nodetype != LYS_GROUPING) {
530 continue;
531 }
532
533 if (name == iter->name) {
534 return (struct lys_node_grp *)iter;
535 }
536 }
537 }
538
539 if (in_submodules) {
540 for (i = 0; i < start->module->inc_size; ++i) {
541 for (iter = start->module->inc[i].submodule->data; iter; iter = iter->next) {
542 if (iter->nodetype != LYS_GROUPING) {
543 continue;
544 }
545
546 if (name == iter->name) {
547 return (struct lys_node_grp *)iter;
548 }
549 }
550 }
551 }
552
553 return NULL;
554}
555
Radek Krejci10c760e2015-08-14 14:45:43 +0200556/*
557 * get next grouping in the root's subtree, in the
558 * first call, tha last is NULL
559 */
560static struct lys_node_grp *
Michal Vasko563ef092015-09-04 13:17:23 +0200561lys_get_next_grouping(struct lys_node_grp *lastgrp, struct lys_node *root)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200562{
Radek Krejci10c760e2015-08-14 14:45:43 +0200563 struct lys_node *last = (struct lys_node *)lastgrp;
564 struct lys_node *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200565
Radek Krejci10c760e2015-08-14 14:45:43 +0200566 assert(root);
567
568 if (!last) {
569 last = root;
570 }
571
572 while (1) {
573 if ((last->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
574 next = last->child;
575 } else {
576 next = NULL;
577 }
578 if (!next) {
579 if (last == root) {
580 /* we are done */
581 return NULL;
582 }
583
584 /* no children, go to siblings */
585 next = last->next;
586 }
587 while (!next) {
588 /* go back through parents */
589 if (last->parent == root) {
590 /* we are done */
591 return NULL;
592 }
593 last = last->parent;
594 next = last->next;
595 }
596
597 if (next->nodetype == LYS_GROUPING) {
598 return (struct lys_node_grp *)next;
599 }
600
601 last = next;
602 }
603}
604
Michal Vasko0d343d12015-08-24 14:57:36 +0200605/* logs directly */
Radek Krejci10c760e2015-08-14 14:45:43 +0200606int
Radek Krejci07911992015-08-14 15:13:31 +0200607lys_check_id(struct lys_node *node, struct lys_node *parent, struct lys_module *module)
608{
Michal Vasko563ef092015-09-04 13:17:23 +0200609 struct lys_node *start, *stop, *iter;
Radek Krejci07911992015-08-14 15:13:31 +0200610 struct lys_node_grp *grp;
611 int down;
612
613 assert(node);
614
615 if (!parent) {
616 assert(module);
617 } else {
618 module = parent->module;
619 }
620
621 switch (node->nodetype) {
622 case LYS_GROUPING:
623 /* 6.2.1, rule 6 */
624 if (parent) {
625 if (parent->child) {
626 down = 1;
627 start = parent->child;
628 } else {
629 down = 0;
630 start = parent;
631 }
632 } else {
633 down = 1;
634 start = module->data;
635 }
636 /* go up */
Michal Vasko563ef092015-09-04 13:17:23 +0200637 if (lys_find_grouping_up(node->name, start, 0)) {
638 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
639 return EXIT_FAILURE;
Radek Krejci07911992015-08-14 15:13:31 +0200640 }
641 /* go down, because grouping can be defined after e.g. container in which is collision */
642 if (down) {
643 for (iter = start, stop = NULL; iter; iter = iter->prev) {
644 if (!stop) {
645 stop = start;
646 } else if (iter == stop) {
647 break;
648 }
649 if (!(iter->nodetype & (LYS_CONTAINER | LYS_CHOICE | LYS_LIST | LYS_GROUPING | LYS_INPUT | LYS_OUTPUT))) {
650 continue;
651 }
652
653 grp = NULL;
654 while ((grp = lys_get_next_grouping(grp, iter))) {
655 if (node->name == grp->name) {
656 LOGVAL(LYE_DUPID, 0, "grouping", node->name);
657 return EXIT_FAILURE;
658 }
659 }
660 }
661 }
662 break;
663 case LYS_LEAF:
664 case LYS_LEAFLIST:
665 case LYS_LIST:
666 case LYS_CONTAINER:
667 case LYS_CHOICE:
668 case LYS_ANYXML:
669 /* 6.2.1, rule 7 */
670 if (parent) {
671 iter = parent;
672 while (iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE))) {
673 iter = iter->parent;
674 }
675 if (!iter) {
676 stop = NULL;
677 iter = module->data;
678 } else {
679 stop = iter;
680 iter = iter->child;
681 }
682 } else {
683 stop = NULL;
684 iter = module->data;
685 }
686 while (iter) {
687 if (iter->nodetype & (LYS_USES | LYS_CASE)) {
688 iter = iter->child;
689 continue;
690 }
691
692 if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
693 if (iter->module == node->module && iter->name == node->name) {
694 LOGVAL(LYE_SPEC, 0, "Duplicated child identifier \"%s\" in \"%s\".", node->name,
695 stop ? stop->name : "(sub)module");
696 return EXIT_FAILURE;
697 }
698 }
699
700 /* special case for choice - we must check the choice's name as
701 * well as the names of nodes under the choice
702 */
703 if (iter->nodetype == LYS_CHOICE) {
704 iter = iter->child;
705 continue;
706 }
707
708 /* go to siblings */
709 if (!iter->next) {
710 /* no sibling, go to parent's sibling */
711 do {
712 iter = iter->parent;
713 if (iter && iter->next) {
714 break;
715 }
716 } while (iter != stop);
717
718 if (iter == stop) {
719 break;
720 }
721 }
722 iter = iter->next;
723 }
724 break;
725 case LYS_CASE:
726 /* 6.2.1, rule 8 */
727 LY_TREE_FOR(parent->child, iter) {
728 if (!(iter->nodetype & (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
729 continue;
730 }
731
732 if (iter->module == node->module && iter->name == node->name) {
733 LOGVAL(LYE_DUPID, 0, "case", node->name);
734 return EXIT_FAILURE;
735 }
736 }
737 break;
738 default:
739 /* no check needed */
740 break;
741 }
742
743 return EXIT_SUCCESS;
744}
745
Michal Vasko0d343d12015-08-24 14:57:36 +0200746/* logs directly */
Radek Krejci07911992015-08-14 15:13:31 +0200747int
Radek Krejci10c760e2015-08-14 14:45:43 +0200748lys_node_addchild(struct lys_node *parent, struct lys_module *module, struct lys_node *child)
749{
Radek Krejci07911992015-08-14 15:13:31 +0200750 struct lys_node *iter, **trg = NULL;
751 int type;
Radek Krejci10c760e2015-08-14 14:45:43 +0200752
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200753 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200754
Radek Krejci10c760e2015-08-14 14:45:43 +0200755 if (parent) {
756 type = parent->nodetype;
757 module = parent->module;
758 } else {
759 assert(module);
760 type = 0;
Radek Krejcic7459c62015-08-17 10:15:12 +0200761 if (child->nodetype == LYS_NOTIF) {
762 trg = &module->notif;
763 } else if (child->nodetype == LYS_RPC) {
764 trg = &module->rpc;
765 } else {
766 trg = &module->data;
767 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200768 }
769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200770 /* checks */
Radek Krejci10c760e2015-08-14 14:45:43 +0200771 switch (type) {
Radek Krejci76512572015-08-04 09:47:08 +0200772 case LYS_CONTAINER:
773 case LYS_LIST:
774 case LYS_GROUPING:
775 case LYS_USES:
776 case LYS_INPUT:
777 case LYS_OUTPUT:
778 case LYS_NOTIF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200779 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200780 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
781 LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200782 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200783 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
784 return EXIT_FAILURE;
785 }
Radek Krejci10c760e2015-08-14 14:45:43 +0200786
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200787 break;
Radek Krejci76512572015-08-04 09:47:08 +0200788 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200789 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200790 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200791 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"choice\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200792 strnodetype(child->nodetype), parent->name);
793 return EXIT_FAILURE;
794 }
795 break;
Radek Krejci76512572015-08-04 09:47:08 +0200796 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200797 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200798 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200799 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"case\" %s.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200800 strnodetype(child->nodetype), parent->name);
801 return EXIT_FAILURE;
802 }
803 break;
Radek Krejci76512572015-08-04 09:47:08 +0200804 case LYS_RPC:
805 if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200806 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"rpc\" %s.",
Michal Vasko38d01f72015-06-15 09:41:06 +0200807 strnodetype(child->nodetype), parent->name);
808 return EXIT_FAILURE;
809 }
810 break;
Radek Krejci76512572015-08-04 09:47:08 +0200811 case LYS_LEAF:
812 case LYS_LEAFLIST:
813 case LYS_ANYXML:
Radek Krejci10c760e2015-08-14 14:45:43 +0200814 LOGVAL(LYE_SPEC, 0, "The \"%s\" statement (%s) cannot have any data substatement.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200815 strnodetype(parent->nodetype), parent->name);
816 return EXIT_FAILURE;
Radek Krejci76512572015-08-04 09:47:08 +0200817 case LYS_AUGMENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200818 if (!(child->nodetype &
Radek Krejci76512572015-08-04 09:47:08 +0200819 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
820 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200821 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200822 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
823 return EXIT_FAILURE;
824 }
Michal Vasko591e0b22015-08-13 13:53:43 +0200825 break;
826 case LYS_UNKNOWN:
Radek Krejci10c760e2015-08-14 14:45:43 +0200827 /* top level */
828 if (!(child->nodetype &
829 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
830 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
Radek Krejci2c0ca272015-08-14 15:31:01 +0200831 LOGVAL(LYE_SPEC, 0, "Unexpected substatement \"%s\" in (sub)module \"%s\"",
832 strnodetype(child->nodetype), module->name);
Radek Krejci10c760e2015-08-14 14:45:43 +0200833 return EXIT_FAILURE;
834 }
835
836 break;;
837 }
838
839 /* check identifier uniqueness */
Radek Krejci07911992015-08-14 15:13:31 +0200840 if (lys_check_id(child, parent, module)) {
841 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200842 }
Radek Krejcib7155b52015-06-10 17:03:01 +0200843
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200844 if (child->parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +0200845 lys_node_unlink(child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200846 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200847
Radek Krejci10c760e2015-08-14 14:45:43 +0200848 if (!parent) {
849 if (*trg) {
850 (*trg)->prev->next = child;
851 child->prev = (*trg)->prev;
852 (*trg)->prev = child;
853 } else {
854 (*trg) = child;
855 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200856 } else {
Radek Krejci10c760e2015-08-14 14:45:43 +0200857 if (!parent->child) {
858 /* the only/first child of the parent */
859 parent->child = child;
860 child->parent = parent;
861 iter = child;
862 } else {
863 /* add a new child at the end of parent's child list */
864 iter = parent->child->prev;
865 iter->next = child;
866 child->prev = iter;
867 }
868 while (iter->next) {
869 iter = iter->next;
870 iter->parent = parent;
871 }
872 parent->child->prev = iter;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200873 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200874
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200875 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200876}
877
Radek Krejcib8048692015-08-05 13:36:34 +0200878API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +0200879lys_parse(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200880{
Michal Vaskof02e3742015-08-05 16:27:02 +0200881 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200882 struct lys_module *mod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200883
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200884 if (!ctx || !data) {
885 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
886 return NULL;
887 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200888
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200889 unres = calloc(1, sizeof *unres);
890
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200891 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200892 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200893 mod = yin_read_module(ctx, data, 1, unres);
894 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200895 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200896 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +0200897 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200898 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200899 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200900
Michal Vasko0bd29d12015-08-19 11:45:49 +0200901 if (mod && unres->count && resolve_unres_schema(mod, unres)) {
Michal Vasko13b15832015-08-19 11:04:48 +0200902 lys_free(mod, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200903 mod = NULL;
904 }
905 free(unres->item);
906 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +0200907 free(unres->str_snode);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200908#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200909 free(unres->line);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200910#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200911 free(unres);
912
913 return mod;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200914}
915
Radek Krejcib8048692015-08-05 13:36:34 +0200916struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +0200917lys_submodule_parse(struct lys_module *module, const char *data, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +0200918{
Michal Vaskof02e3742015-08-05 16:27:02 +0200919 struct unres_schema *unres;
Radek Krejci0b5805d2015-08-13 09:38:02 +0200920 struct lys_submodule *submod = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200921
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200922 assert(module);
923 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200924
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200925 unres = calloc(1, sizeof *unres);
926
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200927 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +0200928 case LYS_IN_YIN:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200929 submod = yin_read_submodule(module, data, implement, unres);
930 break;
Radek Krejcia9167ef2015-08-03 11:01:11 +0200931 case LYS_IN_YANG:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200932 default:
Radek Krejci0b5805d2015-08-13 09:38:02 +0200933 /* TODO */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200934 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200935 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200936
Michal Vasko0bd29d12015-08-19 11:45:49 +0200937 if (submod && unres->count && resolve_unres_schema((struct lys_module *)submod, unres)) {
Michal Vasko13b15832015-08-19 11:04:48 +0200938 lys_submodule_free(submod, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200939 submod = NULL;
940 }
941 free(unres->item);
942 free(unres->type);
Radek Krejci1d82ef62015-08-07 14:44:40 +0200943 free(unres->str_snode);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200944#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200945 free(unres->line);
Michal Vaskoc07187d2015-08-13 15:20:57 +0200946#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200947 free(unres);
948
949 return submod;
Radek Krejciefaeba32015-05-27 14:30:57 +0200950}
951
Radek Krejcib8048692015-08-05 13:36:34 +0200952API struct lys_module *
Radek Krejcia9167ef2015-08-03 11:01:11 +0200953lys_read(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Radek Krejci63a91a92015-07-29 13:31:04 +0200954{
Radek Krejcib8048692015-08-05 13:36:34 +0200955 struct lys_module *module;
Radek Krejci63a91a92015-07-29 13:31:04 +0200956 struct stat sb;
957 char *addr;
958
959 if (!ctx || fd < 0) {
960 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
961 return NULL;
962 }
963
964 /*
965 * TODO
966 * This is just a temporary solution to make working automatic search for
967 * imported modules. This doesn't work e.g. for streams (stdin)
968 */
969 fstat(fd, &sb);
970 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
971 module = lys_parse(ctx, addr, format);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200972 munmap(addr, sb.st_size);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200973
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200974 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200975}
976
Radek Krejcib8048692015-08-05 13:36:34 +0200977struct lys_submodule *
Radek Krejci1d82ef62015-08-07 14:44:40 +0200978lys_submodule_read(struct lys_module *module, int fd, LYS_INFORMAT format, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +0200979{
Radek Krejcib8048692015-08-05 13:36:34 +0200980 struct lys_submodule *submodule;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200981 struct stat sb;
982 char *addr;
Radek Krejciefaeba32015-05-27 14:30:57 +0200983
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200984 assert(module);
985 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +0200986
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200987 /*
988 * TODO
989 * This is just a temporary solution to make working automatic search for
990 * imported modules. This doesn't work e.g. for streams (stdin)
991 */
992 fstat(fd, &sb);
993 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
994 /* TODO addr error check */
Radek Krejci1d82ef62015-08-07 14:44:40 +0200995 submodule = lys_submodule_parse(module, addr, format, implement);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200996 munmap(addr, sb.st_size);
Radek Krejciefaeba32015-05-27 14:30:57 +0200997
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200998 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +0200999
1000}
1001
Radek Krejci1d82ef62015-08-07 14:44:40 +02001002static struct lys_restr *
1003lys_restr_dup(struct ly_ctx *ctx, struct lys_restr *old, int size)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001004{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001005 struct lys_restr *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001006 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001007
Radek Krejci3733a802015-06-19 13:43:21 +02001008 if (!size) {
1009 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001010 }
Radek Krejci3733a802015-06-19 13:43:21 +02001011
1012 result = calloc(size, sizeof *result);
1013 for (i = 0; i < size; i++) {
1014 result[i].expr = lydict_insert(ctx, old[i].expr, 0);
1015 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
1016 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
1017 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
1018 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
1019 }
1020
1021 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001022}
1023
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001024void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001025lys_restr_free(struct ly_ctx *ctx, struct lys_restr *restr)
Radek Krejci0bd5db42015-06-19 13:30:07 +02001026{
1027 assert(ctx);
1028 if (!restr) {
1029 return;
1030 }
1031
1032 lydict_remove(ctx, restr->expr);
1033 lydict_remove(ctx, restr->dsc);
1034 lydict_remove(ctx, restr->ref);
1035 lydict_remove(ctx, restr->eapptag);
1036 lydict_remove(ctx, restr->emsg);
1037}
1038
Radek Krejci1d82ef62015-08-07 14:44:40 +02001039static void
1040lys_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 +02001041 struct unres_schema *unres)
Radek Krejci3733a802015-06-19 13:43:21 +02001042{
1043 int i;
1044
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001045 new->prefix = lydict_insert(mod->ctx, old->prefix, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001046 new->base = old->base;
1047 new->der = old->der;
1048
Michal Vasko0bd29d12015-08-19 11:45:49 +02001049 i = unres_schema_find(unres, old, UNRES_TYPE_DER);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001050 if (i != -1) {
1051 /* HACK for unres */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001052 new->der = (struct lys_tpdf *)parent;
Michal Vasko0bd29d12015-08-19 11:45:49 +02001053 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_DER, unres->str_snode[i], 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02001054 LOGINT;
1055 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001056 return;
1057 }
1058
Radek Krejci3733a802015-06-19 13:43:21 +02001059 switch (new->base) {
1060 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +02001061 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001062 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001063 }
Radek Krejci3733a802015-06-19 13:43:21 +02001064 break;
1065
1066 case LY_TYPE_BITS:
1067 new->info.bits.count = old->info.bits.count;
1068 if (new->info.bits.count) {
1069 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1070 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001071 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1072 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1073 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001074 new->info.bits.bit[i].status = old->info.bits.bit[i].status;
1075 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1076 }
1077 }
1078 break;
1079
Radek Krejcif9401c32015-06-26 16:47:36 +02001080 case LY_TYPE_DEC64:
1081 new->info.dec64.dig = old->info.dec64.dig;
1082 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001083 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +02001084 }
1085 break;
1086
Radek Krejci3733a802015-06-19 13:43:21 +02001087 case LY_TYPE_ENUM:
1088 new->info.enums.count = old->info.enums.count;
1089 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001090 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Radek Krejci3733a802015-06-19 13:43:21 +02001091 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001092 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1093 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1094 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1095 new->info.enums.enm[i].status = old->info.enums.enm[i].status;
1096 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +02001097 }
1098 }
1099 break;
1100
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001101 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001102 if (old->info.ident.ref) {
1103 new->info.ident.ref = old->info.ident.ref;
1104 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001105 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001106 assert(i != -1);
Michal Vasko0bd29d12015-08-19 11:45:49 +02001107 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i], 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02001108 LOGINT;
1109 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001110 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001111 break;
1112
Radek Krejciaf351422015-06-19 14:49:38 +02001113 case LY_TYPE_INST:
1114 new->info.inst.req = old->info.inst.req;
1115 break;
1116
Radek Krejcif2860132015-06-20 12:37:20 +02001117 case LY_TYPE_INT8:
1118 case LY_TYPE_INT16:
1119 case LY_TYPE_INT32:
1120 case LY_TYPE_INT64:
1121 case LY_TYPE_UINT8:
1122 case LY_TYPE_UINT16:
1123 case LY_TYPE_UINT32:
1124 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +02001125 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001126 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001127 }
Radek Krejcif2860132015-06-20 12:37:20 +02001128 break;
1129
Radek Krejcidc4c1412015-06-19 15:39:54 +02001130 case LY_TYPE_LEAFREF:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001131 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02001132 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02001133 LOGINT;
1134 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001135 break;
1136
Radek Krejci3733a802015-06-19 13:43:21 +02001137 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +02001138 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001139 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001140 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001141 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 +02001142 break;
1143
Radek Krejcie4c366b2015-07-02 10:11:31 +02001144 case LY_TYPE_UNION:
1145 new->info.uni.count = old->info.uni.count;
1146 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001147 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001148 for (i = 0; i < new->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001149 lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001150 }
1151 }
1152 break;
1153
Radek Krejci3733a802015-06-19 13:43:21 +02001154 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001155 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001156 break;
1157 }
1158}
1159
1160void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001161lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001162{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001163 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001164
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001165 assert(ctx);
1166 if (!type) {
1167 return;
1168 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001169
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001170 lydict_remove(ctx, type->prefix);
Radek Krejci5a065542015-05-22 15:02:07 +02001171
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001172 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001173 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001174 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001175 free(type->info.binary.length);
1176 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001177 case LY_TYPE_BITS:
1178 for (i = 0; i < type->info.bits.count; i++) {
1179 lydict_remove(ctx, type->info.bits.bit[i].name);
1180 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1181 lydict_remove(ctx, type->info.bits.bit[i].ref);
1182 }
1183 free(type->info.bits.bit);
1184 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001185
1186 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001187 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001188 free(type->info.dec64.range);
1189 break;
1190
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001191 case LY_TYPE_ENUM:
1192 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001193 lydict_remove(ctx, type->info.enums.enm[i].name);
1194 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1195 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001196 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001197 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001198 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001199
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001200 case LY_TYPE_INT8:
1201 case LY_TYPE_INT16:
1202 case LY_TYPE_INT32:
1203 case LY_TYPE_INT64:
1204 case LY_TYPE_UINT8:
1205 case LY_TYPE_UINT16:
1206 case LY_TYPE_UINT32:
1207 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001208 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001209 free(type->info.num.range);
1210 break;
1211
Radek Krejcidc4c1412015-06-19 15:39:54 +02001212 case LY_TYPE_LEAFREF:
1213 lydict_remove(ctx, type->info.lref.path);
1214 break;
1215
Radek Krejci3733a802015-06-19 13:43:21 +02001216 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001217 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001218 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001219 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001220 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001221 }
1222 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001223 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001224
Radek Krejcie4c366b2015-07-02 10:11:31 +02001225 case LY_TYPE_UNION:
1226 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001227 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001228 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001229 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001230 break;
1231
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001232 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001233 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001234 break;
1235 }
Radek Krejci5a065542015-05-22 15:02:07 +02001236}
1237
Radek Krejci1d82ef62015-08-07 14:44:40 +02001238static struct lys_tpdf *
1239lys_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 +02001240{
Radek Krejci1574a8d2015-08-03 14:16:52 +02001241 struct lys_tpdf *result;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001242 int i;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001243
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001244 if (!size) {
1245 return NULL;
1246 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001247
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001248 result = calloc(size, sizeof *result);
1249 for (i = 0; i < size; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001250 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1251 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1252 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001253 result[i].flags = old[i].flags;
1254 result[i].module = old[i].module;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001255
Radek Krejci1d82ef62015-08-07 14:44:40 +02001256 lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001257
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001258 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1259 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001260 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001261
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001262 return result;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001263}
1264
Radek Krejci1d82ef62015-08-07 14:44:40 +02001265static void
1266lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001267{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001268 assert(ctx);
1269 if (!tpdf) {
1270 return;
1271 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001272
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001273 lydict_remove(ctx, tpdf->name);
1274 lydict_remove(ctx, tpdf->dsc);
1275 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001276
Radek Krejci1d82ef62015-08-07 14:44:40 +02001277 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001278
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001279 lydict_remove(ctx, tpdf->units);
1280 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001281}
1282
Radek Krejci1d82ef62015-08-07 14:44:40 +02001283static struct lys_when *
1284lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001285{
Radek Krejci76512572015-08-04 09:47:08 +02001286 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001287
1288 if (!old) {
1289 return NULL;
1290 }
1291
1292 new = calloc(1, sizeof *new);
1293 new->cond = lydict_insert(ctx, old->cond, 0);
1294 new->dsc = lydict_insert(ctx, old->dsc, 0);
1295 new->ref = lydict_insert(ctx, old->ref, 0);
1296
1297 return new;
1298}
1299
Radek Krejci1d82ef62015-08-07 14:44:40 +02001300static void
1301lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001302{
1303 if (!w) {
1304 return;
1305 }
1306
1307 lydict_remove(ctx, w->cond);
1308 lydict_remove(ctx, w->dsc);
1309 lydict_remove(ctx, w->ref);
1310
1311 free(w);
1312}
1313
Radek Krejcib7f5e412015-08-13 10:15:51 +02001314static void
1315lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment aug)
1316{
Radek Krejcib7f5e412015-08-13 10:15:51 +02001317 lydict_remove(ctx, aug.target_name);
1318 lydict_remove(ctx, aug.dsc);
1319 lydict_remove(ctx, aug.ref);
1320
1321 free(aug.features);
1322
1323 lys_when_free(ctx, aug.when);
1324
Michal Vasko7d356a52015-08-19 15:06:31 +02001325 /* Do not free the children, they were appended somewhere and their
1326 * new parent will take care of them.
1327 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001328}
1329
Radek Krejci76512572015-08-04 09:47:08 +02001330static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001331lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001332{
Radek Krejci76512572015-08-04 09:47:08 +02001333 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001334 struct lys_node *old_child, *new_child;
1335 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001336
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001337 if (!size) {
1338 return NULL;
1339 }
Radek Krejci106efc02015-06-10 14:36:27 +02001340
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001341 new = calloc(size, sizeof *new);
1342 for (i = 0; i < size; i++) {
1343 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1344 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1345 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1346 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001347 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001348 new[i].nodetype = old[i].nodetype;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001349 /* this must succeed, it was already resolved once */
1350 if (resolve_schema_nodeid(new[i].target_name, parent->child, new[i].module, LYS_AUGMENT, &new[i].target)) {
1351 LOGINT;
1352 free(new);
1353 return NULL;
1354 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001355 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001356
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001357 /* Correct the augment nodes.
1358 * This function can only be called from lys_node_dup() with uses
1359 * being the node duplicated, so we must have a case of grouping
1360 * with a uses with augments. The augmented nodes have already been
1361 * copied and everything is almost fine except their parent is wrong
1362 * (it was set to their actual data parent, not an augment), so
1363 * we just correct it.
1364 */
1365 LY_TREE_FOR(new[i].target->child, new_child) {
1366 if (new_child->name == old[i].child->name) {
1367 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001368 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001369 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001370 assert(new_child);
1371 LY_TREE_FOR(old[i].child, old_child) {
1372 /* all augment nodes were connected as siblings, there can be no more after this */
1373 if (old_child->parent != (struct lys_node *)&old[i]) {
1374 break;
1375 }
1376
1377 assert(old_child->name == new_child->name);
1378
1379 new_child->parent = (struct lys_node *)&new[i];
1380 new_child = new_child->next;
1381 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001382 }
Radek Krejci106efc02015-06-10 14:36:27 +02001383
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001384 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001385}
1386
Radek Krejci76512572015-08-04 09:47:08 +02001387static struct lys_refine *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001388lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size, struct lys_node_uses *uses,
Michal Vaskof02e3742015-08-05 16:27:02 +02001389 struct unres_schema *unres)
Michal Vasko1982cad2015-06-08 15:49:30 +02001390{
Radek Krejci76512572015-08-04 09:47:08 +02001391 struct lys_refine *result;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001392 int i, j;
Michal Vasko1982cad2015-06-08 15:49:30 +02001393
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001394 if (!size) {
1395 return NULL;
1396 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001397
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001398 result = calloc(size, sizeof *result);
1399 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001400 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001401 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1402 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001403 result[i].flags = old[i].flags;
1404 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001405
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001406 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001407 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001408 for (j = 0; j < result[i].must_size; ++j) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001409 if (unres_schema_add_node(mod, unres, &result[i].must[j], UNRES_MUST, (struct lys_node *)uses, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02001410 free(result);
1411 return NULL;
1412 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001413 }
1414
Radek Krejci76512572015-08-04 09:47:08 +02001415 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001416 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001417 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001418 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001419 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001420 result[i].mod.list = old[i].mod.list;
1421 }
1422 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001423
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001424 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001425}
1426
Radek Krejci1d82ef62015-08-07 14:44:40 +02001427static void
1428lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001429{
Radek Krejcia52656e2015-08-05 13:41:50 +02001430 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001431
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001432 assert(ctx);
1433 if (!ident) {
1434 return;
1435 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001436
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001437 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001438 * if caller free only a single data model which is used (its identity is
1439 * reference from identity in another module), this silly freeing can lead
1440 * to segmentation fault. But without noting if the module is used by some
1441 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001442 *
1443 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001444 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001445 */
1446 while (ident->der) {
1447 der = ident->der;
1448 ident->der = der->next;
1449 free(der);
1450 }
Radek Krejci6793db02015-05-22 17:49:54 +02001451
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001452 lydict_remove(ctx, ident->name);
1453 lydict_remove(ctx, ident->dsc);
1454 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001455
1456}
1457
Radek Krejci1d82ef62015-08-07 14:44:40 +02001458static void
1459lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001460{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001461 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001462
Radek Krejcid12f57b2015-08-06 10:43:39 +02001463 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001464 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001465 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001466 }
1467 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001468}
1469
Radek Krejci1d82ef62015-08-07 14:44:40 +02001470static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001471lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1472{
1473 int i;
1474
1475 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1476 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001477 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001478 }
1479 free(io->tpdf);
1480}
1481
Radek Krejci1d82ef62015-08-07 14:44:40 +02001482static void
1483lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001484{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001485 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001486
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001487 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001488 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001489 }
1490 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001491
Radek Krejci1d82ef62015-08-07 14:44:40 +02001492 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001493}
1494
Radek Krejci1d82ef62015-08-07 14:44:40 +02001495static void
1496lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001497{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001498 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001499
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001500 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001501 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001502 }
1503 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001504
Radek Krejci1d82ef62015-08-07 14:44:40 +02001505 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001506
Radek Krejci1d82ef62015-08-07 14:44:40 +02001507 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001508 lydict_remove(ctx, leaf->units);
1509 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001510}
1511
Radek Krejci1d82ef62015-08-07 14:44:40 +02001512static void
1513lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001514{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001515 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001516
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001517 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001518 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001519 }
1520 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001521
Radek Krejci1d82ef62015-08-07 14:44:40 +02001522 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001523
Radek Krejci1d82ef62015-08-07 14:44:40 +02001524 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001525 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001526}
1527
Radek Krejci1d82ef62015-08-07 14:44:40 +02001528static void
1529lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001530{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001531 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001532
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001533 /* handle only specific parts for LY_NODE_LIST */
1534 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001535 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001536 }
1537 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001538
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001539 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001540 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001541 }
1542 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001543
Radek Krejci1d82ef62015-08-07 14:44:40 +02001544 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001545
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001546 for (i = 0; i < list->unique_size; i++) {
1547 free(list->unique[i].leafs);
1548 }
1549 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001550
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001551 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001552}
1553
Radek Krejci1d82ef62015-08-07 14:44:40 +02001554static void
1555lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001556{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001557 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001558
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001559 /* handle only specific parts for LY_NODE_CONTAINER */
1560 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001561
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001562 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001563 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001564 }
1565 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001566
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001567 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001568 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001569 }
1570 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001571
Radek Krejci1d82ef62015-08-07 14:44:40 +02001572 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001573}
1574
Radek Krejci1d82ef62015-08-07 14:44:40 +02001575static void
1576lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001577{
1578 lydict_remove(ctx, f->name);
1579 lydict_remove(ctx, f->dsc);
1580 lydict_remove(ctx, f->ref);
1581 free(f->features);
1582}
1583
Radek Krejci1d82ef62015-08-07 14:44:40 +02001584static void
1585lys_deviation_free(struct ly_ctx *ctx, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001586{
1587 int i, j;
1588
1589 lydict_remove(ctx, dev->target_name);
1590 lydict_remove(ctx, dev->dsc);
1591 lydict_remove(ctx, dev->ref);
1592
1593 for (i = 0; i < dev->deviate_size; i++) {
1594 lydict_remove(ctx, dev->deviate[i].dflt);
1595 lydict_remove(ctx, dev->deviate[i].units);
1596
1597 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1598 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001599 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001600 }
1601 free(dev->deviate[i].must);
1602
1603 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1604 free(dev->deviate[j].unique[j].leafs);
1605 }
1606 free(dev->deviate[i].unique);
1607 }
1608 }
1609 free(dev->deviate);
1610}
1611
Radek Krejci1d82ef62015-08-07 14:44:40 +02001612static void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001613lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +02001614{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001615 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001616
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001617 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001618 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001619 lydict_remove(ctx, uses->refine[i].dsc);
1620 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001621
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001622 for (j = 0; j < uses->refine[j].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001623 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001624 }
1625 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001626
Radek Krejci76512572015-08-04 09:47:08 +02001627 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001628 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001629 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001630 lydict_remove(ctx, uses->refine[i].mod.presence);
1631 }
1632 }
1633 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001634
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001635 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001636 lys_augment_free(ctx, uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001637 }
1638 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001639
Radek Krejci1d82ef62015-08-07 14:44:40 +02001640 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001641}
1642
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001643void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001644lys_node_free(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001645{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001646 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001647 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001648
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001649 if (!node) {
1650 return;
1651 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001652
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001653 assert(node->module);
1654 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001655
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001656 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001657
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001658 /* common part */
1659 LY_TREE_FOR_SAFE(node->child, next, sub) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001660 lys_node_free(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001661 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001662
Radek Krejcid12f57b2015-08-06 10:43:39 +02001663 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1664 free(node->features);
1665 lydict_remove(ctx, node->name);
1666 lydict_remove(ctx, node->dsc);
1667 lydict_remove(ctx, node->ref);
1668 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001669
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001670 /* specific part */
1671 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001672 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001673 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001674 break;
Radek Krejci76512572015-08-04 09:47:08 +02001675 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001676 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001677 break;
Radek Krejci76512572015-08-04 09:47:08 +02001678 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001679 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001680 break;
Radek Krejci76512572015-08-04 09:47:08 +02001681 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001682 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001683 break;
Radek Krejci76512572015-08-04 09:47:08 +02001684 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001685 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001686 break;
Radek Krejci76512572015-08-04 09:47:08 +02001687 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001688 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001689 break;
Radek Krejci76512572015-08-04 09:47:08 +02001690 case LYS_USES:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001691 lys_uses_free(ctx, (struct lys_node_uses *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001692 break;
Radek Krejci76512572015-08-04 09:47:08 +02001693 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001694 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001695 break;
Radek Krejci76512572015-08-04 09:47:08 +02001696 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001697 /* do nothing */
1698 break;
Radek Krejci76512572015-08-04 09:47:08 +02001699 case LYS_GROUPING:
1700 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001701 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001702 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001703 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001704
1705 case LYS_INPUT:
1706 case LYS_OUTPUT:
1707 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1708 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001709 case LYS_UNKNOWN:
1710 LOGINT;
1711 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001712 }
Radek Krejci5a065542015-05-22 15:02:07 +02001713
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001714 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001715 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001716 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001717}
1718
Michal Vasko13b15832015-08-19 11:04:48 +02001719/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001720static void
Michal Vasko13b15832015-08-19 11:04:48 +02001721module_free_common(struct lys_module *module, int free_int_mods)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001722{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001723 struct ly_ctx *ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001724 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001725 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001726
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001727 assert(module->ctx);
1728 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001729
Radek Krejcidce51452015-06-16 15:20:08 +02001730 /* as first step, free the imported modules */
1731 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa76ee152015-08-17 15:38:22 +02001732 /* do not free internal modules */
Michal Vasko18bd09b2015-08-19 15:07:00 +02001733 if (!free_int_mods) {
1734 for (j = 0; j < int_mods.count; ++j) {
Michal Vaskod83c03a2015-08-21 09:09:24 +02001735 if (module->imp[i].module && !strcmp(int_mods.modules[j].name, module->imp[i].module->name)
Michal Vasko18bd09b2015-08-19 15:07:00 +02001736 && module->imp[i].module->rev
1737 && !strcmp(int_mods.modules[j].revision, module->imp[i].module->rev[0].date)) {
1738 break;
1739 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02001740 }
Michal Vasko18bd09b2015-08-19 15:07:00 +02001741 if (j < int_mods.count) {
1742 continue;
1743 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02001744 }
1745
Radek Krejcidce51452015-06-16 15:20:08 +02001746 /* get the imported module from the context and then free,
1747 * this check is necessary because the imported module can
1748 * be already removed
1749 */
1750 l = ctx->models.used;
1751 for (j = 0; j < l; j++) {
1752 if (ctx->models.list[j] == module->imp[i].module) {
Michal Vasko13b15832015-08-19 11:04:48 +02001753 lys_free(module->imp[i].module, free_int_mods);
Radek Krejcidce51452015-06-16 15:20:08 +02001754 break;
1755 }
1756 }
1757 }
1758 free(module->imp);
1759
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001760 while (module->data) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001761 lys_node_free(module->data);
Radek Krejci21181962015-06-30 14:11:00 +02001762 }
1763 while (module->rpc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001764 lys_node_free(module->rpc);
Radek Krejci21181962015-06-30 14:11:00 +02001765 }
1766 while (module->notif) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001767 lys_node_free(module->notif);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001768 }
Radek Krejci5a065542015-05-22 15:02:07 +02001769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001770 lydict_remove(ctx, module->dsc);
1771 lydict_remove(ctx, module->ref);
1772 lydict_remove(ctx, module->org);
1773 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001774
Radek Krejcieb00f512015-07-01 16:44:58 +02001775 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001776 for (i = 0; i < module->rev_size; i++) {
1777 lydict_remove(ctx, module->rev[i].dsc);
1778 lydict_remove(ctx, module->rev[i].ref);
1779 }
1780 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001781
Radek Krejcieb00f512015-07-01 16:44:58 +02001782 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001783 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001784 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001785 }
1786 module->ident_size = 0;
1787 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001788
Radek Krejcieb00f512015-07-01 16:44:58 +02001789 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001790 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001791 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001792 }
1793 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001794
Radek Krejcieb00f512015-07-01 16:44:58 +02001795 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001796 for (i = 0; i < module->inc_size; i++) {
Michal Vasko13b15832015-08-19 11:04:48 +02001797 lys_submodule_free(module->inc[i].submodule, free_int_mods);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001798 }
1799 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001800
Radek Krejcieb00f512015-07-01 16:44:58 +02001801 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02001802 for (i = 0; i < module->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001803 lys_augment_free(ctx, module->augment[i]);
Radek Krejcif5be10f2015-06-16 13:29:36 +02001804 }
1805 free(module->augment);
1806
Radek Krejcieb00f512015-07-01 16:44:58 +02001807 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001808 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001809 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001810 }
1811 free(module->features);
1812
Radek Krejcieb00f512015-07-01 16:44:58 +02001813 /* deviations */
1814 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001815 lys_deviation_free(ctx, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001816 }
1817 free(module->deviation);
1818
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001819 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02001820}
1821
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001822void
Michal Vasko13b15832015-08-19 11:04:48 +02001823lys_submodule_free(struct lys_submodule *submodule, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02001824{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001825 if (!submodule) {
1826 return;
1827 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001828
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001829 submodule->inc_size = 0;
1830 free(submodule->inc);
1831 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02001832
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001833 /* common part with struct ly_module */
Michal Vasko13b15832015-08-19 11:04:48 +02001834 module_free_common((struct lys_module *)submodule, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02001835
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001836 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02001837
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001838 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001839}
1840
Radek Krejcib8048692015-08-05 13:36:34 +02001841static struct lys_node_leaf *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001842lys_uniq_find(struct lys_node_list *list, struct lys_node_leaf *orig_leaf)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001843{
Radek Krejci1d82ef62015-08-07 14:44:40 +02001844 struct lys_node *node, *node2, *ret = NULL, *parent1, *parent2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001845 int depth = 1, i;
1846
1847 /* find the correct direct descendant of list in orig_leaf */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001848 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001849 while (1) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001850 if (!node->parent) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001851 return NULL;
1852 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001853 if (!strcmp(node->parent->name, list->name)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001854 break;
1855 }
1856
Radek Krejci1d82ef62015-08-07 14:44:40 +02001857 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001858 ++depth;
1859 }
1860
1861 /* make sure the nodes are equal */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001862 parent1 = node->parent->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001863 parent2 = list->parent;
1864 while (1) {
1865 if ((parent1 && !parent2) || (!parent1 && parent2)) {
1866 return NULL;
1867 }
1868
1869 if (parent1 == parent2) {
1870 break;
1871 }
1872
1873 parent1 = parent1->parent;
1874 parent2 = parent2->parent;
1875 }
1876
1877 /* find the descendant in the list */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001878 LY_TREE_FOR(list->child, node2) {
1879 if (!strcmp(node2->name, node->name)) {
1880 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001881 break;
1882 }
1883 }
1884
1885 if (!ret) {
1886 return NULL;
1887 }
1888
1889 /* continue traversing both trees, the nodes are always truly equal */
1890 while (1) {
1891 --depth;
1892 if (!depth) {
Radek Krejci76512572015-08-04 09:47:08 +02001893 if (ret->nodetype != LYS_LEAF) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001894 return NULL;
1895 }
Radek Krejcib8048692015-08-05 13:36:34 +02001896 return (struct lys_node_leaf *)ret;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001897 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001898 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001899 for (i = 0; i < depth-1; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001900 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001901 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001902 LY_TREE_FOR(ret->child, node2) {
1903 if (!strcmp(node2->name, node->name)) {
1904 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001905 break;
1906 }
1907 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001908 if (!node2) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001909 return NULL;
1910 }
1911 }
1912}
1913
Radek Krejci76512572015-08-04 09:47:08 +02001914struct lys_node *
Michal Vasko71e1aa82015-08-12 12:17:51 +02001915lys_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 +02001916 struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001917{
Radek Krejci76512572015-08-04 09:47:08 +02001918 struct lys_node *retval = NULL, *aux, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001919 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001920 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001921
Michal Vaskoc07187d2015-08-13 15:20:57 +02001922 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001923 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001924 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001925 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001926 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001927 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001928 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001929 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001930 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001931 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001932 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001933 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001934 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001935 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001936 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001937 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001938 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001939 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001940 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001941 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001942 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001943 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001944 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001945 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001946
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001947 /* we cannot just duplicate memory since the strings are stored in
1948 * dictionary and we need to update dictionary counters.
1949 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001950
Radek Krejci1d82ef62015-08-07 14:44:40 +02001951 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001952 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001953 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02001954 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001955 break;
1956
Radek Krejci76512572015-08-04 09:47:08 +02001957 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001958 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02001959 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001960 break;
1961
Radek Krejci76512572015-08-04 09:47:08 +02001962 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001963 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02001964 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001965 break;
1966
Radek Krejci76512572015-08-04 09:47:08 +02001967 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001968 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02001969 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001970 break;
1971
Radek Krejci76512572015-08-04 09:47:08 +02001972 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001973 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02001974 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001975 break;
1976
Radek Krejci76512572015-08-04 09:47:08 +02001977 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001978 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02001979 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001980 break;
1981
Radek Krejci76512572015-08-04 09:47:08 +02001982 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001983 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02001984 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001985 break;
1986
Radek Krejci76512572015-08-04 09:47:08 +02001987 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001988 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02001989 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001990 break;
1991
Radek Krejci76512572015-08-04 09:47:08 +02001992 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001993 grp = calloc(1, sizeof *grp);
1994 retval = (struct lys_node *)grp;
1995 break;
1996
Radek Krejci76512572015-08-04 09:47:08 +02001997 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02001998 rpc = calloc(1, sizeof *rpc);
1999 retval = (struct lys_node *)rpc;
2000 break;
2001
Radek Krejci76512572015-08-04 09:47:08 +02002002 case LYS_INPUT:
2003 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002004 io = calloc(1, sizeof *io);
2005 retval = (struct lys_node *)io;
2006 break;
2007
Radek Krejci76512572015-08-04 09:47:08 +02002008 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002009 ntf = calloc(1, sizeof *ntf);
2010 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002011 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002012
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002013 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002014 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002015 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002016 }
Radek Krejcib388c152015-06-04 17:03:03 +02002017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002018 /*
2019 * duplicate generic part of the structure
2020 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002021 retval->name = lydict_insert(ctx, node->name, 0);
2022 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2023 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002024 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002025 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002026 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002027 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002028 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002029 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002030
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002031 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002032 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002033
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002034 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002035
Radek Krejci1d82ef62015-08-07 14:44:40 +02002036 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002037 retval->features = calloc(retval->features_size, sizeof *retval->features);
Radek Krejci1d82ef62015-08-07 14:44:40 +02002038 for (i = 0; i < node->features_size; ++i) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002039 if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002040 retval->features[i] = node->features[i];
Michal Vaskod23ce592015-08-06 09:55:37 +02002041 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002042 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002043
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002044 if (recursive) {
2045 /* go recursively */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002046 LY_TREE_FOR(node->child, child) {
Michal Vasko71e1aa82015-08-12 12:17:51 +02002047 aux = lys_node_dup(module, child, retval->flags, retval->nacm, 1, unres);
Radek Krejci10c760e2015-08-14 14:45:43 +02002048 if (!aux || lys_node_addchild(retval, NULL, aux)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02002049 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002050 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002051 }
2052 }
2053 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002054
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002055 /*
2056 * duplicate specific part of the structure
2057 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002058 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002059 case LYS_CONTAINER:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002060 if (cont_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002061 cont->when = lys_when_dup(ctx, cont_orig->when);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002062 if (unres_schema_add_node(module, unres, cont->when, UNRES_WHEN, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002063 goto error;
2064 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002065 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002066 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002067
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002068 cont->must_size = cont_orig->must_size;
2069 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002070
Radek Krejci1d82ef62015-08-07 14:44:40 +02002071 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002072 for (i = 0; i < cont->must_size; ++i) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002073 if (unres_schema_add_node(module, unres, &cont->must[i], UNRES_MUST, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002074 goto error;
2075 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002076 }
2077
Radek Krejci1d82ef62015-08-07 14:44:40 +02002078 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002079 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002080
Radek Krejci76512572015-08-04 09:47:08 +02002081 case LYS_CHOICE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002082 if (choice_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002083 choice->when = lys_when_dup(ctx, choice_orig->when);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002084 if (unres_schema_add_node(module, unres, choice->when, UNRES_WHEN, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002085 goto error;
2086 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002087 }
2088
2089 if (choice_orig->dflt) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002090 rc = resolve_sibling(choice->module, choice->child, NULL, 0, choice_orig->dflt->name, 0, LYS_ANYXML
Radek Krejci76512572015-08-04 09:47:08 +02002091 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002092 | LYS_LIST, &choice->dflt);
Michal Vasko49168a22015-08-17 16:35:41 +02002093 if (rc) {
2094 if (rc == EXIT_FAILURE) {
2095 LOGINT;
2096 }
2097 goto error;
2098 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002099 } else {
Michal Vaskoc68a2a22015-08-06 09:57:24 +02002100 /* useless to check return value, we don't know whether
2101 * there really wasn't any default defined or it just hasn't
2102 * been resolved, we just hope for the best :)
2103 */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002104 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002105 }
2106 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002107
Radek Krejci76512572015-08-04 09:47:08 +02002108 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002109 lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002110 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2111
2112 if (leaf_orig->dflt) {
2113 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002114 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002115 goto error;
2116 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002117 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002118
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002119 leaf->must_size = leaf_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002120 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002121 for (i = 0; i < leaf->must_size; ++i) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002122 if (unres_schema_add_node(module, unres, &leaf->must[i], UNRES_MUST, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002123 goto error;
2124 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002125 }
Radek Krejci00768f42015-06-18 17:04:04 +02002126
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002127 if (leaf_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002128 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002129 if (unres_schema_add_node(module, unres, leaf->when, UNRES_WHEN, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002130 goto error;
2131 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002132 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002133 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002134
Radek Krejci76512572015-08-04 09:47:08 +02002135 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02002136 lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002137 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002138
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002139 llist->min = llist_orig->min;
2140 llist->max = llist_orig->max;
2141
2142 llist->must_size = llist_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002143 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002144 for (i = 0; i < llist->must_size; ++i) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002145 if (unres_schema_add_node(module, unres, &llist->must[i], UNRES_MUST, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002146 goto error;
2147 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002148 }
Radek Krejci00768f42015-06-18 17:04:04 +02002149
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002150 if (llist_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002151 llist->when = lys_when_dup(ctx, llist_orig->when);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002152 if (unres_schema_add_node(module, unres, llist->when, UNRES_WHEN, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002153 goto error;
2154 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002155 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002156 break;
2157
Radek Krejci76512572015-08-04 09:47:08 +02002158 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002159 list->min = list_orig->min;
2160 list->max = list_orig->max;
2161
2162 list->must_size = list_orig->must_size;
2163 list->tpdf_size = list_orig->tpdf_size;
2164 list->keys_size = list_orig->keys_size;
2165 list->unique_size = list_orig->unique_size;
2166
Radek Krejci1d82ef62015-08-07 14:44:40 +02002167 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002168 for (i = 0; i < list->must_size; ++i) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002169 if (unres_schema_add_node(module, unres, &list->must[i], UNRES_MUST, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002170 goto error;
2171 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002172 }
2173
Radek Krejci1d82ef62015-08-07 14:44:40 +02002174 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002175
2176 if (list->keys_size) {
2177 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002178
2179 /* we managed to resolve it before, resolve it again manually */
2180 if (list_orig->keys[0]) {
2181 for (i = 0; i < list->keys_size; ++i) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002182 rc = resolve_sibling(list->module, list->child, NULL, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2183 (struct lys_node **)&list->keys[i]);
Michal Vasko49168a22015-08-17 16:35:41 +02002184 if (rc) {
2185 if (rc == EXIT_FAILURE) {
2186 LOGINT;
2187 }
2188 goto error;
2189 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002190 }
2191 /* it was not resolved yet, add unres copy */
2192 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002193 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02002194 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002195 goto error;
Michal Vaskod23ce592015-08-06 09:55:37 +02002196 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002197 }
2198 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002199
2200 list->unique = calloc(list->unique_size, sizeof *list->unique);
2201 if (list_orig->unique) {
2202 for (i = 0; i < list->unique_size; ++i) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002203 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
2204 for (j = 0; j < list->unique[i].leafs_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002205 list->unique[i].leafs[j] = lys_uniq_find(list, list_orig->unique[i].leafs[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002206 }
2207 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002208 } else {
2209 for (i = 0; i < list->unique_size; ++i) {
2210 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02002211 list->unique[i].leafs = (struct lys_node_leaf **)list;
Michal Vasko0bd29d12015-08-19 11:45:49 +02002212 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002213 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002214 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002215
2216 if (list_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002217 list->when = lys_when_dup(ctx, list_orig->when);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002218 if (unres_schema_add_node(module, unres, list->when, UNRES_WHEN, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002219 goto error;
2220 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002221 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002222 break;
2223
Radek Krejci76512572015-08-04 09:47:08 +02002224 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002225 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002226 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002227 for (i = 0; i < anyxml->must_size; ++i) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002228 if (unres_schema_add_node(module, unres, &anyxml->must[i], UNRES_MUST, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002229 goto error;
2230 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002231 }
2232
2233 if (anyxml_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002234 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002235 if (unres_schema_add_node(module, unres, anyxml->when, UNRES_WHEN, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002236 goto error;
2237 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002238 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002239 break;
2240
Radek Krejci76512572015-08-04 09:47:08 +02002241 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002242 uses->grp = uses_orig->grp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002243
2244 if (uses_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002245 uses->when = lys_when_dup(ctx, uses_orig->when);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002246 if (unres_schema_add_node(module, unres, uses->when, UNRES_WHEN, (struct lys_node *)uses, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002247 goto error;
2248 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002249 }
2250
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002251 uses->refine_size = uses_orig->refine_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002252 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size, uses, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002253 uses->augment_size = uses_orig->augment_size;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02002254 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Michal Vaskof8c128d2015-08-06 15:25:28 +02002255 if (!uses->child) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002256 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002257 goto error;
2258 }
Michal Vaskof8c128d2015-08-06 15:25:28 +02002259 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002260 break;
2261
Radek Krejci76512572015-08-04 09:47:08 +02002262 case LYS_CASE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002263 if (cs_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002264 cs->when = lys_when_dup(ctx, cs_orig->when);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002265 if (unres_schema_add_node(module, unres, cs->when, UNRES_WHEN, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002266 goto error;
2267 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002268 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002269 break;
2270
Radek Krejci76512572015-08-04 09:47:08 +02002271 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002272 grp->tpdf_size = grp_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002273 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002274 break;
2275
Radek Krejci76512572015-08-04 09:47:08 +02002276 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002277 rpc->tpdf_size = rpc_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002278 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002279 break;
2280
Radek Krejci76512572015-08-04 09:47:08 +02002281 case LYS_INPUT:
2282 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002283 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002284 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002285 break;
2286
Radek Krejci76512572015-08-04 09:47:08 +02002287 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002288 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002289 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcia01e5432015-06-16 10:35:25 +02002290 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002291
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002292 default:
Radek Krejci00768f42015-06-18 17:04:04 +02002293 /* LY_NODE_AUGMENT */
Michal Vaskod23ce592015-08-06 09:55:37 +02002294 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002295 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002296 }
2297
2298 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002299
2300error:
2301
2302 lys_node_free(retval);
2303 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002304}
2305
Michal Vasko13b15832015-08-19 11:04:48 +02002306void
2307lys_free(struct lys_module *module, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02002308{
Radek Krejcidce51452015-06-16 15:20:08 +02002309 struct ly_ctx *ctx;
2310 int i;
2311
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002312 if (!module) {
2313 return;
2314 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002315
Radek Krejcidce51452015-06-16 15:20:08 +02002316 /* remove schema from the context */
2317 ctx = module->ctx;
2318 if (ctx->models.used) {
2319 for (i = 0; i < ctx->models.used; i++) {
2320 if (ctx->models.list[i] == module) {
2321 /* replace the position in the list by the last module in the list */
2322 ctx->models.used--;
2323 ctx->models.list[i] = ctx->models.list[ctx->models.used];
2324 ctx->models.list[ctx->models.used] = NULL;
2325 /* we are done */
2326 break;
2327 }
2328 }
2329 }
2330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002331 /* common part with struct ly_submodule */
Michal Vasko13b15832015-08-19 11:04:48 +02002332 module_free_common(module, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02002333
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002334 /* specific items to free */
2335 lydict_remove(module->ctx, module->ns);
2336 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02002337
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002338 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002339}
Radek Krejci7e97c352015-06-19 16:26:34 +02002340
2341/*
2342 * op: 1 - enable, 0 - disable
2343 */
2344static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002345lys_features_change(struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002346{
2347 int all = 0;
2348 int i, j, k;
2349
2350 if (!module || !name || !strlen(name)) {
2351 return EXIT_FAILURE;
2352 }
2353
2354 if (!strcmp(name, "*")) {
2355 /* enable all */
2356 all = 1;
2357 }
2358
2359 /* module itself */
2360 for (i = 0; i < module->features_size; i++) {
2361 if (all || !strcmp(module->features[i].name, name)) {
2362 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002363 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002364 /* enable referenced features (recursion) */
2365 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002366 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002367 module->features[i].features[k]->name, op);
2368 }
2369 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002370 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002371 }
2372 if (!all) {
2373 return EXIT_SUCCESS;
2374 }
2375 }
2376 }
2377
2378 /* submodules */
2379 for (j = 0; j < module->inc_size; j++) {
2380 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2381 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2382 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002383 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002384 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002385 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002386 }
2387 if (!all) {
2388 return EXIT_SUCCESS;
2389 }
2390 }
2391 }
2392 }
2393
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002394 /* TODO submodules of submodules ... */
2395
Radek Krejci7e97c352015-06-19 16:26:34 +02002396 if (all) {
2397 return EXIT_SUCCESS;
2398 } else {
2399 return EXIT_FAILURE;
2400 }
2401}
2402
2403API int
Radek Krejcib8048692015-08-05 13:36:34 +02002404lys_features_enable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002405{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002406 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002407}
2408
2409API int
Radek Krejcib8048692015-08-05 13:36:34 +02002410lys_features_disable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002411{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002412 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002413}
2414
2415API int
Radek Krejcib8048692015-08-05 13:36:34 +02002416lys_features_state(struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002417{
2418 int i, j;
2419
2420 if (!module || !feature) {
2421 return -1;
2422 }
2423
2424 /* search for the specified feature */
2425 /* module itself */
2426 for (i = 0; i < module->features_size; i++) {
2427 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002428 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002429 return 1;
2430 } else {
2431 return 0;
2432 }
2433 }
2434 }
2435
2436 /* submodules */
2437 for (j = 0; j < module->inc_size; j++) {
2438 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2439 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002440 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002441 return 1;
2442 } else {
2443 return 0;
2444 }
2445 }
2446 }
2447 }
2448
2449 /* TODO submodules of submodules ... */
2450
2451 /* feature definition not found */
2452 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002453}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002454
Radek Krejci96a10da2015-07-30 11:00:14 +02002455API const char **
Radek Krejcib8048692015-08-05 13:36:34 +02002456lys_features_list(struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002457{
Radek Krejci96a10da2015-07-30 11:00:14 +02002458 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002459 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002460 unsigned int count;
2461
2462 if (!module) {
2463 return NULL;
2464 }
2465
2466 count = module->features_size;
2467 for (i = 0; i < module->inc_size; i++) {
2468 count += module->inc[i].submodule->features_size;
2469 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002470 result = malloc((count + 1) * sizeof *result);
2471 if (states) {
2472 *states = malloc((count + 1) * sizeof **states);
Michal Vasko2367e7c2015-07-07 11:33:44 +02002473 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002474 count = 0;
2475
2476 /* module itself */
2477 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002478 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002479 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002480 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002481 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002482 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002483 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002484 }
2485 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002486 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002487 }
2488
2489 /* submodules */
2490 for (j = 0; j < module->inc_size; j++) {
2491 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002492 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002493 if (states) {
2494 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2495 (*states)[count] = 1;
2496 } else {
2497 (*states)[count] = 0;
2498 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002499 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002500 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002501 }
2502 }
2503
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002504 /* TODO submodules of submodules ... */
2505
2506 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002507 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002508
2509 return result;
2510}
Radek Krejcib20c62d2015-07-07 17:07:14 +02002511
2512API struct lyd_node *
Radek Krejci25b9fd32015-08-10 15:06:07 +02002513lyd_parse(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
Radek Krejcib20c62d2015-07-07 17:07:14 +02002514{
2515 if (!ctx || !data) {
2516 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
2517 return NULL;
2518 }
2519
2520 switch (format) {
Radek Krejcia9167ef2015-08-03 11:01:11 +02002521 case LYD_XML:
Radek Krejci25b9fd32015-08-10 15:06:07 +02002522 return xml_read_data(ctx, data, options);
Radek Krejcia9167ef2015-08-03 11:01:11 +02002523 case LYD_JSON:
Radek Krejcib20c62d2015-07-07 17:07:14 +02002524 default:
2525 /* TODO */
2526 return NULL;
2527 }
2528
2529 return NULL;
2530}
2531
Radek Krejci47cda9e2015-08-19 11:52:54 +02002532API int
2533lyd_insert(struct lyd_node *parent, struct lyd_node *node, int options)
2534{
2535 struct lys_node *sparent;
Radek Krejcieab784a2015-08-27 09:56:53 +02002536 struct lyd_node *iter, *next, *last;
Radek Krejci47cda9e2015-08-19 11:52:54 +02002537
2538 if (!node || !parent) {
2539 ly_errno = LY_EINVAL;
2540 return EXIT_FAILURE;
2541 }
2542
2543 if (node->parent || node->prev->next) {
2544 lyd_unlink(node);
2545 }
2546
2547 /* check placing the node to the appropriate place according to the schema */
2548 sparent = node->schema->parent;
2549 while (!(sparent->nodetype & (LYS_CONTAINER | LYS_LIST))) {
2550 sparent = sparent->parent;
2551 }
2552 if (sparent != parent->schema) {
2553 ly_errno = LY_EINVAL;
2554 return EXIT_FAILURE;
2555 }
2556
Radek Krejci47cda9e2015-08-19 11:52:54 +02002557 if (!parent->child) {
2558 /* add as the only child of the parent */
2559 parent->child = node;
2560 } else {
2561 /* add as the last child of the parent */
2562 parent->child->prev->next = node;
2563 node->prev = parent->child->prev;
2564 for (iter = node; iter->next; iter = iter->next);
2565 parent->child->prev = iter;
2566 }
2567 LY_TREE_FOR(node, iter) {
2568 iter->parent = parent;
Radek Krejcia3097ed2015-09-02 16:16:48 +02002569 last = iter; /* remember the last of the inserted nodes */
Radek Krejcieab784a2015-08-27 09:56:53 +02002570 }
2571
2572 ly_errno = 0;
2573 LY_TREE_FOR_SAFE(node, next, iter) {
2574 /* various validation checks */
2575 if (lyv_data_content(iter, 0, options)) {
2576 if (ly_errno) {
2577 return EXIT_FAILURE;
2578 } else {
2579 lyd_free(iter);
2580 }
2581 }
2582
2583 if (iter == last) {
2584 /* we are done - checking only the inserted nodes */
2585 break;
2586 }
Radek Krejci47cda9e2015-08-19 11:52:54 +02002587 }
2588
2589 return EXIT_SUCCESS;
2590}
2591
2592API int
Radek Krejcia3097ed2015-09-02 16:16:48 +02002593lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node, int options)
2594{
2595 struct lys_node *par1, *par2;
2596 struct lyd_node *iter, *next, *last;
2597
2598 if (!node || !sibling) {
2599 ly_errno = LY_EINVAL;
2600 return EXIT_FAILURE;
2601 }
2602
2603 if (node->parent || node->prev->next) {
2604 lyd_unlink(node);
2605 }
2606
2607 /* check placing the node to the appropriate place according to the schema */
2608 for (par1 = sibling->schema->parent; par1 && (par1->nodetype & (LYS_CONTAINER | LYS_LIST)); par1 = par1->parent);
2609 for (par2 = node->schema->parent; par2 && (par2->nodetype & (LYS_CONTAINER | LYS_LIST)); par2 = par2->parent);
2610 if (par1 != par2) {
2611 ly_errno = LY_EINVAL;
2612 return EXIT_FAILURE;
2613 }
2614
2615 LY_TREE_FOR(node, iter) {
2616 iter->parent = sibling->parent;
2617 last = iter; /* remember the last of the inserted nodes */
2618 }
2619
2620 if (sibling->next) {
2621 /* adding into a middle - fix the prev pointer of the node after inserted nodes */
2622 last->next = sibling->next;
2623 sibling->next->prev = last;
2624 } else {
2625 /* at the end - fix the prev pointer of the first node */
2626 if (sibling->parent) {
2627 sibling->parent->child->prev = last;
2628 } else {
2629 for (iter = sibling; iter->prev->next; iter = iter->prev);
2630 iter->prev = last;
2631 }
2632 }
2633 sibling->next = node;
2634 node->prev = sibling;
2635
2636 ly_errno = 0;
2637 LY_TREE_FOR_SAFE(node, next, iter) {
2638 /* various validation checks */
2639 if (lyv_data_content(iter, 0, options)) {
2640 if (ly_errno) {
2641 return EXIT_FAILURE;
2642 } else {
2643 lyd_free(iter);
2644 }
2645 }
2646
2647 if (iter == last) {
2648 /* we are done - checking only the inserted nodes */
2649 break;
2650 }
2651 }
2652
2653 return EXIT_SUCCESS;
2654}
2655
2656API int
Radek Krejci47cda9e2015-08-19 11:52:54 +02002657lyd_unlink(struct lyd_node *node)
2658{
2659 struct lyd_node *iter;
2660
2661 if (!node) {
2662 ly_errno = LY_EINVAL;
2663 return EXIT_FAILURE;
2664 }
2665
Radek Krejci47cda9e2015-08-19 11:52:54 +02002666 /* unlink from siblings */
2667 if (node->prev->next) {
2668 node->prev->next = node->next;
2669 }
2670 if (node->next) {
2671 node->next->prev = node->prev;
2672 } else {
2673 /* unlinking the last node */
2674 iter = node->prev;
2675 while (iter->prev != node) {
2676 iter = iter->prev;
2677 }
2678 /* update the "last" pointer from the first node */
2679 iter->prev = node->prev;
2680 }
Radek Krejci47cda9e2015-08-19 11:52:54 +02002681
2682 /* unlink from parent */
2683 if (node->parent) {
2684 if (node->parent->child == node) {
2685 /* the node is the first child */
2686 node->parent->child = node->next;
2687 }
2688 node->parent = NULL;
2689 }
2690
Radek Krejci58f6e672015-08-19 16:59:53 +02002691 node->next = NULL;
2692 node->prev = node;
2693
Radek Krejci47cda9e2015-08-19 11:52:54 +02002694 return EXIT_SUCCESS;
2695}
2696
Michal Vasko8dee3a52015-08-21 09:09:57 +02002697static void
2698lyd_attr_free(struct ly_ctx *ctx, struct lyd_attr *attr)
2699{
2700 if (!attr) {
2701 return;
2702 }
2703
2704 if (attr->next) {
2705 lyd_attr_free(ctx, attr->next);
2706 }
2707 lydict_remove(ctx, attr->name);
2708 lydict_remove(ctx, attr->value);
2709 free(attr);
2710}
2711
Radek Krejci0e1d1a62015-07-31 11:17:01 +02002712API void
Radek Krejci912da452015-07-29 14:10:06 +02002713lyd_free(struct lyd_node *node)
Radek Krejcib20c62d2015-07-07 17:07:14 +02002714{
2715 struct lyd_node *next, *child;
2716
Radek Krejci52f791c2015-07-15 11:14:17 +02002717 if (!node) {
2718 return;
2719 }
2720
Radek Krejci76512572015-08-04 09:47:08 +02002721 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
Radek Krejcie4748472015-07-08 18:00:22 +02002722 /* free children */
2723 LY_TREE_FOR_SAFE(node->child, next, child) {
Radek Krejci912da452015-07-29 14:10:06 +02002724 lyd_free(child);
Radek Krejcie4748472015-07-08 18:00:22 +02002725 }
Radek Krejci76512572015-08-04 09:47:08 +02002726 } else if (node->schema->nodetype == LYS_ANYXML) {
Radek Krejci9566b092015-07-31 11:18:15 +02002727 lyxml_free_elem(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
Radek Krejcie4748472015-07-08 18:00:22 +02002728 } else {
2729 /* free value */
2730 switch(((struct lyd_node_leaf *)node)->value_type) {
2731 case LY_TYPE_BINARY:
2732 case LY_TYPE_STRING:
2733 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf *)node)->value.string);
2734 break;
Radek Krejci3e3affe2015-07-09 15:38:40 +02002735 case LY_TYPE_BITS:
2736 if (((struct lyd_node_leaf *)node)->value.bit) {
2737 free(((struct lyd_node_leaf *)node)->value.bit);
2738 }
2739 break;
Radek Krejcie4748472015-07-08 18:00:22 +02002740 default:
Radek Krejci7511f402015-07-10 09:56:30 +02002741 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
Radek Krejcie4748472015-07-08 18:00:22 +02002742 break;
2743 }
Radek Krejcib20c62d2015-07-07 17:07:14 +02002744 }
2745
Radek Krejcib3d6d552015-08-19 11:56:13 +02002746 lyd_unlink(node);
Michal Vasko8dee3a52015-08-21 09:09:57 +02002747 lyd_attr_free(node->schema->module->ctx, node->attr);
Radek Krejcib3d6d552015-08-19 11:56:13 +02002748 free(node);
2749}
2750
2751int
Radek Krejci78ce8612015-08-18 14:31:05 +02002752lyd_compare(struct lyd_node *first, struct lyd_node *second, int unique)
2753{
2754 struct lys_node_list *slist;
2755 struct lys_node *snode;
2756 struct lyd_node *diter;
2757 const char *val1, *val2;
2758 int i, j;
2759
Radek Krejcib3d6d552015-08-19 11:56:13 +02002760 assert(first);
2761 assert(second);
Radek Krejci78ce8612015-08-18 14:31:05 +02002762
2763 if (first->schema != second->schema) {
2764 return 1;
2765 }
2766
2767 switch (first->schema->nodetype) {
2768 case LYS_LEAFLIST:
2769 /* compare values */
2770 if (((struct lyd_node_leaflist *)first)->value_str == ((struct lyd_node_leaflist *)second)->value_str) {
2771 return 0;
2772 }
2773 return 1;
2774 case LYS_LIST:
2775 slist = (struct lys_node_list*)first->schema;
2776
2777 if (unique) {
2778 /* compare unique leafs */
2779 for (i = 0; i < slist->unique_size; i++) {
2780 for (j = 0; j < slist->unique[i].leafs_size; j++) {
2781 snode = (struct lys_node *)slist->unique[i].leafs[j];
2782 /* use default values if the instances of unique leafs are not present */
2783 val1 = val2 = ((struct lys_node_leaf *)snode)->dflt;
2784 LY_TREE_FOR(first->child, diter) {
2785 if (diter->schema == snode) {
2786 val1 = ((struct lyd_node_leaf *)diter)->value_str;
2787 break;
2788 }
2789 }
2790 LY_TREE_FOR(second->child, diter) {
2791 if (diter->schema == snode) {
2792 val2 = ((struct lyd_node_leaf *)diter)->value_str;
2793 break;
2794 }
2795 }
2796 if (val1 != val2) {
2797 break;
2798 }
2799 }
2800 if (j && j == slist->unique[i].leafs_size) {
2801 /* all unique leafs are the same in this set */
2802 return 0;
2803 }
2804 }
2805 }
2806
2807 /* compare keys */
2808 for (i = 0; i < slist->keys_size; i++) {
2809 snode = (struct lys_node *)slist->keys[i];
2810 val1 = val2 = NULL;
2811 LY_TREE_FOR(first->child, diter) {
2812 if (diter->schema == snode) {
2813 val1 = ((struct lyd_node_leaf *)diter)->value_str;
2814 break;
2815 }
2816 }
2817 LY_TREE_FOR(second->child, diter) {
2818 if (diter->schema == snode) {
2819 val2 = ((struct lyd_node_leaf *)diter)->value_str;
2820 break;
2821 }
2822 }
2823 if (val1 != val2) {
2824 return 1;
2825 }
2826 }
2827
2828 return 0;
2829 default:
2830 /* no additional check is needed */
2831 return 0;
2832 }
2833}
2834
Radek Krejcife19f692015-08-19 11:46:48 +02002835API struct lyd_set *
2836lyd_set_new(void)
2837{
2838 return calloc(1, sizeof(struct lyd_set));
2839}
2840
2841API void
2842lyd_set_free(struct lyd_set *set)
2843{
2844 if (!set) {
2845 return;
2846 }
2847
2848 free(set->set);
2849 free(set);
2850}
2851
2852API int
2853lyd_set_add(struct lyd_set *set, struct lyd_node *node)
2854{
2855 struct lyd_node **new;
2856
2857 if (!set) {
2858 ly_errno = LY_EINVAL;
2859 return EXIT_FAILURE;
2860 }
2861
2862 if (set->size == set->number) {
2863 new = realloc(set->set, (set->size + 8) * sizeof *(set->set));
2864 if (!new) {
2865 LOGMEM;
2866 return EXIT_FAILURE;
2867 }
2868 set->size += 8;
2869 set->set = new;
2870 }
2871
2872 set->set[set->number++] = node;
2873
2874 return EXIT_SUCCESS;
2875}