blob: 338c31ba8847f2ead30990ec8a3a1ab2e6689bf1 [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
Michal Vasko2d162e12015-09-24 14:33:29 +02002 * @file tree_schema.c
Radek Krejcida04f4a2015-05-21 12:54:09 +02003 * @author Radek Krejci <rkrejci@cesnet.cz>
Michal Vasko2d162e12015-09-24 14:33:29 +02004 * @brief Manipulation with libyang schema data structures
Radek Krejcida04f4a2015-05-21 12:54:09 +02005 *
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
Michal Vaskob84f88a2015-09-24 13:16:10 +02001039static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02001040lys_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 Vaskob84f88a2015-09-24 13:16:10 +02001053 /* all these unres additions can fail even though they did not before */
Michal Vasko0bd29d12015-08-19 11:45:49 +02001054 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_DER, unres->str_snode[i], 0) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001055 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001056 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001057 return EXIT_SUCCESS;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001058 }
1059
Radek Krejci3733a802015-06-19 13:43:21 +02001060 switch (new->base) {
1061 case LY_TYPE_BINARY:
Radek Krejci425adf02015-06-26 16:23:28 +02001062 if (old->info.binary.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001063 new->info.binary.length = lys_restr_dup(mod->ctx, old->info.binary.length, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001064 }
Radek Krejci3733a802015-06-19 13:43:21 +02001065 break;
1066
1067 case LY_TYPE_BITS:
1068 new->info.bits.count = old->info.bits.count;
1069 if (new->info.bits.count) {
1070 new->info.bits.bit = calloc(new->info.bits.count, sizeof *new->info.bits.bit);
1071 for (i = 0; i < new->info.bits.count; i++) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001072 new->info.bits.bit[i].name = lydict_insert(mod->ctx, old->info.bits.bit[i].name, 0);
1073 new->info.bits.bit[i].dsc = lydict_insert(mod->ctx, old->info.bits.bit[i].dsc, 0);
1074 new->info.bits.bit[i].ref = lydict_insert(mod->ctx, old->info.bits.bit[i].ref, 0);
Radek Krejci3733a802015-06-19 13:43:21 +02001075 new->info.bits.bit[i].status = old->info.bits.bit[i].status;
1076 new->info.bits.bit[i].pos = old->info.bits.bit[i].pos;
1077 }
1078 }
1079 break;
1080
Radek Krejcif9401c32015-06-26 16:47:36 +02001081 case LY_TYPE_DEC64:
1082 new->info.dec64.dig = old->info.dec64.dig;
1083 if (old->info.dec64.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001084 new->info.dec64.range = lys_restr_dup(mod->ctx, old->info.dec64.range, 1);
Radek Krejcif9401c32015-06-26 16:47:36 +02001085 }
1086 break;
1087
Radek Krejci3733a802015-06-19 13:43:21 +02001088 case LY_TYPE_ENUM:
1089 new->info.enums.count = old->info.enums.count;
1090 if (new->info.enums.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001091 new->info.enums.enm = calloc(new->info.enums.count, sizeof *new->info.enums.enm);
Radek Krejci3733a802015-06-19 13:43:21 +02001092 for (i = 0; i < new->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001093 new->info.enums.enm[i].name = lydict_insert(mod->ctx, old->info.enums.enm[i].name, 0);
1094 new->info.enums.enm[i].dsc = lydict_insert(mod->ctx, old->info.enums.enm[i].dsc, 0);
1095 new->info.enums.enm[i].ref = lydict_insert(mod->ctx, old->info.enums.enm[i].ref, 0);
1096 new->info.enums.enm[i].status = old->info.enums.enm[i].status;
1097 new->info.enums.enm[i].value = old->info.enums.enm[i].value;
Radek Krejci3733a802015-06-19 13:43:21 +02001098 }
1099 }
1100 break;
1101
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001102 case LY_TYPE_IDENT:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001103 if (old->info.ident.ref) {
1104 new->info.ident.ref = old->info.ident.ref;
1105 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001106 i = unres_schema_find(unres, old, UNRES_TYPE_IDENTREF);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001107 assert(i != -1);
Michal Vasko0bd29d12015-08-19 11:45:49 +02001108 if (unres_schema_add_str(mod, unres, new, UNRES_TYPE_IDENTREF, unres->str_snode[i], 0) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001109 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001110 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001111 }
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001112 break;
1113
Radek Krejciaf351422015-06-19 14:49:38 +02001114 case LY_TYPE_INST:
1115 new->info.inst.req = old->info.inst.req;
1116 break;
1117
Radek Krejcif2860132015-06-20 12:37:20 +02001118 case LY_TYPE_INT8:
1119 case LY_TYPE_INT16:
1120 case LY_TYPE_INT32:
1121 case LY_TYPE_INT64:
1122 case LY_TYPE_UINT8:
1123 case LY_TYPE_UINT16:
1124 case LY_TYPE_UINT32:
1125 case LY_TYPE_UINT64:
Radek Krejci425adf02015-06-26 16:23:28 +02001126 if (old->info.num.range) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001127 new->info.num.range = lys_restr_dup(mod->ctx, old->info.num.range, 1);
Radek Krejci425adf02015-06-26 16:23:28 +02001128 }
Radek Krejcif2860132015-06-20 12:37:20 +02001129 break;
1130
Radek Krejcidc4c1412015-06-19 15:39:54 +02001131 case LY_TYPE_LEAFREF:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001132 new->info.lref.path = lydict_insert(mod->ctx, old->info.lref.path, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02001133 if (unres_schema_add_node(mod, unres, new, UNRES_TYPE_LEAFREF, parent, 0) == -1) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001134 return -1;
Michal Vasko49168a22015-08-17 16:35:41 +02001135 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001136 break;
1137
Radek Krejci3733a802015-06-19 13:43:21 +02001138 case LY_TYPE_STRING:
Radek Krejci5fbc9162015-06-19 14:11:11 +02001139 if (old->info.str.length) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001140 new->info.str.length = lys_restr_dup(mod->ctx, old->info.str.length, 1);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001141 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001142 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 +02001143 break;
1144
Radek Krejcie4c366b2015-07-02 10:11:31 +02001145 case LY_TYPE_UNION:
1146 new->info.uni.count = old->info.uni.count;
1147 if (new->info.uni.count) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001148 new->info.uni.types = calloc(new->info.uni.count, sizeof *new->info.uni.types);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001149 for (i = 0; i < new->info.uni.count; i++) {
Michal Vaskob84f88a2015-09-24 13:16:10 +02001150 if (lys_type_dup(mod, parent, &(new->info.uni.types[i]), &(old->info.uni.types[i]), unres)) {
1151 return -1;
1152 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001153 }
1154 }
1155 break;
1156
Radek Krejci3733a802015-06-19 13:43:21 +02001157 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001158 /* nothing to do for LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci3733a802015-06-19 13:43:21 +02001159 break;
1160 }
Michal Vaskob84f88a2015-09-24 13:16:10 +02001161
1162 return EXIT_SUCCESS;
Radek Krejci3733a802015-06-19 13:43:21 +02001163}
1164
1165void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001166lys_type_free(struct ly_ctx *ctx, struct lys_type *type)
Radek Krejci5a065542015-05-22 15:02:07 +02001167{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001168 int i;
Radek Krejci5a065542015-05-22 15:02:07 +02001169
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001170 assert(ctx);
1171 if (!type) {
1172 return;
1173 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001174
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001175 lydict_remove(ctx, type->prefix);
Radek Krejci5a065542015-05-22 15:02:07 +02001176
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001177 switch (type->base) {
Radek Krejci0bd5db42015-06-19 13:30:07 +02001178 case LY_TYPE_BINARY:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001179 lys_restr_free(ctx, type->info.binary.length);
Radek Krejci0bd5db42015-06-19 13:30:07 +02001180 free(type->info.binary.length);
1181 break;
Radek Krejci994b6f62015-06-18 16:47:27 +02001182 case LY_TYPE_BITS:
1183 for (i = 0; i < type->info.bits.count; i++) {
1184 lydict_remove(ctx, type->info.bits.bit[i].name);
1185 lydict_remove(ctx, type->info.bits.bit[i].dsc);
1186 lydict_remove(ctx, type->info.bits.bit[i].ref);
1187 }
1188 free(type->info.bits.bit);
1189 break;
Radek Krejcif9401c32015-06-26 16:47:36 +02001190
1191 case LY_TYPE_DEC64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001192 lys_restr_free(ctx, type->info.dec64.range);
Radek Krejcif9401c32015-06-26 16:47:36 +02001193 free(type->info.dec64.range);
1194 break;
1195
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001196 case LY_TYPE_ENUM:
1197 for (i = 0; i < type->info.enums.count; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001198 lydict_remove(ctx, type->info.enums.enm[i].name);
1199 lydict_remove(ctx, type->info.enums.enm[i].dsc);
1200 lydict_remove(ctx, type->info.enums.enm[i].ref);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001201 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001202 free(type->info.enums.enm);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001203 break;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001204
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001205 case LY_TYPE_INT8:
1206 case LY_TYPE_INT16:
1207 case LY_TYPE_INT32:
1208 case LY_TYPE_INT64:
1209 case LY_TYPE_UINT8:
1210 case LY_TYPE_UINT16:
1211 case LY_TYPE_UINT32:
1212 case LY_TYPE_UINT64:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001213 lys_restr_free(ctx, type->info.num.range);
Radek Krejci6fcb9dd2015-06-22 10:16:37 +02001214 free(type->info.num.range);
1215 break;
1216
Radek Krejcidc4c1412015-06-19 15:39:54 +02001217 case LY_TYPE_LEAFREF:
1218 lydict_remove(ctx, type->info.lref.path);
1219 break;
1220
Radek Krejci3733a802015-06-19 13:43:21 +02001221 case LY_TYPE_STRING:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001222 lys_restr_free(ctx, type->info.str.length);
Radek Krejci3733a802015-06-19 13:43:21 +02001223 free(type->info.str.length);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001224 for (i = 0; i < type->info.str.pat_count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001225 lys_restr_free(ctx, &type->info.str.patterns[i]);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001226 }
1227 free(type->info.str.patterns);
Radek Krejci3733a802015-06-19 13:43:21 +02001228 break;
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001229
Radek Krejcie4c366b2015-07-02 10:11:31 +02001230 case LY_TYPE_UNION:
1231 for (i = 0; i < type->info.uni.count; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001232 lys_type_free(ctx, &type->info.uni.types[i]);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001233 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001234 free(type->info.uni.types);
Radek Krejci4a7b5ee2015-06-19 14:56:43 +02001235 break;
1236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001237 default:
Radek Krejcic7c85532015-07-02 10:16:54 +02001238 /* nothing to do for LY_TYPE_IDENT, LY_TYPE_INST, LY_TYPE_BOOL, LY_TYPE_EMPTY */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001239 break;
1240 }
Radek Krejci5a065542015-05-22 15:02:07 +02001241}
1242
Radek Krejci1d82ef62015-08-07 14:44:40 +02001243static void
1244lys_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001245{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001246 assert(ctx);
1247 if (!tpdf) {
1248 return;
1249 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001250
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001251 lydict_remove(ctx, tpdf->name);
1252 lydict_remove(ctx, tpdf->dsc);
1253 lydict_remove(ctx, tpdf->ref);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001254
Radek Krejci1d82ef62015-08-07 14:44:40 +02001255 lys_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001257 lydict_remove(ctx, tpdf->units);
1258 lydict_remove(ctx, tpdf->dflt);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001259}
1260
Michal Vaskob84f88a2015-09-24 13:16:10 +02001261static struct lys_tpdf *
1262lys_tpdf_dup(struct lys_module *mod, struct lys_node *parent, struct lys_tpdf *old, int size, struct unres_schema *unres)
1263{
1264 struct lys_tpdf *result;
1265 int i, j;
1266
1267 if (!size) {
1268 return NULL;
1269 }
1270
1271 result = calloc(size, sizeof *result);
1272 for (i = 0; i < size; i++) {
1273 result[i].name = lydict_insert(mod->ctx, old[i].name, 0);
1274 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1275 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
1276 result[i].flags = old[i].flags;
1277 result[i].module = old[i].module;
1278
1279 if (lys_type_dup(mod, parent, &(result[i].type), &(old[i].type), unres)) {
1280 for (j = 0; j <= i; ++j) {
1281 lys_tpdf_free(mod->ctx, &result[j]);
1282 }
1283 free(result);
1284 return NULL;
1285 }
1286
1287 result[i].dflt = lydict_insert(mod->ctx, old[i].dflt, 0);
1288 result[i].units = lydict_insert(mod->ctx, old[i].units, 0);
1289 }
1290
1291 return result;
1292}
1293
Radek Krejci1d82ef62015-08-07 14:44:40 +02001294static struct lys_when *
1295lys_when_dup(struct ly_ctx *ctx, struct lys_when *old)
Radek Krejci00768f42015-06-18 17:04:04 +02001296{
Radek Krejci76512572015-08-04 09:47:08 +02001297 struct lys_when *new;
Radek Krejci00768f42015-06-18 17:04:04 +02001298
1299 if (!old) {
1300 return NULL;
1301 }
1302
1303 new = calloc(1, sizeof *new);
1304 new->cond = lydict_insert(ctx, old->cond, 0);
1305 new->dsc = lydict_insert(ctx, old->dsc, 0);
1306 new->ref = lydict_insert(ctx, old->ref, 0);
1307
1308 return new;
1309}
1310
Michal Vasko0308dd62015-10-07 09:14:40 +02001311void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001312lys_when_free(struct ly_ctx *ctx, struct lys_when *w)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001313{
1314 if (!w) {
1315 return;
1316 }
1317
1318 lydict_remove(ctx, w->cond);
1319 lydict_remove(ctx, w->dsc);
1320 lydict_remove(ctx, w->ref);
1321
1322 free(w);
1323}
1324
Radek Krejcib7f5e412015-08-13 10:15:51 +02001325static void
1326lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment aug)
1327{
Michal Vaskoc4c2e212015-09-23 11:34:41 +02001328 struct lys_node *next, *sub;
1329
1330 /* children from a resolved uses */
1331 LY_TREE_FOR_SAFE(aug.child, next, sub) {
1332 lys_node_free(sub);
1333 }
1334
Radek Krejcib7f5e412015-08-13 10:15:51 +02001335 lydict_remove(ctx, aug.target_name);
1336 lydict_remove(ctx, aug.dsc);
1337 lydict_remove(ctx, aug.ref);
1338
1339 free(aug.features);
1340
1341 lys_when_free(ctx, aug.when);
1342
Michal Vasko7d356a52015-08-19 15:06:31 +02001343 /* Do not free the children, they were appended somewhere and their
1344 * new parent will take care of them.
1345 */
Radek Krejcib7f5e412015-08-13 10:15:51 +02001346}
1347
Radek Krejci76512572015-08-04 09:47:08 +02001348static struct lys_node_augment *
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001349lys_augment_dup(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *old, int size)
Radek Krejci106efc02015-06-10 14:36:27 +02001350{
Radek Krejci76512572015-08-04 09:47:08 +02001351 struct lys_node_augment *new = NULL;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001352 struct lys_node *old_child, *new_child;
1353 int i;
Radek Krejci106efc02015-06-10 14:36:27 +02001354
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001355 if (!size) {
1356 return NULL;
1357 }
Radek Krejci106efc02015-06-10 14:36:27 +02001358
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001359 new = calloc(size, sizeof *new);
1360 for (i = 0; i < size; i++) {
1361 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
1362 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
1363 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
1364 new[i].flags = old[i].flags;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001365 new[i].module = old[i].module;
Michal Vasko591e0b22015-08-13 13:53:43 +02001366 new[i].nodetype = old[i].nodetype;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001367 /* this must succeed, it was already resolved once */
1368 if (resolve_schema_nodeid(new[i].target_name, parent->child, new[i].module, LYS_AUGMENT, &new[i].target)) {
1369 LOGINT;
1370 free(new);
1371 return NULL;
1372 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001373 new[i].parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001374
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001375 /* Correct the augment nodes.
1376 * This function can only be called from lys_node_dup() with uses
1377 * being the node duplicated, so we must have a case of grouping
1378 * with a uses with augments. The augmented nodes have already been
1379 * copied and everything is almost fine except their parent is wrong
Michal Vaskoa5900c52015-09-24 13:17:11 +02001380 * (it was set to their actual data parent, not an augment), and
1381 * the new augment does not have child pointer to its augment nodes,
1382 * so we just correct it.
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001383 */
1384 LY_TREE_FOR(new[i].target->child, new_child) {
1385 if (new_child->name == old[i].child->name) {
1386 break;
Radek Krejcib7f5e412015-08-13 10:15:51 +02001387 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001388 }
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001389 assert(new_child);
Michal Vaskoa5900c52015-09-24 13:17:11 +02001390 new[i].child = new_child;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02001391 LY_TREE_FOR(old[i].child, old_child) {
1392 /* all augment nodes were connected as siblings, there can be no more after this */
1393 if (old_child->parent != (struct lys_node *)&old[i]) {
1394 break;
1395 }
1396
1397 assert(old_child->name == new_child->name);
1398
1399 new_child->parent = (struct lys_node *)&new[i];
1400 new_child = new_child->next;
1401 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001402 }
Radek Krejci106efc02015-06-10 14:36:27 +02001403
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001404 return new;
Radek Krejci106efc02015-06-10 14:36:27 +02001405}
1406
Radek Krejci76512572015-08-04 09:47:08 +02001407static struct lys_refine *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001408lys_refine_dup(struct lys_module *mod, struct lys_refine *old, int size, struct lys_node_uses *uses,
Michal Vaskof02e3742015-08-05 16:27:02 +02001409 struct unres_schema *unres)
Michal Vasko1982cad2015-06-08 15:49:30 +02001410{
Radek Krejci76512572015-08-04 09:47:08 +02001411 struct lys_refine *result;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001412 int i, j;
Michal Vasko1982cad2015-06-08 15:49:30 +02001413
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001414 if (!size) {
1415 return NULL;
1416 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001417
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001418 result = calloc(size, sizeof *result);
1419 for (i = 0; i < size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001420 result[i].target_name = lydict_insert(mod->ctx, old[i].target_name, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001421 result[i].dsc = lydict_insert(mod->ctx, old[i].dsc, 0);
1422 result[i].ref = lydict_insert(mod->ctx, old[i].ref, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001423 result[i].flags = old[i].flags;
1424 result[i].target_type = old[i].target_type;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001425
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001426 result[i].must_size = old[i].must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001427 result[i].must = lys_restr_dup(mod->ctx, old[i].must, old[i].must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001428 for (j = 0; j < result[i].must_size; ++j) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001429 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 +02001430 free(result);
1431 return NULL;
1432 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001433 }
1434
Radek Krejci76512572015-08-04 09:47:08 +02001435 if (result[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001436 result[i].mod.dflt = lydict_insert(mod->ctx, old[i].mod.dflt, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001437 } else if (result[i].target_type == LYS_CONTAINER) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001438 result[i].mod.presence = lydict_insert(mod->ctx, old[i].mod.presence, 0);
Radek Krejci76512572015-08-04 09:47:08 +02001439 } else if (result[i].target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001440 result[i].mod.list = old[i].mod.list;
1441 }
1442 }
Michal Vasko1982cad2015-06-08 15:49:30 +02001443
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001444 return result;
Michal Vasko1982cad2015-06-08 15:49:30 +02001445}
1446
Radek Krejci1d82ef62015-08-07 14:44:40 +02001447static void
1448lys_ident_free(struct ly_ctx *ctx, struct lys_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +02001449{
Radek Krejcia52656e2015-08-05 13:41:50 +02001450 struct lys_ident_der *der;
Radek Krejci6793db02015-05-22 17:49:54 +02001451
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001452 assert(ctx);
1453 if (!ident) {
1454 return;
1455 }
Radek Krejci812b10a2015-05-28 16:48:25 +02001456
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001457 /*
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001458 * if caller free only a single data model which is used (its identity is
1459 * reference from identity in another module), this silly freeing can lead
1460 * to segmentation fault. But without noting if the module is used by some
1461 * other, it cannot be solved.
Radek Krejcia3390692015-06-16 14:13:31 +02001462 *
1463 * Possible solution is to not allow caller to remove particular schema
Radek Krejci1d82ef62015-08-07 14:44:40 +02001464 * from the context. This is the current approach.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001465 */
1466 while (ident->der) {
1467 der = ident->der;
1468 ident->der = der->next;
1469 free(der);
1470 }
Radek Krejci6793db02015-05-22 17:49:54 +02001471
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001472 lydict_remove(ctx, ident->name);
1473 lydict_remove(ctx, ident->dsc);
1474 lydict_remove(ctx, ident->ref);
Radek Krejci6793db02015-05-22 17:49:54 +02001475
1476}
1477
Radek Krejci1d82ef62015-08-07 14:44:40 +02001478static void
1479lys_grp_free(struct ly_ctx *ctx, struct lys_node_grp *grp)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001480{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001481 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001482
Radek Krejcid12f57b2015-08-06 10:43:39 +02001483 /* handle only specific parts for LYS_GROUPING */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001484 for (i = 0; i < grp->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001485 lys_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001486 }
1487 free(grp->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001488}
1489
Radek Krejci1d82ef62015-08-07 14:44:40 +02001490static void
Radek Krejcid12f57b2015-08-06 10:43:39 +02001491lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
1492{
1493 int i;
1494
1495 /* handle only specific parts for LYS_INPUT and LYS_OUTPUT */
1496 for (i = 0; i < io->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001497 lys_tpdf_free(ctx, &io->tpdf[i]);
Radek Krejcid12f57b2015-08-06 10:43:39 +02001498 }
1499 free(io->tpdf);
1500}
1501
Radek Krejci1d82ef62015-08-07 14:44:40 +02001502static void
1503lys_anyxml_free(struct ly_ctx *ctx, struct lys_node_anyxml *anyxml)
Radek Krejci537cf382015-06-04 11:07:01 +02001504{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001505 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001506
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001507 for (i = 0; i < anyxml->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001508 lys_restr_free(ctx, &anyxml->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001509 }
1510 free(anyxml->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001511
Radek Krejci1d82ef62015-08-07 14:44:40 +02001512 lys_when_free(ctx, anyxml->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001513}
1514
Radek Krejci1d82ef62015-08-07 14:44:40 +02001515static void
1516lys_leaf_free(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
Radek Krejci5a065542015-05-22 15:02:07 +02001517{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001518 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001519
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001520 for (i = 0; i < leaf->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001521 lys_restr_free(ctx, &leaf->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001522 }
1523 free(leaf->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001524
Radek Krejci1d82ef62015-08-07 14:44:40 +02001525 lys_when_free(ctx, leaf->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001526
Radek Krejci1d82ef62015-08-07 14:44:40 +02001527 lys_type_free(ctx, &leaf->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001528 lydict_remove(ctx, leaf->units);
1529 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +02001530}
1531
Radek Krejci1d82ef62015-08-07 14:44:40 +02001532static void
1533lys_leaflist_free(struct ly_ctx *ctx, struct lys_node_leaflist *llist)
Radek Krejci5a065542015-05-22 15:02:07 +02001534{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001535 int i;
Radek Krejci537cf382015-06-04 11:07:01 +02001536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001537 for (i = 0; i < llist->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001538 lys_restr_free(ctx, &llist->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001539 }
1540 free(llist->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001541
Radek Krejci1d82ef62015-08-07 14:44:40 +02001542 lys_when_free(ctx, llist->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001543
Radek Krejci1d82ef62015-08-07 14:44:40 +02001544 lys_type_free(ctx, &llist->type);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001545 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +02001546}
1547
Radek Krejci1d82ef62015-08-07 14:44:40 +02001548static void
1549lys_list_free(struct ly_ctx *ctx, struct lys_node_list *list)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001550{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001551 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001552
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001553 /* handle only specific parts for LY_NODE_LIST */
1554 for (i = 0; i < list->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001555 lys_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001556 }
1557 free(list->tpdf);
Radek Krejci537cf382015-06-04 11:07:01 +02001558
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001559 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001560 lys_restr_free(ctx, &list->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001561 }
1562 free(list->must);
Radek Krejci537cf382015-06-04 11:07:01 +02001563
Radek Krejci1d82ef62015-08-07 14:44:40 +02001564 lys_when_free(ctx, list->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001565
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001566 for (i = 0; i < list->unique_size; i++) {
1567 free(list->unique[i].leafs);
1568 }
1569 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +02001570
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001571 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001572}
1573
Radek Krejci1d82ef62015-08-07 14:44:40 +02001574static void
1575lys_container_free(struct ly_ctx *ctx, struct lys_node_container *cont)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001576{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001577 int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001578
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001579 /* handle only specific parts for LY_NODE_CONTAINER */
1580 lydict_remove(ctx, cont->presence);
Radek Krejci800af702015-06-02 13:46:01 +02001581
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001582 for (i = 0; i < cont->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001583 lys_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001584 }
1585 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +02001586
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001587 for (i = 0; i < cont->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001588 lys_restr_free(ctx, &cont->must[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001589 }
1590 free(cont->must);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001591
Radek Krejci1d82ef62015-08-07 14:44:40 +02001592 lys_when_free(ctx, cont->when);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001593}
1594
Radek Krejci1d82ef62015-08-07 14:44:40 +02001595static void
1596lys_feature_free(struct ly_ctx *ctx, struct lys_feature *f)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001597{
1598 lydict_remove(ctx, f->name);
1599 lydict_remove(ctx, f->dsc);
1600 lydict_remove(ctx, f->ref);
1601 free(f->features);
1602}
1603
Radek Krejci1d82ef62015-08-07 14:44:40 +02001604static void
1605lys_deviation_free(struct ly_ctx *ctx, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001606{
1607 int i, j;
1608
1609 lydict_remove(ctx, dev->target_name);
1610 lydict_remove(ctx, dev->dsc);
1611 lydict_remove(ctx, dev->ref);
1612
1613 for (i = 0; i < dev->deviate_size; i++) {
1614 lydict_remove(ctx, dev->deviate[i].dflt);
1615 lydict_remove(ctx, dev->deviate[i].units);
1616
1617 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1618 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001619 lys_restr_free(ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001620 }
1621 free(dev->deviate[i].must);
1622
1623 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1624 free(dev->deviate[j].unique[j].leafs);
1625 }
1626 free(dev->deviate[i].unique);
1627 }
1628 }
1629 free(dev->deviate);
1630}
1631
Radek Krejci1d82ef62015-08-07 14:44:40 +02001632static void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001633lys_uses_free(struct ly_ctx *ctx, struct lys_node_uses *uses)
Radek Krejcie1fa8582015-06-08 09:46:45 +02001634{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001635 int i, j;
Radek Krejcie1fa8582015-06-08 09:46:45 +02001636
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001637 for (i = 0; i < uses->refine_size; i++) {
Radek Krejci76512572015-08-04 09:47:08 +02001638 lydict_remove(ctx, uses->refine[i].target_name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001639 lydict_remove(ctx, uses->refine[i].dsc);
1640 lydict_remove(ctx, uses->refine[i].ref);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001641
Michal Vaskoa275c0a2015-09-24 09:55:42 +02001642 for (j = 0; j < uses->refine[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001643 lys_restr_free(ctx, &uses->refine[i].must[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001644 }
1645 free(uses->refine[i].must);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001646
Radek Krejci76512572015-08-04 09:47:08 +02001647 if (uses->refine[i].target_type & (LYS_LEAF | LYS_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001648 lydict_remove(ctx, uses->refine[i].mod.dflt);
Radek Krejci76512572015-08-04 09:47:08 +02001649 } else if (uses->refine[i].target_type & LYS_CONTAINER) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001650 lydict_remove(ctx, uses->refine[i].mod.presence);
1651 }
1652 }
1653 free(uses->refine);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001654
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001655 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001656 lys_augment_free(ctx, uses->augment[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001657 }
1658 free(uses->augment);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001659
Radek Krejci1d82ef62015-08-07 14:44:40 +02001660 lys_when_free(ctx, uses->when);
Radek Krejcie1fa8582015-06-08 09:46:45 +02001661}
1662
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001663void
Radek Krejci1d82ef62015-08-07 14:44:40 +02001664lys_node_free(struct lys_node *node)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001665{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001666 struct ly_ctx *ctx;
Radek Krejci76512572015-08-04 09:47:08 +02001667 struct lys_node *sub, *next;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001668
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001669 if (!node) {
1670 return;
1671 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001672
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001673 assert(node->module);
1674 assert(node->module->ctx);
Radek Krejci812b10a2015-05-28 16:48:25 +02001675
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001676 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001677
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001678 /* common part */
1679 LY_TREE_FOR_SAFE(node->child, next, sub) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001680 lys_node_free(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001681 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001682
Radek Krejcid12f57b2015-08-06 10:43:39 +02001683 if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
1684 free(node->features);
1685 lydict_remove(ctx, node->name);
1686 lydict_remove(ctx, node->dsc);
1687 lydict_remove(ctx, node->ref);
1688 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001689
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001690 /* specific part */
1691 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001692 case LYS_CONTAINER:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001693 lys_container_free(ctx, (struct lys_node_container *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001694 break;
Radek Krejci76512572015-08-04 09:47:08 +02001695 case LYS_CHOICE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001696 lys_when_free(ctx, ((struct lys_node_choice *)node)->when);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001697 break;
Radek Krejci76512572015-08-04 09:47:08 +02001698 case LYS_LEAF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001699 lys_leaf_free(ctx, (struct lys_node_leaf *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001700 break;
Radek Krejci76512572015-08-04 09:47:08 +02001701 case LYS_LEAFLIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001702 lys_leaflist_free(ctx, (struct lys_node_leaflist *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001703 break;
Radek Krejci76512572015-08-04 09:47:08 +02001704 case LYS_LIST:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001705 lys_list_free(ctx, (struct lys_node_list *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001706 break;
Radek Krejci76512572015-08-04 09:47:08 +02001707 case LYS_ANYXML:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001708 lys_anyxml_free(ctx, (struct lys_node_anyxml *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001709 break;
Radek Krejci76512572015-08-04 09:47:08 +02001710 case LYS_USES:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001711 lys_uses_free(ctx, (struct lys_node_uses *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001712 break;
Radek Krejci76512572015-08-04 09:47:08 +02001713 case LYS_CASE:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001714 lys_when_free(ctx, ((struct lys_node_case *)node)->when);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001715 break;
Radek Krejci76512572015-08-04 09:47:08 +02001716 case LYS_AUGMENT:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001717 /* do nothing */
1718 break;
Radek Krejci76512572015-08-04 09:47:08 +02001719 case LYS_GROUPING:
1720 case LYS_RPC:
Radek Krejci76512572015-08-04 09:47:08 +02001721 case LYS_NOTIF:
Radek Krejci1d82ef62015-08-07 14:44:40 +02001722 lys_grp_free(ctx, (struct lys_node_grp *)node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001723 break;
Radek Krejcid12f57b2015-08-06 10:43:39 +02001724
1725 case LYS_INPUT:
1726 case LYS_OUTPUT:
1727 lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
1728 break;
Michal Vasko591e0b22015-08-13 13:53:43 +02001729 case LYS_UNKNOWN:
1730 LOGINT;
1731 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001732 }
Radek Krejci5a065542015-05-22 15:02:07 +02001733
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001734 /* again common part */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001735 lys_node_unlink(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001736 free(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001737}
1738
Michal Vasko13b15832015-08-19 11:04:48 +02001739/* free_int_mods - flag whether to free the internal modules as well */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001740static void
Michal Vasko13b15832015-08-19 11:04:48 +02001741module_free_common(struct lys_module *module, int free_int_mods)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001742{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001743 struct ly_ctx *ctx;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001744 unsigned int i;
Radek Krejcidce51452015-06-16 15:20:08 +02001745 int j, l;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001746
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001747 assert(module->ctx);
1748 ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001749
Radek Krejcidce51452015-06-16 15:20:08 +02001750 /* as first step, free the imported modules */
1751 for (i = 0; i < module->imp_size; i++) {
Michal Vaskoa76ee152015-08-17 15:38:22 +02001752 /* do not free internal modules */
Michal Vasko18bd09b2015-08-19 15:07:00 +02001753 if (!free_int_mods) {
1754 for (j = 0; j < int_mods.count; ++j) {
Michal Vaskod83c03a2015-08-21 09:09:24 +02001755 if (module->imp[i].module && !strcmp(int_mods.modules[j].name, module->imp[i].module->name)
Michal Vasko18bd09b2015-08-19 15:07:00 +02001756 && module->imp[i].module->rev
1757 && !strcmp(int_mods.modules[j].revision, module->imp[i].module->rev[0].date)) {
1758 break;
1759 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02001760 }
Michal Vasko18bd09b2015-08-19 15:07:00 +02001761 if (j < int_mods.count) {
1762 continue;
1763 }
Michal Vaskoa76ee152015-08-17 15:38:22 +02001764 }
1765
Radek Krejcidce51452015-06-16 15:20:08 +02001766 /* get the imported module from the context and then free,
1767 * this check is necessary because the imported module can
1768 * be already removed
1769 */
1770 l = ctx->models.used;
1771 for (j = 0; j < l; j++) {
1772 if (ctx->models.list[j] == module->imp[i].module) {
Michal Vasko13b15832015-08-19 11:04:48 +02001773 lys_free(module->imp[i].module, free_int_mods);
Radek Krejcidce51452015-06-16 15:20:08 +02001774 break;
1775 }
1776 }
1777 }
1778 free(module->imp);
1779
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001780 while (module->data) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001781 lys_node_free(module->data);
Radek Krejci21181962015-06-30 14:11:00 +02001782 }
1783 while (module->rpc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001784 lys_node_free(module->rpc);
Radek Krejci21181962015-06-30 14:11:00 +02001785 }
1786 while (module->notif) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001787 lys_node_free(module->notif);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001788 }
Radek Krejci5a065542015-05-22 15:02:07 +02001789
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001790 lydict_remove(ctx, module->dsc);
1791 lydict_remove(ctx, module->ref);
1792 lydict_remove(ctx, module->org);
1793 lydict_remove(ctx, module->contact);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001794
Radek Krejcieb00f512015-07-01 16:44:58 +02001795 /* revisions */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001796 for (i = 0; i < module->rev_size; i++) {
1797 lydict_remove(ctx, module->rev[i].dsc);
1798 lydict_remove(ctx, module->rev[i].ref);
1799 }
1800 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001801
Radek Krejcieb00f512015-07-01 16:44:58 +02001802 /* identities */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001803 for (i = 0; i < module->ident_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001804 lys_ident_free(ctx, &module->ident[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001805 }
1806 module->ident_size = 0;
1807 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001808
Radek Krejcieb00f512015-07-01 16:44:58 +02001809 /* typedefs */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001810 for (i = 0; i < module->tpdf_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001811 lys_tpdf_free(ctx, &module->tpdf[i]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001812 }
1813 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001814
Radek Krejcieb00f512015-07-01 16:44:58 +02001815 /* include */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001816 for (i = 0; i < module->inc_size; i++) {
Michal Vasko13b15832015-08-19 11:04:48 +02001817 lys_submodule_free(module->inc[i].submodule, free_int_mods);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001818 }
1819 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +02001820
Radek Krejcieb00f512015-07-01 16:44:58 +02001821 /* augment */
Radek Krejcif5be10f2015-06-16 13:29:36 +02001822 for (i = 0; i < module->augment_size; i++) {
Radek Krejcib7f5e412015-08-13 10:15:51 +02001823 lys_augment_free(ctx, module->augment[i]);
Radek Krejcif5be10f2015-06-16 13:29:36 +02001824 }
1825 free(module->augment);
1826
Radek Krejcieb00f512015-07-01 16:44:58 +02001827 /* features */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001828 for (i = 0; i < module->features_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001829 lys_feature_free(ctx, &module->features[i]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001830 }
1831 free(module->features);
1832
Radek Krejcieb00f512015-07-01 16:44:58 +02001833 /* deviations */
1834 for (i = 0; i < module->deviation_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001835 lys_deviation_free(ctx, &module->deviation[i]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001836 }
1837 free(module->deviation);
1838
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001839 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02001840}
1841
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001842void
Michal Vasko13b15832015-08-19 11:04:48 +02001843lys_submodule_free(struct lys_submodule *submodule, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02001844{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001845 if (!submodule) {
1846 return;
1847 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001848
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001849 submodule->inc_size = 0;
1850 free(submodule->inc);
1851 submodule->inc = NULL;
Radek Krejcif3886932015-06-04 17:36:06 +02001852
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001853 /* common part with struct ly_module */
Michal Vasko13b15832015-08-19 11:04:48 +02001854 module_free_common((struct lys_module *)submodule, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02001855
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001856 /* no specific items to free */
Radek Krejciefaeba32015-05-27 14:30:57 +02001857
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001858 free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02001859}
1860
Radek Krejcib8048692015-08-05 13:36:34 +02001861static struct lys_node_leaf *
Radek Krejci1d82ef62015-08-07 14:44:40 +02001862lys_uniq_find(struct lys_node_list *list, struct lys_node_leaf *orig_leaf)
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001863{
Radek Krejci1d82ef62015-08-07 14:44:40 +02001864 struct lys_node *node, *node2, *ret = NULL, *parent1, *parent2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001865 int depth = 1, i;
1866
1867 /* find the correct direct descendant of list in orig_leaf */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001868 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001869 while (1) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001870 if (!node->parent) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001871 return NULL;
1872 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001873 if (!strcmp(node->parent->name, list->name)) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001874 break;
1875 }
1876
Radek Krejci1d82ef62015-08-07 14:44:40 +02001877 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001878 ++depth;
1879 }
1880
1881 /* make sure the nodes are equal */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001882 parent1 = node->parent->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001883 parent2 = list->parent;
1884 while (1) {
1885 if ((parent1 && !parent2) || (!parent1 && parent2)) {
1886 return NULL;
1887 }
1888
1889 if (parent1 == parent2) {
1890 break;
1891 }
1892
1893 parent1 = parent1->parent;
1894 parent2 = parent2->parent;
1895 }
1896
1897 /* find the descendant in the list */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001898 LY_TREE_FOR(list->child, node2) {
1899 if (!strcmp(node2->name, node->name)) {
1900 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001901 break;
1902 }
1903 }
1904
1905 if (!ret) {
1906 return NULL;
1907 }
1908
1909 /* continue traversing both trees, the nodes are always truly equal */
1910 while (1) {
1911 --depth;
1912 if (!depth) {
Radek Krejci76512572015-08-04 09:47:08 +02001913 if (ret->nodetype != LYS_LEAF) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001914 return NULL;
1915 }
Radek Krejcib8048692015-08-05 13:36:34 +02001916 return (struct lys_node_leaf *)ret;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001917 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001918 node = (struct lys_node *)orig_leaf;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001919 for (i = 0; i < depth-1; ++i) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001920 node = node->parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001921 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001922 LY_TREE_FOR(ret->child, node2) {
1923 if (!strcmp(node2->name, node->name)) {
1924 ret = node2;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001925 break;
1926 }
1927 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001928 if (!node2) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001929 return NULL;
1930 }
1931 }
1932}
1933
Radek Krejci76512572015-08-04 09:47:08 +02001934struct lys_node *
Michal Vasko71e1aa82015-08-12 12:17:51 +02001935lys_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 +02001936 struct unres_schema *unres)
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001937{
Radek Krejci76512572015-08-04 09:47:08 +02001938 struct lys_node *retval = NULL, *aux, *child;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001939 struct ly_ctx *ctx = module->ctx;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001940 int i, j, rc;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001941
Michal Vaskoc07187d2015-08-13 15:20:57 +02001942 struct lys_node_container *cont = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001943 struct lys_node_container *cont_orig = (struct lys_node_container *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001944 struct lys_node_choice *choice = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001945 struct lys_node_choice *choice_orig = (struct lys_node_choice *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001946 struct lys_node_leaf *leaf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001947 struct lys_node_leaf *leaf_orig = (struct lys_node_leaf *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001948 struct lys_node_leaflist *llist = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001949 struct lys_node_leaflist *llist_orig = (struct lys_node_leaflist *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001950 struct lys_node_list *list = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001951 struct lys_node_list *list_orig = (struct lys_node_list *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001952 struct lys_node_anyxml *anyxml = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001953 struct lys_node_anyxml *anyxml_orig = (struct lys_node_anyxml *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001954 struct lys_node_uses *uses = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001955 struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001956 struct lys_node_grp *grp = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001957 struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001958 struct lys_node_rpc *rpc = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001959 struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001960 struct lys_node_rpc_inout *io = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001961 struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001962 struct lys_node_rpc *ntf = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001963 struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
Michal Vaskoc07187d2015-08-13 15:20:57 +02001964 struct lys_node_case *cs = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001965 struct lys_node_case *cs_orig = (struct lys_node_case *)node;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001966
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001967 /* we cannot just duplicate memory since the strings are stored in
1968 * dictionary and we need to update dictionary counters.
1969 */
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001970
Radek Krejci1d82ef62015-08-07 14:44:40 +02001971 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001972 case LYS_CONTAINER:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001973 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02001974 retval = (struct lys_node *)cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001975 break;
1976
Radek Krejci76512572015-08-04 09:47:08 +02001977 case LYS_CHOICE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001978 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02001979 retval = (struct lys_node *)choice;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001980 break;
1981
Radek Krejci76512572015-08-04 09:47:08 +02001982 case LYS_LEAF:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001983 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02001984 retval = (struct lys_node *)leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001985 break;
1986
Radek Krejci76512572015-08-04 09:47:08 +02001987 case LYS_LEAFLIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001988 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02001989 retval = (struct lys_node *)llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001990 break;
1991
Radek Krejci76512572015-08-04 09:47:08 +02001992 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001993 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02001994 retval = (struct lys_node *)list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001995 break;
1996
Radek Krejci76512572015-08-04 09:47:08 +02001997 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001998 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02001999 retval = (struct lys_node *)anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002000 break;
2001
Radek Krejci76512572015-08-04 09:47:08 +02002002 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002003 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02002004 retval = (struct lys_node *)uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002005 break;
2006
Radek Krejci76512572015-08-04 09:47:08 +02002007 case LYS_CASE:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002008 cs = calloc(1, sizeof *cs);
Radek Krejci76512572015-08-04 09:47:08 +02002009 retval = (struct lys_node *)cs;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002010 break;
2011
Radek Krejci76512572015-08-04 09:47:08 +02002012 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002013 grp = calloc(1, sizeof *grp);
2014 retval = (struct lys_node *)grp;
2015 break;
2016
Radek Krejci76512572015-08-04 09:47:08 +02002017 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002018 rpc = calloc(1, sizeof *rpc);
2019 retval = (struct lys_node *)rpc;
2020 break;
2021
Radek Krejci76512572015-08-04 09:47:08 +02002022 case LYS_INPUT:
2023 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002024 io = calloc(1, sizeof *io);
2025 retval = (struct lys_node *)io;
2026 break;
2027
Radek Krejci76512572015-08-04 09:47:08 +02002028 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002029 ntf = calloc(1, sizeof *ntf);
2030 retval = (struct lys_node *)ntf;
Michal Vasko38d01f72015-06-15 09:41:06 +02002031 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002032
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002033 default:
Michal Vaskod23ce592015-08-06 09:55:37 +02002034 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002035 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002036 }
Radek Krejcib388c152015-06-04 17:03:03 +02002037
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002038 /*
2039 * duplicate generic part of the structure
2040 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002041 retval->name = lydict_insert(ctx, node->name, 0);
2042 retval->dsc = lydict_insert(ctx, node->dsc, 0);
2043 retval->ref = lydict_insert(ctx, node->ref, 0);
Michal Vasko71e1aa82015-08-12 12:17:51 +02002044 retval->nacm = nacm;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002045 retval->flags = node->flags;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002046 if (!(retval->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002047 /* set parent's config flag */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002048 retval->flags |= flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002049 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002050
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002051 retval->module = module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002052 retval->nodetype = node->nodetype;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002053
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002054 retval->prev = retval;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002055
Radek Krejci1d82ef62015-08-07 14:44:40 +02002056 retval->features_size = node->features_size;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002057 retval->features = calloc(retval->features_size, sizeof *retval->features);
Radek Krejci1d82ef62015-08-07 14:44:40 +02002058 for (i = 0; i < node->features_size; ++i) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002059 if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002060 retval->features[i] = node->features[i];
Michal Vaskod23ce592015-08-06 09:55:37 +02002061 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002062 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002063
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002064 if (recursive) {
2065 /* go recursively */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002066 LY_TREE_FOR(node->child, child) {
Michal Vasko71e1aa82015-08-12 12:17:51 +02002067 aux = lys_node_dup(module, child, retval->flags, retval->nacm, 1, unres);
Radek Krejci10c760e2015-08-14 14:45:43 +02002068 if (!aux || lys_node_addchild(retval, NULL, aux)) {
Michal Vasko49168a22015-08-17 16:35:41 +02002069 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002070 }
2071 }
2072 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002073
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002074 /*
2075 * duplicate specific part of the structure
2076 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002077 switch (node->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002078 case LYS_CONTAINER:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002079 if (cont_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002080 cont->when = lys_when_dup(ctx, cont_orig->when);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002081 if (unres_schema_add_node(module, unres, cont->when, UNRES_WHEN, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002082 goto error;
2083 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002084 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002085 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002086
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002087 cont->must_size = cont_orig->must_size;
2088 cont->tpdf_size = cont_orig->tpdf_size;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002089
Radek Krejci1d82ef62015-08-07 14:44:40 +02002090 cont->must = lys_restr_dup(ctx, cont_orig->must, cont->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002091 for (i = 0; i < cont->must_size; ++i) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002092 if (unres_schema_add_node(module, unres, &cont->must[i], UNRES_MUST, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002093 goto error;
2094 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002095 }
2096
Radek Krejci1d82ef62015-08-07 14:44:40 +02002097 cont->tpdf = lys_tpdf_dup(module, node->parent, cont_orig->tpdf, cont->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002098 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002099
Radek Krejci76512572015-08-04 09:47:08 +02002100 case LYS_CHOICE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002101 if (choice_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002102 choice->when = lys_when_dup(ctx, choice_orig->when);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002103 if (unres_schema_add_node(module, unres, choice->when, UNRES_WHEN, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002104 goto error;
2105 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002106 }
2107
2108 if (choice_orig->dflt) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002109 rc = resolve_sibling(choice->module, choice->child, NULL, 0, choice_orig->dflt->name, 0, LYS_ANYXML
Radek Krejci76512572015-08-04 09:47:08 +02002110 | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002111 | LYS_LIST, &choice->dflt);
Michal Vasko49168a22015-08-17 16:35:41 +02002112 if (rc) {
2113 if (rc == EXIT_FAILURE) {
2114 LOGINT;
2115 }
2116 goto error;
2117 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002118 } else {
Michal Vaskoc68a2a22015-08-06 09:57:24 +02002119 /* useless to check return value, we don't know whether
2120 * there really wasn't any default defined or it just hasn't
2121 * been resolved, we just hope for the best :)
2122 */
Michal Vasko0bd29d12015-08-19 11:45:49 +02002123 unres_schema_dup(module, unres, choice_orig, UNRES_CHOICE_DFLT, choice);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002124 }
2125 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002126
Radek Krejci76512572015-08-04 09:47:08 +02002127 case LYS_LEAF:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002128 if (lys_type_dup(module, node->parent, &(leaf->type), &(leaf_orig->type), unres)) {
2129 goto error;
2130 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002131 leaf->units = lydict_insert(module->ctx, leaf_orig->units, 0);
2132
2133 if (leaf_orig->dflt) {
2134 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002135 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002136 goto error;
2137 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002138 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002139
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002140 leaf->must_size = leaf_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002141 leaf->must = lys_restr_dup(ctx, leaf_orig->must, leaf->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002142 for (i = 0; i < leaf->must_size; ++i) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002143 if (unres_schema_add_node(module, unres, &leaf->must[i], UNRES_MUST, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002144 goto error;
2145 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002146 }
Radek Krejci00768f42015-06-18 17:04:04 +02002147
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002148 if (leaf_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002149 leaf->when = lys_when_dup(ctx, leaf_orig->when);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002150 if (unres_schema_add_node(module, unres, leaf->when, UNRES_WHEN, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002151 goto error;
2152 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002153 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002154 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002155
Radek Krejci76512572015-08-04 09:47:08 +02002156 case LYS_LEAFLIST:
Michal Vaskob84f88a2015-09-24 13:16:10 +02002157 if (lys_type_dup(module, node->parent, &(llist->type), &(llist_orig->type), unres)) {
2158 goto error;
2159 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002160 llist->units = lydict_insert(module->ctx, llist_orig->units, 0);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002162 llist->min = llist_orig->min;
2163 llist->max = llist_orig->max;
2164
2165 llist->must_size = llist_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002166 llist->must = lys_restr_dup(ctx, llist_orig->must, llist->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002167 for (i = 0; i < llist->must_size; ++i) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002168 if (unres_schema_add_node(module, unres, &llist->must[i], UNRES_MUST, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002169 goto error;
2170 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002171 }
Radek Krejci00768f42015-06-18 17:04:04 +02002172
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002173 if (llist_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002174 llist->when = lys_when_dup(ctx, llist_orig->when);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002175 if (unres_schema_add_node(module, unres, llist->when, UNRES_WHEN, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002176 goto error;
2177 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002178 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002179 break;
2180
Radek Krejci76512572015-08-04 09:47:08 +02002181 case LYS_LIST:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002182 list->min = list_orig->min;
2183 list->max = list_orig->max;
2184
2185 list->must_size = list_orig->must_size;
2186 list->tpdf_size = list_orig->tpdf_size;
2187 list->keys_size = list_orig->keys_size;
2188 list->unique_size = list_orig->unique_size;
2189
Radek Krejci1d82ef62015-08-07 14:44:40 +02002190 list->must = lys_restr_dup(ctx, list_orig->must, list->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002191 for (i = 0; i < list->must_size; ++i) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002192 if (unres_schema_add_node(module, unres, &list->must[i], UNRES_MUST, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002193 goto error;
2194 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002195 }
2196
Radek Krejci1d82ef62015-08-07 14:44:40 +02002197 list->tpdf = lys_tpdf_dup(module, node->parent, list_orig->tpdf, list->tpdf_size, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002198
2199 if (list->keys_size) {
2200 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002201
2202 /* we managed to resolve it before, resolve it again manually */
2203 if (list_orig->keys[0]) {
2204 for (i = 0; i < list->keys_size; ++i) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002205 rc = resolve_sibling(list->module, list->child, NULL, 0, list_orig->keys[i]->name, 0, LYS_LEAF,
2206 (struct lys_node **)&list->keys[i]);
Michal Vasko49168a22015-08-17 16:35:41 +02002207 if (rc) {
2208 if (rc == EXIT_FAILURE) {
2209 LOGINT;
2210 }
2211 goto error;
2212 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002213 }
2214 /* it was not resolved yet, add unres copy */
2215 } else {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002216 if (unres_schema_dup(module, unres, list_orig, UNRES_LIST_KEYS, list)) {
Michal Vaskod23ce592015-08-06 09:55:37 +02002217 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002218 goto error;
Michal Vaskod23ce592015-08-06 09:55:37 +02002219 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002220 }
2221 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002222
2223 list->unique = calloc(list->unique_size, sizeof *list->unique);
2224 if (list_orig->unique) {
2225 for (i = 0; i < list->unique_size; ++i) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002226 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
2227 for (j = 0; j < list->unique[i].leafs_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002228 list->unique[i].leafs[j] = lys_uniq_find(list, list_orig->unique[i].leafs[j]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002229 }
2230 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002231 } else {
2232 for (i = 0; i < list->unique_size; ++i) {
2233 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02002234 list->unique[i].leafs = (struct lys_node_leaf **)list;
Michal Vasko0bd29d12015-08-19 11:45:49 +02002235 unres_schema_dup(module, unres, &list_orig->unique[i], UNRES_LIST_UNIQ, &list->unique[i]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002236 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002237 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002238
2239 if (list_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002240 list->when = lys_when_dup(ctx, list_orig->when);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002241 if (unres_schema_add_node(module, unres, list->when, UNRES_WHEN, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002242 goto error;
2243 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002244 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002245 break;
2246
Radek Krejci76512572015-08-04 09:47:08 +02002247 case LYS_ANYXML:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002248 anyxml->must_size = anyxml_orig->must_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002249 anyxml->must = lys_restr_dup(ctx, anyxml_orig->must, anyxml->must_size);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002250 for (i = 0; i < anyxml->must_size; ++i) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002251 if (unres_schema_add_node(module, unres, &anyxml->must[i], UNRES_MUST, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002252 goto error;
2253 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002254 }
2255
2256 if (anyxml_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002257 anyxml->when = lys_when_dup(ctx, anyxml_orig->when);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002258 if (unres_schema_add_node(module, unres, anyxml->when, UNRES_WHEN, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002259 goto error;
2260 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002261 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002262 break;
2263
Radek Krejci76512572015-08-04 09:47:08 +02002264 case LYS_USES:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002265 uses->grp = uses_orig->grp;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002266
2267 if (uses_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002268 uses->when = lys_when_dup(ctx, uses_orig->when);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002269 if (unres_schema_add_node(module, unres, uses->when, UNRES_WHEN, (struct lys_node *)uses, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002270 goto error;
2271 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002272 }
2273
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002274 uses->refine_size = uses_orig->refine_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002275 uses->refine = lys_refine_dup(module, uses_orig->refine, uses_orig->refine_size, uses, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002276 uses->augment_size = uses_orig->augment_size;
Michal Vaskoffa45cb2015-08-21 12:58:04 +02002277 uses->augment = lys_augment_dup(module, (struct lys_node *)uses, uses_orig->augment, uses_orig->augment_size);
Michal Vaskof8c128d2015-08-06 15:25:28 +02002278 if (!uses->child) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002279 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002280 goto error;
2281 }
Michal Vaskof8c128d2015-08-06 15:25:28 +02002282 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002283 break;
2284
Radek Krejci76512572015-08-04 09:47:08 +02002285 case LYS_CASE:
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002286 if (cs_orig->when) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002287 cs->when = lys_when_dup(ctx, cs_orig->when);
Michal Vasko0bd29d12015-08-19 11:45:49 +02002288 if (unres_schema_add_node(module, unres, cs->when, UNRES_WHEN, retval, 0) == -1) {
Michal Vasko49168a22015-08-17 16:35:41 +02002289 goto error;
2290 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002291 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002292 break;
2293
Radek Krejci76512572015-08-04 09:47:08 +02002294 case LYS_GROUPING:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002295 grp->tpdf_size = grp_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002296 grp->tpdf = lys_tpdf_dup(module, node->parent, grp_orig->tpdf, grp->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002297 break;
2298
Radek Krejci76512572015-08-04 09:47:08 +02002299 case LYS_RPC:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002300 rpc->tpdf_size = rpc_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002301 rpc->tpdf = lys_tpdf_dup(module, node->parent, rpc_orig->tpdf, rpc->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002302 break;
2303
Radek Krejci76512572015-08-04 09:47:08 +02002304 case LYS_INPUT:
2305 case LYS_OUTPUT:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002306 io->tpdf_size = io_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002307 io->tpdf = lys_tpdf_dup(module, node->parent, io_orig->tpdf, io->tpdf_size, unres);
Radek Krejcid12f57b2015-08-06 10:43:39 +02002308 break;
2309
Radek Krejci76512572015-08-04 09:47:08 +02002310 case LYS_NOTIF:
Radek Krejcid12f57b2015-08-06 10:43:39 +02002311 ntf->tpdf_size = ntf_orig->tpdf_size;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002312 ntf->tpdf = lys_tpdf_dup(module, node->parent, ntf_orig->tpdf, ntf->tpdf_size, unres);
Radek Krejcia01e5432015-06-16 10:35:25 +02002313 break;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002314
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002315 default:
Radek Krejci00768f42015-06-18 17:04:04 +02002316 /* LY_NODE_AUGMENT */
Michal Vaskod23ce592015-08-06 09:55:37 +02002317 LOGINT;
Michal Vasko49168a22015-08-17 16:35:41 +02002318 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002319 }
2320
2321 return retval;
Michal Vasko49168a22015-08-17 16:35:41 +02002322
2323error:
2324
2325 lys_node_free(retval);
2326 return NULL;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002327}
2328
Michal Vasko13b15832015-08-19 11:04:48 +02002329void
2330lys_free(struct lys_module *module, int free_int_mods)
Radek Krejciefaeba32015-05-27 14:30:57 +02002331{
Radek Krejcidce51452015-06-16 15:20:08 +02002332 struct ly_ctx *ctx;
2333 int i;
2334
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002335 if (!module) {
2336 return;
2337 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002338
Radek Krejcidce51452015-06-16 15:20:08 +02002339 /* remove schema from the context */
2340 ctx = module->ctx;
2341 if (ctx->models.used) {
2342 for (i = 0; i < ctx->models.used; i++) {
2343 if (ctx->models.list[i] == module) {
2344 /* replace the position in the list by the last module in the list */
2345 ctx->models.used--;
2346 ctx->models.list[i] = ctx->models.list[ctx->models.used];
2347 ctx->models.list[ctx->models.used] = NULL;
2348 /* we are done */
2349 break;
2350 }
2351 }
2352 }
2353
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002354 /* common part with struct ly_submodule */
Michal Vasko13b15832015-08-19 11:04:48 +02002355 module_free_common(module, free_int_mods);
Radek Krejciefaeba32015-05-27 14:30:57 +02002356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002357 /* specific items to free */
2358 lydict_remove(module->ctx, module->ns);
2359 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02002360
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002361 free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002362}
Radek Krejci7e97c352015-06-19 16:26:34 +02002363
2364/*
2365 * op: 1 - enable, 0 - disable
2366 */
2367static int
Radek Krejci1d82ef62015-08-07 14:44:40 +02002368lys_features_change(struct lys_module *module, const char *name, int op)
Radek Krejci7e97c352015-06-19 16:26:34 +02002369{
2370 int all = 0;
2371 int i, j, k;
2372
2373 if (!module || !name || !strlen(name)) {
2374 return EXIT_FAILURE;
2375 }
2376
2377 if (!strcmp(name, "*")) {
2378 /* enable all */
2379 all = 1;
2380 }
2381
2382 /* module itself */
2383 for (i = 0; i < module->features_size; i++) {
2384 if (all || !strcmp(module->features[i].name, name)) {
2385 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002386 module->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002387 /* enable referenced features (recursion) */
2388 for (k = 0; k < module->features[i].features_size; k++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002389 lys_features_change(module->features[i].features[k]->module,
Radek Krejci7e97c352015-06-19 16:26:34 +02002390 module->features[i].features[k]->name, op);
2391 }
2392 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002393 module->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002394 }
2395 if (!all) {
2396 return EXIT_SUCCESS;
2397 }
2398 }
2399 }
2400
2401 /* submodules */
2402 for (j = 0; j < module->inc_size; j++) {
2403 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2404 if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
2405 if (op) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002406 module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002407 } else {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002408 module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
Radek Krejci7e97c352015-06-19 16:26:34 +02002409 }
2410 if (!all) {
2411 return EXIT_SUCCESS;
2412 }
2413 }
2414 }
2415 }
2416
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002417 /* TODO submodules of submodules ... */
2418
Radek Krejci7e97c352015-06-19 16:26:34 +02002419 if (all) {
2420 return EXIT_SUCCESS;
2421 } else {
2422 return EXIT_FAILURE;
2423 }
2424}
2425
2426API int
Radek Krejcib8048692015-08-05 13:36:34 +02002427lys_features_enable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002428{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002429 return lys_features_change(module, feature, 1);
Radek Krejci7e97c352015-06-19 16:26:34 +02002430}
2431
2432API int
Radek Krejcib8048692015-08-05 13:36:34 +02002433lys_features_disable(struct lys_module *module, const char *feature)
Radek Krejci7e97c352015-06-19 16:26:34 +02002434{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002435 return lys_features_change(module, feature, 0);
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002436}
2437
2438API int
Radek Krejcib8048692015-08-05 13:36:34 +02002439lys_features_state(struct lys_module *module, const char *feature)
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002440{
2441 int i, j;
2442
2443 if (!module || !feature) {
2444 return -1;
2445 }
2446
2447 /* search for the specified feature */
2448 /* module itself */
2449 for (i = 0; i < module->features_size; i++) {
2450 if (!strcmp(feature, module->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002451 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002452 return 1;
2453 } else {
2454 return 0;
2455 }
2456 }
2457 }
2458
2459 /* submodules */
2460 for (j = 0; j < module->inc_size; j++) {
2461 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
2462 if (!strcmp(feature, module->inc[j].submodule->features[i].name)) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002463 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002464 return 1;
2465 } else {
2466 return 0;
2467 }
2468 }
2469 }
2470 }
2471
2472 /* TODO submodules of submodules ... */
2473
2474 /* feature definition not found */
2475 return -1;
Radek Krejci7e97c352015-06-19 16:26:34 +02002476}
Michal Vasko2367e7c2015-07-07 11:33:44 +02002477
Radek Krejci96a10da2015-07-30 11:00:14 +02002478API const char **
Radek Krejcib8048692015-08-05 13:36:34 +02002479lys_features_list(struct lys_module *module, uint8_t **states)
Michal Vasko2367e7c2015-07-07 11:33:44 +02002480{
Radek Krejci96a10da2015-07-30 11:00:14 +02002481 const char **result = NULL;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002482 int i, j;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002483 unsigned int count;
2484
2485 if (!module) {
2486 return NULL;
2487 }
2488
2489 count = module->features_size;
2490 for (i = 0; i < module->inc_size; i++) {
2491 count += module->inc[i].submodule->features_size;
2492 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002493 result = malloc((count + 1) * sizeof *result);
2494 if (states) {
2495 *states = malloc((count + 1) * sizeof **states);
Michal Vasko2367e7c2015-07-07 11:33:44 +02002496 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002497 count = 0;
2498
2499 /* module itself */
2500 for (i = 0; i < module->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002501 result[count] = module->features[i].name;
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002502 if (states) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002503 if (module->features[i].flags & LYS_FENABLED) {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002504 (*states)[count] = 1;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002505 } else {
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002506 (*states)[count] = 0;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002507 }
2508 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002509 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002510 }
2511
2512 /* submodules */
2513 for (j = 0; j < module->inc_size; j++) {
2514 for (i = 0; i < module->inc[j].submodule->features_size; i++) {
Radek Krejci96a10da2015-07-30 11:00:14 +02002515 result[count] = module->inc[j].submodule->features[i].name;
Radek Krejci374b94e2015-08-13 09:44:22 +02002516 if (states) {
2517 if (module->inc[j].submodule->features[i].flags & LYS_FENABLED) {
2518 (*states)[count] = 1;
2519 } else {
2520 (*states)[count] = 0;
2521 }
Michal Vasko2367e7c2015-07-07 11:33:44 +02002522 }
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002523 count++;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002524 }
2525 }
2526
Radek Krejcie98bb4b2015-07-30 14:21:41 +02002527 /* TODO submodules of submodules ... */
2528
2529 /* terminating NULL byte */
Michal Vasko2367e7c2015-07-07 11:33:44 +02002530 result[count] = NULL;
Michal Vasko2367e7c2015-07-07 11:33:44 +02002531
2532 return result;
2533}
Michal Vaskobaefb032015-09-24 14:52:10 +02002534
2535API struct lys_node *
2536lys_parent(struct lys_node *node)
2537{
2538 if (!node || !node->parent) {
2539 return NULL;
2540 }
2541
2542 if (node->parent->nodetype == LYS_AUGMENT) {
2543 return ((struct lys_node_augment *)node->parent)->target;
2544 }
2545
2546 return node->parent;
2547}