blob: b17067b6cd16914197f1d4d646ac9c9ee46f8b53 [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"
Radek Krejcic6704c82015-10-06 11:12:45 +020037#include "xml_private.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 Vaskoa5835e92015-10-20 15:07:39 +020088 if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC,
Michal Vasko09319fd2015-10-16 09:52:23 +020089 &snode) || !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 Vaskoa5835e92015-10-20 15:07:39 +0200134 if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_LEAFLIST | LYS_LEAF, &snode)
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200135 || !snode) {
136 return NULL;
137 }
138
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200139 if (type != ((struct lys_node_leaf *)snode)->type.base) {
140 ly_errno = LY_EINVAL;
141 return NULL;
142 }
143
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200144 switch (type) {
145 case LY_TYPE_BINARY:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200146 val_str = (char *)lydict_insert(snode->module->ctx, value.binary, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200147 break;
148
149 case LY_TYPE_BITS:
150 /* find the type definition */
151 for (stype = &((struct lys_node_leaf *)snode)->type; stype->der->module; stype = &stype->der->type) {
152 if (stype->base != LY_TYPE_BITS) {
153 LOGINT;
154 return NULL;
155 }
156 }
157
158 /* concatenate set bits */
159 for (i = 0; i < stype->info.bits.count; ++i) {
Michal Vasko0e3c8722015-09-29 16:06:08 +0200160 if (!value.bit[i]) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200161 continue;
162 }
163
164 prev_len = str_len;
Michal Vasko0e3c8722015-09-29 16:06:08 +0200165 str_len += strlen(value.bit[i]->name) + 1;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200166 val_str = realloc((char *)val_str, str_len * sizeof(char));
167
168 if (prev_len) {
169 val_str[prev_len] = ' ';
170 ++prev_len;
171 }
Michal Vasko0e3c8722015-09-29 16:06:08 +0200172 strcpy(val_str + prev_len, value.bit[i]->name);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200173 }
174
175 val_str = (char *)lydict_insert_zc(snode->module->ctx, val_str);
176 break;
177
178 case LY_TYPE_BOOL:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200179 if (value.bool) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200180 val_str = (char *)lydict_insert(snode->module->ctx, "true", 4);
181 } else {
182 val_str = (char *)lydict_insert(snode->module->ctx, "false", 5);
183 }
184 break;
185
186 case LY_TYPE_DEC64:
187 /* find the type definition */
188 for (stype = &((struct lys_node_leaf *)snode)->type; stype->der->module; stype = &stype->der->type) {
189 if (stype->base != LY_TYPE_DEC64) {
190 LOGINT;
191 return NULL;
192 }
193 }
194
195 for (i = 0, exp = 1; i < stype->info.dec64.dig; ++i, exp *= 10);
Michal Vasko0e3c8722015-09-29 16:06:08 +0200196 sprintf(str_num, "%01.1Lf", ((long double)value.dec64) / exp);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200197 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
198 break;
199
200 case LY_TYPE_EMPTY:
201 break;
202
203 case LY_TYPE_ENUM:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200204 val_str = (char *)lydict_insert(snode->module->ctx, value.enm->name, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200205 break;
206
207 case LY_TYPE_IDENT:
208 /* TODO move to function if used somewhere else (module -> import prefix) */
Michal Vasko0e3c8722015-09-29 16:06:08 +0200209 src_mod = value.ident->module;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200210 if (src_mod->type) {
211 src_mod = ((struct lys_submodule *)src_mod)->belongsto;
212 }
213 dst_mod = snode->module;
214 if (dst_mod->type) {
215 dst_mod = ((struct lys_submodule *)dst_mod)->belongsto;
216 }
217 if (src_mod != dst_mod) {
218 for (i = 0; i < src_mod->imp_size; ++i) {
219 if (src_mod->imp[i].module == dst_mod) {
220 prefix = src_mod->imp[i].prefix;
221 break;
222 }
223 }
224 if (!prefix) {
225 LOGINT;
226 return NULL;
227 }
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200228 }
229
230 if (!prefix) {
Michal Vasko0e3c8722015-09-29 16:06:08 +0200231 val_str = (char *)lydict_insert(snode->module->ctx, value.ident->name, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200232 } else {
Michal Vasko0e3c8722015-09-29 16:06:08 +0200233 val_str = malloc((strlen(prefix) + 1 + strlen(value.ident->name) + 1) * sizeof(char));
234 sprintf(val_str, "%s:%s", prefix, value.ident->name);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200235 val_str = (char *)lydict_insert_zc(snode->module->ctx, val_str);
236 }
237 break;
238
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200239 case LY_TYPE_LEAFREF:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200240 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 +0200241 break;
242
243 case LY_TYPE_STRING:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200244 val_str = (char *)lydict_insert(snode->module->ctx, value.string, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200245 break;
246
247 case LY_TYPE_INT8:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200248 sprintf(str_num, "%hhd", value.int8);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200249 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
250 break;
251
252 case LY_TYPE_INT16:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200253 sprintf(str_num, "%hd", value.int16);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200254 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
255 break;
256
257 case LY_TYPE_INT32:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200258 sprintf(str_num, "%d", value.int32);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200259 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
260 break;
261
262 case LY_TYPE_INT64:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200263 sprintf(str_num, "%ld", value.int64);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200264 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
265 break;
266
267 case LY_TYPE_UINT8:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200268 sprintf(str_num, "%hhu", value.uint8);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200269 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
270 break;
271
272 case LY_TYPE_UINT16:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200273 sprintf(str_num, "%hu", value.uint16);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200274 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
275 break;
276
277 case LY_TYPE_UINT32:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200278 sprintf(str_num, "%u", value.uint32);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200279 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
280 break;
281
282 case LY_TYPE_UINT64:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200283 sprintf(str_num, "%lu", value.uint64);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200284 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
285 break;
286
Michal Vasko14580182015-10-09 14:49:00 +0200287 default: /* LY_TYPE_INST */
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200288 LOGINT;
289 return NULL;
290 }
291
292 ret = calloc(1, sizeof *ret);
293 ret->schema = snode;
294 ret->prev = (struct lyd_node *)ret;
295 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200296 if (lyd_insert(parent, (struct lyd_node *)ret)) {
297 lyd_free((struct lyd_node *)ret);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200298 lydict_remove(snode->module->ctx, val_str);
299 return NULL;
300 }
301 }
Michal Vasko81eef2c2015-10-02 15:37:25 +0200302
303 if (type == LY_TYPE_BINARY) {
304 ret->value.binary = val_str;
305 } else if (type == LY_TYPE_STRING) {
306 ret->value.string = val_str;
307 } else if (type == LY_TYPE_BITS) {
308 /* stype is left with the bits type definition */
309 ret->value.bit = malloc(stype->info.bits.count * sizeof *ret->value.bit);
310 memcpy(ret->value.bit, value.bit, stype->info.bits.count * sizeof *ret->value.bit);
311 } else {
312 ret->value = value;
313 }
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200314 ret->value_str = val_str;
315 ret->value_type = type;
316
317 return (struct lyd_node *)ret;
318}
319
320API struct lyd_node *
321lyd_new_leaf_str(struct lyd_node *parent, struct lys_module *module, const char *name, LY_DATA_TYPE type,
322 const char *val_str)
323{
324 struct lyd_node_leaf_list *ret;
325 struct lys_node *snode = NULL, *siblings;
326 struct lys_type *stype, *utype;
327 int found;
328
329 if ((!parent && !module) || !name) {
330 ly_errno = LY_EINVAL;
331 return NULL;
332 }
333
334 if (!parent) {
335 siblings = module->data;
336 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200337 if (!parent->schema) {
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200338 ly_errno = LY_EINVAL;
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200339 return NULL;
340 }
341 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200342 }
343
Michal Vaskoa5835e92015-10-20 15:07:39 +0200344 if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_LEAFLIST | LYS_LEAF, &snode)
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200345 || !snode) {
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200346 ly_errno = LY_EINVAL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200347 return NULL;
348 }
349
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200350 /* get the correct type struct */
351 stype = &((struct lys_node_leaf *)snode)->type;
352 if (stype->base == LY_TYPE_UNION) {
353 found = 0;
354 utype = stype;
355 stype = lyp_get_next_union_type(utype, NULL, &found);
356 while (stype && (stype->base != type)) {
357 found = 0;
358 stype = lyp_get_next_union_type(utype, stype, &found);
359 }
360 if (!stype) {
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200361 ly_errno = LY_EINVAL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200362 return NULL;
363 }
364 }
365
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200366 if (type && (type != stype->base)) {
367 ly_errno = LY_EINVAL;
368 return NULL;
369 }
370 type = stype->base;
371
372 ret = calloc(1, sizeof *ret);
373 ret->schema = snode;
374 ret->prev = (struct lyd_node *)ret;
375 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200376 if (lyd_insert(parent, (struct lyd_node *)ret)) {
377 lyd_free((struct lyd_node *)ret);
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200378 return NULL;
379 }
380 }
381 ret->value_str = lydict_insert((module ? module->ctx : parent->schema->module->ctx), val_str, 0);
382 ret->value_type = type;
383
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200384 if (lyp_parse_value(ret, stype, 1, NULL, 0)) {
Michal Vasko24337392015-10-16 09:58:16 +0200385 lyd_free((struct lyd_node *)ret);
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200386 ly_errno = LY_EINVAL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200387 return NULL;
388 }
389
390 return (struct lyd_node *)ret;
391
392}
393
394API struct lyd_node *
395lyd_new_anyxml(struct lyd_node *parent, struct lys_module *module, const char *name, const char *val_xml)
396{
Michal Vasko587998f2015-09-29 16:07:53 +0200397 struct lyd_node_anyxml *ret;
398 struct lys_node *siblings, *snode;
399 struct lyxml_elem *root, *first_child, *last_child, *child;
400 struct ly_ctx *ctx;
401 char *xml;
402
403 if ((!parent && !module) || !name || !val_xml) {
404 ly_errno = LY_EINVAL;
405 return NULL;
406 }
407
408 if (!parent) {
409 siblings = module->data;
410 ctx = module->ctx;
411 } else {
412 if (!parent->schema) {
413 return NULL;
414 }
415 siblings = parent->schema->child;
416 ctx = parent->schema->module->ctx;
417 }
418
Michal Vaskoa5835e92015-10-20 15:07:39 +0200419 if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_ANYXML, &snode)
Michal Vasko587998f2015-09-29 16:07:53 +0200420 || !snode) {
421 return NULL;
422 }
423
424 ret = calloc(1, sizeof *ret);
425 ret->schema = snode;
426 ret->prev = (struct lyd_node *)ret;
427 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200428 if (lyd_insert(parent, (struct lyd_node *)ret)) {
429 lyd_free((struct lyd_node *)ret);
Michal Vasko587998f2015-09-29 16:07:53 +0200430 return NULL;
431 }
432 }
433
434 /* add fake root so we can parse the data */
435 asprintf(&xml, "<root>%s</root>", val_xml);
436 root = lyxml_read(ctx, xml, 0);
437 free(xml);
Michal Vasko5b6e78d2015-10-09 15:01:10 +0200438 if (!root) {
Michal Vasko24337392015-10-16 09:58:16 +0200439 lyd_free((struct lyd_node *)ret);
Michal Vasko5b6e78d2015-10-09 15:01:10 +0200440 return NULL;
441 }
Michal Vasko587998f2015-09-29 16:07:53 +0200442
443 /* remove the root */
Radek Krejcie4e4d722015-10-05 16:53:50 +0200444 first_child = last_child = NULL;
Michal Vasko587998f2015-09-29 16:07:53 +0200445 LY_TREE_FOR(root->child, child) {
446 lyxml_unlink_elem(ctx, child, 1);
447 if (!first_child) {
448 first_child = child;
449 last_child = child;
450 } else {
451 last_child->next = child;
452 child->prev = last_child;
453 last_child = child;
454 }
455 }
Radek Krejcie4e4d722015-10-05 16:53:50 +0200456 if (first_child) {
457 first_child->prev = last_child;
458 }
Michal Vasko587998f2015-09-29 16:07:53 +0200459 lyxml_free_elem(ctx, root);
460
461 ret->value = first_child;
462
463 return (struct lyd_node *)ret;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200464}
465
Michal Vasko24337392015-10-16 09:58:16 +0200466API int
467lyd_insert(struct lyd_node *parent, struct lyd_node *node)
Michal Vasko2d162e12015-09-24 14:33:29 +0200468{
469 struct lys_node *sparent;
Michal Vasko24337392015-10-16 09:58:16 +0200470 struct lyd_node *iter;
Michal Vasko2d162e12015-09-24 14:33:29 +0200471
Michal Vasko24337392015-10-16 09:58:16 +0200472 if (!node || !parent) {
473 ly_errno = LY_EINVAL;
474 return EXIT_FAILURE;
Michal Vasko2d162e12015-09-24 14:33:29 +0200475 }
476
477 /* check placing the node to the appropriate place according to the schema */
478 sparent = node->schema->parent;
Radek Krejci8a6794f2015-10-20 17:14:48 +0200479 while (!(sparent->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_NOTIF))) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200480 sparent = sparent->parent;
481 }
482 if (sparent != parent->schema) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200483 return EXIT_FAILURE;
484 }
485
Michal Vasko24337392015-10-16 09:58:16 +0200486 if (node->parent || node->prev->next) {
487 lyd_unlink(node);
488 }
489
Michal Vasko2d162e12015-09-24 14:33:29 +0200490 if (!parent->child) {
491 /* add as the only child of the parent */
492 parent->child = node;
493 } else {
494 /* add as the last child of the parent */
495 parent->child->prev->next = node;
496 node->prev = parent->child->prev;
497 for (iter = node; iter->next; iter = iter->next);
498 parent->child->prev = iter;
499 }
Michal Vasko9cc2d0a2015-10-14 15:49:07 +0200500
Michal Vasko2d162e12015-09-24 14:33:29 +0200501 LY_TREE_FOR(node, iter) {
502 iter->parent = parent;
Michal Vasko2d162e12015-09-24 14:33:29 +0200503 }
504
505 return EXIT_SUCCESS;
506}
507
Michal Vasko02592902015-10-15 12:14:40 +0200508static int
Michal Vasko24337392015-10-16 09:58:16 +0200509lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, int before)
Michal Vasko2d162e12015-09-24 14:33:29 +0200510{
511 struct lys_node *par1, *par2;
Michal Vasko24337392015-10-16 09:58:16 +0200512 struct lyd_node *iter, *last;
Michal Vasko3f7dba12015-10-15 13:09:27 +0200513
514 if (sibling == node) {
515 return EXIT_SUCCESS;
516 }
517
Michal Vasko2d162e12015-09-24 14:33:29 +0200518 /* check placing the node to the appropriate place according to the schema */
519 for (par1 = sibling->schema->parent; par1 && (par1->nodetype & (LYS_CONTAINER | LYS_LIST)); par1 = par1->parent);
520 for (par2 = node->schema->parent; par2 && (par2->nodetype & (LYS_CONTAINER | LYS_LIST)); par2 = par2->parent);
521 if (par1 != par2) {
522 ly_errno = LY_EINVAL;
523 return EXIT_FAILURE;
524 }
525
Michal Vasko24337392015-10-16 09:58:16 +0200526 if (node->parent || node->prev->next) {
527 lyd_unlink(node);
528 }
529
Michal Vasko2d162e12015-09-24 14:33:29 +0200530 LY_TREE_FOR(node, iter) {
531 iter->parent = sibling->parent;
Michal Vasko24337392015-10-16 09:58:16 +0200532 last = iter;
Michal Vasko2d162e12015-09-24 14:33:29 +0200533 }
534
Michal Vasko02592902015-10-15 12:14:40 +0200535 if (before) {
536 if (sibling->prev->next) {
537 /* adding into the list */
538 sibling->prev->next = node;
539 } else if (sibling->parent) {
540 /* at the beginning */
541 sibling->parent->child = node;
Michal Vasko2d162e12015-09-24 14:33:29 +0200542 }
Michal Vasko02592902015-10-15 12:14:40 +0200543 node->prev = sibling->prev;
544 sibling->prev = last;
545 last->next = sibling;
546 } else {
547 if (sibling->next) {
548 /* adding into a middle - fix the prev pointer of the node after inserted nodes */
549 last->next = sibling->next;
550 sibling->next->prev = last;
551 } else {
552 /* at the end - fix the prev pointer of the first node */
553 if (sibling->parent) {
554 sibling->parent->child->prev = last;
555 } else {
556 for (iter = sibling; iter->prev->next; iter = iter->prev);
557 iter->prev = last;
558 }
559 }
560 sibling->next = node;
561 node->prev = sibling;
Michal Vasko2d162e12015-09-24 14:33:29 +0200562 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200563
Michal Vasko24337392015-10-16 09:58:16 +0200564 return EXIT_SUCCESS;
565}
Michal Vasko2d162e12015-09-24 14:33:29 +0200566
Michal Vasko24337392015-10-16 09:58:16 +0200567API int
568lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
569{
570 if (!node || !sibling || lyd_insert_sibling(sibling, node, 1)) {
571 ly_errno = LY_EINVAL;
572 return EXIT_FAILURE;
573 }
574
575 return EXIT_SUCCESS;
576}
577
578API int
579lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
580{
581 if (!node || !sibling || lyd_insert_sibling(sibling, node, 0)) {
582 ly_errno = LY_EINVAL;
583 return EXIT_FAILURE;
584 }
585
586 return EXIT_SUCCESS;
587}
588
589API int
590lyd_validate(struct lyd_node *node, int options)
591{
592 struct lyd_node *next, *iter, *to_free = NULL;
593
594 ly_errno = 0;
595 LY_TREE_DFS_BEGIN(node, next, iter) {
596 if (to_free) {
597 lyd_free(to_free);
598 to_free = NULL;
599 }
600
601 if (lyv_data_content(iter, 0, options, NULL)) {
602 if (ly_errno) {
603 return EXIT_FAILURE;
604 } else {
605 /* safe deferred removal */
606 to_free = iter;
Michal Vasko3f7dba12015-10-15 13:09:27 +0200607 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200608 }
Michal Vasko24337392015-10-16 09:58:16 +0200609
610 LY_TREE_DFS_END(node, next, iter);
Michal Vasko2d162e12015-09-24 14:33:29 +0200611 }
612
Michal Vasko24337392015-10-16 09:58:16 +0200613 if (to_free) {
614 lyd_free(to_free);
615 to_free = NULL;
Michal Vasko02592902015-10-15 12:14:40 +0200616 }
617
618 return EXIT_SUCCESS;
619}
620
Michal Vasko55f60be2015-10-14 13:12:58 +0200621/* return matching namespace in node or any of it's parents */
622static struct lyd_ns *
623lyd_find_ns(struct lyd_node *node, const char *prefix, const char *value)
624{
625 int pref_match, val_match;
626 struct lyd_attr *attr;
627
628 if (!node) {
629 return NULL;
630 }
631
632 for (; node; node = node->parent) {
633 for (attr = node->attr; attr; attr = attr->next) {
634 if (attr->type != LYD_ATTR_NS) {
635 continue;
636 }
637
638 pref_match = 0;
639 if (!prefix && !attr->name) {
640 pref_match = 1;
641 }
642 if (prefix && attr->name && !strcmp(attr->name, prefix)) {
643 pref_match = 1;
644 }
645
646 val_match = 0;
647 if (!value && !attr->value) {
648 val_match = 1;
649 }
650 if (value && attr->value && !strcmp(attr->value, value)) {
651 val_match = 1;
652 }
653
654 if (pref_match && val_match) {
655 return (struct lyd_ns *)attr;
656 }
657 }
658 }
659
660 return NULL;
661}
662
663/* create an attribute copy including correct namespace if used */
664static struct lyd_attr *
665lyd_dup_attr(struct ly_ctx *ctx, struct lyd_node *parent, struct lyd_attr *attr)
666{
667 struct lyd_attr *ret;
668
669 /* allocate new attr */
670 if (!parent->attr) {
671 parent->attr = malloc(sizeof *parent->attr);
672 ret = parent->attr;
673 } else {
674 for (ret = parent->attr; ret->next; ret = ret->next);
675 ret->next = malloc(sizeof *ret);
676 ret = ret->next;
677 }
678
679 /* fill new attr except ns/parent */
680 ret->type = attr->type;
681 ret->next = NULL;
682 ret->name = lydict_insert(ctx, attr->name, 0);
683 ret->value = lydict_insert(ctx, attr->value, 0);
684
685 if (ret->type == LYD_ATTR_NS) {
686 /* fill parent in a NS */
687 ((struct lyd_ns *)ret)->parent = parent;
688 } else if (attr->ns) {
689 /* attr has a namespace */
690
691 /* perhaps the namespace was already copied over? */
692 ret->ns = lyd_find_ns(parent, attr->ns->prefix, attr->ns->value);
693 if (!ret->ns) {
694 /* nope, it wasn't */
695 ret->ns = (struct lyd_ns *)lyd_dup_attr(ctx, parent, (struct lyd_attr *)attr->ns);
696 }
697 } else {
698 /* there is no namespace */
699 ret->ns = NULL;
700 }
701
702 return ret;
703}
704
705/* correct namespaces in the attributes of subtree nodes of node */
706static void
707lyd_correct_ns(struct lyd_node *node)
708{
709 const struct lyd_ns *attr_ns;
710 struct lyd_attr *attr;
711 struct lyd_node *node_root, *ns_root, *tmp;
712
713 /* find the root of node */
714 for (node_root = node; node_root->parent; node_root = node_root->parent);
715
716 LY_TREE_DFS_BEGIN(node, tmp, node) {
717 for (attr = node->attr; attr; attr = attr->next) {
718 if ((attr->type != LYD_ATTR_STD) || !attr->ns) {
719 continue;
720 }
721
722 /* find the root of attr NS */
723 for (ns_root = attr->ns->parent; ns_root->parent; ns_root = ns_root->parent);
724
725 /* attr NS is defined outside node subtree */
726 if (ns_root != node_root) {
727 attr_ns = attr->ns;
728 /* we may have already copied the NS over? */
729 attr->ns = lyd_find_ns(node, attr_ns->prefix, attr_ns->value);
730
731 /* we haven't copied it over, copy it now */
732 if (!attr->ns) {
733 attr->ns = (struct lyd_ns *)lyd_dup_attr(node->schema->module->ctx, node,
734 (struct lyd_attr *)attr_ns);
735 }
736 }
737 }
738 LY_TREE_DFS_END(node, tmp, node);
739 }
740}
741
Michal Vasko2d162e12015-09-24 14:33:29 +0200742API int
743lyd_unlink(struct lyd_node *node)
744{
745 struct lyd_node *iter;
746
747 if (!node) {
748 ly_errno = LY_EINVAL;
749 return EXIT_FAILURE;
750 }
751
752 /* unlink from siblings */
753 if (node->prev->next) {
754 node->prev->next = node->next;
755 }
756 if (node->next) {
757 node->next->prev = node->prev;
758 } else {
759 /* unlinking the last node */
760 iter = node->prev;
761 while (iter->prev != node) {
762 iter = iter->prev;
763 }
764 /* update the "last" pointer from the first node */
765 iter->prev = node->prev;
766 }
767
768 /* unlink from parent */
769 if (node->parent) {
770 if (node->parent->child == node) {
771 /* the node is the first child */
772 node->parent->child = node->next;
773 }
774 node->parent = NULL;
775 }
776
777 node->next = NULL;
778 node->prev = node;
779
Michal Vasko55f60be2015-10-14 13:12:58 +0200780 lyd_correct_ns(node);
Michal Vasko2d162e12015-09-24 14:33:29 +0200781 return EXIT_SUCCESS;
782}
783
Michal Vaskoc0797f82015-10-14 15:51:25 +0200784API struct lyd_node *
785lyd_dup(struct lyd_node *node, int recursive)
786{
787 struct lyd_node *next, *elem, *ret, *parent, *new_node;
788 struct lyd_attr *attr;
789 struct lyd_node_leaf_list *new_leaf;
790 struct lyd_node_anyxml *new_axml;
791 struct lys_type *type;
792
793 if (!node) {
794 ly_errno = LY_EINVAL;
795 return NULL;
796 }
797
798 ret = NULL;
799 parent = NULL;
800
801 /* LY_TREE_DFS */
802 for (elem = next = node; elem; elem = next) {
803
804 /* fill specific part */
805 switch (elem->schema->nodetype) {
806 case LYS_LEAF:
807 case LYS_LEAFLIST:
808 new_leaf = malloc(sizeof *new_leaf);
809 new_node = (struct lyd_node *)new_leaf;
810
811 new_leaf->value = ((struct lyd_node_leaf_list *)elem)->value;
812 new_leaf->value_str = lydict_insert(elem->schema->module->ctx,
813 ((struct lyd_node_leaf_list *)elem)->value_str, 0);
814 new_leaf->value_type = ((struct lyd_node_leaf_list *)elem)->value_type;
815 /* bits type must be treated specially */
816 if (new_leaf->value_type == LY_TYPE_BITS) {
817 for (type = &((struct lys_node_leaf *)elem->schema)->type; type->der->module; type = &type->der->type) {
818 if (type->base != LY_TYPE_BITS) {
819 LOGINT;
Michal Vaskod80e6c72015-10-15 09:37:01 +0200820 lyd_free(new_node);
Michal Vaskoc0797f82015-10-14 15:51:25 +0200821 lyd_free(ret);
822 return NULL;
823 }
824 }
825
826 new_leaf->value.bit = malloc(type->info.bits.count * sizeof *new_leaf->value.bit);
827 memcpy(new_leaf->value.bit, ((struct lyd_node_leaf_list *)elem)->value.bit,
828 type->info.bits.count * sizeof *new_leaf->value.bit);
829 }
830 break;
831 case LYS_ANYXML:
832 new_axml = malloc(sizeof *new_axml);
833 new_node = (struct lyd_node *)new_axml;
834
835 new_axml->value = lyxml_dup_elem(elem->schema->module->ctx, ((struct lyd_node_anyxml *)elem)->value,
836 NULL, 1);
837 break;
838 case LYS_CONTAINER:
839 case LYS_LIST:
840 case LYS_NOTIF:
841 case LYS_RPC:
842 new_node = malloc(sizeof *new_node);
843 new_node->child = NULL;
844 break;
845 default:
Michal Vaskoc0797f82015-10-14 15:51:25 +0200846 lyd_free(ret);
Michal Vasko24337392015-10-16 09:58:16 +0200847 LOGINT;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200848 return NULL;
849 }
850
851 /* fill common part */
852 new_node->schema = elem->schema;
853 new_node->attr = NULL;
854 LY_TREE_FOR(elem->attr, attr) {
855 lyd_dup_attr(elem->schema->module->ctx, new_node, attr);
856 }
857 new_node->next = NULL;
858 new_node->prev = new_node;
859 new_node->parent = NULL;
860
861 if (!ret) {
862 ret = new_node;
863 }
864 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200865 if (lyd_insert(parent, new_node)) {
Michal Vaskoc0797f82015-10-14 15:51:25 +0200866 lyd_free(ret);
Michal Vasko24337392015-10-16 09:58:16 +0200867 LOGINT;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200868 return NULL;
869 }
870 }
871
872 if (!recursive) {
873 break;
874 }
875
876 /* LY_TREE_DFS_END */
877 /* select element for the next run - children first */
878 next = elem->child;
879 /* child exception for lyd_node_leaf and lyd_node_leaflist */
880 if (elem->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML)) {
881 next = NULL;
882 }
883 if (!next) {
884 /* no children, so try siblings */
885 next = elem->next;
886 } else {
887 parent = new_node;
888 }
889 while (!next) {
890 /* no siblings, go back through parents */
891 elem = elem->parent;
892 if (elem->parent == node->parent) {
893 break;
894 }
Michal Vasko785b2ad2015-10-15 09:37:15 +0200895 if (!parent) {
896 LOGINT;
897 }
Michal Vaskoc0797f82015-10-14 15:51:25 +0200898 parent = parent->parent;
899 /* parent is already processed, go to its sibling */
900 next = elem->next;
901 }
902 }
903
904 return ret;
905}
906
Michal Vasko2d162e12015-09-24 14:33:29 +0200907static void
908lyd_attr_free(struct ly_ctx *ctx, struct lyd_attr *attr)
909{
910 if (!attr) {
911 return;
912 }
913
914 if (attr->next) {
915 lyd_attr_free(ctx, attr->next);
916 }
917 lydict_remove(ctx, attr->name);
918 lydict_remove(ctx, attr->value);
919 free(attr);
920}
921
Michal Vaskofd76bd12015-09-24 15:49:57 +0200922struct lyd_node *
923lyd_attr_parent(struct lyd_node *root, struct lyd_attr *attr)
924{
925 struct lyd_node *next, *elem;
926 struct lyd_attr *node_attr;
927
928 LY_TREE_DFS_BEGIN(root, next, elem) {
929 for (node_attr = elem->attr; node_attr; node_attr = node_attr->next) {
930 if (node_attr == attr) {
931 return elem;
932 }
933 }
934 LY_TREE_DFS_END(root, next, elem)
935 }
936
937 return NULL;
938}
939
Radek Krejci134610e2015-10-20 17:15:34 +0200940static struct lyd_ns *
941lyd_get_attr_ns(struct lyd_node *node, const char *prefix)
942{
943 struct lyd_attr *attr;
944 int len;
945
946 while(node) {
947
948 if (!prefix) {
949 len = 0;
950 } else {
951 len = strlen(prefix) + 1;
952 }
953
954 for (attr = node->attr; attr; attr = attr->next) {
955 if (attr->type != LYD_ATTR_NS) {
956 continue;
957 }
958 if (!attr->name) {
959 if (!len) {
960 /* default namespace found */
961 if (!attr->value) {
962 /* empty default namespace -> no default namespace */
963 return NULL;
964 }
965 return (struct lyd_ns *)attr;
966 }
967 } else if (len && !memcmp(attr->name, prefix, len)) {
968 /* prefix found */
969 return (struct lyd_ns *)attr;
970 }
971 }
972 node = node->parent;
973 }
974
975 return NULL;
976}
977
978API struct lyd_attr *
979lyd_insert_attr(struct lyd_node *parent, const char *name, const char *value)
980{
981 struct lyd_ns *ns;
982 struct lyd_attr *a, *iter;
983 struct ly_ctx *ctx;
984 const char *p;
985 char *aux;
986
987 if (!parent || !name || !value) {
988 return NULL;
989 }
990 ctx = parent->schema->module->ctx;
991
992 a = calloc(1, sizeof *a);
993
994 if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || !name[5])) {
995 ns = (struct lyd_ns *)a;
996 ns->type = LYD_ATTR_NS;
997 ns->parent = parent;
998 if (name[5]) {
999 ns->prefix = lydict_insert(ctx, &(name[6]), 0);
1000 }
1001 } else {
1002 a->type = LYD_ATTR_STD;
1003 if ((p = strchr(name, ':'))) {
1004 /* search for the namespace */
1005 aux = strndup(name, p - name);
1006 a->ns = lyd_get_attr_ns(parent, aux);
1007 free(aux);
1008
1009 if (!a->ns) {
1010 /* namespace not found */
1011 free(a);
1012 return NULL;
1013 }
1014 } else {
1015 /* no prefix -> no namespace */
1016 a->name = name;
1017 }
1018 }
1019
1020 a->value = lydict_insert(ctx, value, 0);
1021 if (!parent->attr) {
1022 parent->attr = a;
1023 } else {
1024 for (iter = parent->attr; iter->next; iter = iter->next);
1025 iter->next = a;
1026 }
1027
1028 return a;
1029}
1030
Michal Vasko2d162e12015-09-24 14:33:29 +02001031API void
1032lyd_free(struct lyd_node *node)
1033{
1034 struct lyd_node *next, *child;
1035
1036 if (!node) {
1037 return;
1038 }
1039
1040 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
1041 /* free children */
1042 LY_TREE_FOR_SAFE(node->child, next, child) {
1043 lyd_free(child);
1044 }
1045 } else if (node->schema->nodetype == LYS_ANYXML) {
1046 lyxml_free_elem(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
1047 } else {
1048 /* free value */
Michal Vasko4c183312015-09-25 10:41:47 +02001049 switch(((struct lyd_node_leaf_list *)node)->value_type) {
Michal Vasko2d162e12015-09-24 14:33:29 +02001050 case LY_TYPE_BINARY:
1051 case LY_TYPE_STRING:
Michal Vasko4c183312015-09-25 10:41:47 +02001052 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf_list *)node)->value.string);
Michal Vasko2d162e12015-09-24 14:33:29 +02001053 break;
1054 case LY_TYPE_BITS:
Michal Vasko4c183312015-09-25 10:41:47 +02001055 if (((struct lyd_node_leaf_list *)node)->value.bit) {
1056 free(((struct lyd_node_leaf_list *)node)->value.bit);
Michal Vasko2d162e12015-09-24 14:33:29 +02001057 }
1058 break;
1059 default:
1060 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
1061 break;
1062 }
1063 }
1064
1065 lyd_unlink(node);
1066 lyd_attr_free(node->schema->module->ctx, node->attr);
1067 free(node);
1068}
1069
Michal Vaskoff4c2832015-10-15 13:30:50 +02001070API char *
1071lyxml_serialize(struct lyxml_elem *anyxml)
1072{
1073 FILE *stream;
1074 char *buf;
1075 size_t buf_size;
1076
1077 if (!anyxml) {
1078 ly_errno = LY_EINVAL;
1079 return NULL;
1080 }
1081
1082 stream = open_memstream(&buf, &buf_size);
1083 if (!stream) {
1084 ly_errno = LY_ESYS;
1085 return NULL;
1086 }
1087 if (lyxml_dump(stream, anyxml, 0) == 0) {
1088 free(buf);
1089 buf = NULL;
1090 ly_errno = LY_EINVAL;
1091 }
1092 fclose(stream);
1093
1094 return buf;
1095}
1096
Michal Vasko2d162e12015-09-24 14:33:29 +02001097int
1098lyd_compare(struct lyd_node *first, struct lyd_node *second, int unique)
1099{
1100 struct lys_node_list *slist;
1101 struct lys_node *snode;
1102 struct lyd_node *diter;
1103 const char *val1, *val2;
1104 int i, j;
1105
1106 assert(first);
1107 assert(second);
1108
1109 if (first->schema != second->schema) {
1110 return 1;
1111 }
1112
1113 switch (first->schema->nodetype) {
1114 case LYS_LEAFLIST:
1115 /* compare values */
Michal Vasko4c183312015-09-25 10:41:47 +02001116 if (((struct lyd_node_leaf_list *)first)->value_str == ((struct lyd_node_leaf_list *)second)->value_str) {
Michal Vasko2d162e12015-09-24 14:33:29 +02001117 return 0;
1118 }
1119 return 1;
1120 case LYS_LIST:
Michal Vasko4c183312015-09-25 10:41:47 +02001121 slist = (struct lys_node_list *)first->schema;
Michal Vasko2d162e12015-09-24 14:33:29 +02001122
1123 if (unique) {
1124 /* compare unique leafs */
1125 for (i = 0; i < slist->unique_size; i++) {
1126 for (j = 0; j < slist->unique[i].leafs_size; j++) {
1127 snode = (struct lys_node *)slist->unique[i].leafs[j];
1128 /* use default values if the instances of unique leafs are not present */
1129 val1 = val2 = ((struct lys_node_leaf *)snode)->dflt;
1130 LY_TREE_FOR(first->child, diter) {
1131 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001132 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001133 break;
1134 }
1135 }
1136 LY_TREE_FOR(second->child, diter) {
1137 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001138 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001139 break;
1140 }
1141 }
1142 if (val1 != val2) {
1143 break;
1144 }
1145 }
1146 if (j && j == slist->unique[i].leafs_size) {
1147 /* all unique leafs are the same in this set */
1148 return 0;
1149 }
1150 }
1151 }
1152
1153 /* compare keys */
1154 for (i = 0; i < slist->keys_size; i++) {
1155 snode = (struct lys_node *)slist->keys[i];
1156 val1 = val2 = NULL;
1157 LY_TREE_FOR(first->child, diter) {
1158 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001159 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001160 break;
1161 }
1162 }
1163 LY_TREE_FOR(second->child, diter) {
1164 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001165 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001166 break;
1167 }
1168 }
1169 if (val1 != val2) {
1170 return 1;
1171 }
1172 }
1173
1174 return 0;
1175 default:
1176 /* no additional check is needed */
1177 return 0;
1178 }
1179}
1180
1181API struct lyd_set *
1182lyd_set_new(void)
1183{
1184 return calloc(1, sizeof(struct lyd_set));
1185}
1186
1187API void
1188lyd_set_free(struct lyd_set *set)
1189{
1190 if (!set) {
1191 return;
1192 }
1193
1194 free(set->set);
1195 free(set);
1196}
1197
1198API int
1199lyd_set_add(struct lyd_set *set, struct lyd_node *node)
1200{
1201 struct lyd_node **new;
1202
1203 if (!set) {
1204 ly_errno = LY_EINVAL;
1205 return EXIT_FAILURE;
1206 }
1207
1208 if (set->size == set->number) {
1209 new = realloc(set->set, (set->size + 8) * sizeof *(set->set));
1210 if (!new) {
1211 LOGMEM;
1212 return EXIT_FAILURE;
1213 }
1214 set->size += 8;
1215 set->set = new;
1216 }
1217
1218 set->set[set->number++] = node;
1219
1220 return EXIT_SUCCESS;
1221}