blob: f04b19022f769163163a4e390287b4ea4934bd79 [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;
601 } else {
602 /* safe deferred removal */
603 to_free = iter;
Michal Vasko3f7dba12015-10-15 13:09:27 +0200604 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200605 }
Michal Vasko24337392015-10-16 09:58:16 +0200606
607 LY_TREE_DFS_END(node, next, iter);
Michal Vasko2d162e12015-09-24 14:33:29 +0200608 }
609
Michal Vasko24337392015-10-16 09:58:16 +0200610 if (to_free) {
611 lyd_free(to_free);
612 to_free = NULL;
Michal Vasko02592902015-10-15 12:14:40 +0200613 }
614
615 return EXIT_SUCCESS;
616}
617
Michal Vasko55f60be2015-10-14 13:12:58 +0200618/* return matching namespace in node or any of it's parents */
619static struct lyd_ns *
620lyd_find_ns(struct lyd_node *node, const char *prefix, const char *value)
621{
622 int pref_match, val_match;
623 struct lyd_attr *attr;
624
625 if (!node) {
626 return NULL;
627 }
628
629 for (; node; node = node->parent) {
630 for (attr = node->attr; attr; attr = attr->next) {
631 if (attr->type != LYD_ATTR_NS) {
632 continue;
633 }
634
635 pref_match = 0;
636 if (!prefix && !attr->name) {
637 pref_match = 1;
638 }
639 if (prefix && attr->name && !strcmp(attr->name, prefix)) {
640 pref_match = 1;
641 }
642
643 val_match = 0;
644 if (!value && !attr->value) {
645 val_match = 1;
646 }
647 if (value && attr->value && !strcmp(attr->value, value)) {
648 val_match = 1;
649 }
650
651 if (pref_match && val_match) {
652 return (struct lyd_ns *)attr;
653 }
654 }
655 }
656
657 return NULL;
658}
659
660/* create an attribute copy including correct namespace if used */
661static struct lyd_attr *
662lyd_dup_attr(struct ly_ctx *ctx, struct lyd_node *parent, struct lyd_attr *attr)
663{
664 struct lyd_attr *ret;
665
666 /* allocate new attr */
667 if (!parent->attr) {
668 parent->attr = malloc(sizeof *parent->attr);
669 ret = parent->attr;
670 } else {
671 for (ret = parent->attr; ret->next; ret = ret->next);
672 ret->next = malloc(sizeof *ret);
673 ret = ret->next;
674 }
675
676 /* fill new attr except ns/parent */
677 ret->type = attr->type;
678 ret->next = NULL;
679 ret->name = lydict_insert(ctx, attr->name, 0);
680 ret->value = lydict_insert(ctx, attr->value, 0);
681
682 if (ret->type == LYD_ATTR_NS) {
683 /* fill parent in a NS */
684 ((struct lyd_ns *)ret)->parent = parent;
685 } else if (attr->ns) {
686 /* attr has a namespace */
687
688 /* perhaps the namespace was already copied over? */
689 ret->ns = lyd_find_ns(parent, attr->ns->prefix, attr->ns->value);
690 if (!ret->ns) {
691 /* nope, it wasn't */
692 ret->ns = (struct lyd_ns *)lyd_dup_attr(ctx, parent, (struct lyd_attr *)attr->ns);
693 }
694 } else {
695 /* there is no namespace */
696 ret->ns = NULL;
697 }
698
699 return ret;
700}
701
702/* correct namespaces in the attributes of subtree nodes of node */
703static void
704lyd_correct_ns(struct lyd_node *node)
705{
706 const struct lyd_ns *attr_ns;
707 struct lyd_attr *attr;
708 struct lyd_node *node_root, *ns_root, *tmp;
709
710 /* find the root of node */
711 for (node_root = node; node_root->parent; node_root = node_root->parent);
712
713 LY_TREE_DFS_BEGIN(node, tmp, node) {
714 for (attr = node->attr; attr; attr = attr->next) {
715 if ((attr->type != LYD_ATTR_STD) || !attr->ns) {
716 continue;
717 }
718
719 /* find the root of attr NS */
720 for (ns_root = attr->ns->parent; ns_root->parent; ns_root = ns_root->parent);
721
722 /* attr NS is defined outside node subtree */
723 if (ns_root != node_root) {
724 attr_ns = attr->ns;
725 /* we may have already copied the NS over? */
726 attr->ns = lyd_find_ns(node, attr_ns->prefix, attr_ns->value);
727
728 /* we haven't copied it over, copy it now */
729 if (!attr->ns) {
730 attr->ns = (struct lyd_ns *)lyd_dup_attr(node->schema->module->ctx, node,
731 (struct lyd_attr *)attr_ns);
732 }
733 }
734 }
735 LY_TREE_DFS_END(node, tmp, node);
736 }
737}
738
Michal Vasko2d162e12015-09-24 14:33:29 +0200739API int
740lyd_unlink(struct lyd_node *node)
741{
742 struct lyd_node *iter;
743
744 if (!node) {
745 ly_errno = LY_EINVAL;
746 return EXIT_FAILURE;
747 }
748
749 /* unlink from siblings */
750 if (node->prev->next) {
751 node->prev->next = node->next;
752 }
753 if (node->next) {
754 node->next->prev = node->prev;
755 } else {
756 /* unlinking the last node */
757 iter = node->prev;
758 while (iter->prev != node) {
759 iter = iter->prev;
760 }
761 /* update the "last" pointer from the first node */
762 iter->prev = node->prev;
763 }
764
765 /* unlink from parent */
766 if (node->parent) {
767 if (node->parent->child == node) {
768 /* the node is the first child */
769 node->parent->child = node->next;
770 }
771 node->parent = NULL;
772 }
773
774 node->next = NULL;
775 node->prev = node;
776
Michal Vasko55f60be2015-10-14 13:12:58 +0200777 lyd_correct_ns(node);
Michal Vasko2d162e12015-09-24 14:33:29 +0200778 return EXIT_SUCCESS;
779}
780
Michal Vaskoc0797f82015-10-14 15:51:25 +0200781API struct lyd_node *
782lyd_dup(struct lyd_node *node, int recursive)
783{
784 struct lyd_node *next, *elem, *ret, *parent, *new_node;
785 struct lyd_attr *attr;
786 struct lyd_node_leaf_list *new_leaf;
787 struct lyd_node_anyxml *new_axml;
788 struct lys_type *type;
789
790 if (!node) {
791 ly_errno = LY_EINVAL;
792 return NULL;
793 }
794
795 ret = NULL;
796 parent = NULL;
797
798 /* LY_TREE_DFS */
799 for (elem = next = node; elem; elem = next) {
800
801 /* fill specific part */
802 switch (elem->schema->nodetype) {
803 case LYS_LEAF:
804 case LYS_LEAFLIST:
805 new_leaf = malloc(sizeof *new_leaf);
806 new_node = (struct lyd_node *)new_leaf;
807
808 new_leaf->value = ((struct lyd_node_leaf_list *)elem)->value;
809 new_leaf->value_str = lydict_insert(elem->schema->module->ctx,
810 ((struct lyd_node_leaf_list *)elem)->value_str, 0);
811 new_leaf->value_type = ((struct lyd_node_leaf_list *)elem)->value_type;
812 /* bits type must be treated specially */
813 if (new_leaf->value_type == LY_TYPE_BITS) {
814 for (type = &((struct lys_node_leaf *)elem->schema)->type; type->der->module; type = &type->der->type) {
815 if (type->base != LY_TYPE_BITS) {
816 LOGINT;
Michal Vaskod80e6c72015-10-15 09:37:01 +0200817 lyd_free(new_node);
Michal Vaskoc0797f82015-10-14 15:51:25 +0200818 lyd_free(ret);
819 return NULL;
820 }
821 }
822
823 new_leaf->value.bit = malloc(type->info.bits.count * sizeof *new_leaf->value.bit);
824 memcpy(new_leaf->value.bit, ((struct lyd_node_leaf_list *)elem)->value.bit,
825 type->info.bits.count * sizeof *new_leaf->value.bit);
826 }
827 break;
828 case LYS_ANYXML:
829 new_axml = malloc(sizeof *new_axml);
830 new_node = (struct lyd_node *)new_axml;
831
832 new_axml->value = lyxml_dup_elem(elem->schema->module->ctx, ((struct lyd_node_anyxml *)elem)->value,
833 NULL, 1);
834 break;
835 case LYS_CONTAINER:
836 case LYS_LIST:
837 case LYS_NOTIF:
838 case LYS_RPC:
839 new_node = malloc(sizeof *new_node);
840 new_node->child = NULL;
841 break;
842 default:
Michal Vaskoc0797f82015-10-14 15:51:25 +0200843 lyd_free(ret);
Michal Vasko24337392015-10-16 09:58:16 +0200844 LOGINT;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200845 return NULL;
846 }
847
848 /* fill common part */
849 new_node->schema = elem->schema;
850 new_node->attr = NULL;
851 LY_TREE_FOR(elem->attr, attr) {
852 lyd_dup_attr(elem->schema->module->ctx, new_node, attr);
853 }
854 new_node->next = NULL;
855 new_node->prev = new_node;
856 new_node->parent = NULL;
857
858 if (!ret) {
859 ret = new_node;
860 }
861 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200862 if (lyd_insert(parent, new_node)) {
Michal Vaskoc0797f82015-10-14 15:51:25 +0200863 lyd_free(ret);
Michal Vasko24337392015-10-16 09:58:16 +0200864 LOGINT;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200865 return NULL;
866 }
867 }
868
869 if (!recursive) {
870 break;
871 }
872
873 /* LY_TREE_DFS_END */
874 /* select element for the next run - children first */
875 next = elem->child;
876 /* child exception for lyd_node_leaf and lyd_node_leaflist */
877 if (elem->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML)) {
878 next = NULL;
879 }
880 if (!next) {
881 /* no children, so try siblings */
882 next = elem->next;
883 } else {
884 parent = new_node;
885 }
886 while (!next) {
887 /* no siblings, go back through parents */
888 elem = elem->parent;
889 if (elem->parent == node->parent) {
890 break;
891 }
Michal Vasko785b2ad2015-10-15 09:37:15 +0200892 if (!parent) {
893 LOGINT;
894 }
Michal Vaskoc0797f82015-10-14 15:51:25 +0200895 parent = parent->parent;
896 /* parent is already processed, go to its sibling */
897 next = elem->next;
898 }
899 }
900
901 return ret;
902}
903
Michal Vasko2d162e12015-09-24 14:33:29 +0200904static void
905lyd_attr_free(struct ly_ctx *ctx, struct lyd_attr *attr)
906{
907 if (!attr) {
908 return;
909 }
910
911 if (attr->next) {
912 lyd_attr_free(ctx, attr->next);
913 }
914 lydict_remove(ctx, attr->name);
915 lydict_remove(ctx, attr->value);
916 free(attr);
917}
918
Michal Vaskofd76bd12015-09-24 15:49:57 +0200919struct lyd_node *
920lyd_attr_parent(struct lyd_node *root, struct lyd_attr *attr)
921{
922 struct lyd_node *next, *elem;
923 struct lyd_attr *node_attr;
924
925 LY_TREE_DFS_BEGIN(root, next, elem) {
926 for (node_attr = elem->attr; node_attr; node_attr = node_attr->next) {
927 if (node_attr == attr) {
928 return elem;
929 }
930 }
931 LY_TREE_DFS_END(root, next, elem)
932 }
933
934 return NULL;
935}
936
Radek Krejci134610e2015-10-20 17:15:34 +0200937static struct lyd_ns *
938lyd_get_attr_ns(struct lyd_node *node, const char *prefix)
939{
940 struct lyd_attr *attr;
941 int len;
942
943 while(node) {
944
945 if (!prefix) {
946 len = 0;
947 } else {
948 len = strlen(prefix) + 1;
949 }
950
951 for (attr = node->attr; attr; attr = attr->next) {
952 if (attr->type != LYD_ATTR_NS) {
953 continue;
954 }
955 if (!attr->name) {
956 if (!len) {
957 /* default namespace found */
958 if (!attr->value) {
959 /* empty default namespace -> no default namespace */
960 return NULL;
961 }
962 return (struct lyd_ns *)attr;
963 }
964 } else if (len && !memcmp(attr->name, prefix, len)) {
965 /* prefix found */
966 return (struct lyd_ns *)attr;
967 }
968 }
969 node = node->parent;
970 }
971
972 return NULL;
973}
974
975API struct lyd_attr *
976lyd_insert_attr(struct lyd_node *parent, const char *name, const char *value)
977{
978 struct lyd_ns *ns;
979 struct lyd_attr *a, *iter;
980 struct ly_ctx *ctx;
981 const char *p;
982 char *aux;
983
984 if (!parent || !name || !value) {
985 return NULL;
986 }
987 ctx = parent->schema->module->ctx;
988
989 a = calloc(1, sizeof *a);
990
991 if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || !name[5])) {
992 ns = (struct lyd_ns *)a;
993 ns->type = LYD_ATTR_NS;
994 ns->parent = parent;
995 if (name[5]) {
996 ns->prefix = lydict_insert(ctx, &(name[6]), 0);
997 }
998 } else {
999 a->type = LYD_ATTR_STD;
1000 if ((p = strchr(name, ':'))) {
1001 /* search for the namespace */
1002 aux = strndup(name, p - name);
1003 a->ns = lyd_get_attr_ns(parent, aux);
1004 free(aux);
1005
1006 if (!a->ns) {
1007 /* namespace not found */
1008 free(a);
1009 return NULL;
1010 }
1011 } else {
1012 /* no prefix -> no namespace */
1013 a->name = name;
1014 }
1015 }
1016
1017 a->value = lydict_insert(ctx, value, 0);
1018 if (!parent->attr) {
1019 parent->attr = a;
1020 } else {
1021 for (iter = parent->attr; iter->next; iter = iter->next);
1022 iter->next = a;
1023 }
1024
1025 return a;
1026}
1027
Michal Vasko2d162e12015-09-24 14:33:29 +02001028API void
1029lyd_free(struct lyd_node *node)
1030{
1031 struct lyd_node *next, *child;
1032
1033 if (!node) {
1034 return;
1035 }
1036
1037 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
1038 /* free children */
1039 LY_TREE_FOR_SAFE(node->child, next, child) {
1040 lyd_free(child);
1041 }
1042 } else if (node->schema->nodetype == LYS_ANYXML) {
1043 lyxml_free_elem(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
1044 } else {
1045 /* free value */
Michal Vasko4c183312015-09-25 10:41:47 +02001046 switch(((struct lyd_node_leaf_list *)node)->value_type) {
Michal Vasko2d162e12015-09-24 14:33:29 +02001047 case LY_TYPE_BINARY:
1048 case LY_TYPE_STRING:
Michal Vasko4c183312015-09-25 10:41:47 +02001049 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf_list *)node)->value.string);
Michal Vasko2d162e12015-09-24 14:33:29 +02001050 break;
1051 case LY_TYPE_BITS:
Michal Vasko4c183312015-09-25 10:41:47 +02001052 if (((struct lyd_node_leaf_list *)node)->value.bit) {
1053 free(((struct lyd_node_leaf_list *)node)->value.bit);
Michal Vasko2d162e12015-09-24 14:33:29 +02001054 }
1055 break;
1056 default:
1057 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
1058 break;
1059 }
1060 }
1061
1062 lyd_unlink(node);
1063 lyd_attr_free(node->schema->module->ctx, node->attr);
1064 free(node);
1065}
1066
Michal Vaskoff4c2832015-10-15 13:30:50 +02001067API char *
1068lyxml_serialize(struct lyxml_elem *anyxml)
1069{
1070 FILE *stream;
1071 char *buf;
1072 size_t buf_size;
1073
1074 if (!anyxml) {
1075 ly_errno = LY_EINVAL;
1076 return NULL;
1077 }
1078
1079 stream = open_memstream(&buf, &buf_size);
1080 if (!stream) {
1081 ly_errno = LY_ESYS;
1082 return NULL;
1083 }
1084 if (lyxml_dump(stream, anyxml, 0) == 0) {
1085 free(buf);
1086 buf = NULL;
1087 ly_errno = LY_EINVAL;
1088 }
1089 fclose(stream);
1090
1091 return buf;
1092}
1093
Michal Vasko2d162e12015-09-24 14:33:29 +02001094int
1095lyd_compare(struct lyd_node *first, struct lyd_node *second, int unique)
1096{
1097 struct lys_node_list *slist;
1098 struct lys_node *snode;
1099 struct lyd_node *diter;
1100 const char *val1, *val2;
1101 int i, j;
1102
1103 assert(first);
1104 assert(second);
1105
1106 if (first->schema != second->schema) {
1107 return 1;
1108 }
1109
1110 switch (first->schema->nodetype) {
1111 case LYS_LEAFLIST:
1112 /* compare values */
Michal Vasko4c183312015-09-25 10:41:47 +02001113 if (((struct lyd_node_leaf_list *)first)->value_str == ((struct lyd_node_leaf_list *)second)->value_str) {
Michal Vasko2d162e12015-09-24 14:33:29 +02001114 return 0;
1115 }
1116 return 1;
1117 case LYS_LIST:
Michal Vasko4c183312015-09-25 10:41:47 +02001118 slist = (struct lys_node_list *)first->schema;
Michal Vasko2d162e12015-09-24 14:33:29 +02001119
1120 if (unique) {
1121 /* compare unique leafs */
1122 for (i = 0; i < slist->unique_size; i++) {
1123 for (j = 0; j < slist->unique[i].leafs_size; j++) {
1124 snode = (struct lys_node *)slist->unique[i].leafs[j];
1125 /* use default values if the instances of unique leafs are not present */
1126 val1 = val2 = ((struct lys_node_leaf *)snode)->dflt;
1127 LY_TREE_FOR(first->child, diter) {
1128 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001129 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001130 break;
1131 }
1132 }
1133 LY_TREE_FOR(second->child, diter) {
1134 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001135 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001136 break;
1137 }
1138 }
1139 if (val1 != val2) {
1140 break;
1141 }
1142 }
1143 if (j && j == slist->unique[i].leafs_size) {
1144 /* all unique leafs are the same in this set */
1145 return 0;
1146 }
1147 }
1148 }
1149
1150 /* compare keys */
1151 for (i = 0; i < slist->keys_size; i++) {
1152 snode = (struct lys_node *)slist->keys[i];
1153 val1 = val2 = NULL;
1154 LY_TREE_FOR(first->child, diter) {
1155 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001156 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001157 break;
1158 }
1159 }
1160 LY_TREE_FOR(second->child, diter) {
1161 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001162 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001163 break;
1164 }
1165 }
1166 if (val1 != val2) {
1167 return 1;
1168 }
1169 }
1170
1171 return 0;
1172 default:
1173 /* no additional check is needed */
1174 return 0;
1175 }
1176}
1177
1178API struct lyd_set *
1179lyd_set_new(void)
1180{
1181 return calloc(1, sizeof(struct lyd_set));
1182}
1183
1184API void
1185lyd_set_free(struct lyd_set *set)
1186{
1187 if (!set) {
1188 return;
1189 }
1190
1191 free(set->set);
1192 free(set);
1193}
1194
1195API int
1196lyd_set_add(struct lyd_set *set, struct lyd_node *node)
1197{
1198 struct lyd_node **new;
1199
1200 if (!set) {
1201 ly_errno = LY_EINVAL;
1202 return EXIT_FAILURE;
1203 }
1204
1205 if (set->size == set->number) {
1206 new = realloc(set->set, (set->size + 8) * sizeof *(set->set));
1207 if (!new) {
1208 LOGMEM;
1209 return EXIT_FAILURE;
1210 }
1211 set->size += 8;
1212 set->set = new;
1213 }
1214
1215 set->set[set->number++] = node;
1216
1217 return EXIT_SUCCESS;
1218}