blob: 42836225c6ea05dc6ff023808f2787ece687ffce [file] [log] [blame]
Michal Vasko2d162e12015-09-24 14:33:29 +02001/**
2 * @file tree_data.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#define _GNU_SOURCE
22
23#include <assert.h>
24#include <ctype.h>
25#include <stdlib.h>
26#include <sys/mman.h>
27#include <sys/stat.h>
28#include <string.h>
29
30#include "common.h"
31#include "context.h"
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020032#include "tree_data.h"
Michal Vasko2d162e12015-09-24 14:33:29 +020033#include "parser.h"
34#include "resolve.h"
35#include "xml.h"
36#include "tree_internal.h"
37#include "validation.h"
38
39API struct lyd_node *
40lyd_parse(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
41{
42 if (!ctx || !data) {
43 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
44 return NULL;
45 }
46
47 switch (format) {
48 case LYD_XML:
49 return xml_read_data(ctx, data, options);
50 case LYD_JSON:
51 default:
52 /* TODO */
53 return NULL;
54 }
55
56 return NULL;
57}
58
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020059API struct lyd_node *
60lyd_new(struct lyd_node *parent, struct lys_module *module, const char *name)
61{
62 struct lyd_node *ret;
63 struct lys_node *snode = NULL, *siblings;
64
65 if ((!parent && !module) || !name) {
66 ly_errno = LY_EINVAL;
67 return NULL;
68 }
69
70 if (!parent) {
71 siblings = module->data;
72 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +020073 if (!parent->schema) {
74 return NULL;
75 }
76 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020077 }
78
79 if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_CONTAINER | LYS_INPUT | LYS_OUTPUT
80 | LYS_NOTIF | LYS_RPC, &snode) || !snode) {
81 return NULL;
82 }
83
84 ret = calloc(1, sizeof *ret);
85 ret->schema = snode;
86 ret->prev = ret;
87 if (parent) {
88 if (lyd_insert(parent, ret, 0)) {
89 free(ret);
90 return NULL;
91 }
92 }
93
94 return ret;
95}
96
97API struct lyd_node *
98lyd_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 +020099 lyd_val value)
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200100{
101 struct lyd_node_leaf_list *ret;
102 struct lys_node *snode = NULL, *siblings;
103 struct lys_type *stype;
104 struct lys_module *src_mod, *dst_mod;
105 char *val_str = NULL, str_num[22];
106 const char *prefix;
107 int i, str_len = 0, prev_len;
108 uint64_t exp;
109
Michal Vasko0e3c8722015-09-29 16:06:08 +0200110 if ((!parent && !module) || !name) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200111 ly_errno = LY_EINVAL;
112 return NULL;
113 }
114
115 if (!parent) {
116 siblings = module->data;
117 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200118 if (!parent->schema) {
119 return NULL;
120 }
121 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200122 }
123
124 if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_LEAFLIST | LYS_LEAF, &snode)
125 || !snode) {
126 return NULL;
127 }
128
129 switch (type) {
130 case LY_TYPE_BINARY:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200131 val_str = (char *)lydict_insert(snode->module->ctx, value.binary, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200132 break;
133
134 case LY_TYPE_BITS:
135 /* find the type definition */
136 for (stype = &((struct lys_node_leaf *)snode)->type; stype->der->module; stype = &stype->der->type) {
137 if (stype->base != LY_TYPE_BITS) {
138 LOGINT;
139 return NULL;
140 }
141 }
142
143 /* concatenate set bits */
144 for (i = 0; i < stype->info.bits.count; ++i) {
Michal Vasko0e3c8722015-09-29 16:06:08 +0200145 if (!value.bit[i]) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200146 continue;
147 }
148
149 prev_len = str_len;
Michal Vasko0e3c8722015-09-29 16:06:08 +0200150 str_len += strlen(value.bit[i]->name) + 1;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200151 val_str = realloc((char *)val_str, str_len * sizeof(char));
152
153 if (prev_len) {
154 val_str[prev_len] = ' ';
155 ++prev_len;
156 }
Michal Vasko0e3c8722015-09-29 16:06:08 +0200157 strcpy(val_str + prev_len, value.bit[i]->name);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200158 }
159
160 val_str = (char *)lydict_insert_zc(snode->module->ctx, val_str);
161 break;
162
163 case LY_TYPE_BOOL:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200164 if (value.bool) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200165 val_str = (char *)lydict_insert(snode->module->ctx, "true", 4);
166 } else {
167 val_str = (char *)lydict_insert(snode->module->ctx, "false", 5);
168 }
169 break;
170
171 case LY_TYPE_DEC64:
172 /* find the type definition */
173 for (stype = &((struct lys_node_leaf *)snode)->type; stype->der->module; stype = &stype->der->type) {
174 if (stype->base != LY_TYPE_DEC64) {
175 LOGINT;
176 return NULL;
177 }
178 }
179
180 for (i = 0, exp = 1; i < stype->info.dec64.dig; ++i, exp *= 10);
Michal Vasko0e3c8722015-09-29 16:06:08 +0200181 sprintf(str_num, "%01.1Lf", ((long double)value.dec64) / exp);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200182 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
183 break;
184
185 case LY_TYPE_EMPTY:
186 break;
187
188 case LY_TYPE_ENUM:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200189 val_str = (char *)lydict_insert(snode->module->ctx, value.enm->name, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200190 break;
191
192 case LY_TYPE_IDENT:
193 /* TODO move to function if used somewhere else (module -> import prefix) */
Michal Vasko0e3c8722015-09-29 16:06:08 +0200194 src_mod = value.ident->module;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200195 if (src_mod->type) {
196 src_mod = ((struct lys_submodule *)src_mod)->belongsto;
197 }
198 dst_mod = snode->module;
199 if (dst_mod->type) {
200 dst_mod = ((struct lys_submodule *)dst_mod)->belongsto;
201 }
202 if (src_mod != dst_mod) {
203 for (i = 0; i < src_mod->imp_size; ++i) {
204 if (src_mod->imp[i].module == dst_mod) {
205 prefix = src_mod->imp[i].prefix;
206 break;
207 }
208 }
209 if (!prefix) {
210 LOGINT;
211 return NULL;
212 }
213 } else {
214 prefix = NULL;
215 }
216
217 if (!prefix) {
Michal Vasko0e3c8722015-09-29 16:06:08 +0200218 val_str = (char *)lydict_insert(snode->module->ctx, value.ident->name, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200219 } else {
Michal Vasko0e3c8722015-09-29 16:06:08 +0200220 val_str = malloc((strlen(prefix) + 1 + strlen(value.ident->name) + 1) * sizeof(char));
221 sprintf(val_str, "%s:%s", prefix, value.ident->name);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200222 val_str = (char *)lydict_insert_zc(snode->module->ctx, val_str);
223 }
224 break;
225
226 case LY_TYPE_INST:
227 /* TODO */
228 break;
229
230 case LY_TYPE_LEAFREF:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200231 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 +0200232 break;
233
234 case LY_TYPE_STRING:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200235 val_str = (char *)lydict_insert(snode->module->ctx, value.string, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200236 break;
237
238 case LY_TYPE_INT8:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200239 sprintf(str_num, "%hhd", value.int8);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200240 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
241 break;
242
243 case LY_TYPE_INT16:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200244 sprintf(str_num, "%hd", value.int16);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200245 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
246 break;
247
248 case LY_TYPE_INT32:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200249 sprintf(str_num, "%d", value.int32);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200250 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
251 break;
252
253 case LY_TYPE_INT64:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200254 sprintf(str_num, "%ld", value.int64);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200255 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
256 break;
257
258 case LY_TYPE_UINT8:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200259 sprintf(str_num, "%hhu", value.uint8);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200260 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
261 break;
262
263 case LY_TYPE_UINT16:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200264 sprintf(str_num, "%hu", value.uint16);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200265 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
266 break;
267
268 case LY_TYPE_UINT32:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200269 sprintf(str_num, "%u", value.uint32);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200270 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
271 break;
272
273 case LY_TYPE_UINT64:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200274 sprintf(str_num, "%lu", value.uint64);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200275 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
276 break;
277
278 default:
279 LOGINT;
280 return NULL;
281 }
282
283 ret = calloc(1, sizeof *ret);
284 ret->schema = snode;
285 ret->prev = (struct lyd_node *)ret;
286 if (parent) {
287 if (lyd_insert(parent, (struct lyd_node *)ret, 0)) {
288 free(ret);
289 lydict_remove(snode->module->ctx, val_str);
290 return NULL;
291 }
292 }
Michal Vasko0e3c8722015-09-29 16:06:08 +0200293 ret->value = value;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200294 ret->value_str = val_str;
295 ret->value_type = type;
296
297 return (struct lyd_node *)ret;
298}
299
300API struct lyd_node *
301lyd_new_leaf_str(struct lyd_node *parent, struct lys_module *module, const char *name, LY_DATA_TYPE type,
302 const char *val_str)
303{
304 struct lyd_node_leaf_list *ret;
305 struct lys_node *snode = NULL, *siblings;
306 struct lys_type *stype, *utype;
307 int found;
308
309 if ((!parent && !module) || !name) {
310 ly_errno = LY_EINVAL;
311 return NULL;
312 }
313
314 if (!parent) {
315 siblings = module->data;
316 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200317 if (!parent->schema) {
318 return NULL;
319 }
320 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200321 }
322
323 if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_LEAFLIST | LYS_LEAF, &snode)
324 || !snode) {
325 return NULL;
326 }
327
328 ret = calloc(1, sizeof *ret);
329 ret->schema = snode;
330 ret->prev = (struct lyd_node *)ret;
331 if (parent) {
332 if (lyd_insert(parent, (struct lyd_node *)ret, 0)) {
333 free(ret);
334 return NULL;
335 }
336 }
337 ret->value_str = val_str;
338 ret->value_type = type;
339
340 /* get the correct type struct */
341 stype = &((struct lys_node_leaf *)snode)->type;
342 if (stype->base == LY_TYPE_UNION) {
343 found = 0;
344 utype = stype;
345 stype = lyp_get_next_union_type(utype, NULL, &found);
346 while (stype && (stype->base != type)) {
347 found = 0;
348 stype = lyp_get_next_union_type(utype, stype, &found);
349 }
350 if (!stype) {
351 free(ret);
352 return NULL;
353 }
354 }
355
356 if (lyp_parse_value(ret, stype, 1, NULL, 0)) {
357 free(ret);
358 return NULL;
359 }
360
361 return (struct lyd_node *)ret;
362
363}
364
365API struct lyd_node *
366lyd_new_anyxml(struct lyd_node *parent, struct lys_module *module, const char *name, const char *val_xml)
367{
368 /* TODO */
369 return NULL;
370}
371
Michal Vasko2d162e12015-09-24 14:33:29 +0200372API int
373lyd_insert(struct lyd_node *parent, struct lyd_node *node, int options)
374{
375 struct lys_node *sparent;
376 struct lyd_node *iter, *next, *last;
377
378 if (!node || !parent) {
379 ly_errno = LY_EINVAL;
380 return EXIT_FAILURE;
381 }
382
383 if (node->parent || node->prev->next) {
384 lyd_unlink(node);
385 }
386
387 /* check placing the node to the appropriate place according to the schema */
388 sparent = node->schema->parent;
389 while (!(sparent->nodetype & (LYS_CONTAINER | LYS_LIST))) {
390 sparent = sparent->parent;
391 }
392 if (sparent != parent->schema) {
393 ly_errno = LY_EINVAL;
394 return EXIT_FAILURE;
395 }
396
397 if (!parent->child) {
398 /* add as the only child of the parent */
399 parent->child = node;
400 } else {
401 /* add as the last child of the parent */
402 parent->child->prev->next = node;
403 node->prev = parent->child->prev;
404 for (iter = node; iter->next; iter = iter->next);
405 parent->child->prev = iter;
406 }
407 LY_TREE_FOR(node, iter) {
408 iter->parent = parent;
409 last = iter; /* remember the last of the inserted nodes */
410 }
411
412 ly_errno = 0;
413 LY_TREE_FOR_SAFE(node, next, iter) {
414 /* various validation checks */
415 if (lyv_data_content(iter, 0, options)) {
416 if (ly_errno) {
417 return EXIT_FAILURE;
418 } else {
419 lyd_free(iter);
420 }
421 }
422
423 if (iter == last) {
424 /* we are done - checking only the inserted nodes */
425 break;
426 }
427 }
428
429 return EXIT_SUCCESS;
430}
431
432API int
433lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node, int options)
434{
435 struct lys_node *par1, *par2;
436 struct lyd_node *iter, *next, *last;
437
438 if (!node || !sibling) {
439 ly_errno = LY_EINVAL;
440 return EXIT_FAILURE;
441 }
442
443 if (node->parent || node->prev->next) {
444 lyd_unlink(node);
445 }
446
447 /* check placing the node to the appropriate place according to the schema */
448 for (par1 = sibling->schema->parent; par1 && (par1->nodetype & (LYS_CONTAINER | LYS_LIST)); par1 = par1->parent);
449 for (par2 = node->schema->parent; par2 && (par2->nodetype & (LYS_CONTAINER | LYS_LIST)); par2 = par2->parent);
450 if (par1 != par2) {
451 ly_errno = LY_EINVAL;
452 return EXIT_FAILURE;
453 }
454
455 LY_TREE_FOR(node, iter) {
456 iter->parent = sibling->parent;
457 last = iter; /* remember the last of the inserted nodes */
458 }
459
460 if (sibling->next) {
461 /* adding into a middle - fix the prev pointer of the node after inserted nodes */
462 last->next = sibling->next;
463 sibling->next->prev = last;
464 } else {
465 /* at the end - fix the prev pointer of the first node */
466 if (sibling->parent) {
467 sibling->parent->child->prev = last;
468 } else {
469 for (iter = sibling; iter->prev->next; iter = iter->prev);
470 iter->prev = last;
471 }
472 }
473 sibling->next = node;
474 node->prev = sibling;
475
476 ly_errno = 0;
477 LY_TREE_FOR_SAFE(node, next, iter) {
478 /* various validation checks */
479 if (lyv_data_content(iter, 0, options)) {
480 if (ly_errno) {
481 return EXIT_FAILURE;
482 } else {
483 lyd_free(iter);
484 }
485 }
486
487 if (iter == last) {
488 /* we are done - checking only the inserted nodes */
489 break;
490 }
491 }
492
493 return EXIT_SUCCESS;
494}
495
496API int
497lyd_unlink(struct lyd_node *node)
498{
499 struct lyd_node *iter;
500
501 if (!node) {
502 ly_errno = LY_EINVAL;
503 return EXIT_FAILURE;
504 }
505
506 /* unlink from siblings */
507 if (node->prev->next) {
508 node->prev->next = node->next;
509 }
510 if (node->next) {
511 node->next->prev = node->prev;
512 } else {
513 /* unlinking the last node */
514 iter = node->prev;
515 while (iter->prev != node) {
516 iter = iter->prev;
517 }
518 /* update the "last" pointer from the first node */
519 iter->prev = node->prev;
520 }
521
522 /* unlink from parent */
523 if (node->parent) {
524 if (node->parent->child == node) {
525 /* the node is the first child */
526 node->parent->child = node->next;
527 }
528 node->parent = NULL;
529 }
530
531 node->next = NULL;
532 node->prev = node;
533
534 return EXIT_SUCCESS;
535}
536
537static void
538lyd_attr_free(struct ly_ctx *ctx, struct lyd_attr *attr)
539{
540 if (!attr) {
541 return;
542 }
543
544 if (attr->next) {
545 lyd_attr_free(ctx, attr->next);
546 }
547 lydict_remove(ctx, attr->name);
548 lydict_remove(ctx, attr->value);
549 free(attr);
550}
551
552API void
553lyd_free(struct lyd_node *node)
554{
555 struct lyd_node *next, *child;
556
557 if (!node) {
558 return;
559 }
560
561 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
562 /* free children */
563 LY_TREE_FOR_SAFE(node->child, next, child) {
564 lyd_free(child);
565 }
566 } else if (node->schema->nodetype == LYS_ANYXML) {
567 lyxml_free_elem(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
568 } else {
569 /* free value */
Michal Vasko4c183312015-09-25 10:41:47 +0200570 switch(((struct lyd_node_leaf_list *)node)->value_type) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200571 case LY_TYPE_BINARY:
572 case LY_TYPE_STRING:
Michal Vasko4c183312015-09-25 10:41:47 +0200573 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf_list *)node)->value.string);
Michal Vasko2d162e12015-09-24 14:33:29 +0200574 break;
575 case LY_TYPE_BITS:
Michal Vasko4c183312015-09-25 10:41:47 +0200576 if (((struct lyd_node_leaf_list *)node)->value.bit) {
577 free(((struct lyd_node_leaf_list *)node)->value.bit);
Michal Vasko2d162e12015-09-24 14:33:29 +0200578 }
579 break;
580 default:
581 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
582 break;
583 }
Michal Vasko0ff62832015-09-25 11:09:44 +0200584
585 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf_list *)node)->value_str);
Michal Vasko2d162e12015-09-24 14:33:29 +0200586 }
587
588 lyd_unlink(node);
589 lyd_attr_free(node->schema->module->ctx, node->attr);
590 free(node);
591}
592
593int
594lyd_compare(struct lyd_node *first, struct lyd_node *second, int unique)
595{
596 struct lys_node_list *slist;
597 struct lys_node *snode;
598 struct lyd_node *diter;
599 const char *val1, *val2;
600 int i, j;
601
602 assert(first);
603 assert(second);
604
605 if (first->schema != second->schema) {
606 return 1;
607 }
608
609 switch (first->schema->nodetype) {
610 case LYS_LEAFLIST:
611 /* compare values */
Michal Vasko4c183312015-09-25 10:41:47 +0200612 if (((struct lyd_node_leaf_list *)first)->value_str == ((struct lyd_node_leaf_list *)second)->value_str) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200613 return 0;
614 }
615 return 1;
616 case LYS_LIST:
Michal Vasko4c183312015-09-25 10:41:47 +0200617 slist = (struct lys_node_list *)first->schema;
Michal Vasko2d162e12015-09-24 14:33:29 +0200618
619 if (unique) {
620 /* compare unique leafs */
621 for (i = 0; i < slist->unique_size; i++) {
622 for (j = 0; j < slist->unique[i].leafs_size; j++) {
623 snode = (struct lys_node *)slist->unique[i].leafs[j];
624 /* use default values if the instances of unique leafs are not present */
625 val1 = val2 = ((struct lys_node_leaf *)snode)->dflt;
626 LY_TREE_FOR(first->child, diter) {
627 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200628 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200629 break;
630 }
631 }
632 LY_TREE_FOR(second->child, diter) {
633 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200634 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200635 break;
636 }
637 }
638 if (val1 != val2) {
639 break;
640 }
641 }
642 if (j && j == slist->unique[i].leafs_size) {
643 /* all unique leafs are the same in this set */
644 return 0;
645 }
646 }
647 }
648
649 /* compare keys */
650 for (i = 0; i < slist->keys_size; i++) {
651 snode = (struct lys_node *)slist->keys[i];
652 val1 = val2 = NULL;
653 LY_TREE_FOR(first->child, diter) {
654 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200655 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200656 break;
657 }
658 }
659 LY_TREE_FOR(second->child, diter) {
660 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200661 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200662 break;
663 }
664 }
665 if (val1 != val2) {
666 return 1;
667 }
668 }
669
670 return 0;
671 default:
672 /* no additional check is needed */
673 return 0;
674 }
675}
676
677API struct lyd_set *
678lyd_set_new(void)
679{
680 return calloc(1, sizeof(struct lyd_set));
681}
682
683API void
684lyd_set_free(struct lyd_set *set)
685{
686 if (!set) {
687 return;
688 }
689
690 free(set->set);
691 free(set);
692}
693
694API int
695lyd_set_add(struct lyd_set *set, struct lyd_node *node)
696{
697 struct lyd_node **new;
698
699 if (!set) {
700 ly_errno = LY_EINVAL;
701 return EXIT_FAILURE;
702 }
703
704 if (set->size == set->number) {
705 new = realloc(set->set, (set->size + 8) * sizeof *(set->set));
706 if (!new) {
707 LOGMEM;
708 return EXIT_FAILURE;
709 }
710 set->size += 8;
711 set->set = new;
712 }
713
714 set->set[set->number++] = node;
715
716 return EXIT_SUCCESS;
717}