blob: ea4896a17a052a28bd4ad241e8652a8de272afc8 [file] [log] [blame]
Radek Krejcic6704c82015-10-06 11:12:45 +02001
Michal Vasko2d162e12015-09-24 14:33:29 +02002/**
3 * @file tree_data.c
4 * @author Radek Krejci <rkrejci@cesnet.cz>
5 * @brief Manipulation with libyang data structures
6 *
7 * Copyright (c) 2015 CESNET, z.s.p.o.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * 3. Neither the name of the Company nor the names of its contributors
19 * may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
21 */
22#define _GNU_SOURCE
Michal Vaskoff4c2832015-10-15 13:30:50 +020023#define _XOPEN_SOURCE 700
Michal Vasko2d162e12015-09-24 14:33:29 +020024
25#include <assert.h>
26#include <ctype.h>
Michal Vasko3e671b52015-10-23 16:23:15 +020027#include <limits.h>
Michal Vasko2d162e12015-09-24 14:33:29 +020028#include <stdlib.h>
Michal Vasko662610a2015-12-07 11:25:45 +010029#include <sys/types.h>
Michal Vasko2d162e12015-09-24 14:33:29 +020030#include <sys/mman.h>
31#include <sys/stat.h>
Michal Vasko662610a2015-12-07 11:25:45 +010032#include <fcntl.h>
33#include <unistd.h>
Michal Vasko2d162e12015-09-24 14:33:29 +020034#include <string.h>
Michal Vasko662610a2015-12-07 11:25:45 +010035#include <errno.h>
Michal Vasko2d162e12015-09-24 14:33:29 +020036
Michal Vasko662610a2015-12-07 11:25:45 +010037#include "libyang.h"
Michal Vasko2d162e12015-09-24 14:33:29 +020038#include "common.h"
39#include "context.h"
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020040#include "tree_data.h"
Michal Vasko2d162e12015-09-24 14:33:29 +020041#include "parser.h"
42#include "resolve.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020043#include "xml_internal.h"
Michal Vasko2d162e12015-09-24 14:33:29 +020044#include "tree_internal.h"
45#include "validation.h"
46
Michal Vasko36ef6932015-12-01 14:30:17 +010047static struct lyd_node *
48lyd_parse_(struct ly_ctx *ctx, const struct lys_node *parent, const char *data, LYD_FORMAT format, int options)
Michal Vasko2d162e12015-09-24 14:33:29 +020049{
Radek Krejci5974c1f2015-10-09 09:53:24 +020050 struct lyxml_elem *xml;
51 struct lyd_node *result = NULL;
52
Michal Vasko2d162e12015-09-24 14:33:29 +020053 if (!ctx || !data) {
54 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
55 return NULL;
56 }
57
58 switch (format) {
59 case LYD_XML:
Radek Krejci452fb952015-10-02 16:07:46 +020060 case LYD_XML_FORMAT:
Michal Vasko70f92c32015-12-10 09:57:24 +010061 xml = lyxml_read_data(ctx, data, 0);
Michal Vasko36ef6932015-12-01 14:30:17 +010062 if (parent) {
63 result = lyd_parse_output_xml(parent, xml, options);
64 } else {
65 result = lyd_parse_xml(ctx, xml, options);
66 }
Michal Vasko345da0a2015-12-02 10:35:55 +010067 lyxml_free(ctx, xml);
Radek Krejci5974c1f2015-10-09 09:53:24 +020068 break;
Michal Vasko2d162e12015-09-24 14:33:29 +020069 case LYD_JSON:
Michal Vasko36ef6932015-12-01 14:30:17 +010070 result = lyd_parse_json(ctx, parent, data, options);
Radek Krejci5449d472015-10-26 14:35:56 +010071 break;
Michal Vasko2d162e12015-09-24 14:33:29 +020072 default:
Radek Krejci5449d472015-10-26 14:35:56 +010073 /* error */
Michal Vasko2d162e12015-09-24 14:33:29 +020074 return NULL;
75 }
76
Radek Krejci5974c1f2015-10-09 09:53:24 +020077 return result;
Michal Vasko2d162e12015-09-24 14:33:29 +020078}
79
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020080API struct lyd_node *
Michal Vasko662610a2015-12-07 11:25:45 +010081lyd_parse_data(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
Michal Vasko36ef6932015-12-01 14:30:17 +010082{
83 return lyd_parse_(ctx, NULL, data, format, options);
84}
85
86API struct lyd_node *
Michal Vasko662610a2015-12-07 11:25:45 +010087lyd_parse_fd(struct ly_ctx *ctx, int fd, LYD_FORMAT format, int options)
88{
89 struct lyd_node *ret;
90 struct stat sb;
91 char *data;
92
93 if (!ctx || (fd == -1)) {
94 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
95 return NULL;
96 }
97
98 if (fstat(fd, &sb) == -1) {
99 LOGERR(LY_ESYS, "Failed to stat the file descriptor (%s).", strerror(errno));
100 return NULL;
101 }
102
103 data = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
104 if (data == MAP_FAILED) {
105 LOGERR(LY_ESYS, "Mapping file descriptor into memory failed.");
106 return NULL;
107 }
108
109 ret = lyd_parse_data(ctx, data, format, options);
110 munmap(data, sb.st_size);
111 return ret;
112}
113
114API struct lyd_node *
115lyd_parse_path(struct ly_ctx *ctx, const char *path, LYD_FORMAT format, int options)
116{
117 int fd;
118 struct lyd_node *ret;
119
120 if (!ctx || !path) {
121 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
122 return NULL;
123 }
124
125 fd = open(path, O_RDONLY);
126 if (fd == -1) {
127 LOGERR(LY_ESYS, "Failed to open data file \"%s\" (%s).", path, strerror(errno));
128 return NULL;
129 }
130
131 ret = lyd_parse_fd(ctx, fd, format, options);
132 close(fd);
133 return ret;
134}
135
136API struct lyd_node *
137lyd_parse_output_data(const struct lys_node *rpc, const char *data, LYD_FORMAT format, int options)
Michal Vasko36ef6932015-12-01 14:30:17 +0100138{
139 if (!rpc || (rpc->nodetype != LYS_RPC)) {
140 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
141 return NULL;
142 }
143
144 return lyd_parse_(rpc->module->ctx, rpc, data, format, options);
145}
146
147API struct lyd_node *
Michal Vasko1e62a092015-12-01 12:27:20 +0100148lyd_new(struct lyd_node *parent, const struct lys_module *module, const char *name)
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200149{
150 struct lyd_node *ret;
Michal Vasko1e62a092015-12-01 12:27:20 +0100151 const struct lys_node *snode = NULL, *siblings;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200152
153 if ((!parent && !module) || !name) {
154 ly_errno = LY_EINVAL;
155 return NULL;
156 }
157
158 if (!parent) {
159 siblings = module->data;
160 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200161 if (!parent->schema) {
162 return NULL;
163 }
164 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200165 }
166
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200167 if (lys_get_data_sibling(module, siblings, name, LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC, &snode)
168 || !snode) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200169 return NULL;
170 }
171
172 ret = calloc(1, sizeof *ret);
Michal Vasko1e62a092015-12-01 12:27:20 +0100173 ret->schema = (struct lys_node *)snode;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200174 ret->prev = ret;
175 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200176 if (lyd_insert(parent, ret)) {
177 lyd_free(ret);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200178 return NULL;
179 }
180 }
181
182 return ret;
183}
184
185API struct lyd_node *
Michal Vasko1e62a092015-12-01 12:27:20 +0100186lyd_new_leaf(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str)
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200187{
188 struct lyd_node_leaf_list *ret;
Michal Vasko1e62a092015-12-01 12:27:20 +0100189 const struct lys_node *snode = NULL, *siblings;
Michal Vasko3e671b52015-10-23 16:23:15 +0200190 struct lys_type *stype, *type;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200191 int found;
192
193 if ((!parent && !module) || !name) {
194 ly_errno = LY_EINVAL;
195 return NULL;
196 }
197
198 if (!parent) {
199 siblings = module->data;
200 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200201 if (!parent->schema) {
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200202 ly_errno = LY_EINVAL;
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200203 return NULL;
204 }
205 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200206 }
207
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200208 if (lys_get_data_sibling(module, siblings, name, LYS_LEAFLIST | LYS_LEAF, &snode) || !snode) {
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200209 ly_errno = LY_EINVAL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200210 return NULL;
211 }
212
Michal Vasko3e671b52015-10-23 16:23:15 +0200213 /* create the new leaf */
214 ret = calloc(1, sizeof *ret);
Michal Vasko1e62a092015-12-01 12:27:20 +0100215 ret->schema = (struct lys_node *)snode;
Michal Vasko3e671b52015-10-23 16:23:15 +0200216 ret->prev = (struct lyd_node *)ret;
217 ret->value_str = lydict_insert((module ? module->ctx : parent->schema->module->ctx), val_str, 0);
218
219 /* resolve the type correctly */
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200220 stype = &((struct lys_node_leaf *)snode)->type;
221 if (stype->base == LY_TYPE_UNION) {
222 found = 0;
Radek Krejcif7388492015-10-30 16:12:53 +0100223 type = NULL;
224 while ((type = lyp_get_next_union_type(stype, type, &found))) {
Michal Vasko3e671b52015-10-23 16:23:15 +0200225 ret->value_type = type->base;
226 if (!lyp_parse_value(ret, type, 1, NULL, UINT_MAX)) {
227 /* success! */
228 break;
229 }
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200230 found = 0;
Radek Krejcif7388492015-10-30 16:12:53 +0100231 }
Michal Vasko3e671b52015-10-23 16:23:15 +0200232
233 if (!type) {
234 /* fail */
235 ly_errno = LY_EINVAL;
236 lyd_free((struct lyd_node *)ret);
237 return NULL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200238 }
Michal Vasko3e671b52015-10-23 16:23:15 +0200239 } else {
240 ret->value_type = stype->base;
241 if (lyp_parse_value(ret, stype, 1, NULL, 0)) {
242 lyd_free((struct lyd_node *)ret);
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200243 ly_errno = LY_EINVAL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200244 return NULL;
245 }
246 }
247
Michal Vasko3e671b52015-10-23 16:23:15 +0200248 /* connect to parent */
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200249 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200250 if (lyd_insert(parent, (struct lyd_node *)ret)) {
251 lyd_free((struct lyd_node *)ret);
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200252 return NULL;
253 }
254 }
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200255
256 return (struct lyd_node *)ret;
257
258}
259
260API struct lyd_node *
Michal Vasko1e62a092015-12-01 12:27:20 +0100261lyd_new_anyxml(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_xml)
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200262{
Michal Vasko587998f2015-09-29 16:07:53 +0200263 struct lyd_node_anyxml *ret;
Michal Vasko1e62a092015-12-01 12:27:20 +0100264 const struct lys_node *siblings, *snode;
Michal Vasko17cc7062015-12-10 14:31:48 +0100265 struct lyxml_elem *root;
Michal Vasko587998f2015-09-29 16:07:53 +0200266 struct ly_ctx *ctx;
267 char *xml;
268
Michal Vasko14d88772015-12-03 10:54:59 +0100269 if ((!parent && !module) || !name) {
Michal Vasko587998f2015-09-29 16:07:53 +0200270 ly_errno = LY_EINVAL;
271 return NULL;
272 }
273
274 if (!parent) {
275 siblings = module->data;
276 ctx = module->ctx;
277 } else {
278 if (!parent->schema) {
279 return NULL;
280 }
281 siblings = parent->schema->child;
282 ctx = parent->schema->module->ctx;
283 }
284
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200285 if (lys_get_data_sibling(module, siblings, name, LYS_ANYXML, &snode) || !snode) {
Michal Vasko587998f2015-09-29 16:07:53 +0200286 return NULL;
287 }
288
289 ret = calloc(1, sizeof *ret);
Michal Vasko1e62a092015-12-01 12:27:20 +0100290 ret->schema = (struct lys_node *)snode;
Michal Vasko587998f2015-09-29 16:07:53 +0200291 ret->prev = (struct lyd_node *)ret;
292 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200293 if (lyd_insert(parent, (struct lyd_node *)ret)) {
294 lyd_free((struct lyd_node *)ret);
Michal Vasko587998f2015-09-29 16:07:53 +0200295 return NULL;
296 }
297 }
298
Michal Vasko17cc7062015-12-10 14:31:48 +0100299 /* add fake root and top-level and parse the data */
300 asprintf(&xml, "<root><%s>%s</%s></root>", name, (val_xml ? val_xml : ""), name);
301 root = lyxml_read_data(ctx, xml, 0);
302 free(xml);
303 if (!root) {
304 lyd_free((struct lyd_node *)ret);
305 return NULL;
Michal Vasko14d88772015-12-03 10:54:59 +0100306 }
Michal Vasko587998f2015-09-29 16:07:53 +0200307
Michal Vasko17cc7062015-12-10 14:31:48 +0100308 /* remove the root */
309 ret->value = root->child;
310 lyxml_unlink_elem(ctx, root->child, 1);
311
312 lyxml_free(ctx, root);
313
Michal Vasko587998f2015-09-29 16:07:53 +0200314 return (struct lyd_node *)ret;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200315}
316
Michal Vasko24337392015-10-16 09:58:16 +0200317API int
318lyd_insert(struct lyd_node *parent, struct lyd_node *node)
Michal Vasko2d162e12015-09-24 14:33:29 +0200319{
320 struct lys_node *sparent;
Michal Vasko24337392015-10-16 09:58:16 +0200321 struct lyd_node *iter;
Michal Vasko2d162e12015-09-24 14:33:29 +0200322
Michal Vasko24337392015-10-16 09:58:16 +0200323 if (!node || !parent) {
324 ly_errno = LY_EINVAL;
325 return EXIT_FAILURE;
Michal Vasko2d162e12015-09-24 14:33:29 +0200326 }
327
Michal Vasko72d65c92015-12-07 14:02:35 +0100328 /* check placing the node to the appropriate place according to the schema (if LYS_OUTPUT is returned,
329 * the parent's schema will never match and it fails as it should) */
330 for (sparent = node->schema->parent;
331 sparent && !(sparent->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_OUTPUT | LYS_NOTIF));
332 sparent = sparent->parent);
Michal Vasko2d162e12015-09-24 14:33:29 +0200333 if (sparent != parent->schema) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200334 return EXIT_FAILURE;
335 }
336
Michal Vasko24337392015-10-16 09:58:16 +0200337 if (node->parent || node->prev->next) {
338 lyd_unlink(node);
339 }
340
Michal Vasko2d162e12015-09-24 14:33:29 +0200341 if (!parent->child) {
342 /* add as the only child of the parent */
343 parent->child = node;
344 } else {
345 /* add as the last child of the parent */
346 parent->child->prev->next = node;
347 node->prev = parent->child->prev;
348 for (iter = node; iter->next; iter = iter->next);
349 parent->child->prev = iter;
350 }
Michal Vasko9cc2d0a2015-10-14 15:49:07 +0200351
Michal Vasko2d162e12015-09-24 14:33:29 +0200352 LY_TREE_FOR(node, iter) {
353 iter->parent = parent;
Michal Vasko2d162e12015-09-24 14:33:29 +0200354 }
355
356 return EXIT_SUCCESS;
357}
358
Michal Vasko02592902015-10-15 12:14:40 +0200359static int
Michal Vasko24337392015-10-16 09:58:16 +0200360lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, int before)
Michal Vasko2d162e12015-09-24 14:33:29 +0200361{
362 struct lys_node *par1, *par2;
Michal Vasko24337392015-10-16 09:58:16 +0200363 struct lyd_node *iter, *last;
Michal Vasko3f7dba12015-10-15 13:09:27 +0200364
365 if (sibling == node) {
366 return EXIT_SUCCESS;
367 }
368
Michal Vasko2d162e12015-09-24 14:33:29 +0200369 /* check placing the node to the appropriate place according to the schema */
Radek Krejci2b7bb492015-12-02 15:46:29 +0100370 for (par1 = sibling->schema->parent;
371 par1 && !(par1->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF));
372 par1 = par1->parent);
373 for (par2 = node->schema->parent;
374 par2 && !(par2->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF));
375 par2 = par2->parent);
Michal Vasko2d162e12015-09-24 14:33:29 +0200376 if (par1 != par2) {
377 ly_errno = LY_EINVAL;
378 return EXIT_FAILURE;
379 }
380
Michal Vasko24337392015-10-16 09:58:16 +0200381 if (node->parent || node->prev->next) {
382 lyd_unlink(node);
383 }
384
Michal Vasko2d162e12015-09-24 14:33:29 +0200385 LY_TREE_FOR(node, iter) {
386 iter->parent = sibling->parent;
Michal Vasko24337392015-10-16 09:58:16 +0200387 last = iter;
Michal Vasko2d162e12015-09-24 14:33:29 +0200388 }
389
Michal Vasko02592902015-10-15 12:14:40 +0200390 if (before) {
391 if (sibling->prev->next) {
392 /* adding into the list */
393 sibling->prev->next = node;
394 } else if (sibling->parent) {
395 /* at the beginning */
396 sibling->parent->child = node;
Michal Vasko2d162e12015-09-24 14:33:29 +0200397 }
Michal Vasko02592902015-10-15 12:14:40 +0200398 node->prev = sibling->prev;
399 sibling->prev = last;
400 last->next = sibling;
401 } else {
402 if (sibling->next) {
403 /* adding into a middle - fix the prev pointer of the node after inserted nodes */
404 last->next = sibling->next;
405 sibling->next->prev = last;
406 } else {
407 /* at the end - fix the prev pointer of the first node */
408 if (sibling->parent) {
409 sibling->parent->child->prev = last;
410 } else {
411 for (iter = sibling; iter->prev->next; iter = iter->prev);
412 iter->prev = last;
413 }
414 }
415 sibling->next = node;
416 node->prev = sibling;
Michal Vasko2d162e12015-09-24 14:33:29 +0200417 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200418
Michal Vasko24337392015-10-16 09:58:16 +0200419 return EXIT_SUCCESS;
420}
Michal Vasko2d162e12015-09-24 14:33:29 +0200421
Michal Vasko24337392015-10-16 09:58:16 +0200422API int
423lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
424{
425 if (!node || !sibling || lyd_insert_sibling(sibling, node, 1)) {
426 ly_errno = LY_EINVAL;
427 return EXIT_FAILURE;
428 }
429
430 return EXIT_SUCCESS;
431}
432
433API int
434lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
435{
436 if (!node || !sibling || lyd_insert_sibling(sibling, node, 0)) {
437 ly_errno = LY_EINVAL;
438 return EXIT_FAILURE;
439 }
440
441 return EXIT_SUCCESS;
442}
443
444API int
445lyd_validate(struct lyd_node *node, int options)
446{
447 struct lyd_node *next, *iter, *to_free = NULL;
448
449 ly_errno = 0;
450 LY_TREE_DFS_BEGIN(node, next, iter) {
451 if (to_free) {
452 lyd_free(to_free);
453 to_free = NULL;
454 }
455
Radek Krejcif03ec152015-12-03 13:18:37 +0100456 if (lyv_data_context(iter, options, 0, NULL)) {
457 return EXIT_FAILURE;
458 }
459 if (lyv_data_content(iter, options, 0, NULL)) {
Michal Vasko24337392015-10-16 09:58:16 +0200460 if (ly_errno) {
461 return EXIT_FAILURE;
462 } else {
463 /* safe deferred removal */
464 to_free = iter;
Radek Krejciefe6a142015-12-03 14:01:00 +0100465 if (iter == node) {
466 /* removing the whole subtree */
467 break;
468 }
Michal Vasko3f7dba12015-10-15 13:09:27 +0200469 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200470 }
Michal Vasko24337392015-10-16 09:58:16 +0200471
472 LY_TREE_DFS_END(node, next, iter);
Michal Vasko2d162e12015-09-24 14:33:29 +0200473 }
474
Michal Vasko24337392015-10-16 09:58:16 +0200475 if (to_free) {
476 lyd_free(to_free);
477 to_free = NULL;
Michal Vasko02592902015-10-15 12:14:40 +0200478 }
479
480 return EXIT_SUCCESS;
481}
482
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100483/* create an attribute copy */
Michal Vasko55f60be2015-10-14 13:12:58 +0200484static struct lyd_attr *
485lyd_dup_attr(struct ly_ctx *ctx, struct lyd_node *parent, struct lyd_attr *attr)
486{
487 struct lyd_attr *ret;
488
489 /* allocate new attr */
490 if (!parent->attr) {
491 parent->attr = malloc(sizeof *parent->attr);
492 ret = parent->attr;
493 } else {
494 for (ret = parent->attr; ret->next; ret = ret->next);
495 ret->next = malloc(sizeof *ret);
496 ret = ret->next;
497 }
498
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100499 /* fill new attr except */
Michal Vasko55f60be2015-10-14 13:12:58 +0200500 ret->next = NULL;
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100501 ret->module = attr->module;
Michal Vasko55f60be2015-10-14 13:12:58 +0200502 ret->name = lydict_insert(ctx, attr->name, 0);
503 ret->value = lydict_insert(ctx, attr->value, 0);
504
Michal Vasko55f60be2015-10-14 13:12:58 +0200505 return ret;
506}
507
Michal Vasko2d162e12015-09-24 14:33:29 +0200508API int
509lyd_unlink(struct lyd_node *node)
510{
511 struct lyd_node *iter;
512
513 if (!node) {
514 ly_errno = LY_EINVAL;
515 return EXIT_FAILURE;
516 }
517
518 /* unlink from siblings */
519 if (node->prev->next) {
520 node->prev->next = node->next;
521 }
522 if (node->next) {
523 node->next->prev = node->prev;
524 } else {
525 /* unlinking the last node */
526 iter = node->prev;
527 while (iter->prev != node) {
528 iter = iter->prev;
529 }
530 /* update the "last" pointer from the first node */
531 iter->prev = node->prev;
532 }
533
534 /* unlink from parent */
535 if (node->parent) {
536 if (node->parent->child == node) {
537 /* the node is the first child */
538 node->parent->child = node->next;
539 }
540 node->parent = NULL;
541 }
542
543 node->next = NULL;
544 node->prev = node;
545
546 return EXIT_SUCCESS;
547}
548
Michal Vaskoc0797f82015-10-14 15:51:25 +0200549API struct lyd_node *
Michal Vasko1e62a092015-12-01 12:27:20 +0100550lyd_dup(const struct lyd_node *node, int recursive)
Michal Vaskoc0797f82015-10-14 15:51:25 +0200551{
Michal Vasko1e62a092015-12-01 12:27:20 +0100552 const struct lyd_node *next, *elem;
553 struct lyd_node *ret, *parent, *new_node;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200554 struct lyd_attr *attr;
555 struct lyd_node_leaf_list *new_leaf;
556 struct lyd_node_anyxml *new_axml;
557 struct lys_type *type;
558
559 if (!node) {
560 ly_errno = LY_EINVAL;
561 return NULL;
562 }
563
564 ret = NULL;
565 parent = NULL;
566
567 /* LY_TREE_DFS */
568 for (elem = next = node; elem; elem = next) {
569
570 /* fill specific part */
571 switch (elem->schema->nodetype) {
572 case LYS_LEAF:
573 case LYS_LEAFLIST:
574 new_leaf = malloc(sizeof *new_leaf);
575 new_node = (struct lyd_node *)new_leaf;
576
577 new_leaf->value = ((struct lyd_node_leaf_list *)elem)->value;
578 new_leaf->value_str = lydict_insert(elem->schema->module->ctx,
579 ((struct lyd_node_leaf_list *)elem)->value_str, 0);
580 new_leaf->value_type = ((struct lyd_node_leaf_list *)elem)->value_type;
581 /* bits type must be treated specially */
582 if (new_leaf->value_type == LY_TYPE_BITS) {
583 for (type = &((struct lys_node_leaf *)elem->schema)->type; type->der->module; type = &type->der->type) {
584 if (type->base != LY_TYPE_BITS) {
585 LOGINT;
Michal Vaskod80e6c72015-10-15 09:37:01 +0200586 lyd_free(new_node);
Michal Vaskoc0797f82015-10-14 15:51:25 +0200587 lyd_free(ret);
588 return NULL;
589 }
590 }
591
592 new_leaf->value.bit = malloc(type->info.bits.count * sizeof *new_leaf->value.bit);
593 memcpy(new_leaf->value.bit, ((struct lyd_node_leaf_list *)elem)->value.bit,
594 type->info.bits.count * sizeof *new_leaf->value.bit);
595 }
596 break;
597 case LYS_ANYXML:
598 new_axml = malloc(sizeof *new_axml);
599 new_node = (struct lyd_node *)new_axml;
600
601 new_axml->value = lyxml_dup_elem(elem->schema->module->ctx, ((struct lyd_node_anyxml *)elem)->value,
602 NULL, 1);
603 break;
604 case LYS_CONTAINER:
605 case LYS_LIST:
606 case LYS_NOTIF:
607 case LYS_RPC:
608 new_node = malloc(sizeof *new_node);
609 new_node->child = NULL;
610 break;
611 default:
Michal Vaskoc0797f82015-10-14 15:51:25 +0200612 lyd_free(ret);
Michal Vasko24337392015-10-16 09:58:16 +0200613 LOGINT;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200614 return NULL;
615 }
616
617 /* fill common part */
618 new_node->schema = elem->schema;
619 new_node->attr = NULL;
620 LY_TREE_FOR(elem->attr, attr) {
621 lyd_dup_attr(elem->schema->module->ctx, new_node, attr);
622 }
623 new_node->next = NULL;
624 new_node->prev = new_node;
625 new_node->parent = NULL;
626
627 if (!ret) {
628 ret = new_node;
629 }
630 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200631 if (lyd_insert(parent, new_node)) {
Michal Vaskoc0797f82015-10-14 15:51:25 +0200632 lyd_free(ret);
Michal Vasko24337392015-10-16 09:58:16 +0200633 LOGINT;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200634 return NULL;
635 }
636 }
637
638 if (!recursive) {
639 break;
640 }
641
642 /* LY_TREE_DFS_END */
643 /* select element for the next run - children first */
644 next = elem->child;
645 /* child exception for lyd_node_leaf and lyd_node_leaflist */
646 if (elem->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML)) {
647 next = NULL;
648 }
649 if (!next) {
650 /* no children, so try siblings */
651 next = elem->next;
652 } else {
653 parent = new_node;
654 }
655 while (!next) {
656 /* no siblings, go back through parents */
657 elem = elem->parent;
658 if (elem->parent == node->parent) {
659 break;
660 }
Michal Vasko785b2ad2015-10-15 09:37:15 +0200661 if (!parent) {
Michal Vaskoc8f5d802015-10-23 10:14:39 +0200662 lyd_free(ret);
Michal Vasko785b2ad2015-10-15 09:37:15 +0200663 LOGINT;
Michal Vaskoc8f5d802015-10-23 10:14:39 +0200664 return NULL;
Michal Vasko785b2ad2015-10-15 09:37:15 +0200665 }
Michal Vaskoc0797f82015-10-14 15:51:25 +0200666 parent = parent->parent;
667 /* parent is already processed, go to its sibling */
668 next = elem->next;
669 }
670 }
671
672 return ret;
673}
674
Radek Krejci88f29302015-10-30 15:42:33 +0100675API void
676lyd_free_attr(struct ly_ctx *ctx, struct lyd_node *parent, struct lyd_attr *attr, int recursive)
Michal Vasko2d162e12015-09-24 14:33:29 +0200677{
Radek Krejci88f29302015-10-30 15:42:33 +0100678 struct lyd_attr *iter;
679
680 if (!ctx || !attr) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200681 return;
682 }
683
Radek Krejci88f29302015-10-30 15:42:33 +0100684 if (parent) {
685 if (parent->attr == attr) {
686 if (recursive) {
687 parent->attr = NULL;
688 } else {
689 parent->attr = attr->next;
690 }
691 } else {
692 for (iter = parent->attr; iter->next != attr; iter = iter->next);
693 if (iter->next) {
694 if (recursive) {
695 iter->next = NULL;
696 } else {
697 iter->next = attr->next;
698 }
699 }
700 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200701 }
Radek Krejci88f29302015-10-30 15:42:33 +0100702
703 if (!recursive) {
704 attr->next = NULL;
705 }
706
707 for(iter = attr; iter; ) {
708 attr = iter;
709 iter = iter->next;
710
711 lydict_remove(ctx, attr->name);
712 lydict_remove(ctx, attr->value);
713 free(attr);
714 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200715}
716
Michal Vaskofd76bd12015-09-24 15:49:57 +0200717struct lyd_node *
718lyd_attr_parent(struct lyd_node *root, struct lyd_attr *attr)
719{
720 struct lyd_node *next, *elem;
721 struct lyd_attr *node_attr;
722
723 LY_TREE_DFS_BEGIN(root, next, elem) {
724 for (node_attr = elem->attr; node_attr; node_attr = node_attr->next) {
725 if (node_attr == attr) {
726 return elem;
727 }
728 }
729 LY_TREE_DFS_END(root, next, elem)
730 }
731
732 return NULL;
733}
734
Radek Krejci134610e2015-10-20 17:15:34 +0200735API struct lyd_attr *
736lyd_insert_attr(struct lyd_node *parent, const char *name, const char *value)
737{
Radek Krejci134610e2015-10-20 17:15:34 +0200738 struct lyd_attr *a, *iter;
739 struct ly_ctx *ctx;
Michal Vasko1e62a092015-12-01 12:27:20 +0100740 const struct lys_module *module;
Radek Krejci134610e2015-10-20 17:15:34 +0200741 const char *p;
742 char *aux;
743
744 if (!parent || !name || !value) {
745 return NULL;
746 }
747 ctx = parent->schema->module->ctx;
748
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100749 if ((p = strchr(name, ':'))) {
750 /* search for the namespace */
751 aux = strndup(name, p - name);
752 module = ly_ctx_get_module(ctx, aux, NULL);
753 free(aux);
754 name = p + 1;
Radek Krejci134610e2015-10-20 17:15:34 +0200755
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100756 if (!module) {
757 /* module not found */
Radek Krejcia008ca92015-10-30 15:52:05 +0100758 LOGERR(LY_EINVAL, "Attribute prefix does not match any schema in the context.");
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100759 return NULL;
Radek Krejci134610e2015-10-20 17:15:34 +0200760 }
761 } else {
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100762 /* no prefix -> module is the same as for the parent */
763 module = parent->schema->module;
Radek Krejci134610e2015-10-20 17:15:34 +0200764 }
765
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100766 a = malloc(sizeof *a);
Michal Vasko1e62a092015-12-01 12:27:20 +0100767 a->module = (struct lys_module *)module;
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100768 a->next = NULL;
769 a->name = lydict_insert(ctx, name, 0);
Radek Krejci134610e2015-10-20 17:15:34 +0200770 a->value = lydict_insert(ctx, value, 0);
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100771
Radek Krejci134610e2015-10-20 17:15:34 +0200772 if (!parent->attr) {
773 parent->attr = a;
774 } else {
775 for (iter = parent->attr; iter->next; iter = iter->next);
776 iter->next = a;
777 }
778
779 return a;
780}
781
Michal Vasko2d162e12015-09-24 14:33:29 +0200782API void
783lyd_free(struct lyd_node *node)
784{
785 struct lyd_node *next, *child;
786
787 if (!node) {
788 return;
789 }
790
791 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
792 /* free children */
793 LY_TREE_FOR_SAFE(node->child, next, child) {
794 lyd_free(child);
795 }
796 } else if (node->schema->nodetype == LYS_ANYXML) {
Michal Vasko345da0a2015-12-02 10:35:55 +0100797 lyxml_free(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
Michal Vasko2d162e12015-09-24 14:33:29 +0200798 } else {
799 /* free value */
Michal Vasko4c183312015-09-25 10:41:47 +0200800 switch(((struct lyd_node_leaf_list *)node)->value_type) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200801 case LY_TYPE_BINARY:
802 case LY_TYPE_STRING:
Michal Vasko4c183312015-09-25 10:41:47 +0200803 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf_list *)node)->value.string);
Michal Vasko2d162e12015-09-24 14:33:29 +0200804 break;
805 case LY_TYPE_BITS:
Michal Vasko4c183312015-09-25 10:41:47 +0200806 if (((struct lyd_node_leaf_list *)node)->value.bit) {
807 free(((struct lyd_node_leaf_list *)node)->value.bit);
Michal Vasko2d162e12015-09-24 14:33:29 +0200808 }
809 break;
810 default:
811 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
812 break;
813 }
814 }
815
816 lyd_unlink(node);
Radek Krejci88f29302015-10-30 15:42:33 +0100817 lyd_free_attr(node->schema->module->ctx, node, node->attr, 1);
Michal Vasko2d162e12015-09-24 14:33:29 +0200818 free(node);
819}
820
Michal Vaskoff4c2832015-10-15 13:30:50 +0200821API char *
Michal Vasko1e62a092015-12-01 12:27:20 +0100822lyxml_serialize(const struct lyxml_elem *anyxml)
Michal Vaskoff4c2832015-10-15 13:30:50 +0200823{
824 FILE *stream;
825 char *buf;
826 size_t buf_size;
827
828 if (!anyxml) {
829 ly_errno = LY_EINVAL;
830 return NULL;
831 }
832
833 stream = open_memstream(&buf, &buf_size);
834 if (!stream) {
835 ly_errno = LY_ESYS;
836 return NULL;
837 }
Michal Vasko70f92c32015-12-10 09:57:24 +0100838 if (lyxml_dump_file(stream, anyxml, 0) == 0) {
Michal Vaskoff4c2832015-10-15 13:30:50 +0200839 free(buf);
840 buf = NULL;
841 ly_errno = LY_EINVAL;
842 }
843 fclose(stream);
844
845 return buf;
846}
847
Michal Vasko2d162e12015-09-24 14:33:29 +0200848int
849lyd_compare(struct lyd_node *first, struct lyd_node *second, int unique)
850{
851 struct lys_node_list *slist;
Michal Vasko1e62a092015-12-01 12:27:20 +0100852 const struct lys_node *snode = NULL;
Michal Vasko2d162e12015-09-24 14:33:29 +0200853 struct lyd_node *diter;
854 const char *val1, *val2;
855 int i, j;
856
857 assert(first);
858 assert(second);
859
860 if (first->schema != second->schema) {
861 return 1;
862 }
863
864 switch (first->schema->nodetype) {
865 case LYS_LEAFLIST:
866 /* compare values */
Michal Vasko4c183312015-09-25 10:41:47 +0200867 if (((struct lyd_node_leaf_list *)first)->value_str == ((struct lyd_node_leaf_list *)second)->value_str) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200868 return 0;
869 }
870 return 1;
871 case LYS_LIST:
Michal Vasko4c183312015-09-25 10:41:47 +0200872 slist = (struct lys_node_list *)first->schema;
Michal Vasko2d162e12015-09-24 14:33:29 +0200873
874 if (unique) {
875 /* compare unique leafs */
876 for (i = 0; i < slist->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +0100877 for (j = 0; j < slist->unique[i].expr_size; j++) {
878 /* first */
879 diter = resolve_data_nodeid(slist->unique[i].expr[j], first->child);
880 if (diter) {
881 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
882 } else {
883 /* use default value */
884 resolve_schema_nodeid(slist->unique[i].expr[j], first->schema->child, first->schema->module, LYS_LEAF, &snode);
885 val1 = ((struct lys_node_leaf *)snode)->dflt;
Michal Vasko2d162e12015-09-24 14:33:29 +0200886 }
Radek Krejci581ce772015-11-10 17:22:40 +0100887
888 /* second */
889 diter = resolve_data_nodeid(slist->unique[i].expr[j], second->child);
890 if (diter) {
891 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
892 } else {
893 /* use default value */
894 resolve_schema_nodeid(slist->unique[i].expr[j], second->schema->child, second->schema->module, LYS_LEAF, &snode);
895 val2 = ((struct lys_node_leaf *)snode)->dflt;
Michal Vasko2d162e12015-09-24 14:33:29 +0200896 }
Radek Krejci581ce772015-11-10 17:22:40 +0100897
Michal Vasko2d162e12015-09-24 14:33:29 +0200898 if (val1 != val2) {
899 break;
900 }
901 }
Radek Krejci581ce772015-11-10 17:22:40 +0100902 if (j && j == slist->unique[i].expr_size) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200903 /* all unique leafs are the same in this set */
904 return 0;
905 }
906 }
907 }
908
909 /* compare keys */
910 for (i = 0; i < slist->keys_size; i++) {
911 snode = (struct lys_node *)slist->keys[i];
912 val1 = val2 = NULL;
913 LY_TREE_FOR(first->child, diter) {
914 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200915 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200916 break;
917 }
918 }
919 LY_TREE_FOR(second->child, diter) {
920 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200921 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200922 break;
923 }
924 }
925 if (val1 != val2) {
926 return 1;
927 }
928 }
929
930 return 0;
931 default:
932 /* no additional check is needed */
933 return 0;
934 }
935}
936
937API struct lyd_set *
938lyd_set_new(void)
939{
940 return calloc(1, sizeof(struct lyd_set));
941}
942
943API void
944lyd_set_free(struct lyd_set *set)
945{
946 if (!set) {
947 return;
948 }
949
950 free(set->set);
951 free(set);
952}
953
954API int
955lyd_set_add(struct lyd_set *set, struct lyd_node *node)
956{
957 struct lyd_node **new;
958
959 if (!set) {
960 ly_errno = LY_EINVAL;
961 return EXIT_FAILURE;
962 }
963
964 if (set->size == set->number) {
965 new = realloc(set->set, (set->size + 8) * sizeof *(set->set));
966 if (!new) {
967 LOGMEM;
968 return EXIT_FAILURE;
969 }
970 set->size += 8;
971 set->set = new;
972 }
973
974 set->set[set->number++] = node;
975
976 return EXIT_SUCCESS;
977}