blob: 7bfd6acc90196b243eaa72fc9ac6894e357819e5 [file] [log] [blame]
Radek Krejcic6704c82015-10-06 11:12:45 +02001
Michal Vasko2d162e12015-09-24 14:33:29 +02002/**
3 * @file tree_data.c
4 * @author Radek Krejci <rkrejci@cesnet.cz>
5 * @brief Manipulation with libyang data structures
6 *
7 * Copyright (c) 2015 CESNET, z.s.p.o.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * 3. Neither the name of the Company nor the names of its contributors
19 * may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
21 */
22#define _GNU_SOURCE
23
24#include <assert.h>
25#include <ctype.h>
26#include <stdlib.h>
27#include <sys/mman.h>
28#include <sys/stat.h>
29#include <string.h>
30
31#include "common.h"
32#include "context.h"
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020033#include "tree_data.h"
Michal Vasko2d162e12015-09-24 14:33:29 +020034#include "parser.h"
35#include "resolve.h"
Radek Krejcic6704c82015-10-06 11:12:45 +020036#include "xml_private.h"
Michal Vasko2d162e12015-09-24 14:33:29 +020037#include "tree_internal.h"
38#include "validation.h"
39
40API struct lyd_node *
41lyd_parse(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
42{
Radek Krejci5974c1f2015-10-09 09:53:24 +020043 struct lyxml_elem *xml;
44 struct lyd_node *result = NULL;
45
Michal Vasko2d162e12015-09-24 14:33:29 +020046 if (!ctx || !data) {
47 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
48 return NULL;
49 }
50
51 switch (format) {
52 case LYD_XML:
Radek Krejci452fb952015-10-02 16:07:46 +020053 case LYD_XML_FORMAT:
Radek Krejci5974c1f2015-10-09 09:53:24 +020054 xml = lyxml_read(ctx, data, 0);
55 result = lyd_parse_xml(ctx, xml, options);
56 lyxml_free_elem(ctx, xml);
57 break;
Michal Vasko2d162e12015-09-24 14:33:29 +020058 case LYD_JSON:
59 default:
60 /* TODO */
61 return NULL;
62 }
63
Radek Krejci5974c1f2015-10-09 09:53:24 +020064 return result;
Michal Vasko2d162e12015-09-24 14:33:29 +020065}
66
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020067API struct lyd_node *
68lyd_new(struct lyd_node *parent, struct lys_module *module, const char *name)
69{
70 struct lyd_node *ret;
71 struct lys_node *snode = NULL, *siblings;
72
73 if ((!parent && !module) || !name) {
74 ly_errno = LY_EINVAL;
75 return NULL;
76 }
77
78 if (!parent) {
79 siblings = module->data;
80 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +020081 if (!parent->schema) {
82 return NULL;
83 }
84 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020085 }
86
87 if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_CONTAINER | LYS_INPUT | LYS_OUTPUT
88 | LYS_NOTIF | LYS_RPC, &snode) || !snode) {
89 return NULL;
90 }
91
92 ret = calloc(1, sizeof *ret);
93 ret->schema = snode;
94 ret->prev = ret;
95 if (parent) {
96 if (lyd_insert(parent, ret, 0)) {
97 free(ret);
98 return NULL;
99 }
100 }
101
102 return ret;
103}
104
105API struct lyd_node *
106lyd_new_leaf_val(struct lyd_node *parent, struct lys_module *module, const char *name, LY_DATA_TYPE type,
Michal Vasko0e3c8722015-09-29 16:06:08 +0200107 lyd_val value)
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200108{
109 struct lyd_node_leaf_list *ret;
110 struct lys_node *snode = NULL, *siblings;
Radek Krejcie4e4d722015-10-05 16:53:50 +0200111 struct lys_type *stype = NULL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200112 struct lys_module *src_mod, *dst_mod;
113 char *val_str = NULL, str_num[22];
Radek Krejcie4e4d722015-10-05 16:53:50 +0200114 const char *prefix = NULL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200115 int i, str_len = 0, prev_len;
116 uint64_t exp;
117
Michal Vasko0e3c8722015-09-29 16:06:08 +0200118 if ((!parent && !module) || !name) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200119 ly_errno = LY_EINVAL;
120 return NULL;
121 }
122
123 if (!parent) {
124 siblings = module->data;
125 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200126 if (!parent->schema) {
127 return NULL;
128 }
129 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200130 }
131
132 if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_LEAFLIST | LYS_LEAF, &snode)
133 || !snode) {
134 return NULL;
135 }
136
137 switch (type) {
138 case LY_TYPE_BINARY:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200139 val_str = (char *)lydict_insert(snode->module->ctx, value.binary, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200140 break;
141
142 case LY_TYPE_BITS:
143 /* find the type definition */
144 for (stype = &((struct lys_node_leaf *)snode)->type; stype->der->module; stype = &stype->der->type) {
145 if (stype->base != LY_TYPE_BITS) {
146 LOGINT;
147 return NULL;
148 }
149 }
150
151 /* concatenate set bits */
152 for (i = 0; i < stype->info.bits.count; ++i) {
Michal Vasko0e3c8722015-09-29 16:06:08 +0200153 if (!value.bit[i]) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200154 continue;
155 }
156
157 prev_len = str_len;
Michal Vasko0e3c8722015-09-29 16:06:08 +0200158 str_len += strlen(value.bit[i]->name) + 1;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200159 val_str = realloc((char *)val_str, str_len * sizeof(char));
160
161 if (prev_len) {
162 val_str[prev_len] = ' ';
163 ++prev_len;
164 }
Michal Vasko0e3c8722015-09-29 16:06:08 +0200165 strcpy(val_str + prev_len, value.bit[i]->name);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200166 }
167
168 val_str = (char *)lydict_insert_zc(snode->module->ctx, val_str);
169 break;
170
171 case LY_TYPE_BOOL:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200172 if (value.bool) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200173 val_str = (char *)lydict_insert(snode->module->ctx, "true", 4);
174 } else {
175 val_str = (char *)lydict_insert(snode->module->ctx, "false", 5);
176 }
177 break;
178
179 case LY_TYPE_DEC64:
180 /* find the type definition */
181 for (stype = &((struct lys_node_leaf *)snode)->type; stype->der->module; stype = &stype->der->type) {
182 if (stype->base != LY_TYPE_DEC64) {
183 LOGINT;
184 return NULL;
185 }
186 }
187
188 for (i = 0, exp = 1; i < stype->info.dec64.dig; ++i, exp *= 10);
Michal Vasko0e3c8722015-09-29 16:06:08 +0200189 sprintf(str_num, "%01.1Lf", ((long double)value.dec64) / exp);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200190 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
191 break;
192
193 case LY_TYPE_EMPTY:
194 break;
195
196 case LY_TYPE_ENUM:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200197 val_str = (char *)lydict_insert(snode->module->ctx, value.enm->name, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200198 break;
199
200 case LY_TYPE_IDENT:
201 /* TODO move to function if used somewhere else (module -> import prefix) */
Michal Vasko0e3c8722015-09-29 16:06:08 +0200202 src_mod = value.ident->module;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200203 if (src_mod->type) {
204 src_mod = ((struct lys_submodule *)src_mod)->belongsto;
205 }
206 dst_mod = snode->module;
207 if (dst_mod->type) {
208 dst_mod = ((struct lys_submodule *)dst_mod)->belongsto;
209 }
210 if (src_mod != dst_mod) {
211 for (i = 0; i < src_mod->imp_size; ++i) {
212 if (src_mod->imp[i].module == dst_mod) {
213 prefix = src_mod->imp[i].prefix;
214 break;
215 }
216 }
217 if (!prefix) {
218 LOGINT;
219 return NULL;
220 }
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200221 }
222
223 if (!prefix) {
Michal Vasko0e3c8722015-09-29 16:06:08 +0200224 val_str = (char *)lydict_insert(snode->module->ctx, value.ident->name, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200225 } else {
Michal Vasko0e3c8722015-09-29 16:06:08 +0200226 val_str = malloc((strlen(prefix) + 1 + strlen(value.ident->name) + 1) * sizeof(char));
227 sprintf(val_str, "%s:%s", prefix, value.ident->name);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200228 val_str = (char *)lydict_insert_zc(snode->module->ctx, val_str);
229 }
230 break;
231
232 case LY_TYPE_INST:
233 /* TODO */
234 break;
235
236 case LY_TYPE_LEAFREF:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200237 val_str = (char *)lydict_insert(snode->module->ctx, ((struct lyd_node_leaf_list *)value.leafref)->value_str, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200238 break;
239
240 case LY_TYPE_STRING:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200241 val_str = (char *)lydict_insert(snode->module->ctx, value.string, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200242 break;
243
244 case LY_TYPE_INT8:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200245 sprintf(str_num, "%hhd", value.int8);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200246 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
247 break;
248
249 case LY_TYPE_INT16:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200250 sprintf(str_num, "%hd", value.int16);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200251 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
252 break;
253
254 case LY_TYPE_INT32:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200255 sprintf(str_num, "%d", value.int32);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200256 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
257 break;
258
259 case LY_TYPE_INT64:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200260 sprintf(str_num, "%ld", value.int64);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200261 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
262 break;
263
264 case LY_TYPE_UINT8:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200265 sprintf(str_num, "%hhu", value.uint8);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200266 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
267 break;
268
269 case LY_TYPE_UINT16:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200270 sprintf(str_num, "%hu", value.uint16);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200271 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
272 break;
273
274 case LY_TYPE_UINT32:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200275 sprintf(str_num, "%u", value.uint32);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200276 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
277 break;
278
279 case LY_TYPE_UINT64:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200280 sprintf(str_num, "%lu", value.uint64);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200281 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
282 break;
283
284 default:
285 LOGINT;
286 return NULL;
287 }
288
289 ret = calloc(1, sizeof *ret);
290 ret->schema = snode;
291 ret->prev = (struct lyd_node *)ret;
292 if (parent) {
293 if (lyd_insert(parent, (struct lyd_node *)ret, 0)) {
294 free(ret);
295 lydict_remove(snode->module->ctx, val_str);
296 return NULL;
297 }
298 }
Michal Vasko81eef2c2015-10-02 15:37:25 +0200299
300 if (type == LY_TYPE_BINARY) {
301 ret->value.binary = val_str;
302 } else if (type == LY_TYPE_STRING) {
303 ret->value.string = val_str;
304 } else if (type == LY_TYPE_BITS) {
305 /* stype is left with the bits type definition */
306 ret->value.bit = malloc(stype->info.bits.count * sizeof *ret->value.bit);
307 memcpy(ret->value.bit, value.bit, stype->info.bits.count * sizeof *ret->value.bit);
308 } else {
309 ret->value = value;
310 }
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200311 ret->value_str = val_str;
312 ret->value_type = type;
313
314 return (struct lyd_node *)ret;
315}
316
317API struct lyd_node *
318lyd_new_leaf_str(struct lyd_node *parent, struct lys_module *module, const char *name, LY_DATA_TYPE type,
319 const char *val_str)
320{
321 struct lyd_node_leaf_list *ret;
322 struct lys_node *snode = NULL, *siblings;
323 struct lys_type *stype, *utype;
324 int found;
325
326 if ((!parent && !module) || !name) {
327 ly_errno = LY_EINVAL;
328 return NULL;
329 }
330
331 if (!parent) {
332 siblings = module->data;
333 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200334 if (!parent->schema) {
335 return NULL;
336 }
337 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200338 }
339
340 if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_LEAFLIST | LYS_LEAF, &snode)
341 || !snode) {
342 return NULL;
343 }
344
345 ret = calloc(1, sizeof *ret);
346 ret->schema = snode;
347 ret->prev = (struct lyd_node *)ret;
348 if (parent) {
349 if (lyd_insert(parent, (struct lyd_node *)ret, 0)) {
350 free(ret);
351 return NULL;
352 }
353 }
354 ret->value_str = val_str;
355 ret->value_type = type;
356
357 /* get the correct type struct */
358 stype = &((struct lys_node_leaf *)snode)->type;
359 if (stype->base == LY_TYPE_UNION) {
360 found = 0;
361 utype = stype;
362 stype = lyp_get_next_union_type(utype, NULL, &found);
363 while (stype && (stype->base != type)) {
364 found = 0;
365 stype = lyp_get_next_union_type(utype, stype, &found);
366 }
367 if (!stype) {
368 free(ret);
369 return NULL;
370 }
371 }
372
373 if (lyp_parse_value(ret, stype, 1, NULL, 0)) {
374 free(ret);
375 return NULL;
376 }
377
378 return (struct lyd_node *)ret;
379
380}
381
382API struct lyd_node *
383lyd_new_anyxml(struct lyd_node *parent, struct lys_module *module, const char *name, const char *val_xml)
384{
Michal Vasko587998f2015-09-29 16:07:53 +0200385 struct lyd_node_anyxml *ret;
386 struct lys_node *siblings, *snode;
387 struct lyxml_elem *root, *first_child, *last_child, *child;
388 struct ly_ctx *ctx;
389 char *xml;
390
391 if ((!parent && !module) || !name || !val_xml) {
392 ly_errno = LY_EINVAL;
393 return NULL;
394 }
395
396 if (!parent) {
397 siblings = module->data;
398 ctx = module->ctx;
399 } else {
400 if (!parent->schema) {
401 return NULL;
402 }
403 siblings = parent->schema->child;
404 ctx = parent->schema->module->ctx;
405 }
406
407 if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_ANYXML, &snode)
408 || !snode) {
409 return NULL;
410 }
411
412 ret = calloc(1, sizeof *ret);
413 ret->schema = snode;
414 ret->prev = (struct lyd_node *)ret;
415 if (parent) {
416 if (lyd_insert(parent, (struct lyd_node *)ret, 0)) {
417 free(ret);
418 return NULL;
419 }
420 }
421
422 /* add fake root so we can parse the data */
423 asprintf(&xml, "<root>%s</root>", val_xml);
424 root = lyxml_read(ctx, xml, 0);
Radek Krejcie4e4d722015-10-05 16:53:50 +0200425 /* TODO: check return value */
Michal Vasko587998f2015-09-29 16:07:53 +0200426 free(xml);
427
428 /* remove the root */
Radek Krejcie4e4d722015-10-05 16:53:50 +0200429 first_child = last_child = NULL;
Michal Vasko587998f2015-09-29 16:07:53 +0200430 LY_TREE_FOR(root->child, child) {
431 lyxml_unlink_elem(ctx, child, 1);
432 if (!first_child) {
433 first_child = child;
434 last_child = child;
435 } else {
436 last_child->next = child;
437 child->prev = last_child;
438 last_child = child;
439 }
440 }
Radek Krejcie4e4d722015-10-05 16:53:50 +0200441 if (first_child) {
442 first_child->prev = last_child;
443 }
Michal Vasko587998f2015-09-29 16:07:53 +0200444 lyxml_free_elem(ctx, root);
445
446 ret->value = first_child;
447
448 return (struct lyd_node *)ret;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200449}
450
Michal Vasko2d162e12015-09-24 14:33:29 +0200451API int
452lyd_insert(struct lyd_node *parent, struct lyd_node *node, int options)
453{
454 struct lys_node *sparent;
455 struct lyd_node *iter, *next, *last;
456
457 if (!node || !parent) {
458 ly_errno = LY_EINVAL;
459 return EXIT_FAILURE;
460 }
461
462 if (node->parent || node->prev->next) {
463 lyd_unlink(node);
464 }
465
466 /* check placing the node to the appropriate place according to the schema */
467 sparent = node->schema->parent;
468 while (!(sparent->nodetype & (LYS_CONTAINER | LYS_LIST))) {
469 sparent = sparent->parent;
470 }
471 if (sparent != parent->schema) {
472 ly_errno = LY_EINVAL;
473 return EXIT_FAILURE;
474 }
475
476 if (!parent->child) {
477 /* add as the only child of the parent */
478 parent->child = node;
479 } else {
480 /* add as the last child of the parent */
481 parent->child->prev->next = node;
482 node->prev = parent->child->prev;
483 for (iter = node; iter->next; iter = iter->next);
484 parent->child->prev = iter;
485 }
486 LY_TREE_FOR(node, iter) {
487 iter->parent = parent;
488 last = iter; /* remember the last of the inserted nodes */
489 }
490
491 ly_errno = 0;
492 LY_TREE_FOR_SAFE(node, next, iter) {
493 /* various validation checks */
Michal Vaskocf024702015-10-08 15:01:42 +0200494 if (lyv_data_content(iter, 0, options, NULL)) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200495 if (ly_errno) {
496 return EXIT_FAILURE;
497 } else {
498 lyd_free(iter);
499 }
500 }
501
502 if (iter == last) {
503 /* we are done - checking only the inserted nodes */
504 break;
505 }
506 }
507
508 return EXIT_SUCCESS;
509}
510
511API int
512lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node, int options)
513{
514 struct lys_node *par1, *par2;
515 struct lyd_node *iter, *next, *last;
516
517 if (!node || !sibling) {
518 ly_errno = LY_EINVAL;
519 return EXIT_FAILURE;
520 }
521
522 if (node->parent || node->prev->next) {
523 lyd_unlink(node);
524 }
525
526 /* check placing the node to the appropriate place according to the schema */
527 for (par1 = sibling->schema->parent; par1 && (par1->nodetype & (LYS_CONTAINER | LYS_LIST)); par1 = par1->parent);
528 for (par2 = node->schema->parent; par2 && (par2->nodetype & (LYS_CONTAINER | LYS_LIST)); par2 = par2->parent);
529 if (par1 != par2) {
530 ly_errno = LY_EINVAL;
531 return EXIT_FAILURE;
532 }
533
534 LY_TREE_FOR(node, iter) {
535 iter->parent = sibling->parent;
536 last = iter; /* remember the last of the inserted nodes */
537 }
538
539 if (sibling->next) {
540 /* adding into a middle - fix the prev pointer of the node after inserted nodes */
541 last->next = sibling->next;
542 sibling->next->prev = last;
543 } else {
544 /* at the end - fix the prev pointer of the first node */
545 if (sibling->parent) {
546 sibling->parent->child->prev = last;
547 } else {
548 for (iter = sibling; iter->prev->next; iter = iter->prev);
549 iter->prev = last;
550 }
551 }
552 sibling->next = node;
553 node->prev = sibling;
554
555 ly_errno = 0;
556 LY_TREE_FOR_SAFE(node, next, iter) {
557 /* various validation checks */
Michal Vaskocf024702015-10-08 15:01:42 +0200558 if (lyv_data_content(iter, 0, options, NULL)) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200559 if (ly_errno) {
560 return EXIT_FAILURE;
561 } else {
562 lyd_free(iter);
563 }
564 }
565
566 if (iter == last) {
567 /* we are done - checking only the inserted nodes */
568 break;
569 }
570 }
571
572 return EXIT_SUCCESS;
573}
574
575API int
576lyd_unlink(struct lyd_node *node)
577{
578 struct lyd_node *iter;
579
580 if (!node) {
581 ly_errno = LY_EINVAL;
582 return EXIT_FAILURE;
583 }
584
585 /* unlink from siblings */
586 if (node->prev->next) {
587 node->prev->next = node->next;
588 }
589 if (node->next) {
590 node->next->prev = node->prev;
591 } else {
592 /* unlinking the last node */
593 iter = node->prev;
594 while (iter->prev != node) {
595 iter = iter->prev;
596 }
597 /* update the "last" pointer from the first node */
598 iter->prev = node->prev;
599 }
600
601 /* unlink from parent */
602 if (node->parent) {
603 if (node->parent->child == node) {
604 /* the node is the first child */
605 node->parent->child = node->next;
606 }
607 node->parent = NULL;
608 }
609
610 node->next = NULL;
611 node->prev = node;
612
613 return EXIT_SUCCESS;
614}
615
616static void
617lyd_attr_free(struct ly_ctx *ctx, struct lyd_attr *attr)
618{
619 if (!attr) {
620 return;
621 }
622
623 if (attr->next) {
624 lyd_attr_free(ctx, attr->next);
625 }
626 lydict_remove(ctx, attr->name);
627 lydict_remove(ctx, attr->value);
628 free(attr);
629}
630
Michal Vaskofd76bd12015-09-24 15:49:57 +0200631struct lyd_node *
632lyd_attr_parent(struct lyd_node *root, struct lyd_attr *attr)
633{
634 struct lyd_node *next, *elem;
635 struct lyd_attr *node_attr;
636
637 LY_TREE_DFS_BEGIN(root, next, elem) {
638 for (node_attr = elem->attr; node_attr; node_attr = node_attr->next) {
639 if (node_attr == attr) {
640 return elem;
641 }
642 }
643 LY_TREE_DFS_END(root, next, elem)
644 }
645
646 return NULL;
647}
648
Michal Vasko2d162e12015-09-24 14:33:29 +0200649API void
650lyd_free(struct lyd_node *node)
651{
652 struct lyd_node *next, *child;
653
654 if (!node) {
655 return;
656 }
657
658 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
659 /* free children */
660 LY_TREE_FOR_SAFE(node->child, next, child) {
661 lyd_free(child);
662 }
663 } else if (node->schema->nodetype == LYS_ANYXML) {
664 lyxml_free_elem(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
665 } else {
666 /* free value */
Michal Vasko4c183312015-09-25 10:41:47 +0200667 switch(((struct lyd_node_leaf_list *)node)->value_type) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200668 case LY_TYPE_BINARY:
669 case LY_TYPE_STRING:
Michal Vasko4c183312015-09-25 10:41:47 +0200670 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf_list *)node)->value.string);
Michal Vasko2d162e12015-09-24 14:33:29 +0200671 break;
672 case LY_TYPE_BITS:
Michal Vasko4c183312015-09-25 10:41:47 +0200673 if (((struct lyd_node_leaf_list *)node)->value.bit) {
674 free(((struct lyd_node_leaf_list *)node)->value.bit);
Michal Vasko2d162e12015-09-24 14:33:29 +0200675 }
676 break;
677 default:
678 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
679 break;
680 }
681 }
682
683 lyd_unlink(node);
684 lyd_attr_free(node->schema->module->ctx, node->attr);
685 free(node);
686}
687
688int
689lyd_compare(struct lyd_node *first, struct lyd_node *second, int unique)
690{
691 struct lys_node_list *slist;
692 struct lys_node *snode;
693 struct lyd_node *diter;
694 const char *val1, *val2;
695 int i, j;
696
697 assert(first);
698 assert(second);
699
700 if (first->schema != second->schema) {
701 return 1;
702 }
703
704 switch (first->schema->nodetype) {
705 case LYS_LEAFLIST:
706 /* compare values */
Michal Vasko4c183312015-09-25 10:41:47 +0200707 if (((struct lyd_node_leaf_list *)first)->value_str == ((struct lyd_node_leaf_list *)second)->value_str) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200708 return 0;
709 }
710 return 1;
711 case LYS_LIST:
Michal Vasko4c183312015-09-25 10:41:47 +0200712 slist = (struct lys_node_list *)first->schema;
Michal Vasko2d162e12015-09-24 14:33:29 +0200713
714 if (unique) {
715 /* compare unique leafs */
716 for (i = 0; i < slist->unique_size; i++) {
717 for (j = 0; j < slist->unique[i].leafs_size; j++) {
718 snode = (struct lys_node *)slist->unique[i].leafs[j];
719 /* use default values if the instances of unique leafs are not present */
720 val1 = val2 = ((struct lys_node_leaf *)snode)->dflt;
721 LY_TREE_FOR(first->child, diter) {
722 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200723 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200724 break;
725 }
726 }
727 LY_TREE_FOR(second->child, diter) {
728 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200729 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200730 break;
731 }
732 }
733 if (val1 != val2) {
734 break;
735 }
736 }
737 if (j && j == slist->unique[i].leafs_size) {
738 /* all unique leafs are the same in this set */
739 return 0;
740 }
741 }
742 }
743
744 /* compare keys */
745 for (i = 0; i < slist->keys_size; i++) {
746 snode = (struct lys_node *)slist->keys[i];
747 val1 = val2 = NULL;
748 LY_TREE_FOR(first->child, diter) {
749 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200750 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200751 break;
752 }
753 }
754 LY_TREE_FOR(second->child, diter) {
755 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200756 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200757 break;
758 }
759 }
760 if (val1 != val2) {
761 return 1;
762 }
763 }
764
765 return 0;
766 default:
767 /* no additional check is needed */
768 return 0;
769 }
770}
771
772API struct lyd_set *
773lyd_set_new(void)
774{
775 return calloc(1, sizeof(struct lyd_set));
776}
777
778API void
779lyd_set_free(struct lyd_set *set)
780{
781 if (!set) {
782 return;
783 }
784
785 free(set->set);
786 free(set);
787}
788
789API int
790lyd_set_add(struct lyd_set *set, struct lyd_node *node)
791{
792 struct lyd_node **new;
793
794 if (!set) {
795 ly_errno = LY_EINVAL;
796 return EXIT_FAILURE;
797 }
798
799 if (set->size == set->number) {
800 new = realloc(set->set, (set->size + 8) * sizeof *(set->set));
801 if (!new) {
802 LOGMEM;
803 return EXIT_FAILURE;
804 }
805 set->size += 8;
806 set->set = new;
807 }
808
809 set->set[set->number++] = node;
810
811 return EXIT_SUCCESS;
812}