blob: 7c0d82af509fa379bc9d6cd385bd123f435c130b [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
2 * @file tree.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Manipulation with libyang data structures
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 */
21
Radek Krejci812b10a2015-05-28 16:48:25 +020022#include <assert.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020023#include <stdlib.h>
24#include <sys/mman.h>
25#include <sys/stat.h>
Radek Krejci8bc9ca02015-06-04 15:52:46 +020026#include <string.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020027
28#include "common.h"
29#include "context.h"
Radek Krejci3045cf32015-05-28 10:58:52 +020030#include "parser.h"
Radek Krejci106efc02015-06-10 14:36:27 +020031#include "xml.h"
Radek Krejci8bc9ca02015-06-04 15:52:46 +020032#include "tree_internal.h"
Radek Krejciefaeba32015-05-27 14:30:57 +020033
34void ly_submodule_free(struct ly_submodule *submodule);
35
Radek Krejcib7155b52015-06-10 17:03:01 +020036static const char *strnodetype(LY_NODE_TYPE type)
37{
38 switch(type) {
39 case LY_NODE_AUGMENT:
40 return "augment";
41 case LY_NODE_CONTAINER:
42 return "container";
43 case LY_NODE_CHOICE:
44 return "choice";
45 case LY_NODE_LEAF:
46 return "leaf";
47 case LY_NODE_LEAFLIST:
48 return "leaf-list";
49 case LY_NODE_LIST:
50 return "list";
51 case LY_NODE_ANYXML:
52 return "anyxml";
53 case LY_NODE_USES:
54 return "uses";
55 case LY_NODE_GROUPING:
56 return "grouping";
57 case LY_NODE_CASE:
58 return "case";
59 case LY_NODE_INPUT:
60 return "input";
61 case LY_NODE_OUTPUT:
62 return "output";
63 case LY_NODE_NOTIF:
64 return "notification";
Michal Vasko38d01f72015-06-15 09:41:06 +020065 case LY_NODE_RPC:
66 return "rpc";
Radek Krejcib7155b52015-06-10 17:03:01 +020067 }
68
69 return NULL;
70}
71
Radek Krejci8bc9ca02015-06-04 15:52:46 +020072struct ly_mnode_leaf *find_leaf(struct ly_mnode *parent, const char *name, int len)
73{
74 struct ly_mnode *child;
75 struct ly_mnode_leaf *result;
76
77 if (!len) {
78 len = strlen(name);
79 }
80
81 LY_TREE_FOR(parent->child, child) {
82 switch (child->nodetype) {
83 case LY_NODE_LEAF:
84 /* direct check */
Radek Krejci1e9b9992015-06-04 17:57:04 +020085 if (child->name == name || (!strncmp(child->name, name, len) && !child->name[len])) {
Radek Krejci8bc9ca02015-06-04 15:52:46 +020086 return (struct ly_mnode_leaf *)child;
87 }
88 break;
89 case LY_NODE_USES:
90 /* search recursively */
91 result = find_leaf(child, name, len);
92 if (result) {
93 return result;
94 }
95 break;
96 default:
97 /* ignore */
98 break;
99 }
100 }
101
102 return NULL;
103}
Radek Krejcida04f4a2015-05-21 12:54:09 +0200104
105void ly_mnode_unlink(struct ly_mnode *node)
106{
107 struct ly_mnode *parent, *first;
108
109 if (!node) {
110 return;
111 }
112
113 /* unlink from data model if necessary */
114 if (node->module) {
115 if (node->module->data == node) {
116 node->module->data = node->next;
117 }
118 }
119
120 /* store pointers to important nodes */
121 parent = node->parent;
Radek Krejci106efc02015-06-10 14:36:27 +0200122 if (parent && !parent->nodetype) {
123 /* handle augments - first, unlink it from the augment parent ... */
124 if (parent->child == node) {
125 parent->child = node->next;
126 }
127 /* and then continue with the target parent */
128 parent = ((struct ly_augment *)parent)->target;
129 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200130
131 /* unlink from parent */
132 if (parent) {
133 if (parent->child == node) {
134 parent->child = node->next;
135 }
136 node->parent = NULL;
137 }
138
139 /* unlink from siblings */
140 if (node->prev == node) {
141 /* there are no more siblings */
Radek Krejcida04f4a2015-05-21 12:54:09 +0200142 return;
143 }
144 if (node->next) {
145 node->next->prev = node->prev;
146 } else {
147 /* unlinking the last element */
148 if (parent) {
149 first = parent->child;
150 } else {
151 first = node;
152 while (node->prev->next) {
153 first = node->prev;
154 }
155 }
156 first->prev = node->prev;
157 }
158 if (node->prev->next) {
159 node->prev->next = node->next;
160 }
161
162 /* clean up the unlinked element */
163 node->next = NULL;
164 node->prev = node;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200165}
166
167/*
168 * Add child model node at the end of the parent's child list.
169 * If the child is connected somewhere (has a parent), it is completely
170 * unlinked and none of the following conditions applies.
171 * If the child has prev sibling(s), they are ignored (child is added at the
172 * end of the child list).
173 * If the child has next sibling(s), all of them are connected with the parent.
174 */
175int ly_mnode_addchild(struct ly_mnode *parent, struct ly_mnode *child)
176{
177 struct ly_mnode *last;
178
Radek Krejci812b10a2015-05-28 16:48:25 +0200179 assert(parent);
180 assert(child);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200181
Radek Krejcib7155b52015-06-10 17:03:01 +0200182 /* checks */
183 switch(parent->nodetype) {
184 case LY_NODE_CONTAINER:
185 case LY_NODE_LIST:
186 case LY_NODE_GROUPING:
187 case LY_NODE_USES:
Michal Vasko38d01f72015-06-15 09:41:06 +0200188 case LY_NODE_INPUT:
189 case LY_NODE_OUTPUT:
Radek Krejcib7155b52015-06-10 17:03:01 +0200190 if (!(child->nodetype & (LY_NODE_ANYXML | LY_NODE_CHOICE
191 | LY_NODE_CONTAINER | LY_NODE_GROUPING | LY_NODE_LEAF
192 | LY_NODE_LEAFLIST | LY_NODE_LIST | LY_NODE_USES))) {
193 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"%s\" (%s).",
194 strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
195 return EXIT_FAILURE;
196 }
197 break;
198 case LY_NODE_CHOICE:
199 if (!(child->nodetype & (LY_NODE_ANYXML | LY_NODE_CASE
200 | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST
201 | LY_NODE_LIST))) {
202 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"choice\" %s.",
203 strnodetype(child->nodetype), parent->name);
204 return EXIT_FAILURE;
205 }
206 break;
207 case LY_NODE_CASE:
208 if (!(child->nodetype & (LY_NODE_ANYXML | LY_NODE_CHOICE
209 | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST
210 | LY_NODE_LIST | LY_NODE_USES))) {
211 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"case\" %s.",
212 strnodetype(child->nodetype), parent->name);
213 return EXIT_FAILURE;
214 }
215 break;
Michal Vasko38d01f72015-06-15 09:41:06 +0200216 case LY_NODE_RPC:
217 if (!(child->nodetype & (LY_NODE_INPUT | LY_NODE_OUTPUT
218 | LY_NODE_GROUPING))) {
219 LOGVAL(VE_SPEC, 0, "Unexpected substatement \"%s\" in \"rpc\" %s.",
220 strnodetype(child->nodetype), parent->name);
221 return EXIT_FAILURE;
222 }
223 break;
Radek Krejcib7155b52015-06-10 17:03:01 +0200224 case LY_NODE_LEAF:
225 case LY_NODE_LEAFLIST:
226 case LY_NODE_ANYXML:
227 LOGVAL(VE_SPEC, 0, "The \"%s\" statement (%s) cannot have any substatement.",
228 strnodetype(parent->nodetype), parent->name);
229 return EXIT_FAILURE;
230 case LY_NODE_AUGMENT:
231 LOGVAL(VE_SPEC, 0, "Internal error (%s:%d)", __FILE__, __LINE__);
232 return EXIT_FAILURE;
Radek Krejcib7155b52015-06-10 17:03:01 +0200233 case LY_NODE_NOTIF:
234 LOGVAL(VE_SPEC, 0, "\"%s\" not yet implemented (%s:%d)",
235 strnodetype(parent->nodetype), __FILE__, __LINE__);
236 return EXIT_FAILURE;
237 }
238
Radek Krejcida04f4a2015-05-21 12:54:09 +0200239 if (child->parent) {
240 ly_mnode_unlink(child);
241 }
242
243 if (!parent->child) {
244 /* the only/first child of the parent */
245 parent->child = child;
246 child->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +0200247 last = child;
248 } else {
249 /* add a new child at the end of parent's child list */
250 last = parent->child->prev;
251 last->next = child;
252 child->prev = last;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200253 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200254 while (last->next) {
255 last = last->next;
256 last->parent = parent;
257 }
258 parent->child->prev = last;
259
260 return EXIT_SUCCESS;
261}
262
Radek Krejci3bde87f2015-06-05 16:51:58 +0200263/*
Michal Vasko25880b42015-06-12 10:16:33 +0200264 * id - schema-nodeid
Radek Krejci3bde87f2015-06-05 16:51:58 +0200265 */
Michal Vasko25880b42015-06-12 10:16:33 +0200266struct ly_mnode *resolve_schema_nodeid(const char *id, struct ly_mnode *start)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200267{
Michal Vasko25880b42015-06-12 10:16:33 +0200268 char *id_cpy, *ptr, *name, *prefix;
269 struct ly_mnode *sibling;
270 struct ly_submodule *sub_mod;
271 int i, j;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200272
Michal Vasko25880b42015-06-12 10:16:33 +0200273 id_cpy = malloc((strlen(id)+1)*sizeof(char));
274 strcpy(id_cpy, id);
Radek Krejci3bde87f2015-06-05 16:51:58 +0200275
Michal Vasko25880b42015-06-12 10:16:33 +0200276 prefix = strtok_r(id_cpy, "/", &ptr);
277 name = strchr(prefix, ':');
278 if (name) {
279 name[0] = '\0';
280 name++;
281 } else {
282 name = prefix;
283 prefix = NULL;
284 }
285
286 /* identifier now refers to start or its sibling */
287 start = start->child;
288
289 /* absolute-schema-nodeid */
Radek Krejci3bde87f2015-06-05 16:51:58 +0200290 if (id[0] == '/') {
Michal Vasko25880b42015-06-12 10:16:33 +0200291 /* it is not the local prefix */
292 if (prefix && strcmp(prefix, start->module->prefix)) {
293 for (i = 0; i < start->module->imp_size; i++) {
294 if (!strcmp(start->module->imp[i].prefix, prefix)) {
295 start = start->module->imp[i].module->data;
296 break;
297 }
298 }
299 /* no match */
300 if (i == start->module->imp_size) {
301 free(id_cpy);
Radek Krejci3bde87f2015-06-05 16:51:58 +0200302 return NULL;
303 }
Michal Vasko25880b42015-06-12 10:16:33 +0200304
305 /* it is likely the local prefix */
Radek Krejci3bde87f2015-06-05 16:51:58 +0200306 } else {
Michal Vasko25880b42015-06-12 10:16:33 +0200307 start = start->module->data;
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200308 }
309 }
310
Michal Vasko25880b42015-06-12 10:16:33 +0200311 /* descendant-schema-nodeid */
312 while (1) {
313 if (!strcmp(name, ".")) {
314 /* this node - start does not change */
315 } else if (!strcmp(name, "..")) {
316 start = start->parent;
317 } else {
318 LY_TREE_FOR(start, sibling) {
319 /* match */
320 if (!strcmp(name, sibling->name)) {
321 /* prefix check, it's not our own */
322 if (prefix && strcmp(sibling->module->prefix, prefix)) {
323
324 /* import prefix check */
325 for (i = 0; i < sibling->module->imp_size; i++) {
326 if (!strcmp(sibling->module->imp[i].prefix, prefix) && sibling->module->imp[i].module == sibling->module) {
327 break;
328 }
329 }
330
331 /* import prefix check failed */
332 if (i == sibling->module->imp_size) {
333 /* include import prefix check */
334 for (i = 0; i < sibling->module->inc_size; i++) {
335 sub_mod = sibling->module->inc[i].submodule;
336 for (j = 0; j < sub_mod->imp_size; j++) {
337 if (!strcmp(sub_mod->imp[j].prefix, prefix) && sub_mod->imp[j].module == sibling->module) {
338 break;
339 }
340 }
341
342 if (j < sub_mod->imp_size) {
343 break;
344 }
345 }
346
347 /* include import prefix check failed too - definite fail */
348 if (i == sibling->module->inc_size) {
349 free(id_cpy);
350 return NULL;
351 }
352 }
353 }
354
355 /* the result node? */
356 prefix = strtok_r(NULL, "/", &ptr);
357 if (!prefix) {
358 free(id_cpy);
359 return sibling;
360 }
361
362 /* check for shorthand cases - then 'start' does not change */
363 if (!sibling->parent || sibling->parent->nodetype != LY_NODE_CHOICE || sibling->nodetype == LY_NODE_CASE) {
364 start = sibling->child;
365 }
366 break;
367 }
368 }
369 /* no match */
370 if (!sibling) {
371 free(id_cpy);
372 return NULL;
373 }
374 }
375
376 /* parse prefix */
377 name = strchr(prefix, ':');
378 if (name) {
379 name[0] = '\0';
380 name++;
381 } else {
382 name = prefix;
383 prefix = NULL;
384 }
385
386 /*
387 * Now is 'prefix' NULL or the prefix finished with '\0',
388 * 'name' the node name finished with '\0'.
389 */
390 }
391
392 /* cannot get here */
393 return NULL;
Radek Krejci3bde87f2015-06-05 16:51:58 +0200394}
395
Radek Krejciefaeba32015-05-27 14:30:57 +0200396API struct ly_module *ly_module_read(struct ly_ctx *ctx, const char *data,
Michal Vaskoe3d2ee02015-06-03 15:03:41 +0200397 LY_MINFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200398{
399 if (!ctx || !data) {
Radek Krejci812b10a2015-05-28 16:48:25 +0200400 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200401 return NULL;
402 }
403
404 switch (format) {
Michal Vaskoe3d2ee02015-06-03 15:03:41 +0200405 case LY_IN_YIN:
Radek Krejciefaeba32015-05-27 14:30:57 +0200406 return yin_read_module(ctx, data);
Michal Vaskoe3d2ee02015-06-03 15:03:41 +0200407 case LY_IN_YANG:
Radek Krejci5a065542015-05-22 15:02:07 +0200408 default:
Radek Krejcida04f4a2015-05-21 12:54:09 +0200409 /* TODO */
410 return NULL;
411 }
412
413 return NULL;
414}
415
Radek Krejciefaeba32015-05-27 14:30:57 +0200416struct ly_submodule *ly_submodule_read(struct ly_module *module,
Michal Vaskoe3d2ee02015-06-03 15:03:41 +0200417 const char *data, LY_MINFORMAT format)
Radek Krejciefaeba32015-05-27 14:30:57 +0200418{
Radek Krejci812b10a2015-05-28 16:48:25 +0200419 assert(module);
420 assert(data);
Radek Krejciefaeba32015-05-27 14:30:57 +0200421
422 switch (format) {
Michal Vaskoe3d2ee02015-06-03 15:03:41 +0200423 case LY_IN_YIN:
Radek Krejciefaeba32015-05-27 14:30:57 +0200424 return yin_read_submodule(module, data);
Michal Vaskoe3d2ee02015-06-03 15:03:41 +0200425 case LY_IN_YANG:
Radek Krejciefaeba32015-05-27 14:30:57 +0200426 default:
427 /* TODO */
428 return NULL;
429 }
430
431 return NULL;
432}
433
434API struct ly_module *ly_module_read_fd(struct ly_ctx *ctx, int fd,
Michal Vaskoe3d2ee02015-06-03 15:03:41 +0200435 LY_MINFORMAT format)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200436{
437 struct ly_module *module;
438 struct stat sb;
439 char *addr;
440
441 if (!ctx || fd < 0) {
Radek Krejci812b10a2015-05-28 16:48:25 +0200442 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200443 return NULL;
444 }
445
446 /*
447 * TODO
448 * This is just a temporary solution to make working automatic search for
449 * imported modules. This doesn't work e.g. for streams (stdin)
450 */
451 fstat(fd, &sb);
452 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Radek Krejciefaeba32015-05-27 14:30:57 +0200453 module = ly_module_read(ctx, addr, format);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200454 munmap(addr, sb.st_size);
455
456 return module;
457}
458
Radek Krejciefaeba32015-05-27 14:30:57 +0200459struct ly_submodule *ly_submodule_read_fd(struct ly_module *module, int fd,
Michal Vaskoe3d2ee02015-06-03 15:03:41 +0200460 LY_MINFORMAT format)
Radek Krejciefaeba32015-05-27 14:30:57 +0200461{
462 struct ly_submodule *submodule;
463 struct stat sb;
464 char *addr;
465
Radek Krejci812b10a2015-05-28 16:48:25 +0200466 assert(module);
467 assert(fd >= 0);
Radek Krejciefaeba32015-05-27 14:30:57 +0200468
469 /*
470 * TODO
471 * This is just a temporary solution to make working automatic search for
472 * imported modules. This doesn't work e.g. for streams (stdin)
473 */
474 fstat(fd, &sb);
475 addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Radek Krejci812b10a2015-05-28 16:48:25 +0200476 /* TODO addr error check */
Radek Krejciefaeba32015-05-27 14:30:57 +0200477 submodule = ly_submodule_read(module, addr, format);
478 munmap(addr, sb.st_size);
479
480 return submodule;
481
482}
483
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200484void ly_type_dup(struct ly_ctx *ctx, struct ly_type *new, struct ly_type *old)
485{
486 int i;
487
488 new->prefix = lydict_insert(ctx, old->prefix, 0);
489 new->base = old->base;
490 new->der = old->der;
491
492 switch(new->base) {
493 case LY_TYPE_ENUM:
494 new->info.enums.count = old->info.enums.count;
495 if (new->info.enums.count) {
496 new->info.enums.list = calloc(new->info.enums.count, sizeof *new->info.enums.list);
497 for (i = 0; i < new->info.enums.count; i++) {
498 new->info.enums.list[i].name = lydict_insert(ctx, old->info.enums.list[i].name, 0);
499 new->info.enums.list[i].dsc = lydict_insert(ctx, old->info.enums.list[i].dsc, 0);
500 new->info.enums.list[i].ref = lydict_insert(ctx, old->info.enums.list[i].ref, 0);
501 }
502 }
503 break;
504 default:
505 /* TODO */
506 break;
507 }
508}
509
Radek Krejci5a065542015-05-22 15:02:07 +0200510void ly_type_free(struct ly_ctx *ctx, struct ly_type *type)
511{
512 int i;
513
Radek Krejci812b10a2015-05-28 16:48:25 +0200514 assert(ctx);
515 if (!type) {
516 return;
517 }
518
Radek Krejci5a065542015-05-22 15:02:07 +0200519 lydict_remove(ctx, type->prefix);
520
521 switch(type->base) {
522 case LY_TYPE_ENUM:
523 for (i = 0; i < type->info.enums.count; i++) {
524 lydict_remove(ctx, type->info.enums.list[i].name);
525 lydict_remove(ctx, type->info.enums.list[i].dsc);
526 lydict_remove(ctx, type->info.enums.list[i].ref);
527 }
528 free(type->info.enums.list);
529 break;
530 default:
531 /* TODO */
532 break;
533 }
534}
535
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200536struct ly_tpdf *ly_tpdf_dup(struct ly_ctx *ctx, struct ly_tpdf *old, int size)
537{
538 struct ly_tpdf *result;
539 int i;
540
541 if (!size) {
542 return NULL;
543 }
544
545 result = calloc(size, sizeof *result);
546 for (i = 0; i < size; i++) {
547 result[i].name = lydict_insert(ctx, old[i].name, 0);
548 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
549 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
550 result[i].flags = old[i].flags;
551 result[i].module = old[i].module;
552
553 ly_type_dup(ctx, &(result[i].type), &(old[i].type));
554
555 result[i].dflt = lydict_insert(ctx, old[i].dflt, 0);
556 result[i].units = lydict_insert(ctx, old[i].units, 0);
557 }
558
559 return result;
560}
561
Radek Krejcida04f4a2015-05-21 12:54:09 +0200562void ly_tpdf_free(struct ly_ctx *ctx, struct ly_tpdf *tpdf)
563{
Radek Krejci812b10a2015-05-28 16:48:25 +0200564 assert(ctx);
565 if (!tpdf) {
566 return;
567 }
568
Radek Krejcida04f4a2015-05-21 12:54:09 +0200569 lydict_remove(ctx, tpdf->name);
570 lydict_remove(ctx, tpdf->dsc);
571 lydict_remove(ctx, tpdf->ref);
572
Radek Krejci5a065542015-05-22 15:02:07 +0200573 ly_type_free(ctx, &tpdf->type);
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200574
575 lydict_remove(ctx, tpdf->units);
576 lydict_remove(ctx, tpdf->dflt);
577}
578
579struct ly_must *ly_must_dup(struct ly_ctx *ctx, struct ly_must *old, int size)
580{
581 struct ly_must *result;
582 int i;
583
584 if (!size) {
585 return NULL;
586 }
587
588 result = calloc(size, sizeof *result);
589 for (i = 0; i < size; i++) {
590 result[i].cond = lydict_insert(ctx, old[i].cond, 0);
591 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
592 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
593 result[i].eapptag = lydict_insert(ctx, old[i].eapptag, 0);
594 result[i].emsg = lydict_insert(ctx, old[i].emsg, 0);
595 }
596
597 return result;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200598}
599
Radek Krejci800af702015-06-02 13:46:01 +0200600void ly_must_free(struct ly_ctx *ctx, struct ly_must *must)
601{
602 assert(ctx);
603 if (!must) {
604 return;
605 }
606
607 lydict_remove(ctx, must->cond);
608 lydict_remove(ctx, must->dsc);
609 lydict_remove(ctx, must->ref);
610 lydict_remove(ctx, must->eapptag);
611 lydict_remove(ctx, must->emsg);
612}
613
Radek Krejci106efc02015-06-10 14:36:27 +0200614struct ly_augment *ly_augment_dup(struct ly_module *module, struct ly_mnode *parent, struct ly_augment *old, int size)
615{
616 struct ly_augment *new = NULL;
617 int i = -1;
618
619 if (!size) {
620 return NULL;
621 }
622
623 new = calloc(size, sizeof *new);
624 for (i = 0; i < size; i++) {
625 new[i].target_name = lydict_insert(module->ctx, old[i].target_name, 0);
626 new[i].dsc = lydict_insert(module->ctx, old[i].dsc, 0);
627 new[i].ref = lydict_insert(module->ctx, old[i].ref, 0);
628 new[i].flags = old[i].flags;
629 /* .target = NULL; .nodetype = 0 */
630
631 new[i].parent = parent;
632
633 /* copy the definition of augment nodes */
634 if (old[i].child) {
635 new[i].child = (struct ly_mnode *) lyxml_dup_elem(module->ctx, (struct lyxml_elem *)old[i].child, NULL, 1);
636 }
637 }
638
639 return new;
640}
641
Michal Vasko1982cad2015-06-08 15:49:30 +0200642struct ly_refine *ly_refine_dup(struct ly_ctx *ctx, struct ly_refine *old, int size)
643{
644 struct ly_refine *result;
645 int i;
646
647 if (!size) {
648 return NULL;
649 }
650
651 result = calloc(size, sizeof *result);
652 for (i = 0; i < size; i++) {
653 result[i].target = lydict_insert(ctx, old[i].target, 0);
654 result[i].dsc = lydict_insert(ctx, old[i].dsc, 0);
655 result[i].ref = lydict_insert(ctx, old[i].ref, 0);
656 result[i].flags = old[i].flags;
657 result[i].target_type = old[i].target_type;
658 result[i].must_size = old[i].must_size;
659 result[i].must = ly_must_dup(ctx, old[i].must, old[i].must_size);
660 if (result[i].target_type & (LY_NODE_LEAF | LY_NODE_CHOICE)) {
661 result[i].mod.dflt = lydict_insert(ctx, old[i].mod.dflt, 0);
662 } else if (result[i].target_type == LY_NODE_CONTAINER) {
663 result[i].mod.presence = lydict_insert(ctx, old[i].mod.presence, 0);
664 } else if (result[i].target_type & (LY_NODE_LIST | LY_NODE_LEAFLIST)) {
665 result[i].mod.list = old[i].mod.list;
666 }
667 }
668
669 return result;
670}
671
Radek Krejci6793db02015-05-22 17:49:54 +0200672void ly_ident_free(struct ly_ctx *ctx, struct ly_ident *ident)
673{
674 struct ly_ident_der *der;
675
Radek Krejci812b10a2015-05-28 16:48:25 +0200676 assert(ctx);
677 if (!ident) {
678 return;
679 }
680
Radek Krejci6793db02015-05-22 17:49:54 +0200681 /*
682 * TODO
683 * if caller free only a single data model which is used (its identity is
684 * reference from identity in another module), this silly freeing can lead
685 * to segmentation fault. But without noting if the module is used by some
686 * other, it cannot be solved.
687 */
688 while(ident->der) {
689 der = ident->der;
690 ident->der = der->next;
691 free(der);
692 }
693
694 lydict_remove(ctx, ident->name);
695 lydict_remove(ctx, ident->dsc);
696 lydict_remove(ctx, ident->ref);
697
698}
699
Radek Krejcida04f4a2015-05-21 12:54:09 +0200700void ly_grp_free(struct ly_ctx *ctx, struct ly_mnode_grp *grp)
701{
702 int i;
703
704 /* handle only specific parts for LY_NODE_GROUPING */
Radek Krejci537cf382015-06-04 11:07:01 +0200705 for (i = 0; i < grp->tpdf_size; i++) {
706 ly_tpdf_free(ctx, &grp->tpdf[i]);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200707 }
Radek Krejci537cf382015-06-04 11:07:01 +0200708 free(grp->tpdf);
709}
710
711void ly_anyxml_free(struct ly_ctx *ctx, struct ly_mnode_anyxml *anyxml)
712{
713 int i;
714
715 for (i = 0; i < anyxml->must_size; i++) {
716 ly_must_free(ctx, &anyxml->must[i]);
717 }
718 free(anyxml->must);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200719}
720
Radek Krejci5a065542015-05-22 15:02:07 +0200721void ly_leaf_free(struct ly_ctx *ctx, struct ly_mnode_leaf *leaf)
722{
Radek Krejci537cf382015-06-04 11:07:01 +0200723 int i;
724
725 for (i = 0; i < leaf->must_size; i++) {
726 ly_must_free(ctx, &leaf->must[i]);
727 }
728 free(leaf->must);
729
Radek Krejci5a065542015-05-22 15:02:07 +0200730 ly_type_free(ctx, &leaf->type);
Radek Krejci537cf382015-06-04 11:07:01 +0200731 lydict_remove(ctx, leaf->units);
732 lydict_remove(ctx, leaf->dflt);
Radek Krejci5a065542015-05-22 15:02:07 +0200733}
734
735void ly_leaflist_free(struct ly_ctx *ctx, struct ly_mnode_leaflist *llist)
736{
Radek Krejci537cf382015-06-04 11:07:01 +0200737 int i;
738
739 for (i = 0; i < llist->must_size; i++) {
740 ly_must_free(ctx, &llist->must[i]);
741 }
742 free(llist->must);
743
Radek Krejci5a065542015-05-22 15:02:07 +0200744 ly_type_free(ctx, &llist->type);
Radek Krejci537cf382015-06-04 11:07:01 +0200745 lydict_remove(ctx, llist->units);
Radek Krejci5a065542015-05-22 15:02:07 +0200746}
747
Radek Krejcida04f4a2015-05-21 12:54:09 +0200748void ly_list_free(struct ly_ctx *ctx, struct ly_mnode_list *list)
749{
750 int i;
751
752 /* handle only specific parts for LY_NODE_LIST */
Radek Krejci537cf382015-06-04 11:07:01 +0200753 for (i = 0; i < list->tpdf_size; i++) {
754 ly_tpdf_free(ctx, &list->tpdf[i]);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200755 }
Radek Krejci537cf382015-06-04 11:07:01 +0200756 free(list->tpdf);
757
758 for (i = 0; i < list->must_size; i++) {
759 ly_must_free(ctx, &list->must[i]);
760 }
761 free(list->must);
762
763 for (i = 0; i < list->unique_size; i++) {
764 free(list->unique[i].leafs);
765 }
766 free(list->unique);
Radek Krejcid7f0d012015-05-25 15:04:52 +0200767
768 free(list->keys);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200769}
770
771void ly_container_free(struct ly_ctx *ctx, struct ly_mnode_container *cont)
772{
773 int i;
774
775 /* handle only specific parts for LY_NODE_CONTAINER */
Radek Krejci800af702015-06-02 13:46:01 +0200776 lydict_remove(ctx, cont->presence);
777
Radek Krejci537cf382015-06-04 11:07:01 +0200778 for (i = 0; i < cont->tpdf_size; i++) {
779 ly_tpdf_free(ctx, &cont->tpdf[i]);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200780 }
Radek Krejci537cf382015-06-04 11:07:01 +0200781 free(cont->tpdf);
Radek Krejci800af702015-06-02 13:46:01 +0200782
Radek Krejci537cf382015-06-04 11:07:01 +0200783 for (i = 0; i < cont->must_size; i++) {
784 ly_must_free(ctx, &cont->must[i]);
Radek Krejci800af702015-06-02 13:46:01 +0200785 }
Radek Krejci537cf382015-06-04 11:07:01 +0200786 free(cont->must);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200787}
788
Michal Vasko38d01f72015-06-15 09:41:06 +0200789void ly_rpc_free(struct ly_ctx *ctx, struct ly_mnode_rpc *rpc)
790{
791 int i;
792
793 for (i = 0; i < rpc->tpdf_size; i++) {
794 ly_tpdf_free(ctx, &rpc->tpdf[i]);
795 }
796 free(rpc->tpdf);
797}
798
799void ly_input_output_free(struct ly_ctx *ctx, struct ly_mnode_input_output *inout)
800{
801 int i;
802
803 for (i = 0; i < inout->tpdf_size; i++) {
804 ly_tpdf_free(ctx, &inout->tpdf[i]);
805 }
806 free(inout->tpdf);
807}
808
Radek Krejcie1fa8582015-06-08 09:46:45 +0200809void ly_uses_free(struct ly_ctx *ctx, struct ly_mnode_uses *uses)
810{
811 int i, j;
812
813 for (i = 0; i < uses->refine_size; i++) {
814 lydict_remove(ctx, uses->refine[i].target);
815 lydict_remove(ctx, uses->refine[i].dsc);
816 lydict_remove(ctx, uses->refine[i].ref);
817
818 for (j = 0; j < uses->refine[j].must_size; j++) {
819 ly_must_free(ctx, &uses->refine[i].must[j]);
820 }
821 free(uses->refine[i].must);
822
823 if (uses->refine[i].target_type & (LY_NODE_LEAF | LY_NODE_CHOICE)) {
824 lydict_remove(ctx, uses->refine[i].mod.dflt);
825 } else if (uses->refine[i].target_type & LY_NODE_CONTAINER) {
826 lydict_remove(ctx, uses->refine[i].mod.presence);
827 }
828 }
829 free(uses->refine);
830
831 for (i = 0; i < uses->augment_size; i++) {
Radek Krejci106efc02015-06-10 14:36:27 +0200832 lydict_remove(ctx, uses->augment[i].target_name);
833 lydict_remove(ctx, uses->augment[i].dsc);
834 lydict_remove(ctx, uses->augment[i].ref);
835
836 lyxml_free_elem(ctx, (struct lyxml_elem *)uses->augment[i].child);
Radek Krejcie1fa8582015-06-08 09:46:45 +0200837 }
838 free(uses->augment);
839
840}
841
Radek Krejcida04f4a2015-05-21 12:54:09 +0200842void ly_mnode_free(struct ly_mnode *node)
843{
844 struct ly_ctx *ctx;
845 struct ly_mnode *sub, *next;
846
847 if (!node) {
848 return;
849 }
850
Radek Krejci812b10a2015-05-28 16:48:25 +0200851 assert(node->module);
852 assert(node->module->ctx);
853
Radek Krejcida04f4a2015-05-21 12:54:09 +0200854 ctx = node->module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200855
856 /* common part */
857 LY_TREE_FOR_SAFE(node->child, next, sub) {
858 ly_mnode_free(sub);
859 }
860
861 lydict_remove(ctx, node->name);
862 lydict_remove(ctx, node->dsc);
863 lydict_remove(ctx, node->ref);
864
865 /* specific part */
866 switch(node->nodetype) {
867 case LY_NODE_CONTAINER:
868 ly_container_free(ctx, (struct ly_mnode_container *)node);
869 break;
870 case LY_NODE_CHOICE:
871 break;
872 case LY_NODE_LEAF:
Radek Krejci5a065542015-05-22 15:02:07 +0200873 ly_leaf_free(ctx, (struct ly_mnode_leaf *)node);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200874 break;
875 case LY_NODE_LEAFLIST:
Radek Krejci5a065542015-05-22 15:02:07 +0200876 ly_leaflist_free(ctx, (struct ly_mnode_leaflist *)node);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200877 break;
878 case LY_NODE_LIST:
879 ly_list_free(ctx, (struct ly_mnode_list *)node);
880 break;
881 case LY_NODE_ANYXML:
Radek Krejci537cf382015-06-04 11:07:01 +0200882 ly_anyxml_free(ctx, (struct ly_mnode_anyxml *)node);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200883 break;
884 case LY_NODE_USES:
Radek Krejcie1fa8582015-06-08 09:46:45 +0200885 ly_uses_free(ctx, (struct ly_mnode_uses *)node);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200886 break;
887 case LY_NODE_GROUPING:
888 ly_grp_free(ctx, (struct ly_mnode_grp *)node);
889 break;
Radek Krejcib4cf2022015-06-03 14:40:05 +0200890 case LY_NODE_CASE:
Radek Krejcib7155b52015-06-10 17:03:01 +0200891 case LY_NODE_AUGMENT:
892 /* do nothing */
Radek Krejcib4cf2022015-06-03 14:40:05 +0200893 break;
Radek Krejci106efc02015-06-10 14:36:27 +0200894 case LY_NODE_INPUT:
Radek Krejci106efc02015-06-10 14:36:27 +0200895 case LY_NODE_OUTPUT:
Michal Vasko38d01f72015-06-15 09:41:06 +0200896 ly_input_output_free(ctx, (struct ly_mnode_input_output *)node);
Radek Krejci106efc02015-06-10 14:36:27 +0200897 break;
898 case LY_NODE_NOTIF:
899 /* TODO */
900 break;
Michal Vasko38d01f72015-06-15 09:41:06 +0200901 case LY_NODE_RPC:
902 ly_rpc_free(ctx, (struct ly_mnode_rpc *)node);
903 break;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200904 }
Radek Krejci5a065542015-05-22 15:02:07 +0200905
906 /* again common part */
907 ly_mnode_unlink(node);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200908 free(node);
909}
910
Radek Krejciefaeba32015-05-27 14:30:57 +0200911static void module_free_common(struct ly_module *module)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200912{
913 struct ly_ctx *ctx;
914 struct ly_mnode *mnode;
Radek Krejcice7fb782015-05-29 16:52:34 +0200915 unsigned int i;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200916
Radek Krejci812b10a2015-05-28 16:48:25 +0200917 assert(module->ctx);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200918 ctx = module->ctx;
919
Radek Krejciefaeba32015-05-27 14:30:57 +0200920 while (module->data) {
Radek Krejci5a065542015-05-22 15:02:07 +0200921 mnode = module->data;
922 module->data = mnode;
923 ly_mnode_free(mnode);
924 }
925
Radek Krejcida04f4a2015-05-21 12:54:09 +0200926 lydict_remove(ctx, module->dsc);
927 lydict_remove(ctx, module->ref);
928 lydict_remove(ctx, module->org);
929 lydict_remove(ctx, module->contact);
930
Radek Krejcice7fb782015-05-29 16:52:34 +0200931 for (i = 0; i < module->rev_size; i++) {
932 lydict_remove(ctx, module->rev[i].dsc);
933 lydict_remove(ctx, module->rev[i].ref);
934 }
Radek Krejcif3886932015-06-04 17:36:06 +0200935 free(module->rev);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200936
Radek Krejcice7fb782015-05-29 16:52:34 +0200937 for (i = 0; i < module->ident_size; i++) {
938 ly_ident_free(ctx, &module->ident[i]);
939 }
940 module->ident_size = 0;
Radek Krejcif3886932015-06-04 17:36:06 +0200941 free(module->ident);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200942
Radek Krejcice7fb782015-05-29 16:52:34 +0200943 for (i = 0; i < module->tpdf_size; i++) {
944 ly_tpdf_free(ctx, &module->tpdf[i]);
945 }
Radek Krejcif3886932015-06-04 17:36:06 +0200946 free(module->tpdf);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200947
Radek Krejcif3886932015-06-04 17:36:06 +0200948 free(module->imp);
Radek Krejci6793db02015-05-22 17:49:54 +0200949
Radek Krejcice7fb782015-05-29 16:52:34 +0200950 for (i = 0; i < module->inc_size; i++) {
951 ly_submodule_free(module->inc[i].submodule);
952 }
Radek Krejcif3886932015-06-04 17:36:06 +0200953 free(module->inc);
Radek Krejciefaeba32015-05-27 14:30:57 +0200954
Radek Krejci6793db02015-05-22 17:49:54 +0200955 lydict_remove(ctx, module->name);
Radek Krejciefaeba32015-05-27 14:30:57 +0200956}
957
958void ly_submodule_free(struct ly_submodule *submodule)
959{
960 if (!submodule) {
961 return;
962 }
963
Radek Krejcif3886932015-06-04 17:36:06 +0200964 submodule->inc_size = 0;
965 free(submodule->inc);
966 submodule->inc = NULL;
967
Radek Krejciefaeba32015-05-27 14:30:57 +0200968 /* common part with struct ly_module */
969 module_free_common((struct ly_module *)submodule);
970
971 /* no specific items to free */
972
973 free(submodule);
974}
975
Radek Krejci3bde87f2015-06-05 16:51:58 +0200976struct ly_mnode *ly_mnode_dup(struct ly_module *module, struct ly_mnode *mnode, uint8_t flags, int recursive, unsigned int line)
Radek Krejci8bc9ca02015-06-04 15:52:46 +0200977{
978 struct ly_mnode *retval = NULL, *aux, *child;
979 struct ly_ctx *ctx = module->ctx;
980 int i, j;
981
982 struct ly_mnode_container *cont;
983 struct ly_mnode_container *cont_orig = (struct ly_mnode_container *)mnode;
984 struct ly_mnode_choice *choice;
985 struct ly_mnode_choice *choice_orig = (struct ly_mnode_choice *)mnode;
986 struct ly_mnode_leaf *leaf;
987 struct ly_mnode_leaf *leaf_orig = (struct ly_mnode_leaf *)mnode;
988 struct ly_mnode_leaflist *llist;
989 struct ly_mnode_leaflist *llist_orig = (struct ly_mnode_leaflist *)mnode;
990 struct ly_mnode_list *list;
991 struct ly_mnode_list *list_orig = (struct ly_mnode_list *)mnode;
992 struct ly_mnode_anyxml *anyxml;
993 struct ly_mnode_anyxml *anyxml_orig = (struct ly_mnode_anyxml *)mnode;
994 struct ly_mnode_uses *uses;
995 struct ly_mnode_uses *uses_orig = (struct ly_mnode_uses *)mnode;
996 struct ly_mnode_grp *grp;
997 struct ly_mnode_grp *grp_orig = (struct ly_mnode_grp *)mnode;
998 struct ly_mnode_case *cs;
Michal Vasko38d01f72015-06-15 09:41:06 +0200999 struct ly_mnode_rpc *rpc;
1000 struct ly_mnode_rpc *rpc_orig = (struct ly_mnode_rpc *)mnode;
1001 struct ly_mnode_input_output *inout;
1002 struct ly_mnode_input_output *inout_orig = (struct ly_mnode_input_output *)mnode;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001003
1004 /* we cannot just duplicate memory since the strings are stored in
1005 * dictionary and we need to update dictionary counters.
1006 */
1007
1008 switch(mnode->nodetype) {
1009 case LY_NODE_CONTAINER:
1010 cont = calloc(1, sizeof *cont);
1011 retval = (struct ly_mnode *)cont;
1012 break;
1013 case LY_NODE_CHOICE:
1014 choice = calloc(1, sizeof *choice);
1015 retval = (struct ly_mnode *)choice;
1016 break;
1017 case LY_NODE_LEAF:
1018 leaf = calloc(1, sizeof *leaf);
1019 retval = (struct ly_mnode *)leaf;
1020 break;
1021 case LY_NODE_LEAFLIST:
1022 llist = calloc(1, sizeof *llist);
1023 retval = (struct ly_mnode *)llist;
1024 break;
1025 case LY_NODE_LIST:
1026 list = calloc(1, sizeof *list);
1027 retval = (struct ly_mnode *)list;
1028 break;
1029 case LY_NODE_ANYXML:
1030 anyxml = calloc(1, sizeof *anyxml);
1031 retval = (struct ly_mnode *)anyxml;
1032 break;
1033 case LY_NODE_USES:
1034 uses = calloc(1, sizeof *uses);
1035 retval = (struct ly_mnode *)uses;
1036 break;
1037 case LY_NODE_GROUPING:
1038 grp = calloc(1, sizeof *grp);
1039 retval = (struct ly_mnode *)grp;
1040 break;
1041 case LY_NODE_CASE:
1042 cs = calloc(1, sizeof *cs);
1043 retval = (struct ly_mnode *)cs;
1044 break;
Michal Vasko38d01f72015-06-15 09:41:06 +02001045 case LY_NODE_RPC:
1046 rpc = calloc(1, sizeof *rpc);
1047 retval = (struct ly_mnode *)rpc;
1048 break;
1049 case LY_NODE_INPUT:
1050 case LY_NODE_OUTPUT:
1051 inout = calloc(1, sizeof *inout);
1052 retval = (struct ly_mnode *)inout;
1053 break;
Radek Krejci106efc02015-06-10 14:36:27 +02001054 default:
Michal Vasko38d01f72015-06-15 09:41:06 +02001055 /* LY_NODE_NOTIF */
Radek Krejci106efc02015-06-10 14:36:27 +02001056 goto error;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001057 }
1058
1059 /*
1060 * duplicate generic part of the structure
1061 */
1062 retval->name = lydict_insert(ctx, mnode->name, 0);
1063 retval->dsc = lydict_insert(ctx, mnode->dsc, 0);
1064 retval->ref = lydict_insert(ctx, mnode->ref, 0);
1065 retval->flags = mnode->flags;
Radek Krejcib388c152015-06-04 17:03:03 +02001066 if (!(retval->flags & LY_NODE_CONFIG_MASK)) {
1067 /* set parent's config flag */
1068 retval->flags |= flags & LY_NODE_CONFIG_MASK;
1069 }
1070
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001071 retval->module = module;
1072 retval->nodetype = mnode->nodetype;
1073
1074 retval->prev = retval;
1075
1076 retval->feature = NULL; /* TODO */
1077 retval->when = NULL; /* TODO */
1078
1079 if (recursive) {
1080 /* go recursively */
1081 LY_TREE_FOR(mnode->child, child) {
Radek Krejci3bde87f2015-06-05 16:51:58 +02001082 aux = ly_mnode_dup(module, child, retval->flags, 1, line);
Radek Krejcib7155b52015-06-10 17:03:01 +02001083 if (!aux || ly_mnode_addchild(retval, aux)) {
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001084 goto error;
1085 }
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001086 }
1087 }
1088
1089 /*
1090 * duplicate specific part of the structure
1091 */
1092 switch(mnode->nodetype) {
1093 case LY_NODE_CONTAINER:
1094 cont->presence = lydict_insert(ctx, cont_orig->presence, 0);
1095
1096 cont->must_size = cont_orig->must_size;
1097 cont->tpdf_size = cont_orig->tpdf_size;
1098
1099 cont->must = ly_must_dup(ctx, cont_orig->must, cont->must_size);
1100 cont->tpdf = ly_tpdf_dup(ctx, cont_orig->tpdf, cont->tpdf_size);
1101 break;
1102 case LY_NODE_CHOICE:
1103 if (choice->dflt) {
1104 LY_TREE_FOR(choice->child, child) {
1105 if (child->name == choice_orig->dflt->name) {
1106 choice->dflt = child;
1107 break;
1108 }
1109 }
1110 }
1111 break;
1112 case LY_NODE_LEAF:
1113 ly_type_dup(ctx, &(leaf->type), &(leaf_orig->type));
1114 leaf->units = lydict_insert(ctx, leaf_orig->units, 0);
1115 leaf->dflt = lydict_insert(ctx, leaf_orig->dflt, 0);
1116
1117 leaf->must_size = leaf_orig->must_size;
1118 leaf->must = ly_must_dup(ctx, leaf_orig->must, leaf->must_size);
1119 break;
1120 case LY_NODE_LEAFLIST:
1121
1122 ly_type_dup(ctx, &(llist->type), &(llist_orig->type));
1123 llist->units = lydict_insert(ctx, llist_orig->units, 0);
1124
1125 llist->min = llist_orig->min;
1126 llist->max = llist_orig->max;
1127
1128 llist->must_size = llist_orig->must_size;
1129 llist->must = ly_must_dup(ctx, llist_orig->must, llist->must_size);
1130 break;
1131 case LY_NODE_LIST:
1132 list->min = list_orig->min;
1133 list->max = list_orig->max;
1134
1135 list->must_size = list_orig->must_size;
1136 list->tpdf_size = list_orig->tpdf_size;
1137 list->keys_size = list_orig->keys_size;
1138 list->unique_size = list_orig->unique_size;
1139
1140 list->must = ly_must_dup(ctx, list_orig->must, list->must_size);
1141 list->tpdf = ly_tpdf_dup(ctx, list_orig->tpdf, list->tpdf_size);
1142
1143 if (list->keys_size) {
1144 list->keys = calloc(list->keys_size, sizeof *list->keys);
1145 for (i = 0; i < list->keys_size; i++) {
1146 list->keys[i] = find_leaf(retval, list_orig->keys[i]->name, 0);
1147 }
1148 }
1149 if (list->unique_size) {
1150 list->unique = calloc(list->unique_size, sizeof *list->unique);
1151 for (i = 0; i < list->unique_size; i++) {
1152 list->unique[i].leafs = calloc(list->unique[i].leafs_size, sizeof *list->unique[i].leafs);
1153 for (j = 0; j < list->unique[i].leafs_size; j++) {
1154 list->unique[i].leafs[j] = find_leaf(retval, list_orig->unique[i].leafs[j]->name, 0);
1155 }
1156 }
1157 }
1158 break;
1159 case LY_NODE_ANYXML:
1160 anyxml->must_size = anyxml_orig->must_size;
1161 anyxml->must = ly_must_dup(ctx, anyxml_orig->must, anyxml->must_size);
1162 break;
1163 case LY_NODE_USES:
1164 uses->grp = uses_orig->grp;
Michal Vasko1982cad2015-06-08 15:49:30 +02001165 uses->refine_size = uses_orig->refine_size;
1166 uses->refine = ly_refine_dup(ctx, uses_orig->refine, uses_orig->refine_size);
1167 uses->augment_size = uses_orig->augment_size;
Radek Krejci106efc02015-06-10 14:36:27 +02001168 uses->augment = ly_augment_dup(module, (struct ly_mnode *)uses, uses_orig->augment, uses_orig->augment_size);
Radek Krejci3bde87f2015-06-05 16:51:58 +02001169 if (resolve_uses(uses, line)) {
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001170 goto error;
1171 }
1172 break;
1173 case LY_NODE_GROUPING:
1174 grp->tpdf_size = grp_orig->tpdf_size;
1175 grp->tpdf = ly_tpdf_dup(ctx, grp_orig->tpdf, grp->tpdf_size);
1176 break;
1177 case LY_NODE_CASE:
1178 /* nothing to do */
1179 break;
Michal Vasko38d01f72015-06-15 09:41:06 +02001180 case LY_NODE_RPC:
1181 rpc->tpdf_size = rpc_orig->tpdf_size;
1182 rpc->tpdf = ly_tpdf_dup(ctx, rpc_orig->tpdf, rpc->tpdf_size);
1183 break;
1184 case LY_NODE_INPUT:
1185 case LY_NODE_OUTPUT:
1186 inout->tpdf_size = inout_orig->tpdf_size;
1187 inout->tpdf = ly_tpdf_dup(ctx, inout_orig->tpdf, inout->tpdf_size);
Radek Krejci106efc02015-06-10 14:36:27 +02001188 default:
Michal Vasko38d01f72015-06-15 09:41:06 +02001189 /* LY_NODE_NOTIF */
Radek Krejci106efc02015-06-10 14:36:27 +02001190 goto error;
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001191 }
1192
Radek Krejci8bc9ca02015-06-04 15:52:46 +02001193 return retval;
1194
1195error:
1196 LOGDBG("error: %s:%d", __FILE__, __LINE__);
1197
1198 ly_mnode_free(retval);
1199 return NULL;
1200}
1201
Radek Krejciefaeba32015-05-27 14:30:57 +02001202API void ly_module_free(struct ly_module *module)
1203{
1204 if (!module) {
1205 return;
1206 }
1207
1208 /* common part with struct ly_submodule */
1209 module_free_common(module);
1210
1211 /* specific items to free */
1212 lydict_remove(module->ctx, module->ns);
1213 lydict_remove(module->ctx, module->prefix);
Radek Krejci6793db02015-05-22 17:49:54 +02001214
Radek Krejcida04f4a2015-05-21 12:54:09 +02001215 free(module);
1216}
1217
1218