blob: 3e6100e3f8ec8998aeb43bdb92209d61326c1fae [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>
27#include <stdlib.h>
28#include <sys/mman.h>
29#include <sys/stat.h>
30#include <string.h>
31
32#include "common.h"
33#include "context.h"
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020034#include "tree_data.h"
Michal Vasko2d162e12015-09-24 14:33:29 +020035#include "parser.h"
36#include "resolve.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020037#include "xml_internal.h"
Michal Vasko2d162e12015-09-24 14:33:29 +020038#include "tree_internal.h"
39#include "validation.h"
40
41API struct lyd_node *
42lyd_parse(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
43{
Radek Krejci5974c1f2015-10-09 09:53:24 +020044 struct lyxml_elem *xml;
45 struct lyd_node *result = NULL;
46
Michal Vasko2d162e12015-09-24 14:33:29 +020047 if (!ctx || !data) {
48 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
49 return NULL;
50 }
51
52 switch (format) {
53 case LYD_XML:
Radek Krejci452fb952015-10-02 16:07:46 +020054 case LYD_XML_FORMAT:
Radek Krejci5974c1f2015-10-09 09:53:24 +020055 xml = lyxml_read(ctx, data, 0);
56 result = lyd_parse_xml(ctx, xml, options);
57 lyxml_free_elem(ctx, xml);
58 break;
Michal Vasko2d162e12015-09-24 14:33:29 +020059 case LYD_JSON:
60 default:
61 /* TODO */
62 return NULL;
63 }
64
Radek Krejci5974c1f2015-10-09 09:53:24 +020065 return result;
Michal Vasko2d162e12015-09-24 14:33:29 +020066}
67
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020068API struct lyd_node *
69lyd_new(struct lyd_node *parent, struct lys_module *module, const char *name)
70{
71 struct lyd_node *ret;
72 struct lys_node *snode = NULL, *siblings;
73
74 if ((!parent && !module) || !name) {
75 ly_errno = LY_EINVAL;
76 return NULL;
77 }
78
79 if (!parent) {
80 siblings = module->data;
81 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +020082 if (!parent->schema) {
83 return NULL;
84 }
85 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020086 }
87
Michal Vaskoa45cf2b2015-10-23 09:45:36 +020088 if (lys_get_data_sibling(module, siblings, name, LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC, &snode)
89 || !snode) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020090 return NULL;
91 }
92
93 ret = calloc(1, sizeof *ret);
94 ret->schema = snode;
95 ret->prev = ret;
96 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +020097 if (lyd_insert(parent, ret)) {
98 lyd_free(ret);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020099 return NULL;
100 }
101 }
102
103 return ret;
104}
105
106API struct lyd_node *
107lyd_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 +0200108 lyd_val value)
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200109{
110 struct lyd_node_leaf_list *ret;
111 struct lys_node *snode = NULL, *siblings;
Radek Krejcie4e4d722015-10-05 16:53:50 +0200112 struct lys_type *stype = NULL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200113 struct lys_module *src_mod, *dst_mod;
114 char *val_str = NULL, str_num[22];
Radek Krejcie4e4d722015-10-05 16:53:50 +0200115 const char *prefix = NULL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200116 int i, str_len = 0, prev_len;
117 uint64_t exp;
118
Michal Vasko0e3c8722015-09-29 16:06:08 +0200119 if ((!parent && !module) || !name) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200120 ly_errno = LY_EINVAL;
121 return NULL;
122 }
123
124 if (!parent) {
125 siblings = module->data;
126 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200127 if (!parent->schema) {
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200128 ly_errno = LY_EINVAL;
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200129 return NULL;
130 }
131 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200132 }
133
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200134 if (lys_get_data_sibling(module, siblings, name, LYS_LEAFLIST | LYS_LEAF, &snode) || !snode) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200135 return NULL;
136 }
137
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200138 if (type != ((struct lys_node_leaf *)snode)->type.base) {
139 ly_errno = LY_EINVAL;
140 return NULL;
141 }
142
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200143 switch (type) {
144 case LY_TYPE_BINARY:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200145 val_str = (char *)lydict_insert(snode->module->ctx, value.binary, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200146 break;
147
148 case LY_TYPE_BITS:
149 /* find the type definition */
150 for (stype = &((struct lys_node_leaf *)snode)->type; stype->der->module; stype = &stype->der->type) {
151 if (stype->base != LY_TYPE_BITS) {
152 LOGINT;
153 return NULL;
154 }
155 }
156
157 /* concatenate set bits */
158 for (i = 0; i < stype->info.bits.count; ++i) {
Michal Vasko0e3c8722015-09-29 16:06:08 +0200159 if (!value.bit[i]) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200160 continue;
161 }
162
163 prev_len = str_len;
Michal Vasko0e3c8722015-09-29 16:06:08 +0200164 str_len += strlen(value.bit[i]->name) + 1;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200165 val_str = realloc((char *)val_str, str_len * sizeof(char));
166
167 if (prev_len) {
168 val_str[prev_len] = ' ';
169 ++prev_len;
170 }
Michal Vasko0e3c8722015-09-29 16:06:08 +0200171 strcpy(val_str + prev_len, value.bit[i]->name);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200172 }
173
174 val_str = (char *)lydict_insert_zc(snode->module->ctx, val_str);
175 break;
176
177 case LY_TYPE_BOOL:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200178 if (value.bool) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200179 val_str = (char *)lydict_insert(snode->module->ctx, "true", 4);
180 } else {
181 val_str = (char *)lydict_insert(snode->module->ctx, "false", 5);
182 }
183 break;
184
185 case LY_TYPE_DEC64:
186 /* find the type definition */
187 for (stype = &((struct lys_node_leaf *)snode)->type; stype->der->module; stype = &stype->der->type) {
188 if (stype->base != LY_TYPE_DEC64) {
189 LOGINT;
190 return NULL;
191 }
192 }
193
194 for (i = 0, exp = 1; i < stype->info.dec64.dig; ++i, exp *= 10);
Michal Vasko0e3c8722015-09-29 16:06:08 +0200195 sprintf(str_num, "%01.1Lf", ((long double)value.dec64) / exp);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200196 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
197 break;
198
199 case LY_TYPE_EMPTY:
200 break;
201
202 case LY_TYPE_ENUM:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200203 val_str = (char *)lydict_insert(snode->module->ctx, value.enm->name, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200204 break;
205
206 case LY_TYPE_IDENT:
207 /* TODO move to function if used somewhere else (module -> import prefix) */
Michal Vasko0e3c8722015-09-29 16:06:08 +0200208 src_mod = value.ident->module;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200209 if (src_mod->type) {
210 src_mod = ((struct lys_submodule *)src_mod)->belongsto;
211 }
212 dst_mod = snode->module;
213 if (dst_mod->type) {
214 dst_mod = ((struct lys_submodule *)dst_mod)->belongsto;
215 }
216 if (src_mod != dst_mod) {
217 for (i = 0; i < src_mod->imp_size; ++i) {
218 if (src_mod->imp[i].module == dst_mod) {
219 prefix = src_mod->imp[i].prefix;
220 break;
221 }
222 }
223 if (!prefix) {
224 LOGINT;
225 return NULL;
226 }
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200227 }
228
229 if (!prefix) {
Michal Vasko0e3c8722015-09-29 16:06:08 +0200230 val_str = (char *)lydict_insert(snode->module->ctx, value.ident->name, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200231 } else {
Michal Vasko0e3c8722015-09-29 16:06:08 +0200232 val_str = malloc((strlen(prefix) + 1 + strlen(value.ident->name) + 1) * sizeof(char));
233 sprintf(val_str, "%s:%s", prefix, value.ident->name);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200234 val_str = (char *)lydict_insert_zc(snode->module->ctx, val_str);
235 }
236 break;
237
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200238 case LY_TYPE_LEAFREF:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200239 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 +0200240 break;
241
242 case LY_TYPE_STRING:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200243 val_str = (char *)lydict_insert(snode->module->ctx, value.string, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200244 break;
245
246 case LY_TYPE_INT8:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200247 sprintf(str_num, "%hhd", value.int8);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200248 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
249 break;
250
251 case LY_TYPE_INT16:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200252 sprintf(str_num, "%hd", value.int16);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200253 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
254 break;
255
256 case LY_TYPE_INT32:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200257 sprintf(str_num, "%d", value.int32);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200258 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
259 break;
260
261 case LY_TYPE_INT64:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200262 sprintf(str_num, "%ld", value.int64);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200263 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
264 break;
265
266 case LY_TYPE_UINT8:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200267 sprintf(str_num, "%hhu", value.uint8);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200268 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
269 break;
270
271 case LY_TYPE_UINT16:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200272 sprintf(str_num, "%hu", value.uint16);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200273 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
274 break;
275
276 case LY_TYPE_UINT32:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200277 sprintf(str_num, "%u", value.uint32);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200278 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
279 break;
280
281 case LY_TYPE_UINT64:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200282 sprintf(str_num, "%lu", value.uint64);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200283 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
284 break;
285
Michal Vasko14580182015-10-09 14:49:00 +0200286 default: /* LY_TYPE_INST */
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200287 LOGINT;
288 return NULL;
289 }
290
291 ret = calloc(1, sizeof *ret);
292 ret->schema = snode;
293 ret->prev = (struct lyd_node *)ret;
294 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200295 if (lyd_insert(parent, (struct lyd_node *)ret)) {
296 lyd_free((struct lyd_node *)ret);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200297 lydict_remove(snode->module->ctx, val_str);
298 return NULL;
299 }
300 }
Michal Vasko81eef2c2015-10-02 15:37:25 +0200301
302 if (type == LY_TYPE_BINARY) {
303 ret->value.binary = val_str;
304 } else if (type == LY_TYPE_STRING) {
305 ret->value.string = val_str;
306 } else if (type == LY_TYPE_BITS) {
307 /* stype is left with the bits type definition */
308 ret->value.bit = malloc(stype->info.bits.count * sizeof *ret->value.bit);
309 memcpy(ret->value.bit, value.bit, stype->info.bits.count * sizeof *ret->value.bit);
310 } else {
311 ret->value = value;
312 }
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200313 ret->value_str = val_str;
314 ret->value_type = type;
315
316 return (struct lyd_node *)ret;
317}
318
319API struct lyd_node *
320lyd_new_leaf_str(struct lyd_node *parent, struct lys_module *module, const char *name, LY_DATA_TYPE type,
321 const char *val_str)
322{
323 struct lyd_node_leaf_list *ret;
324 struct lys_node *snode = NULL, *siblings;
325 struct lys_type *stype, *utype;
326 int found;
327
328 if ((!parent && !module) || !name) {
329 ly_errno = LY_EINVAL;
330 return NULL;
331 }
332
333 if (!parent) {
334 siblings = module->data;
335 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200336 if (!parent->schema) {
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200337 ly_errno = LY_EINVAL;
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200338 return NULL;
339 }
340 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200341 }
342
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200343 if (lys_get_data_sibling(module, siblings, name, LYS_LEAFLIST | LYS_LEAF, &snode) || !snode) {
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200344 ly_errno = LY_EINVAL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200345 return NULL;
346 }
347
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200348 /* get the correct type struct */
349 stype = &((struct lys_node_leaf *)snode)->type;
350 if (stype->base == LY_TYPE_UNION) {
351 found = 0;
352 utype = stype;
353 stype = lyp_get_next_union_type(utype, NULL, &found);
354 while (stype && (stype->base != type)) {
355 found = 0;
356 stype = lyp_get_next_union_type(utype, stype, &found);
357 }
358 if (!stype) {
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200359 ly_errno = LY_EINVAL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200360 return NULL;
361 }
362 }
363
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200364 if (type && (type != stype->base)) {
365 ly_errno = LY_EINVAL;
366 return NULL;
367 }
368 type = stype->base;
369
370 ret = calloc(1, sizeof *ret);
371 ret->schema = snode;
372 ret->prev = (struct lyd_node *)ret;
373 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200374 if (lyd_insert(parent, (struct lyd_node *)ret)) {
375 lyd_free((struct lyd_node *)ret);
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200376 return NULL;
377 }
378 }
379 ret->value_str = lydict_insert((module ? module->ctx : parent->schema->module->ctx), val_str, 0);
380 ret->value_type = type;
381
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200382 if (lyp_parse_value(ret, stype, 1, NULL, 0)) {
Michal Vasko24337392015-10-16 09:58:16 +0200383 lyd_free((struct lyd_node *)ret);
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200384 ly_errno = LY_EINVAL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200385 return NULL;
386 }
387
388 return (struct lyd_node *)ret;
389
390}
391
392API struct lyd_node *
393lyd_new_anyxml(struct lyd_node *parent, struct lys_module *module, const char *name, const char *val_xml)
394{
Michal Vasko587998f2015-09-29 16:07:53 +0200395 struct lyd_node_anyxml *ret;
396 struct lys_node *siblings, *snode;
397 struct lyxml_elem *root, *first_child, *last_child, *child;
398 struct ly_ctx *ctx;
399 char *xml;
400
401 if ((!parent && !module) || !name || !val_xml) {
402 ly_errno = LY_EINVAL;
403 return NULL;
404 }
405
406 if (!parent) {
407 siblings = module->data;
408 ctx = module->ctx;
409 } else {
410 if (!parent->schema) {
411 return NULL;
412 }
413 siblings = parent->schema->child;
414 ctx = parent->schema->module->ctx;
415 }
416
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200417 if (lys_get_data_sibling(module, siblings, name, LYS_ANYXML, &snode) || !snode) {
Michal Vasko587998f2015-09-29 16:07:53 +0200418 return NULL;
419 }
420
421 ret = calloc(1, sizeof *ret);
422 ret->schema = snode;
423 ret->prev = (struct lyd_node *)ret;
424 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200425 if (lyd_insert(parent, (struct lyd_node *)ret)) {
426 lyd_free((struct lyd_node *)ret);
Michal Vasko587998f2015-09-29 16:07:53 +0200427 return NULL;
428 }
429 }
430
431 /* add fake root so we can parse the data */
432 asprintf(&xml, "<root>%s</root>", val_xml);
433 root = lyxml_read(ctx, xml, 0);
434 free(xml);
Michal Vasko5b6e78d2015-10-09 15:01:10 +0200435 if (!root) {
Michal Vasko24337392015-10-16 09:58:16 +0200436 lyd_free((struct lyd_node *)ret);
Michal Vasko5b6e78d2015-10-09 15:01:10 +0200437 return NULL;
438 }
Michal Vasko587998f2015-09-29 16:07:53 +0200439
440 /* remove the root */
Radek Krejcie4e4d722015-10-05 16:53:50 +0200441 first_child = last_child = NULL;
Michal Vasko587998f2015-09-29 16:07:53 +0200442 LY_TREE_FOR(root->child, child) {
443 lyxml_unlink_elem(ctx, child, 1);
444 if (!first_child) {
445 first_child = child;
446 last_child = child;
447 } else {
448 last_child->next = child;
449 child->prev = last_child;
450 last_child = child;
451 }
452 }
Radek Krejcie4e4d722015-10-05 16:53:50 +0200453 if (first_child) {
454 first_child->prev = last_child;
455 }
Michal Vasko587998f2015-09-29 16:07:53 +0200456 lyxml_free_elem(ctx, root);
457
458 ret->value = first_child;
459
460 return (struct lyd_node *)ret;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200461}
462
Michal Vasko24337392015-10-16 09:58:16 +0200463API int
464lyd_insert(struct lyd_node *parent, struct lyd_node *node)
Michal Vasko2d162e12015-09-24 14:33:29 +0200465{
466 struct lys_node *sparent;
Michal Vasko24337392015-10-16 09:58:16 +0200467 struct lyd_node *iter;
Michal Vasko2d162e12015-09-24 14:33:29 +0200468
Michal Vasko24337392015-10-16 09:58:16 +0200469 if (!node || !parent) {
470 ly_errno = LY_EINVAL;
471 return EXIT_FAILURE;
Michal Vasko2d162e12015-09-24 14:33:29 +0200472 }
473
474 /* check placing the node to the appropriate place according to the schema */
475 sparent = node->schema->parent;
Radek Krejci8a6794f2015-10-20 17:14:48 +0200476 while (!(sparent->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_NOTIF))) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200477 sparent = sparent->parent;
478 }
479 if (sparent != parent->schema) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200480 return EXIT_FAILURE;
481 }
482
Michal Vasko24337392015-10-16 09:58:16 +0200483 if (node->parent || node->prev->next) {
484 lyd_unlink(node);
485 }
486
Michal Vasko2d162e12015-09-24 14:33:29 +0200487 if (!parent->child) {
488 /* add as the only child of the parent */
489 parent->child = node;
490 } else {
491 /* add as the last child of the parent */
492 parent->child->prev->next = node;
493 node->prev = parent->child->prev;
494 for (iter = node; iter->next; iter = iter->next);
495 parent->child->prev = iter;
496 }
Michal Vasko9cc2d0a2015-10-14 15:49:07 +0200497
Michal Vasko2d162e12015-09-24 14:33:29 +0200498 LY_TREE_FOR(node, iter) {
499 iter->parent = parent;
Michal Vasko2d162e12015-09-24 14:33:29 +0200500 }
501
502 return EXIT_SUCCESS;
503}
504
Michal Vasko02592902015-10-15 12:14:40 +0200505static int
Michal Vasko24337392015-10-16 09:58:16 +0200506lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, int before)
Michal Vasko2d162e12015-09-24 14:33:29 +0200507{
508 struct lys_node *par1, *par2;
Michal Vasko24337392015-10-16 09:58:16 +0200509 struct lyd_node *iter, *last;
Michal Vasko3f7dba12015-10-15 13:09:27 +0200510
511 if (sibling == node) {
512 return EXIT_SUCCESS;
513 }
514
Michal Vasko2d162e12015-09-24 14:33:29 +0200515 /* check placing the node to the appropriate place according to the schema */
516 for (par1 = sibling->schema->parent; par1 && (par1->nodetype & (LYS_CONTAINER | LYS_LIST)); par1 = par1->parent);
517 for (par2 = node->schema->parent; par2 && (par2->nodetype & (LYS_CONTAINER | LYS_LIST)); par2 = par2->parent);
518 if (par1 != par2) {
519 ly_errno = LY_EINVAL;
520 return EXIT_FAILURE;
521 }
522
Michal Vasko24337392015-10-16 09:58:16 +0200523 if (node->parent || node->prev->next) {
524 lyd_unlink(node);
525 }
526
Michal Vasko2d162e12015-09-24 14:33:29 +0200527 LY_TREE_FOR(node, iter) {
528 iter->parent = sibling->parent;
Michal Vasko24337392015-10-16 09:58:16 +0200529 last = iter;
Michal Vasko2d162e12015-09-24 14:33:29 +0200530 }
531
Michal Vasko02592902015-10-15 12:14:40 +0200532 if (before) {
533 if (sibling->prev->next) {
534 /* adding into the list */
535 sibling->prev->next = node;
536 } else if (sibling->parent) {
537 /* at the beginning */
538 sibling->parent->child = node;
Michal Vasko2d162e12015-09-24 14:33:29 +0200539 }
Michal Vasko02592902015-10-15 12:14:40 +0200540 node->prev = sibling->prev;
541 sibling->prev = last;
542 last->next = sibling;
543 } else {
544 if (sibling->next) {
545 /* adding into a middle - fix the prev pointer of the node after inserted nodes */
546 last->next = sibling->next;
547 sibling->next->prev = last;
548 } else {
549 /* at the end - fix the prev pointer of the first node */
550 if (sibling->parent) {
551 sibling->parent->child->prev = last;
552 } else {
553 for (iter = sibling; iter->prev->next; iter = iter->prev);
554 iter->prev = last;
555 }
556 }
557 sibling->next = node;
558 node->prev = sibling;
Michal Vasko2d162e12015-09-24 14:33:29 +0200559 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200560
Michal Vasko24337392015-10-16 09:58:16 +0200561 return EXIT_SUCCESS;
562}
Michal Vasko2d162e12015-09-24 14:33:29 +0200563
Michal Vasko24337392015-10-16 09:58:16 +0200564API int
565lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
566{
567 if (!node || !sibling || lyd_insert_sibling(sibling, node, 1)) {
568 ly_errno = LY_EINVAL;
569 return EXIT_FAILURE;
570 }
571
572 return EXIT_SUCCESS;
573}
574
575API int
576lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
577{
578 if (!node || !sibling || lyd_insert_sibling(sibling, node, 0)) {
579 ly_errno = LY_EINVAL;
580 return EXIT_FAILURE;
581 }
582
583 return EXIT_SUCCESS;
584}
585
586API int
587lyd_validate(struct lyd_node *node, int options)
588{
589 struct lyd_node *next, *iter, *to_free = NULL;
590
591 ly_errno = 0;
592 LY_TREE_DFS_BEGIN(node, next, iter) {
593 if (to_free) {
594 lyd_free(to_free);
595 to_free = NULL;
596 }
597
598 if (lyv_data_content(iter, 0, options, NULL)) {
599 if (ly_errno) {
600 return EXIT_FAILURE;
Michal Vasko2fce5f52015-10-23 10:14:08 +0200601 } else if (iter == node) {
602 /* removing the whole subtree */
603 to_free = node;
604 break;
Michal Vasko24337392015-10-16 09:58:16 +0200605 } else {
606 /* safe deferred removal */
607 to_free = iter;
Michal Vasko3f7dba12015-10-15 13:09:27 +0200608 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200609 }
Michal Vasko24337392015-10-16 09:58:16 +0200610
611 LY_TREE_DFS_END(node, next, iter);
Michal Vasko2d162e12015-09-24 14:33:29 +0200612 }
613
Michal Vasko24337392015-10-16 09:58:16 +0200614 if (to_free) {
615 lyd_free(to_free);
616 to_free = NULL;
Michal Vasko02592902015-10-15 12:14:40 +0200617 }
618
619 return EXIT_SUCCESS;
620}
621
Michal Vasko55f60be2015-10-14 13:12:58 +0200622/* return matching namespace in node or any of it's parents */
623static struct lyd_ns *
624lyd_find_ns(struct lyd_node *node, const char *prefix, const char *value)
625{
626 int pref_match, val_match;
627 struct lyd_attr *attr;
628
629 if (!node) {
630 return NULL;
631 }
632
633 for (; node; node = node->parent) {
634 for (attr = node->attr; attr; attr = attr->next) {
635 if (attr->type != LYD_ATTR_NS) {
636 continue;
637 }
638
639 pref_match = 0;
640 if (!prefix && !attr->name) {
641 pref_match = 1;
642 }
643 if (prefix && attr->name && !strcmp(attr->name, prefix)) {
644 pref_match = 1;
645 }
646
647 val_match = 0;
648 if (!value && !attr->value) {
649 val_match = 1;
650 }
651 if (value && attr->value && !strcmp(attr->value, value)) {
652 val_match = 1;
653 }
654
655 if (pref_match && val_match) {
656 return (struct lyd_ns *)attr;
657 }
658 }
659 }
660
661 return NULL;
662}
663
664/* create an attribute copy including correct namespace if used */
665static struct lyd_attr *
666lyd_dup_attr(struct ly_ctx *ctx, struct lyd_node *parent, struct lyd_attr *attr)
667{
668 struct lyd_attr *ret;
669
670 /* allocate new attr */
671 if (!parent->attr) {
672 parent->attr = malloc(sizeof *parent->attr);
673 ret = parent->attr;
674 } else {
675 for (ret = parent->attr; ret->next; ret = ret->next);
676 ret->next = malloc(sizeof *ret);
677 ret = ret->next;
678 }
679
680 /* fill new attr except ns/parent */
681 ret->type = attr->type;
682 ret->next = NULL;
683 ret->name = lydict_insert(ctx, attr->name, 0);
684 ret->value = lydict_insert(ctx, attr->value, 0);
685
686 if (ret->type == LYD_ATTR_NS) {
687 /* fill parent in a NS */
688 ((struct lyd_ns *)ret)->parent = parent;
689 } else if (attr->ns) {
690 /* attr has a namespace */
691
692 /* perhaps the namespace was already copied over? */
693 ret->ns = lyd_find_ns(parent, attr->ns->prefix, attr->ns->value);
694 if (!ret->ns) {
695 /* nope, it wasn't */
696 ret->ns = (struct lyd_ns *)lyd_dup_attr(ctx, parent, (struct lyd_attr *)attr->ns);
697 }
698 } else {
699 /* there is no namespace */
700 ret->ns = NULL;
701 }
702
703 return ret;
704}
705
706/* correct namespaces in the attributes of subtree nodes of node */
707static void
708lyd_correct_ns(struct lyd_node *node)
709{
710 const struct lyd_ns *attr_ns;
711 struct lyd_attr *attr;
712 struct lyd_node *node_root, *ns_root, *tmp;
713
714 /* find the root of node */
715 for (node_root = node; node_root->parent; node_root = node_root->parent);
716
717 LY_TREE_DFS_BEGIN(node, tmp, node) {
718 for (attr = node->attr; attr; attr = attr->next) {
719 if ((attr->type != LYD_ATTR_STD) || !attr->ns) {
720 continue;
721 }
722
723 /* find the root of attr NS */
724 for (ns_root = attr->ns->parent; ns_root->parent; ns_root = ns_root->parent);
725
726 /* attr NS is defined outside node subtree */
727 if (ns_root != node_root) {
728 attr_ns = attr->ns;
729 /* we may have already copied the NS over? */
730 attr->ns = lyd_find_ns(node, attr_ns->prefix, attr_ns->value);
731
732 /* we haven't copied it over, copy it now */
733 if (!attr->ns) {
734 attr->ns = (struct lyd_ns *)lyd_dup_attr(node->schema->module->ctx, node,
735 (struct lyd_attr *)attr_ns);
736 }
737 }
738 }
739 LY_TREE_DFS_END(node, tmp, node);
740 }
741}
742
Michal Vasko2d162e12015-09-24 14:33:29 +0200743API int
744lyd_unlink(struct lyd_node *node)
745{
746 struct lyd_node *iter;
747
748 if (!node) {
749 ly_errno = LY_EINVAL;
750 return EXIT_FAILURE;
751 }
752
753 /* unlink from siblings */
754 if (node->prev->next) {
755 node->prev->next = node->next;
756 }
757 if (node->next) {
758 node->next->prev = node->prev;
759 } else {
760 /* unlinking the last node */
761 iter = node->prev;
762 while (iter->prev != node) {
763 iter = iter->prev;
764 }
765 /* update the "last" pointer from the first node */
766 iter->prev = node->prev;
767 }
768
769 /* unlink from parent */
770 if (node->parent) {
771 if (node->parent->child == node) {
772 /* the node is the first child */
773 node->parent->child = node->next;
774 }
775 node->parent = NULL;
776 }
777
778 node->next = NULL;
779 node->prev = node;
780
Michal Vasko55f60be2015-10-14 13:12:58 +0200781 lyd_correct_ns(node);
Michal Vasko2d162e12015-09-24 14:33:29 +0200782 return EXIT_SUCCESS;
783}
784
Michal Vaskoc0797f82015-10-14 15:51:25 +0200785API struct lyd_node *
786lyd_dup(struct lyd_node *node, int recursive)
787{
788 struct lyd_node *next, *elem, *ret, *parent, *new_node;
789 struct lyd_attr *attr;
790 struct lyd_node_leaf_list *new_leaf;
791 struct lyd_node_anyxml *new_axml;
792 struct lys_type *type;
793
794 if (!node) {
795 ly_errno = LY_EINVAL;
796 return NULL;
797 }
798
799 ret = NULL;
800 parent = NULL;
801
802 /* LY_TREE_DFS */
803 for (elem = next = node; elem; elem = next) {
804
805 /* fill specific part */
806 switch (elem->schema->nodetype) {
807 case LYS_LEAF:
808 case LYS_LEAFLIST:
809 new_leaf = malloc(sizeof *new_leaf);
810 new_node = (struct lyd_node *)new_leaf;
811
812 new_leaf->value = ((struct lyd_node_leaf_list *)elem)->value;
813 new_leaf->value_str = lydict_insert(elem->schema->module->ctx,
814 ((struct lyd_node_leaf_list *)elem)->value_str, 0);
815 new_leaf->value_type = ((struct lyd_node_leaf_list *)elem)->value_type;
816 /* bits type must be treated specially */
817 if (new_leaf->value_type == LY_TYPE_BITS) {
818 for (type = &((struct lys_node_leaf *)elem->schema)->type; type->der->module; type = &type->der->type) {
819 if (type->base != LY_TYPE_BITS) {
820 LOGINT;
Michal Vaskod80e6c72015-10-15 09:37:01 +0200821 lyd_free(new_node);
Michal Vaskoc0797f82015-10-14 15:51:25 +0200822 lyd_free(ret);
823 return NULL;
824 }
825 }
826
827 new_leaf->value.bit = malloc(type->info.bits.count * sizeof *new_leaf->value.bit);
828 memcpy(new_leaf->value.bit, ((struct lyd_node_leaf_list *)elem)->value.bit,
829 type->info.bits.count * sizeof *new_leaf->value.bit);
830 }
831 break;
832 case LYS_ANYXML:
833 new_axml = malloc(sizeof *new_axml);
834 new_node = (struct lyd_node *)new_axml;
835
836 new_axml->value = lyxml_dup_elem(elem->schema->module->ctx, ((struct lyd_node_anyxml *)elem)->value,
837 NULL, 1);
838 break;
839 case LYS_CONTAINER:
840 case LYS_LIST:
841 case LYS_NOTIF:
842 case LYS_RPC:
843 new_node = malloc(sizeof *new_node);
844 new_node->child = NULL;
845 break;
846 default:
Michal Vaskoc0797f82015-10-14 15:51:25 +0200847 lyd_free(ret);
Michal Vasko24337392015-10-16 09:58:16 +0200848 LOGINT;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200849 return NULL;
850 }
851
852 /* fill common part */
853 new_node->schema = elem->schema;
854 new_node->attr = NULL;
855 LY_TREE_FOR(elem->attr, attr) {
856 lyd_dup_attr(elem->schema->module->ctx, new_node, attr);
857 }
858 new_node->next = NULL;
859 new_node->prev = new_node;
860 new_node->parent = NULL;
861
862 if (!ret) {
863 ret = new_node;
864 }
865 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200866 if (lyd_insert(parent, new_node)) {
Michal Vaskoc0797f82015-10-14 15:51:25 +0200867 lyd_free(ret);
Michal Vasko24337392015-10-16 09:58:16 +0200868 LOGINT;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200869 return NULL;
870 }
871 }
872
873 if (!recursive) {
874 break;
875 }
876
877 /* LY_TREE_DFS_END */
878 /* select element for the next run - children first */
879 next = elem->child;
880 /* child exception for lyd_node_leaf and lyd_node_leaflist */
881 if (elem->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML)) {
882 next = NULL;
883 }
884 if (!next) {
885 /* no children, so try siblings */
886 next = elem->next;
887 } else {
888 parent = new_node;
889 }
890 while (!next) {
891 /* no siblings, go back through parents */
892 elem = elem->parent;
893 if (elem->parent == node->parent) {
894 break;
895 }
Michal Vasko785b2ad2015-10-15 09:37:15 +0200896 if (!parent) {
897 LOGINT;
898 }
Michal Vaskoc0797f82015-10-14 15:51:25 +0200899 parent = parent->parent;
900 /* parent is already processed, go to its sibling */
901 next = elem->next;
902 }
903 }
904
905 return ret;
906}
907
Michal Vasko2d162e12015-09-24 14:33:29 +0200908static void
909lyd_attr_free(struct ly_ctx *ctx, struct lyd_attr *attr)
910{
911 if (!attr) {
912 return;
913 }
914
915 if (attr->next) {
916 lyd_attr_free(ctx, attr->next);
917 }
918 lydict_remove(ctx, attr->name);
919 lydict_remove(ctx, attr->value);
920 free(attr);
921}
922
Michal Vaskofd76bd12015-09-24 15:49:57 +0200923struct lyd_node *
924lyd_attr_parent(struct lyd_node *root, struct lyd_attr *attr)
925{
926 struct lyd_node *next, *elem;
927 struct lyd_attr *node_attr;
928
929 LY_TREE_DFS_BEGIN(root, next, elem) {
930 for (node_attr = elem->attr; node_attr; node_attr = node_attr->next) {
931 if (node_attr == attr) {
932 return elem;
933 }
934 }
935 LY_TREE_DFS_END(root, next, elem)
936 }
937
938 return NULL;
939}
940
Radek Krejci134610e2015-10-20 17:15:34 +0200941static struct lyd_ns *
942lyd_get_attr_ns(struct lyd_node *node, const char *prefix)
943{
944 struct lyd_attr *attr;
945 int len;
946
947 while(node) {
948
949 if (!prefix) {
950 len = 0;
951 } else {
952 len = strlen(prefix) + 1;
953 }
954
955 for (attr = node->attr; attr; attr = attr->next) {
956 if (attr->type != LYD_ATTR_NS) {
957 continue;
958 }
959 if (!attr->name) {
960 if (!len) {
961 /* default namespace found */
962 if (!attr->value) {
963 /* empty default namespace -> no default namespace */
964 return NULL;
965 }
966 return (struct lyd_ns *)attr;
967 }
968 } else if (len && !memcmp(attr->name, prefix, len)) {
969 /* prefix found */
970 return (struct lyd_ns *)attr;
971 }
972 }
973 node = node->parent;
974 }
975
976 return NULL;
977}
978
979API struct lyd_attr *
980lyd_insert_attr(struct lyd_node *parent, const char *name, const char *value)
981{
982 struct lyd_ns *ns;
983 struct lyd_attr *a, *iter;
984 struct ly_ctx *ctx;
985 const char *p;
986 char *aux;
987
988 if (!parent || !name || !value) {
989 return NULL;
990 }
991 ctx = parent->schema->module->ctx;
992
993 a = calloc(1, sizeof *a);
994
995 if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || !name[5])) {
996 ns = (struct lyd_ns *)a;
997 ns->type = LYD_ATTR_NS;
998 ns->parent = parent;
999 if (name[5]) {
1000 ns->prefix = lydict_insert(ctx, &(name[6]), 0);
1001 }
1002 } else {
1003 a->type = LYD_ATTR_STD;
1004 if ((p = strchr(name, ':'))) {
1005 /* search for the namespace */
1006 aux = strndup(name, p - name);
1007 a->ns = lyd_get_attr_ns(parent, aux);
1008 free(aux);
1009
1010 if (!a->ns) {
1011 /* namespace not found */
1012 free(a);
1013 return NULL;
1014 }
1015 } else {
1016 /* no prefix -> no namespace */
1017 a->name = name;
1018 }
1019 }
1020
1021 a->value = lydict_insert(ctx, value, 0);
1022 if (!parent->attr) {
1023 parent->attr = a;
1024 } else {
1025 for (iter = parent->attr; iter->next; iter = iter->next);
1026 iter->next = a;
1027 }
1028
1029 return a;
1030}
1031
Michal Vasko2d162e12015-09-24 14:33:29 +02001032API void
1033lyd_free(struct lyd_node *node)
1034{
1035 struct lyd_node *next, *child;
1036
1037 if (!node) {
1038 return;
1039 }
1040
1041 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
1042 /* free children */
1043 LY_TREE_FOR_SAFE(node->child, next, child) {
1044 lyd_free(child);
1045 }
1046 } else if (node->schema->nodetype == LYS_ANYXML) {
1047 lyxml_free_elem(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
1048 } else {
1049 /* free value */
Michal Vasko4c183312015-09-25 10:41:47 +02001050 switch(((struct lyd_node_leaf_list *)node)->value_type) {
Michal Vasko2d162e12015-09-24 14:33:29 +02001051 case LY_TYPE_BINARY:
1052 case LY_TYPE_STRING:
Michal Vasko4c183312015-09-25 10:41:47 +02001053 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf_list *)node)->value.string);
Michal Vasko2d162e12015-09-24 14:33:29 +02001054 break;
1055 case LY_TYPE_BITS:
Michal Vasko4c183312015-09-25 10:41:47 +02001056 if (((struct lyd_node_leaf_list *)node)->value.bit) {
1057 free(((struct lyd_node_leaf_list *)node)->value.bit);
Michal Vasko2d162e12015-09-24 14:33:29 +02001058 }
1059 break;
1060 default:
1061 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
1062 break;
1063 }
1064 }
1065
1066 lyd_unlink(node);
1067 lyd_attr_free(node->schema->module->ctx, node->attr);
1068 free(node);
1069}
1070
Michal Vaskoff4c2832015-10-15 13:30:50 +02001071API char *
1072lyxml_serialize(struct lyxml_elem *anyxml)
1073{
1074 FILE *stream;
1075 char *buf;
1076 size_t buf_size;
1077
1078 if (!anyxml) {
1079 ly_errno = LY_EINVAL;
1080 return NULL;
1081 }
1082
1083 stream = open_memstream(&buf, &buf_size);
1084 if (!stream) {
1085 ly_errno = LY_ESYS;
1086 return NULL;
1087 }
1088 if (lyxml_dump(stream, anyxml, 0) == 0) {
1089 free(buf);
1090 buf = NULL;
1091 ly_errno = LY_EINVAL;
1092 }
1093 fclose(stream);
1094
1095 return buf;
1096}
1097
Michal Vasko2d162e12015-09-24 14:33:29 +02001098int
1099lyd_compare(struct lyd_node *first, struct lyd_node *second, int unique)
1100{
1101 struct lys_node_list *slist;
1102 struct lys_node *snode;
1103 struct lyd_node *diter;
1104 const char *val1, *val2;
1105 int i, j;
1106
1107 assert(first);
1108 assert(second);
1109
1110 if (first->schema != second->schema) {
1111 return 1;
1112 }
1113
1114 switch (first->schema->nodetype) {
1115 case LYS_LEAFLIST:
1116 /* compare values */
Michal Vasko4c183312015-09-25 10:41:47 +02001117 if (((struct lyd_node_leaf_list *)first)->value_str == ((struct lyd_node_leaf_list *)second)->value_str) {
Michal Vasko2d162e12015-09-24 14:33:29 +02001118 return 0;
1119 }
1120 return 1;
1121 case LYS_LIST:
Michal Vasko4c183312015-09-25 10:41:47 +02001122 slist = (struct lys_node_list *)first->schema;
Michal Vasko2d162e12015-09-24 14:33:29 +02001123
1124 if (unique) {
1125 /* compare unique leafs */
1126 for (i = 0; i < slist->unique_size; i++) {
1127 for (j = 0; j < slist->unique[i].leafs_size; j++) {
1128 snode = (struct lys_node *)slist->unique[i].leafs[j];
1129 /* use default values if the instances of unique leafs are not present */
1130 val1 = val2 = ((struct lys_node_leaf *)snode)->dflt;
1131 LY_TREE_FOR(first->child, diter) {
1132 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001133 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001134 break;
1135 }
1136 }
1137 LY_TREE_FOR(second->child, diter) {
1138 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001139 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001140 break;
1141 }
1142 }
1143 if (val1 != val2) {
1144 break;
1145 }
1146 }
1147 if (j && j == slist->unique[i].leafs_size) {
1148 /* all unique leafs are the same in this set */
1149 return 0;
1150 }
1151 }
1152 }
1153
1154 /* compare keys */
1155 for (i = 0; i < slist->keys_size; i++) {
1156 snode = (struct lys_node *)slist->keys[i];
1157 val1 = val2 = NULL;
1158 LY_TREE_FOR(first->child, diter) {
1159 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001160 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001161 break;
1162 }
1163 }
1164 LY_TREE_FOR(second->child, diter) {
1165 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001166 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001167 break;
1168 }
1169 }
1170 if (val1 != val2) {
1171 return 1;
1172 }
1173 }
1174
1175 return 0;
1176 default:
1177 /* no additional check is needed */
1178 return 0;
1179 }
1180}
1181
1182API struct lyd_set *
1183lyd_set_new(void)
1184{
1185 return calloc(1, sizeof(struct lyd_set));
1186}
1187
1188API void
1189lyd_set_free(struct lyd_set *set)
1190{
1191 if (!set) {
1192 return;
1193 }
1194
1195 free(set->set);
1196 free(set);
1197}
1198
1199API int
1200lyd_set_add(struct lyd_set *set, struct lyd_node *node)
1201{
1202 struct lyd_node **new;
1203
1204 if (!set) {
1205 ly_errno = LY_EINVAL;
1206 return EXIT_FAILURE;
1207 }
1208
1209 if (set->size == set->number) {
1210 new = realloc(set->set, (set->size + 8) * sizeof *(set->set));
1211 if (!new) {
1212 LOGMEM;
1213 return EXIT_FAILURE;
1214 }
1215 set->size += 8;
1216 set->set = new;
1217 }
1218
1219 set->set[set->number++] = node;
1220
1221 return EXIT_SUCCESS;
1222}