blob: 8e138478656269d83c0aae4ae236c80fa79d63ce [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
Michal Vaskoff4c2832015-10-15 13:30:50 +020023#define _XOPEN_SOURCE 700
Michal Vasko2d162e12015-09-24 14:33:29 +020024
25#include <assert.h>
26#include <ctype.h>
Michal Vasko3e671b52015-10-23 16:23:15 +020027#include <limits.h>
Radek Krejci4a49bdf2016-01-12 17:17:01 +010028#include <stdarg.h>
Michal Vasko2d162e12015-09-24 14:33:29 +020029#include <stdlib.h>
Michal Vasko662610a2015-12-07 11:25:45 +010030#include <sys/types.h>
Michal Vasko2d162e12015-09-24 14:33:29 +020031#include <sys/mman.h>
32#include <sys/stat.h>
Michal Vasko662610a2015-12-07 11:25:45 +010033#include <fcntl.h>
34#include <unistd.h>
Michal Vasko2d162e12015-09-24 14:33:29 +020035#include <string.h>
Michal Vasko662610a2015-12-07 11:25:45 +010036#include <errno.h>
Michal Vasko2d162e12015-09-24 14:33:29 +020037
Michal Vasko662610a2015-12-07 11:25:45 +010038#include "libyang.h"
Michal Vasko2d162e12015-09-24 14:33:29 +020039#include "common.h"
40#include "context.h"
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020041#include "tree_data.h"
Michal Vasko2d162e12015-09-24 14:33:29 +020042#include "parser.h"
43#include "resolve.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020044#include "xml_internal.h"
Michal Vasko2d162e12015-09-24 14:33:29 +020045#include "tree_internal.h"
46#include "validation.h"
47
Michal Vasko36ef6932015-12-01 14:30:17 +010048static struct lyd_node *
49lyd_parse_(struct ly_ctx *ctx, const struct lys_node *parent, const char *data, LYD_FORMAT format, int options)
Michal Vasko2d162e12015-09-24 14:33:29 +020050{
Radek Krejci5974c1f2015-10-09 09:53:24 +020051 struct lyxml_elem *xml;
52 struct lyd_node *result = NULL;
Radek Krejci86538212015-12-17 15:59:01 +010053 int xmlopt = LYXML_READ_MULTIROOT;
Radek Krejci5974c1f2015-10-09 09:53:24 +020054
Michal Vasko2d162e12015-09-24 14:33:29 +020055 if (!ctx || !data) {
56 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
57 return NULL;
58 }
59
Radek Krejci86538212015-12-17 15:59:01 +010060 if (options & LYD_OPT_NOSIBLINGS) {
61 xmlopt = 0;
62 }
63
Michal Vasko2d162e12015-09-24 14:33:29 +020064 switch (format) {
65 case LYD_XML:
Radek Krejci452fb952015-10-02 16:07:46 +020066 case LYD_XML_FORMAT:
Radek Krejci86538212015-12-17 15:59:01 +010067 xml = lyxml_read_data(ctx, data, xmlopt);
Radek Krejci4a49bdf2016-01-12 17:17:01 +010068 result = lyd_parse_xml(ctx, &xml, options, parent);
Michal Vasko345da0a2015-12-02 10:35:55 +010069 lyxml_free(ctx, xml);
Radek Krejci5974c1f2015-10-09 09:53:24 +020070 break;
Michal Vasko2d162e12015-09-24 14:33:29 +020071 case LYD_JSON:
Michal Vasko36ef6932015-12-01 14:30:17 +010072 result = lyd_parse_json(ctx, parent, data, options);
Radek Krejci5449d472015-10-26 14:35:56 +010073 break;
Michal Vasko2d162e12015-09-24 14:33:29 +020074 default:
Radek Krejci5449d472015-10-26 14:35:56 +010075 /* error */
Michal Vasko2d162e12015-09-24 14:33:29 +020076 return NULL;
77 }
78
Radek Krejci5974c1f2015-10-09 09:53:24 +020079 return result;
Michal Vasko2d162e12015-09-24 14:33:29 +020080}
81
Radek Krejci4a49bdf2016-01-12 17:17:01 +010082static struct lyd_node *
83lyd_parse_data_(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options, va_list ap)
Michal Vasko36ef6932015-12-01 14:30:17 +010084{
Radek Krejci4a49bdf2016-01-12 17:17:01 +010085 const struct lys_node *rpc = NULL;
86
87 if (lyp_check_options(options)) {
88 LOGERR(LY_EINVAL, "%s: Invalid options (multiple data type flags set).", __func__);
89 return NULL;
90 }
91
92 if (options & LYD_OPT_RPCREPLY) {
93 rpc = va_arg(ap, struct lys_node*);
94 if (!rpc || (rpc->nodetype != LYS_RPC)) {
95 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
96 return NULL;
97 }
98 }
99
100 return lyd_parse_(ctx, rpc, data, format, options);
Michal Vasko36ef6932015-12-01 14:30:17 +0100101}
102
103API struct lyd_node *
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100104lyd_parse_data(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options, ...)
105{
106 va_list ap;
107 struct lyd_node *result;
108
109 va_start(ap, options);
110 result = lyd_parse_data_(ctx, data, format, options, ap);
111 va_end(ap);
112
113 return result;
114}
115
116API struct lyd_node *
117lyd_parse_fd(struct ly_ctx *ctx, int fd, LYD_FORMAT format, int options, ...)
Michal Vasko662610a2015-12-07 11:25:45 +0100118{
119 struct lyd_node *ret;
120 struct stat sb;
121 char *data;
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100122 va_list ap;
Michal Vasko662610a2015-12-07 11:25:45 +0100123
124 if (!ctx || (fd == -1)) {
125 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
126 return NULL;
127 }
128
129 if (fstat(fd, &sb) == -1) {
130 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
131 return NULL;
132 }
133
Radek Krejci3006be02015-12-17 11:24:33 +0100134 data = mmap(NULL, sb.st_size + 1, PROT_READ, MAP_PRIVATE, fd, 0);
Michal Vasko662610a2015-12-07 11:25:45 +0100135 if (data == MAP_FAILED) {
136 LOGERR(LY_ESYS, "Mapping file descriptor into memory failed.");
137 return NULL;
138 }
139
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100140 va_start(ap, options);
141 ret = lyd_parse_data_(ctx, data, format, options, ap);
142
143 va_end(ap);
Michal Vasko662610a2015-12-07 11:25:45 +0100144 munmap(data, sb.st_size);
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100145
Michal Vasko662610a2015-12-07 11:25:45 +0100146 return ret;
147}
148
149API struct lyd_node *
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100150lyd_parse_path(struct ly_ctx *ctx, const char *path, LYD_FORMAT format, int options, ...)
Michal Vasko662610a2015-12-07 11:25:45 +0100151{
152 int fd;
153 struct lyd_node *ret;
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100154 va_list ap;
Michal Vasko662610a2015-12-07 11:25:45 +0100155
156 if (!ctx || !path) {
157 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
158 return NULL;
159 }
160
161 fd = open(path, O_RDONLY);
162 if (fd == -1) {
163 LOGERR(LY_ESYS, "Failed to open data file \"%s\" (%s).", path, strerror(errno));
164 return NULL;
165 }
166
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100167 va_start(ap, options);
Michal Vasko662610a2015-12-07 11:25:45 +0100168 ret = lyd_parse_fd(ctx, fd, format, options);
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100169
170 va_end(ap);
Michal Vasko662610a2015-12-07 11:25:45 +0100171 close(fd);
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100172
Michal Vasko662610a2015-12-07 11:25:45 +0100173 return ret;
174}
175
176API struct lyd_node *
Michal Vasko1e62a092015-12-01 12:27:20 +0100177lyd_new(struct lyd_node *parent, const struct lys_module *module, const char *name)
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200178{
179 struct lyd_node *ret;
Michal Vasko1e62a092015-12-01 12:27:20 +0100180 const struct lys_node *snode = NULL, *siblings;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200181
182 if ((!parent && !module) || !name) {
183 ly_errno = LY_EINVAL;
184 return NULL;
185 }
186
187 if (!parent) {
188 siblings = module->data;
189 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200190 if (!parent->schema) {
191 return NULL;
192 }
193 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200194 }
195
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200196 if (lys_get_data_sibling(module, siblings, name, LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC, &snode)
197 || !snode) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200198 return NULL;
199 }
200
201 ret = calloc(1, sizeof *ret);
Michal Vasko253035f2015-12-17 16:58:13 +0100202 if (!ret) {
203 LOGMEM;
204 return NULL;
205 }
Michal Vasko1e62a092015-12-01 12:27:20 +0100206 ret->schema = (struct lys_node *)snode;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200207 ret->prev = ret;
208 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200209 if (lyd_insert(parent, ret)) {
210 lyd_free(ret);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200211 return NULL;
212 }
213 }
214
215 return ret;
216}
217
218API struct lyd_node *
Michal Vasko1e62a092015-12-01 12:27:20 +0100219lyd_new_leaf(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str)
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200220{
221 struct lyd_node_leaf_list *ret;
Michal Vasko1e62a092015-12-01 12:27:20 +0100222 const struct lys_node *snode = NULL, *siblings;
Michal Vasko3e671b52015-10-23 16:23:15 +0200223 struct lys_type *stype, *type;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200224 int found;
225
226 if ((!parent && !module) || !name) {
227 ly_errno = LY_EINVAL;
228 return NULL;
229 }
230
231 if (!parent) {
232 siblings = module->data;
233 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200234 if (!parent->schema) {
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200235 ly_errno = LY_EINVAL;
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200236 return NULL;
237 }
238 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200239 }
240
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200241 if (lys_get_data_sibling(module, siblings, name, LYS_LEAFLIST | LYS_LEAF, &snode) || !snode) {
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200242 ly_errno = LY_EINVAL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200243 return NULL;
244 }
245
Michal Vasko3e671b52015-10-23 16:23:15 +0200246 /* create the new leaf */
247 ret = calloc(1, sizeof *ret);
Michal Vasko253035f2015-12-17 16:58:13 +0100248 if (!ret) {
249 LOGMEM;
250 return NULL;
251 }
Michal Vasko1e62a092015-12-01 12:27:20 +0100252 ret->schema = (struct lys_node *)snode;
Michal Vasko3e671b52015-10-23 16:23:15 +0200253 ret->prev = (struct lyd_node *)ret;
254 ret->value_str = lydict_insert((module ? module->ctx : parent->schema->module->ctx), val_str, 0);
255
256 /* resolve the type correctly */
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200257 stype = &((struct lys_node_leaf *)snode)->type;
258 if (stype->base == LY_TYPE_UNION) {
259 found = 0;
Radek Krejcif7388492015-10-30 16:12:53 +0100260 type = NULL;
261 while ((type = lyp_get_next_union_type(stype, type, &found))) {
Michal Vasko3e671b52015-10-23 16:23:15 +0200262 ret->value_type = type->base;
263 if (!lyp_parse_value(ret, type, 1, NULL, UINT_MAX)) {
264 /* success! */
265 break;
266 }
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200267 found = 0;
Radek Krejcif7388492015-10-30 16:12:53 +0100268 }
Michal Vasko3e671b52015-10-23 16:23:15 +0200269
270 if (!type) {
271 /* fail */
272 ly_errno = LY_EINVAL;
273 lyd_free((struct lyd_node *)ret);
274 return NULL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200275 }
Michal Vasko3e671b52015-10-23 16:23:15 +0200276 } else {
277 ret->value_type = stype->base;
278 if (lyp_parse_value(ret, stype, 1, NULL, 0)) {
279 lyd_free((struct lyd_node *)ret);
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200280 ly_errno = LY_EINVAL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200281 return NULL;
282 }
283 }
284
Michal Vasko3e671b52015-10-23 16:23:15 +0200285 /* connect to parent */
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200286 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200287 if (lyd_insert(parent, (struct lyd_node *)ret)) {
288 lyd_free((struct lyd_node *)ret);
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200289 return NULL;
290 }
291 }
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200292
293 return (struct lyd_node *)ret;
294
295}
296
297API struct lyd_node *
Michal Vasko1e62a092015-12-01 12:27:20 +0100298lyd_new_anyxml(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_xml)
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200299{
Michal Vasko587998f2015-09-29 16:07:53 +0200300 struct lyd_node_anyxml *ret;
Michal Vasko1e62a092015-12-01 12:27:20 +0100301 const struct lys_node *siblings, *snode;
Michal Vasko17cc7062015-12-10 14:31:48 +0100302 struct lyxml_elem *root;
Michal Vasko587998f2015-09-29 16:07:53 +0200303 struct ly_ctx *ctx;
304 char *xml;
305
Michal Vasko14d88772015-12-03 10:54:59 +0100306 if ((!parent && !module) || !name) {
Michal Vasko587998f2015-09-29 16:07:53 +0200307 ly_errno = LY_EINVAL;
308 return NULL;
309 }
310
311 if (!parent) {
312 siblings = module->data;
313 ctx = module->ctx;
314 } else {
315 if (!parent->schema) {
316 return NULL;
317 }
318 siblings = parent->schema->child;
319 ctx = parent->schema->module->ctx;
320 }
321
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200322 if (lys_get_data_sibling(module, siblings, name, LYS_ANYXML, &snode) || !snode) {
Michal Vasko587998f2015-09-29 16:07:53 +0200323 return NULL;
324 }
325
326 ret = calloc(1, sizeof *ret);
Michal Vasko253035f2015-12-17 16:58:13 +0100327 if (!ret) {
328 LOGMEM;
329 return NULL;
330 }
Michal Vasko1e62a092015-12-01 12:27:20 +0100331 ret->schema = (struct lys_node *)snode;
Michal Vasko587998f2015-09-29 16:07:53 +0200332 ret->prev = (struct lyd_node *)ret;
333 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200334 if (lyd_insert(parent, (struct lyd_node *)ret)) {
335 lyd_free((struct lyd_node *)ret);
Michal Vasko587998f2015-09-29 16:07:53 +0200336 return NULL;
337 }
338 }
339
Radek Krejci86538212015-12-17 15:59:01 +0100340 /* store the anyxml data together with the anyxml element */
341 asprintf(&xml, "<%s>%s</%s>", name, (val_xml ? val_xml : ""), name);
Michal Vasko17cc7062015-12-10 14:31:48 +0100342 root = lyxml_read_data(ctx, xml, 0);
343 free(xml);
344 if (!root) {
345 lyd_free((struct lyd_node *)ret);
346 return NULL;
Michal Vasko14d88772015-12-03 10:54:59 +0100347 }
Michal Vasko587998f2015-09-29 16:07:53 +0200348
Michal Vasko17cc7062015-12-10 14:31:48 +0100349 /* remove the root */
350 ret->value = root->child;
351 lyxml_unlink_elem(ctx, root->child, 1);
352
353 lyxml_free(ctx, root);
354
Michal Vasko587998f2015-09-29 16:07:53 +0200355 return (struct lyd_node *)ret;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200356}
357
Michal Vasko0df122f2015-12-14 13:38:21 +0100358API struct lyd_node *
359lyd_new_output(const struct lys_node *rpc_schema)
360{
361 struct lyd_node *ret;
362 struct lys_node *output;
363
364 if (!rpc_schema || (rpc_schema->nodetype != LYS_RPC)) {
365 ly_errno = LY_EINVAL;
366 return NULL;
367 }
368
369 if (rpc_schema->child->nodetype == LYS_OUTPUT) {
370 output = rpc_schema->child;
371 } else if (rpc_schema->child->next->nodetype == LYS_OUTPUT) {
372 output = rpc_schema->child->next;
373 } else {
374 ly_errno = LY_EINVAL;
375 return NULL;
376 }
377
378 ret = calloc(1, sizeof *ret);
Michal Vasko253035f2015-12-17 16:58:13 +0100379 if (!ret) {
380 LOGMEM;
381 return NULL;
382 }
Michal Vasko0df122f2015-12-14 13:38:21 +0100383 ret->schema = output;
384 ret->prev = ret;
385
386 return (struct lyd_node *)ret;
387}
388
Michal Vasko24337392015-10-16 09:58:16 +0200389API int
390lyd_insert(struct lyd_node *parent, struct lyd_node *node)
Michal Vasko2d162e12015-09-24 14:33:29 +0200391{
392 struct lys_node *sparent;
Michal Vasko24337392015-10-16 09:58:16 +0200393 struct lyd_node *iter;
Michal Vasko2d162e12015-09-24 14:33:29 +0200394
Michal Vasko24337392015-10-16 09:58:16 +0200395 if (!node || !parent) {
396 ly_errno = LY_EINVAL;
397 return EXIT_FAILURE;
Michal Vasko2d162e12015-09-24 14:33:29 +0200398 }
399
Michal Vasko72d65c92015-12-07 14:02:35 +0100400 /* check placing the node to the appropriate place according to the schema (if LYS_OUTPUT is returned,
401 * the parent's schema will never match and it fails as it should) */
Michal Vaskob9f6a6c2016-01-04 15:41:58 +0100402 for (sparent = lys_parent(node->schema);
Michal Vasko72d65c92015-12-07 14:02:35 +0100403 sparent && !(sparent->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_OUTPUT | LYS_NOTIF));
Michal Vaskob9f6a6c2016-01-04 15:41:58 +0100404 sparent = lys_parent(sparent));
Michal Vasko2d162e12015-09-24 14:33:29 +0200405 if (sparent != parent->schema) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200406 return EXIT_FAILURE;
407 }
408
Michal Vasko24337392015-10-16 09:58:16 +0200409 if (node->parent || node->prev->next) {
410 lyd_unlink(node);
411 }
412
Michal Vasko2d162e12015-09-24 14:33:29 +0200413 if (!parent->child) {
414 /* add as the only child of the parent */
415 parent->child = node;
416 } else {
417 /* add as the last child of the parent */
418 parent->child->prev->next = node;
419 node->prev = parent->child->prev;
420 for (iter = node; iter->next; iter = iter->next);
421 parent->child->prev = iter;
422 }
Michal Vasko9cc2d0a2015-10-14 15:49:07 +0200423
Michal Vasko2d162e12015-09-24 14:33:29 +0200424 LY_TREE_FOR(node, iter) {
425 iter->parent = parent;
Michal Vasko2d162e12015-09-24 14:33:29 +0200426 }
427
428 return EXIT_SUCCESS;
429}
430
Michal Vasko02592902015-10-15 12:14:40 +0200431static int
Michal Vasko24337392015-10-16 09:58:16 +0200432lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, int before)
Michal Vasko2d162e12015-09-24 14:33:29 +0200433{
434 struct lys_node *par1, *par2;
Michal Vasko24337392015-10-16 09:58:16 +0200435 struct lyd_node *iter, *last;
Michal Vasko3f7dba12015-10-15 13:09:27 +0200436
437 if (sibling == node) {
438 return EXIT_SUCCESS;
439 }
440
Michal Vasko2d162e12015-09-24 14:33:29 +0200441 /* check placing the node to the appropriate place according to the schema */
Michal Vaskob9f6a6c2016-01-04 15:41:58 +0100442 for (par1 = lys_parent(sibling->schema);
Radek Krejci2b7bb492015-12-02 15:46:29 +0100443 par1 && !(par1->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF));
Michal Vaskob9f6a6c2016-01-04 15:41:58 +0100444 par1 = lys_parent(par1));
445 for (par2 = lys_parent(node->schema);
Radek Krejci2b7bb492015-12-02 15:46:29 +0100446 par2 && !(par2->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF));
Michal Vaskob9f6a6c2016-01-04 15:41:58 +0100447 par2 = lys_parent(par2));
Michal Vasko2d162e12015-09-24 14:33:29 +0200448 if (par1 != par2) {
449 ly_errno = LY_EINVAL;
450 return EXIT_FAILURE;
451 }
452
Michal Vasko24337392015-10-16 09:58:16 +0200453 if (node->parent || node->prev->next) {
454 lyd_unlink(node);
455 }
456
Michal Vasko2d162e12015-09-24 14:33:29 +0200457 LY_TREE_FOR(node, iter) {
458 iter->parent = sibling->parent;
Michal Vasko24337392015-10-16 09:58:16 +0200459 last = iter;
Michal Vasko2d162e12015-09-24 14:33:29 +0200460 }
461
Michal Vasko02592902015-10-15 12:14:40 +0200462 if (before) {
463 if (sibling->prev->next) {
464 /* adding into the list */
465 sibling->prev->next = node;
466 } else if (sibling->parent) {
467 /* at the beginning */
468 sibling->parent->child = node;
Michal Vasko2d162e12015-09-24 14:33:29 +0200469 }
Michal Vasko02592902015-10-15 12:14:40 +0200470 node->prev = sibling->prev;
471 sibling->prev = last;
472 last->next = sibling;
473 } else {
474 if (sibling->next) {
475 /* adding into a middle - fix the prev pointer of the node after inserted nodes */
476 last->next = sibling->next;
477 sibling->next->prev = last;
478 } else {
479 /* at the end - fix the prev pointer of the first node */
480 if (sibling->parent) {
481 sibling->parent->child->prev = last;
482 } else {
483 for (iter = sibling; iter->prev->next; iter = iter->prev);
484 iter->prev = last;
485 }
486 }
487 sibling->next = node;
488 node->prev = sibling;
Michal Vasko2d162e12015-09-24 14:33:29 +0200489 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200490
Michal Vasko24337392015-10-16 09:58:16 +0200491 return EXIT_SUCCESS;
492}
Michal Vasko2d162e12015-09-24 14:33:29 +0200493
Michal Vasko24337392015-10-16 09:58:16 +0200494API int
495lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
496{
497 if (!node || !sibling || lyd_insert_sibling(sibling, node, 1)) {
498 ly_errno = LY_EINVAL;
499 return EXIT_FAILURE;
500 }
501
502 return EXIT_SUCCESS;
503}
504
505API int
506lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
507{
508 if (!node || !sibling || lyd_insert_sibling(sibling, node, 0)) {
509 ly_errno = LY_EINVAL;
510 return EXIT_FAILURE;
511 }
512
513 return EXIT_SUCCESS;
514}
515
516API int
517lyd_validate(struct lyd_node *node, int options)
518{
519 struct lyd_node *next, *iter, *to_free = NULL;
520
521 ly_errno = 0;
522 LY_TREE_DFS_BEGIN(node, next, iter) {
523 if (to_free) {
524 lyd_free(to_free);
525 to_free = NULL;
526 }
527
Radek Krejcif03ec152015-12-03 13:18:37 +0100528 if (lyv_data_context(iter, options, 0, NULL)) {
529 return EXIT_FAILURE;
530 }
531 if (lyv_data_content(iter, options, 0, NULL)) {
Michal Vasko24337392015-10-16 09:58:16 +0200532 if (ly_errno) {
533 return EXIT_FAILURE;
534 } else {
535 /* safe deferred removal */
536 to_free = iter;
Radek Krejciefe6a142015-12-03 14:01:00 +0100537 if (iter == node) {
538 /* removing the whole subtree */
539 break;
540 }
Michal Vasko3f7dba12015-10-15 13:09:27 +0200541 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200542 }
Michal Vasko24337392015-10-16 09:58:16 +0200543
544 LY_TREE_DFS_END(node, next, iter);
Michal Vasko2d162e12015-09-24 14:33:29 +0200545 }
546
Michal Vasko24337392015-10-16 09:58:16 +0200547 if (to_free) {
548 lyd_free(to_free);
549 to_free = NULL;
Michal Vasko02592902015-10-15 12:14:40 +0200550 }
551
552 return EXIT_SUCCESS;
553}
554
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100555/* create an attribute copy */
Michal Vasko55f60be2015-10-14 13:12:58 +0200556static struct lyd_attr *
557lyd_dup_attr(struct ly_ctx *ctx, struct lyd_node *parent, struct lyd_attr *attr)
558{
559 struct lyd_attr *ret;
560
561 /* allocate new attr */
562 if (!parent->attr) {
563 parent->attr = malloc(sizeof *parent->attr);
564 ret = parent->attr;
565 } else {
566 for (ret = parent->attr; ret->next; ret = ret->next);
567 ret->next = malloc(sizeof *ret);
568 ret = ret->next;
569 }
Michal Vasko253035f2015-12-17 16:58:13 +0100570 if (!ret) {
571 LOGMEM;
572 return NULL;
573 }
Michal Vasko55f60be2015-10-14 13:12:58 +0200574
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100575 /* fill new attr except */
Michal Vasko55f60be2015-10-14 13:12:58 +0200576 ret->next = NULL;
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100577 ret->module = attr->module;
Michal Vasko55f60be2015-10-14 13:12:58 +0200578 ret->name = lydict_insert(ctx, attr->name, 0);
579 ret->value = lydict_insert(ctx, attr->value, 0);
580
Michal Vasko55f60be2015-10-14 13:12:58 +0200581 return ret;
582}
583
Michal Vasko2d162e12015-09-24 14:33:29 +0200584API int
585lyd_unlink(struct lyd_node *node)
586{
587 struct lyd_node *iter;
588
589 if (!node) {
590 ly_errno = LY_EINVAL;
591 return EXIT_FAILURE;
592 }
593
594 /* unlink from siblings */
595 if (node->prev->next) {
596 node->prev->next = node->next;
597 }
598 if (node->next) {
599 node->next->prev = node->prev;
600 } else {
601 /* unlinking the last node */
Radek Krejci32636312016-01-07 13:49:48 +0100602 if (node->parent) {
603 iter = node->parent->child;
604 } else {
605 iter = node->prev;
606 while (iter->prev != node) {
607 iter = iter->prev;
608 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200609 }
610 /* update the "last" pointer from the first node */
611 iter->prev = node->prev;
612 }
613
614 /* unlink from parent */
615 if (node->parent) {
616 if (node->parent->child == node) {
617 /* the node is the first child */
618 node->parent->child = node->next;
619 }
620 node->parent = NULL;
621 }
622
623 node->next = NULL;
624 node->prev = node;
625
626 return EXIT_SUCCESS;
627}
628
Michal Vaskoc0797f82015-10-14 15:51:25 +0200629API struct lyd_node *
Michal Vasko1e62a092015-12-01 12:27:20 +0100630lyd_dup(const struct lyd_node *node, int recursive)
Michal Vaskoc0797f82015-10-14 15:51:25 +0200631{
Michal Vasko1e62a092015-12-01 12:27:20 +0100632 const struct lyd_node *next, *elem;
633 struct lyd_node *ret, *parent, *new_node;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200634 struct lyd_attr *attr;
635 struct lyd_node_leaf_list *new_leaf;
636 struct lyd_node_anyxml *new_axml;
637 struct lys_type *type;
638
639 if (!node) {
640 ly_errno = LY_EINVAL;
641 return NULL;
642 }
643
644 ret = NULL;
645 parent = NULL;
646
647 /* LY_TREE_DFS */
648 for (elem = next = node; elem; elem = next) {
649
650 /* fill specific part */
651 switch (elem->schema->nodetype) {
652 case LYS_LEAF:
653 case LYS_LEAFLIST:
654 new_leaf = malloc(sizeof *new_leaf);
655 new_node = (struct lyd_node *)new_leaf;
Michal Vasko253035f2015-12-17 16:58:13 +0100656 if (!new_node) {
657 LOGMEM;
658 return NULL;
659 }
Michal Vaskoc0797f82015-10-14 15:51:25 +0200660
661 new_leaf->value = ((struct lyd_node_leaf_list *)elem)->value;
662 new_leaf->value_str = lydict_insert(elem->schema->module->ctx,
663 ((struct lyd_node_leaf_list *)elem)->value_str, 0);
664 new_leaf->value_type = ((struct lyd_node_leaf_list *)elem)->value_type;
665 /* bits type must be treated specially */
666 if (new_leaf->value_type == LY_TYPE_BITS) {
667 for (type = &((struct lys_node_leaf *)elem->schema)->type; type->der->module; type = &type->der->type) {
668 if (type->base != LY_TYPE_BITS) {
669 LOGINT;
Michal Vaskod80e6c72015-10-15 09:37:01 +0200670 lyd_free(new_node);
Michal Vaskoc0797f82015-10-14 15:51:25 +0200671 lyd_free(ret);
672 return NULL;
673 }
674 }
675
676 new_leaf->value.bit = malloc(type->info.bits.count * sizeof *new_leaf->value.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100677 if (!new_leaf->value.bit) {
678 LOGMEM;
679 lyd_free(new_node);
680 lyd_free(ret);
681 return NULL;
682 }
Michal Vaskoc0797f82015-10-14 15:51:25 +0200683 memcpy(new_leaf->value.bit, ((struct lyd_node_leaf_list *)elem)->value.bit,
684 type->info.bits.count * sizeof *new_leaf->value.bit);
685 }
686 break;
687 case LYS_ANYXML:
688 new_axml = malloc(sizeof *new_axml);
689 new_node = (struct lyd_node *)new_axml;
Michal Vasko253035f2015-12-17 16:58:13 +0100690 if (!new_node) {
691 LOGMEM;
692 return NULL;
693 }
Michal Vaskoc0797f82015-10-14 15:51:25 +0200694
695 new_axml->value = lyxml_dup_elem(elem->schema->module->ctx, ((struct lyd_node_anyxml *)elem)->value,
696 NULL, 1);
697 break;
698 case LYS_CONTAINER:
699 case LYS_LIST:
700 case LYS_NOTIF:
701 case LYS_RPC:
702 new_node = malloc(sizeof *new_node);
Michal Vasko253035f2015-12-17 16:58:13 +0100703 if (!new_node) {
704 LOGMEM;
705 return NULL;
706 }
Michal Vaskoc0797f82015-10-14 15:51:25 +0200707 new_node->child = NULL;
708 break;
709 default:
Michal Vaskoc0797f82015-10-14 15:51:25 +0200710 lyd_free(ret);
Michal Vasko24337392015-10-16 09:58:16 +0200711 LOGINT;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200712 return NULL;
713 }
714
715 /* fill common part */
716 new_node->schema = elem->schema;
717 new_node->attr = NULL;
718 LY_TREE_FOR(elem->attr, attr) {
719 lyd_dup_attr(elem->schema->module->ctx, new_node, attr);
720 }
721 new_node->next = NULL;
722 new_node->prev = new_node;
723 new_node->parent = NULL;
724
725 if (!ret) {
726 ret = new_node;
727 }
728 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200729 if (lyd_insert(parent, new_node)) {
Michal Vaskoc0797f82015-10-14 15:51:25 +0200730 lyd_free(ret);
Michal Vasko24337392015-10-16 09:58:16 +0200731 LOGINT;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200732 return NULL;
733 }
734 }
735
736 if (!recursive) {
737 break;
738 }
739
740 /* LY_TREE_DFS_END */
741 /* select element for the next run - children first */
742 next = elem->child;
743 /* child exception for lyd_node_leaf and lyd_node_leaflist */
744 if (elem->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML)) {
745 next = NULL;
746 }
747 if (!next) {
748 /* no children, so try siblings */
749 next = elem->next;
750 } else {
751 parent = new_node;
752 }
753 while (!next) {
754 /* no siblings, go back through parents */
755 elem = elem->parent;
756 if (elem->parent == node->parent) {
757 break;
758 }
Michal Vasko785b2ad2015-10-15 09:37:15 +0200759 if (!parent) {
Michal Vaskoc8f5d802015-10-23 10:14:39 +0200760 lyd_free(ret);
Michal Vasko785b2ad2015-10-15 09:37:15 +0200761 LOGINT;
Michal Vaskoc8f5d802015-10-23 10:14:39 +0200762 return NULL;
Michal Vasko785b2ad2015-10-15 09:37:15 +0200763 }
Michal Vaskoc0797f82015-10-14 15:51:25 +0200764 parent = parent->parent;
765 /* parent is already processed, go to its sibling */
766 next = elem->next;
767 }
768 }
769
770 return ret;
771}
772
Radek Krejci88f29302015-10-30 15:42:33 +0100773API void
774lyd_free_attr(struct ly_ctx *ctx, struct lyd_node *parent, struct lyd_attr *attr, int recursive)
Michal Vasko2d162e12015-09-24 14:33:29 +0200775{
Radek Krejci88f29302015-10-30 15:42:33 +0100776 struct lyd_attr *iter;
777
778 if (!ctx || !attr) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200779 return;
780 }
781
Radek Krejci88f29302015-10-30 15:42:33 +0100782 if (parent) {
783 if (parent->attr == attr) {
784 if (recursive) {
785 parent->attr = NULL;
786 } else {
787 parent->attr = attr->next;
788 }
789 } else {
790 for (iter = parent->attr; iter->next != attr; iter = iter->next);
791 if (iter->next) {
792 if (recursive) {
793 iter->next = NULL;
794 } else {
795 iter->next = attr->next;
796 }
797 }
798 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200799 }
Radek Krejci88f29302015-10-30 15:42:33 +0100800
801 if (!recursive) {
802 attr->next = NULL;
803 }
804
805 for(iter = attr; iter; ) {
806 attr = iter;
807 iter = iter->next;
808
809 lydict_remove(ctx, attr->name);
810 lydict_remove(ctx, attr->value);
811 free(attr);
812 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200813}
814
Michal Vaskofd76bd12015-09-24 15:49:57 +0200815struct lyd_node *
816lyd_attr_parent(struct lyd_node *root, struct lyd_attr *attr)
817{
818 struct lyd_node *next, *elem;
819 struct lyd_attr *node_attr;
820
821 LY_TREE_DFS_BEGIN(root, next, elem) {
822 for (node_attr = elem->attr; node_attr; node_attr = node_attr->next) {
823 if (node_attr == attr) {
824 return elem;
825 }
826 }
827 LY_TREE_DFS_END(root, next, elem)
828 }
829
830 return NULL;
831}
832
Radek Krejci134610e2015-10-20 17:15:34 +0200833API struct lyd_attr *
834lyd_insert_attr(struct lyd_node *parent, const char *name, const char *value)
835{
Radek Krejci134610e2015-10-20 17:15:34 +0200836 struct lyd_attr *a, *iter;
837 struct ly_ctx *ctx;
Michal Vasko1e62a092015-12-01 12:27:20 +0100838 const struct lys_module *module;
Radek Krejci134610e2015-10-20 17:15:34 +0200839 const char *p;
840 char *aux;
841
842 if (!parent || !name || !value) {
843 return NULL;
844 }
845 ctx = parent->schema->module->ctx;
846
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100847 if ((p = strchr(name, ':'))) {
848 /* search for the namespace */
849 aux = strndup(name, p - name);
Michal Vasko253035f2015-12-17 16:58:13 +0100850 if (!aux) {
851 LOGMEM;
852 return NULL;
853 }
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100854 module = ly_ctx_get_module(ctx, aux, NULL);
855 free(aux);
856 name = p + 1;
Radek Krejci134610e2015-10-20 17:15:34 +0200857
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100858 if (!module) {
859 /* module not found */
Radek Krejcia008ca92015-10-30 15:52:05 +0100860 LOGERR(LY_EINVAL, "Attribute prefix does not match any schema in the context.");
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100861 return NULL;
Radek Krejci134610e2015-10-20 17:15:34 +0200862 }
863 } else {
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100864 /* no prefix -> module is the same as for the parent */
865 module = parent->schema->module;
Radek Krejci134610e2015-10-20 17:15:34 +0200866 }
867
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100868 a = malloc(sizeof *a);
Michal Vasko253035f2015-12-17 16:58:13 +0100869 if (!a) {
870 LOGMEM;
871 return NULL;
872 }
Michal Vasko1e62a092015-12-01 12:27:20 +0100873 a->module = (struct lys_module *)module;
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100874 a->next = NULL;
875 a->name = lydict_insert(ctx, name, 0);
Radek Krejci134610e2015-10-20 17:15:34 +0200876 a->value = lydict_insert(ctx, value, 0);
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100877
Radek Krejci134610e2015-10-20 17:15:34 +0200878 if (!parent->attr) {
879 parent->attr = a;
880 } else {
881 for (iter = parent->attr; iter->next; iter = iter->next);
882 iter->next = a;
883 }
884
885 return a;
886}
887
Michal Vasko2d162e12015-09-24 14:33:29 +0200888API void
889lyd_free(struct lyd_node *node)
890{
891 struct lyd_node *next, *child;
892
893 if (!node) {
894 return;
895 }
896
897 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
898 /* free children */
899 LY_TREE_FOR_SAFE(node->child, next, child) {
900 lyd_free(child);
901 }
902 } else if (node->schema->nodetype == LYS_ANYXML) {
Michal Vasko345da0a2015-12-02 10:35:55 +0100903 lyxml_free(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
Michal Vasko2d162e12015-09-24 14:33:29 +0200904 } else {
905 /* free value */
Michal Vasko4c183312015-09-25 10:41:47 +0200906 switch(((struct lyd_node_leaf_list *)node)->value_type) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200907 case LY_TYPE_BINARY:
908 case LY_TYPE_STRING:
Michal Vasko4c183312015-09-25 10:41:47 +0200909 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf_list *)node)->value.string);
Michal Vasko2d162e12015-09-24 14:33:29 +0200910 break;
911 case LY_TYPE_BITS:
Michal Vasko4c183312015-09-25 10:41:47 +0200912 if (((struct lyd_node_leaf_list *)node)->value.bit) {
913 free(((struct lyd_node_leaf_list *)node)->value.bit);
Michal Vasko2d162e12015-09-24 14:33:29 +0200914 }
915 break;
916 default:
917 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
918 break;
919 }
920 }
921
922 lyd_unlink(node);
Radek Krejci88f29302015-10-30 15:42:33 +0100923 lyd_free_attr(node->schema->module->ctx, node, node->attr, 1);
Michal Vasko2d162e12015-09-24 14:33:29 +0200924 free(node);
925}
926
Radek Krejci81468402016-01-07 13:52:40 +0100927API void
928lyd_free_withsiblings(struct lyd_node *node)
929{
930 struct lyd_node *iter, *aux;
931
932 if (!node) {
933 return;
934 }
935
936 /* optimization - avoid freeing (unlinking) the last node of the siblings list */
937 /* so, first, free the node's predecessors to the beginning of the list ... */
938 for(iter = node->prev; iter->next; iter = aux) {
939 aux = iter->prev;
940 lyd_free(iter);
941 }
942 /* ... then, the node is the first in the siblings list, so free them all */
943 LY_TREE_FOR_SAFE(node, aux, iter) {
944 lyd_free(iter);
945 }
946}
947
Michal Vaskoff4c2832015-10-15 13:30:50 +0200948API char *
Michal Vasko1e62a092015-12-01 12:27:20 +0100949lyxml_serialize(const struct lyxml_elem *anyxml)
Michal Vaskoff4c2832015-10-15 13:30:50 +0200950{
951 FILE *stream;
952 char *buf;
953 size_t buf_size;
954
955 if (!anyxml) {
956 ly_errno = LY_EINVAL;
957 return NULL;
958 }
959
960 stream = open_memstream(&buf, &buf_size);
961 if (!stream) {
962 ly_errno = LY_ESYS;
963 return NULL;
964 }
Michal Vasko70f92c32015-12-10 09:57:24 +0100965 if (lyxml_dump_file(stream, anyxml, 0) == 0) {
Michal Vaskoff4c2832015-10-15 13:30:50 +0200966 free(buf);
967 buf = NULL;
968 ly_errno = LY_EINVAL;
969 }
970 fclose(stream);
971
972 return buf;
973}
974
Michal Vasko2d162e12015-09-24 14:33:29 +0200975int
976lyd_compare(struct lyd_node *first, struct lyd_node *second, int unique)
977{
978 struct lys_node_list *slist;
Michal Vasko1e62a092015-12-01 12:27:20 +0100979 const struct lys_node *snode = NULL;
Michal Vasko2d162e12015-09-24 14:33:29 +0200980 struct lyd_node *diter;
981 const char *val1, *val2;
982 int i, j;
983
984 assert(first);
985 assert(second);
986
987 if (first->schema != second->schema) {
988 return 1;
989 }
990
991 switch (first->schema->nodetype) {
992 case LYS_LEAFLIST:
993 /* compare values */
Michal Vasko4c183312015-09-25 10:41:47 +0200994 if (((struct lyd_node_leaf_list *)first)->value_str == ((struct lyd_node_leaf_list *)second)->value_str) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200995 return 0;
996 }
997 return 1;
998 case LYS_LIST:
Michal Vasko4c183312015-09-25 10:41:47 +0200999 slist = (struct lys_node_list *)first->schema;
Michal Vasko2d162e12015-09-24 14:33:29 +02001000
1001 if (unique) {
1002 /* compare unique leafs */
1003 for (i = 0; i < slist->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001004 for (j = 0; j < slist->unique[i].expr_size; j++) {
1005 /* first */
1006 diter = resolve_data_nodeid(slist->unique[i].expr[j], first->child);
1007 if (diter) {
1008 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
1009 } else {
1010 /* use default value */
Radek Krejci3eb09b62015-12-16 15:22:19 +01001011 if (resolve_schema_nodeid(slist->unique[i].expr[j], first->schema->child, first->schema->module, LYS_LEAF, &snode)) {
1012 /* error, but unique expression was checked when the schema was parsed */
1013 return -1;
1014 }
Radek Krejci581ce772015-11-10 17:22:40 +01001015 val1 = ((struct lys_node_leaf *)snode)->dflt;
Michal Vasko2d162e12015-09-24 14:33:29 +02001016 }
Radek Krejci581ce772015-11-10 17:22:40 +01001017
1018 /* second */
1019 diter = resolve_data_nodeid(slist->unique[i].expr[j], second->child);
1020 if (diter) {
1021 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
1022 } else {
1023 /* use default value */
Radek Krejci3eb09b62015-12-16 15:22:19 +01001024 if (resolve_schema_nodeid(slist->unique[i].expr[j], second->schema->child, second->schema->module, LYS_LEAF, &snode)) {
1025 /* error, but unique expression was checked when the schema was parsed */
1026 return -1;
1027 }
Radek Krejci581ce772015-11-10 17:22:40 +01001028 val2 = ((struct lys_node_leaf *)snode)->dflt;
Michal Vasko2d162e12015-09-24 14:33:29 +02001029 }
Radek Krejci581ce772015-11-10 17:22:40 +01001030
Michal Vasko2d162e12015-09-24 14:33:29 +02001031 if (val1 != val2) {
1032 break;
1033 }
1034 }
Radek Krejci581ce772015-11-10 17:22:40 +01001035 if (j && j == slist->unique[i].expr_size) {
Michal Vasko2d162e12015-09-24 14:33:29 +02001036 /* all unique leafs are the same in this set */
1037 return 0;
1038 }
1039 }
1040 }
1041
1042 /* compare keys */
1043 for (i = 0; i < slist->keys_size; i++) {
1044 snode = (struct lys_node *)slist->keys[i];
1045 val1 = val2 = NULL;
1046 LY_TREE_FOR(first->child, diter) {
1047 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001048 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001049 break;
1050 }
1051 }
1052 LY_TREE_FOR(second->child, diter) {
1053 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001054 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001055 break;
1056 }
1057 }
1058 if (val1 != val2) {
1059 return 1;
1060 }
1061 }
1062
1063 return 0;
1064 default:
1065 /* no additional check is needed */
1066 return 0;
1067 }
1068}
1069
1070API struct lyd_set *
1071lyd_set_new(void)
1072{
1073 return calloc(1, sizeof(struct lyd_set));
1074}
1075
1076API void
1077lyd_set_free(struct lyd_set *set)
1078{
1079 if (!set) {
1080 return;
1081 }
1082
1083 free(set->set);
1084 free(set);
1085}
1086
1087API int
1088lyd_set_add(struct lyd_set *set, struct lyd_node *node)
1089{
1090 struct lyd_node **new;
1091
1092 if (!set) {
1093 ly_errno = LY_EINVAL;
1094 return EXIT_FAILURE;
1095 }
1096
1097 if (set->size == set->number) {
Radek Krejcic5c45982016-01-07 12:50:44 +01001098 new = realloc(set->set, (set->size + 8) * sizeof *(set->set));
Michal Vasko2d162e12015-09-24 14:33:29 +02001099 if (!new) {
1100 LOGMEM;
1101 return EXIT_FAILURE;
1102 }
1103 set->size += 8;
1104 set->set = new;
1105 }
1106
1107 set->set[set->number++] = node;
1108
1109 return EXIT_SUCCESS;
1110}