blob: b5e34a2a833e168f22628db826777af552733737 [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>
29#include <sys/mman.h>
30#include <sys/stat.h>
31#include <string.h>
32
33#include "common.h"
34#include "context.h"
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020035#include "tree_data.h"
Michal Vasko2d162e12015-09-24 14:33:29 +020036#include "parser.h"
37#include "resolve.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020038#include "xml_internal.h"
Michal Vasko2d162e12015-09-24 14:33:29 +020039#include "tree_internal.h"
40#include "validation.h"
41
Michal Vasko36ef6932015-12-01 14:30:17 +010042static struct lyd_node *
43lyd_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 +020044{
Radek Krejci5974c1f2015-10-09 09:53:24 +020045 struct lyxml_elem *xml;
46 struct lyd_node *result = NULL;
47
Michal Vasko2d162e12015-09-24 14:33:29 +020048 if (!ctx || !data) {
49 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
50 return NULL;
51 }
52
53 switch (format) {
54 case LYD_XML:
Radek Krejci452fb952015-10-02 16:07:46 +020055 case LYD_XML_FORMAT:
Radek Krejci5974c1f2015-10-09 09:53:24 +020056 xml = lyxml_read(ctx, data, 0);
Michal Vasko36ef6932015-12-01 14:30:17 +010057 if (parent) {
58 result = lyd_parse_output_xml(parent, xml, options);
59 } else {
60 result = lyd_parse_xml(ctx, xml, options);
61 }
Michal Vasko345da0a2015-12-02 10:35:55 +010062 lyxml_free(ctx, xml);
Radek Krejci5974c1f2015-10-09 09:53:24 +020063 break;
Michal Vasko2d162e12015-09-24 14:33:29 +020064 case LYD_JSON:
Michal Vasko36ef6932015-12-01 14:30:17 +010065 result = lyd_parse_json(ctx, parent, data, options);
Radek Krejci5449d472015-10-26 14:35:56 +010066 break;
Michal Vasko2d162e12015-09-24 14:33:29 +020067 default:
Radek Krejci5449d472015-10-26 14:35:56 +010068 /* error */
Michal Vasko2d162e12015-09-24 14:33:29 +020069 return NULL;
70 }
71
Radek Krejci5974c1f2015-10-09 09:53:24 +020072 return result;
Michal Vasko2d162e12015-09-24 14:33:29 +020073}
74
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020075API struct lyd_node *
Michal Vasko36ef6932015-12-01 14:30:17 +010076lyd_parse(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
77{
78 return lyd_parse_(ctx, NULL, data, format, options);
79}
80
81API struct lyd_node *
82lyd_parse_output(const struct lys_node *rpc, const char *data, LYD_FORMAT format, int options)
83{
84 if (!rpc || (rpc->nodetype != LYS_RPC)) {
85 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
86 return NULL;
87 }
88
89 return lyd_parse_(rpc->module->ctx, rpc, data, format, options);
90}
91
92API struct lyd_node *
Michal Vasko1e62a092015-12-01 12:27:20 +010093lyd_new(struct lyd_node *parent, const struct lys_module *module, const char *name)
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020094{
95 struct lyd_node *ret;
Michal Vasko1e62a092015-12-01 12:27:20 +010096 const struct lys_node *snode = NULL, *siblings;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020097
98 if ((!parent && !module) || !name) {
99 ly_errno = LY_EINVAL;
100 return NULL;
101 }
102
103 if (!parent) {
104 siblings = module->data;
105 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200106 if (!parent->schema) {
107 return NULL;
108 }
109 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200110 }
111
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200112 if (lys_get_data_sibling(module, siblings, name, LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC, &snode)
113 || !snode) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200114 return NULL;
115 }
116
117 ret = calloc(1, sizeof *ret);
Michal Vasko1e62a092015-12-01 12:27:20 +0100118 ret->schema = (struct lys_node *)snode;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200119 ret->prev = ret;
120 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200121 if (lyd_insert(parent, ret)) {
122 lyd_free(ret);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200123 return NULL;
124 }
125 }
126
127 return ret;
128}
129
130API struct lyd_node *
Michal Vasko1e62a092015-12-01 12:27:20 +0100131lyd_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 +0200132{
133 struct lyd_node_leaf_list *ret;
Michal Vasko1e62a092015-12-01 12:27:20 +0100134 const struct lys_node *snode = NULL, *siblings;
Michal Vasko3e671b52015-10-23 16:23:15 +0200135 struct lys_type *stype, *type;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200136 int found;
137
138 if ((!parent && !module) || !name) {
139 ly_errno = LY_EINVAL;
140 return NULL;
141 }
142
143 if (!parent) {
144 siblings = module->data;
145 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200146 if (!parent->schema) {
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200147 ly_errno = LY_EINVAL;
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200148 return NULL;
149 }
150 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200151 }
152
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200153 if (lys_get_data_sibling(module, siblings, name, LYS_LEAFLIST | LYS_LEAF, &snode) || !snode) {
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200154 ly_errno = LY_EINVAL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200155 return NULL;
156 }
157
Michal Vasko3e671b52015-10-23 16:23:15 +0200158 /* create the new leaf */
159 ret = calloc(1, sizeof *ret);
Michal Vasko1e62a092015-12-01 12:27:20 +0100160 ret->schema = (struct lys_node *)snode;
Michal Vasko3e671b52015-10-23 16:23:15 +0200161 ret->prev = (struct lyd_node *)ret;
162 ret->value_str = lydict_insert((module ? module->ctx : parent->schema->module->ctx), val_str, 0);
163
164 /* resolve the type correctly */
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200165 stype = &((struct lys_node_leaf *)snode)->type;
166 if (stype->base == LY_TYPE_UNION) {
167 found = 0;
Radek Krejcif7388492015-10-30 16:12:53 +0100168 type = NULL;
169 while ((type = lyp_get_next_union_type(stype, type, &found))) {
Michal Vasko3e671b52015-10-23 16:23:15 +0200170 ret->value_type = type->base;
171 if (!lyp_parse_value(ret, type, 1, NULL, UINT_MAX)) {
172 /* success! */
173 break;
174 }
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200175 found = 0;
Radek Krejcif7388492015-10-30 16:12:53 +0100176 }
Michal Vasko3e671b52015-10-23 16:23:15 +0200177
178 if (!type) {
179 /* fail */
180 ly_errno = LY_EINVAL;
181 lyd_free((struct lyd_node *)ret);
182 return NULL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200183 }
Michal Vasko3e671b52015-10-23 16:23:15 +0200184 } else {
185 ret->value_type = stype->base;
186 if (lyp_parse_value(ret, stype, 1, NULL, 0)) {
187 lyd_free((struct lyd_node *)ret);
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200188 ly_errno = LY_EINVAL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200189 return NULL;
190 }
191 }
192
Michal Vasko3e671b52015-10-23 16:23:15 +0200193 /* connect to parent */
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200194 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200195 if (lyd_insert(parent, (struct lyd_node *)ret)) {
196 lyd_free((struct lyd_node *)ret);
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200197 return NULL;
198 }
199 }
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200200
201 return (struct lyd_node *)ret;
202
203}
204
205API struct lyd_node *
Michal Vasko1e62a092015-12-01 12:27:20 +0100206lyd_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 +0200207{
Michal Vasko587998f2015-09-29 16:07:53 +0200208 struct lyd_node_anyxml *ret;
Michal Vasko1e62a092015-12-01 12:27:20 +0100209 const struct lys_node *siblings, *snode;
Michal Vasko587998f2015-09-29 16:07:53 +0200210 struct lyxml_elem *root, *first_child, *last_child, *child;
211 struct ly_ctx *ctx;
212 char *xml;
213
214 if ((!parent && !module) || !name || !val_xml) {
215 ly_errno = LY_EINVAL;
216 return NULL;
217 }
218
219 if (!parent) {
220 siblings = module->data;
221 ctx = module->ctx;
222 } else {
223 if (!parent->schema) {
224 return NULL;
225 }
226 siblings = parent->schema->child;
227 ctx = parent->schema->module->ctx;
228 }
229
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200230 if (lys_get_data_sibling(module, siblings, name, LYS_ANYXML, &snode) || !snode) {
Michal Vasko587998f2015-09-29 16:07:53 +0200231 return NULL;
232 }
233
234 ret = calloc(1, sizeof *ret);
Michal Vasko1e62a092015-12-01 12:27:20 +0100235 ret->schema = (struct lys_node *)snode;
Michal Vasko587998f2015-09-29 16:07:53 +0200236 ret->prev = (struct lyd_node *)ret;
237 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200238 if (lyd_insert(parent, (struct lyd_node *)ret)) {
239 lyd_free((struct lyd_node *)ret);
Michal Vasko587998f2015-09-29 16:07:53 +0200240 return NULL;
241 }
242 }
243
244 /* add fake root so we can parse the data */
245 asprintf(&xml, "<root>%s</root>", val_xml);
246 root = lyxml_read(ctx, xml, 0);
247 free(xml);
Michal Vasko5b6e78d2015-10-09 15:01:10 +0200248 if (!root) {
Michal Vasko24337392015-10-16 09:58:16 +0200249 lyd_free((struct lyd_node *)ret);
Michal Vasko5b6e78d2015-10-09 15:01:10 +0200250 return NULL;
251 }
Michal Vasko587998f2015-09-29 16:07:53 +0200252
253 /* remove the root */
Radek Krejcie4e4d722015-10-05 16:53:50 +0200254 first_child = last_child = NULL;
Michal Vasko587998f2015-09-29 16:07:53 +0200255 LY_TREE_FOR(root->child, child) {
256 lyxml_unlink_elem(ctx, child, 1);
257 if (!first_child) {
258 first_child = child;
259 last_child = child;
260 } else {
261 last_child->next = child;
262 child->prev = last_child;
263 last_child = child;
264 }
265 }
Radek Krejcie4e4d722015-10-05 16:53:50 +0200266 if (first_child) {
267 first_child->prev = last_child;
268 }
Michal Vasko345da0a2015-12-02 10:35:55 +0100269 lyxml_free(ctx, root);
Michal Vasko587998f2015-09-29 16:07:53 +0200270
271 ret->value = first_child;
272
273 return (struct lyd_node *)ret;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200274}
275
Michal Vasko24337392015-10-16 09:58:16 +0200276API int
277lyd_insert(struct lyd_node *parent, struct lyd_node *node)
Michal Vasko2d162e12015-09-24 14:33:29 +0200278{
279 struct lys_node *sparent;
Michal Vasko24337392015-10-16 09:58:16 +0200280 struct lyd_node *iter;
Michal Vasko2d162e12015-09-24 14:33:29 +0200281
Michal Vasko24337392015-10-16 09:58:16 +0200282 if (!node || !parent) {
283 ly_errno = LY_EINVAL;
284 return EXIT_FAILURE;
Michal Vasko2d162e12015-09-24 14:33:29 +0200285 }
286
287 /* check placing the node to the appropriate place according to the schema */
288 sparent = node->schema->parent;
Radek Krejci8a6794f2015-10-20 17:14:48 +0200289 while (!(sparent->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_NOTIF))) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200290 sparent = sparent->parent;
291 }
292 if (sparent != parent->schema) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200293 return EXIT_FAILURE;
294 }
295
Michal Vasko24337392015-10-16 09:58:16 +0200296 if (node->parent || node->prev->next) {
297 lyd_unlink(node);
298 }
299
Michal Vasko2d162e12015-09-24 14:33:29 +0200300 if (!parent->child) {
301 /* add as the only child of the parent */
302 parent->child = node;
303 } else {
304 /* add as the last child of the parent */
305 parent->child->prev->next = node;
306 node->prev = parent->child->prev;
307 for (iter = node; iter->next; iter = iter->next);
308 parent->child->prev = iter;
309 }
Michal Vasko9cc2d0a2015-10-14 15:49:07 +0200310
Michal Vasko2d162e12015-09-24 14:33:29 +0200311 LY_TREE_FOR(node, iter) {
312 iter->parent = parent;
Michal Vasko2d162e12015-09-24 14:33:29 +0200313 }
314
315 return EXIT_SUCCESS;
316}
317
Michal Vasko02592902015-10-15 12:14:40 +0200318static int
Michal Vasko24337392015-10-16 09:58:16 +0200319lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, int before)
Michal Vasko2d162e12015-09-24 14:33:29 +0200320{
321 struct lys_node *par1, *par2;
Michal Vasko24337392015-10-16 09:58:16 +0200322 struct lyd_node *iter, *last;
Michal Vasko3f7dba12015-10-15 13:09:27 +0200323
324 if (sibling == node) {
325 return EXIT_SUCCESS;
326 }
327
Michal Vasko2d162e12015-09-24 14:33:29 +0200328 /* check placing the node to the appropriate place according to the schema */
329 for (par1 = sibling->schema->parent; par1 && (par1->nodetype & (LYS_CONTAINER | LYS_LIST)); par1 = par1->parent);
330 for (par2 = node->schema->parent; par2 && (par2->nodetype & (LYS_CONTAINER | LYS_LIST)); par2 = par2->parent);
331 if (par1 != par2) {
332 ly_errno = LY_EINVAL;
333 return EXIT_FAILURE;
334 }
335
Michal Vasko24337392015-10-16 09:58:16 +0200336 if (node->parent || node->prev->next) {
337 lyd_unlink(node);
338 }
339
Michal Vasko2d162e12015-09-24 14:33:29 +0200340 LY_TREE_FOR(node, iter) {
341 iter->parent = sibling->parent;
Michal Vasko24337392015-10-16 09:58:16 +0200342 last = iter;
Michal Vasko2d162e12015-09-24 14:33:29 +0200343 }
344
Michal Vasko02592902015-10-15 12:14:40 +0200345 if (before) {
346 if (sibling->prev->next) {
347 /* adding into the list */
348 sibling->prev->next = node;
349 } else if (sibling->parent) {
350 /* at the beginning */
351 sibling->parent->child = node;
Michal Vasko2d162e12015-09-24 14:33:29 +0200352 }
Michal Vasko02592902015-10-15 12:14:40 +0200353 node->prev = sibling->prev;
354 sibling->prev = last;
355 last->next = sibling;
356 } else {
357 if (sibling->next) {
358 /* adding into a middle - fix the prev pointer of the node after inserted nodes */
359 last->next = sibling->next;
360 sibling->next->prev = last;
361 } else {
362 /* at the end - fix the prev pointer of the first node */
363 if (sibling->parent) {
364 sibling->parent->child->prev = last;
365 } else {
366 for (iter = sibling; iter->prev->next; iter = iter->prev);
367 iter->prev = last;
368 }
369 }
370 sibling->next = node;
371 node->prev = sibling;
Michal Vasko2d162e12015-09-24 14:33:29 +0200372 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200373
Michal Vasko24337392015-10-16 09:58:16 +0200374 return EXIT_SUCCESS;
375}
Michal Vasko2d162e12015-09-24 14:33:29 +0200376
Michal Vasko24337392015-10-16 09:58:16 +0200377API int
378lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
379{
380 if (!node || !sibling || lyd_insert_sibling(sibling, node, 1)) {
381 ly_errno = LY_EINVAL;
382 return EXIT_FAILURE;
383 }
384
385 return EXIT_SUCCESS;
386}
387
388API int
389lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
390{
391 if (!node || !sibling || lyd_insert_sibling(sibling, node, 0)) {
392 ly_errno = LY_EINVAL;
393 return EXIT_FAILURE;
394 }
395
396 return EXIT_SUCCESS;
397}
398
399API int
400lyd_validate(struct lyd_node *node, int options)
401{
402 struct lyd_node *next, *iter, *to_free = NULL;
403
404 ly_errno = 0;
405 LY_TREE_DFS_BEGIN(node, next, iter) {
406 if (to_free) {
407 lyd_free(to_free);
408 to_free = NULL;
409 }
410
411 if (lyv_data_content(iter, 0, options, NULL)) {
412 if (ly_errno) {
413 return EXIT_FAILURE;
Michal Vasko2fce5f52015-10-23 10:14:08 +0200414 } else if (iter == node) {
415 /* removing the whole subtree */
416 to_free = node;
417 break;
Michal Vasko24337392015-10-16 09:58:16 +0200418 } else {
419 /* safe deferred removal */
420 to_free = iter;
Michal Vasko3f7dba12015-10-15 13:09:27 +0200421 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200422 }
Michal Vasko24337392015-10-16 09:58:16 +0200423
424 LY_TREE_DFS_END(node, next, iter);
Michal Vasko2d162e12015-09-24 14:33:29 +0200425 }
426
Michal Vasko24337392015-10-16 09:58:16 +0200427 if (to_free) {
428 lyd_free(to_free);
429 to_free = NULL;
Michal Vasko02592902015-10-15 12:14:40 +0200430 }
431
432 return EXIT_SUCCESS;
433}
434
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100435/* create an attribute copy */
Michal Vasko55f60be2015-10-14 13:12:58 +0200436static struct lyd_attr *
437lyd_dup_attr(struct ly_ctx *ctx, struct lyd_node *parent, struct lyd_attr *attr)
438{
439 struct lyd_attr *ret;
440
441 /* allocate new attr */
442 if (!parent->attr) {
443 parent->attr = malloc(sizeof *parent->attr);
444 ret = parent->attr;
445 } else {
446 for (ret = parent->attr; ret->next; ret = ret->next);
447 ret->next = malloc(sizeof *ret);
448 ret = ret->next;
449 }
450
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100451 /* fill new attr except */
Michal Vasko55f60be2015-10-14 13:12:58 +0200452 ret->next = NULL;
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100453 ret->module = attr->module;
Michal Vasko55f60be2015-10-14 13:12:58 +0200454 ret->name = lydict_insert(ctx, attr->name, 0);
455 ret->value = lydict_insert(ctx, attr->value, 0);
456
Michal Vasko55f60be2015-10-14 13:12:58 +0200457 return ret;
458}
459
Michal Vasko2d162e12015-09-24 14:33:29 +0200460API int
461lyd_unlink(struct lyd_node *node)
462{
463 struct lyd_node *iter;
464
465 if (!node) {
466 ly_errno = LY_EINVAL;
467 return EXIT_FAILURE;
468 }
469
470 /* unlink from siblings */
471 if (node->prev->next) {
472 node->prev->next = node->next;
473 }
474 if (node->next) {
475 node->next->prev = node->prev;
476 } else {
477 /* unlinking the last node */
478 iter = node->prev;
479 while (iter->prev != node) {
480 iter = iter->prev;
481 }
482 /* update the "last" pointer from the first node */
483 iter->prev = node->prev;
484 }
485
486 /* unlink from parent */
487 if (node->parent) {
488 if (node->parent->child == node) {
489 /* the node is the first child */
490 node->parent->child = node->next;
491 }
492 node->parent = NULL;
493 }
494
495 node->next = NULL;
496 node->prev = node;
497
498 return EXIT_SUCCESS;
499}
500
Michal Vaskoc0797f82015-10-14 15:51:25 +0200501API struct lyd_node *
Michal Vasko1e62a092015-12-01 12:27:20 +0100502lyd_dup(const struct lyd_node *node, int recursive)
Michal Vaskoc0797f82015-10-14 15:51:25 +0200503{
Michal Vasko1e62a092015-12-01 12:27:20 +0100504 const struct lyd_node *next, *elem;
505 struct lyd_node *ret, *parent, *new_node;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200506 struct lyd_attr *attr;
507 struct lyd_node_leaf_list *new_leaf;
508 struct lyd_node_anyxml *new_axml;
509 struct lys_type *type;
510
511 if (!node) {
512 ly_errno = LY_EINVAL;
513 return NULL;
514 }
515
516 ret = NULL;
517 parent = NULL;
518
519 /* LY_TREE_DFS */
520 for (elem = next = node; elem; elem = next) {
521
522 /* fill specific part */
523 switch (elem->schema->nodetype) {
524 case LYS_LEAF:
525 case LYS_LEAFLIST:
526 new_leaf = malloc(sizeof *new_leaf);
527 new_node = (struct lyd_node *)new_leaf;
528
529 new_leaf->value = ((struct lyd_node_leaf_list *)elem)->value;
530 new_leaf->value_str = lydict_insert(elem->schema->module->ctx,
531 ((struct lyd_node_leaf_list *)elem)->value_str, 0);
532 new_leaf->value_type = ((struct lyd_node_leaf_list *)elem)->value_type;
533 /* bits type must be treated specially */
534 if (new_leaf->value_type == LY_TYPE_BITS) {
535 for (type = &((struct lys_node_leaf *)elem->schema)->type; type->der->module; type = &type->der->type) {
536 if (type->base != LY_TYPE_BITS) {
537 LOGINT;
Michal Vaskod80e6c72015-10-15 09:37:01 +0200538 lyd_free(new_node);
Michal Vaskoc0797f82015-10-14 15:51:25 +0200539 lyd_free(ret);
540 return NULL;
541 }
542 }
543
544 new_leaf->value.bit = malloc(type->info.bits.count * sizeof *new_leaf->value.bit);
545 memcpy(new_leaf->value.bit, ((struct lyd_node_leaf_list *)elem)->value.bit,
546 type->info.bits.count * sizeof *new_leaf->value.bit);
547 }
548 break;
549 case LYS_ANYXML:
550 new_axml = malloc(sizeof *new_axml);
551 new_node = (struct lyd_node *)new_axml;
552
553 new_axml->value = lyxml_dup_elem(elem->schema->module->ctx, ((struct lyd_node_anyxml *)elem)->value,
554 NULL, 1);
555 break;
556 case LYS_CONTAINER:
557 case LYS_LIST:
558 case LYS_NOTIF:
559 case LYS_RPC:
560 new_node = malloc(sizeof *new_node);
561 new_node->child = NULL;
562 break;
563 default:
Michal Vaskoc0797f82015-10-14 15:51:25 +0200564 lyd_free(ret);
Michal Vasko24337392015-10-16 09:58:16 +0200565 LOGINT;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200566 return NULL;
567 }
568
569 /* fill common part */
570 new_node->schema = elem->schema;
571 new_node->attr = NULL;
572 LY_TREE_FOR(elem->attr, attr) {
573 lyd_dup_attr(elem->schema->module->ctx, new_node, attr);
574 }
575 new_node->next = NULL;
576 new_node->prev = new_node;
577 new_node->parent = NULL;
578
579 if (!ret) {
580 ret = new_node;
581 }
582 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200583 if (lyd_insert(parent, new_node)) {
Michal Vaskoc0797f82015-10-14 15:51:25 +0200584 lyd_free(ret);
Michal Vasko24337392015-10-16 09:58:16 +0200585 LOGINT;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200586 return NULL;
587 }
588 }
589
590 if (!recursive) {
591 break;
592 }
593
594 /* LY_TREE_DFS_END */
595 /* select element for the next run - children first */
596 next = elem->child;
597 /* child exception for lyd_node_leaf and lyd_node_leaflist */
598 if (elem->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML)) {
599 next = NULL;
600 }
601 if (!next) {
602 /* no children, so try siblings */
603 next = elem->next;
604 } else {
605 parent = new_node;
606 }
607 while (!next) {
608 /* no siblings, go back through parents */
609 elem = elem->parent;
610 if (elem->parent == node->parent) {
611 break;
612 }
Michal Vasko785b2ad2015-10-15 09:37:15 +0200613 if (!parent) {
Michal Vaskoc8f5d802015-10-23 10:14:39 +0200614 lyd_free(ret);
Michal Vasko785b2ad2015-10-15 09:37:15 +0200615 LOGINT;
Michal Vaskoc8f5d802015-10-23 10:14:39 +0200616 return NULL;
Michal Vasko785b2ad2015-10-15 09:37:15 +0200617 }
Michal Vaskoc0797f82015-10-14 15:51:25 +0200618 parent = parent->parent;
619 /* parent is already processed, go to its sibling */
620 next = elem->next;
621 }
622 }
623
624 return ret;
625}
626
Radek Krejci88f29302015-10-30 15:42:33 +0100627API void
628lyd_free_attr(struct ly_ctx *ctx, struct lyd_node *parent, struct lyd_attr *attr, int recursive)
Michal Vasko2d162e12015-09-24 14:33:29 +0200629{
Radek Krejci88f29302015-10-30 15:42:33 +0100630 struct lyd_attr *iter;
631
632 if (!ctx || !attr) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200633 return;
634 }
635
Radek Krejci88f29302015-10-30 15:42:33 +0100636 if (parent) {
637 if (parent->attr == attr) {
638 if (recursive) {
639 parent->attr = NULL;
640 } else {
641 parent->attr = attr->next;
642 }
643 } else {
644 for (iter = parent->attr; iter->next != attr; iter = iter->next);
645 if (iter->next) {
646 if (recursive) {
647 iter->next = NULL;
648 } else {
649 iter->next = attr->next;
650 }
651 }
652 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200653 }
Radek Krejci88f29302015-10-30 15:42:33 +0100654
655 if (!recursive) {
656 attr->next = NULL;
657 }
658
659 for(iter = attr; iter; ) {
660 attr = iter;
661 iter = iter->next;
662
663 lydict_remove(ctx, attr->name);
664 lydict_remove(ctx, attr->value);
665 free(attr);
666 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200667}
668
Michal Vaskofd76bd12015-09-24 15:49:57 +0200669struct lyd_node *
670lyd_attr_parent(struct lyd_node *root, struct lyd_attr *attr)
671{
672 struct lyd_node *next, *elem;
673 struct lyd_attr *node_attr;
674
675 LY_TREE_DFS_BEGIN(root, next, elem) {
676 for (node_attr = elem->attr; node_attr; node_attr = node_attr->next) {
677 if (node_attr == attr) {
678 return elem;
679 }
680 }
681 LY_TREE_DFS_END(root, next, elem)
682 }
683
684 return NULL;
685}
686
Radek Krejci134610e2015-10-20 17:15:34 +0200687API struct lyd_attr *
688lyd_insert_attr(struct lyd_node *parent, const char *name, const char *value)
689{
Radek Krejci134610e2015-10-20 17:15:34 +0200690 struct lyd_attr *a, *iter;
691 struct ly_ctx *ctx;
Michal Vasko1e62a092015-12-01 12:27:20 +0100692 const struct lys_module *module;
Radek Krejci134610e2015-10-20 17:15:34 +0200693 const char *p;
694 char *aux;
695
696 if (!parent || !name || !value) {
697 return NULL;
698 }
699 ctx = parent->schema->module->ctx;
700
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100701 if ((p = strchr(name, ':'))) {
702 /* search for the namespace */
703 aux = strndup(name, p - name);
704 module = ly_ctx_get_module(ctx, aux, NULL);
705 free(aux);
706 name = p + 1;
Radek Krejci134610e2015-10-20 17:15:34 +0200707
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100708 if (!module) {
709 /* module not found */
Radek Krejcia008ca92015-10-30 15:52:05 +0100710 LOGERR(LY_EINVAL, "Attribute prefix does not match any schema in the context.");
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100711 return NULL;
Radek Krejci134610e2015-10-20 17:15:34 +0200712 }
713 } else {
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100714 /* no prefix -> module is the same as for the parent */
715 module = parent->schema->module;
Radek Krejci134610e2015-10-20 17:15:34 +0200716 }
717
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100718 a = malloc(sizeof *a);
Michal Vasko1e62a092015-12-01 12:27:20 +0100719 a->module = (struct lys_module *)module;
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100720 a->next = NULL;
721 a->name = lydict_insert(ctx, name, 0);
Radek Krejci134610e2015-10-20 17:15:34 +0200722 a->value = lydict_insert(ctx, value, 0);
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100723
Radek Krejci134610e2015-10-20 17:15:34 +0200724 if (!parent->attr) {
725 parent->attr = a;
726 } else {
727 for (iter = parent->attr; iter->next; iter = iter->next);
728 iter->next = a;
729 }
730
731 return a;
732}
733
Michal Vasko2d162e12015-09-24 14:33:29 +0200734API void
735lyd_free(struct lyd_node *node)
736{
737 struct lyd_node *next, *child;
738
739 if (!node) {
740 return;
741 }
742
743 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
744 /* free children */
745 LY_TREE_FOR_SAFE(node->child, next, child) {
746 lyd_free(child);
747 }
748 } else if (node->schema->nodetype == LYS_ANYXML) {
Michal Vasko345da0a2015-12-02 10:35:55 +0100749 lyxml_free(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
Michal Vasko2d162e12015-09-24 14:33:29 +0200750 } else {
751 /* free value */
Michal Vasko4c183312015-09-25 10:41:47 +0200752 switch(((struct lyd_node_leaf_list *)node)->value_type) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200753 case LY_TYPE_BINARY:
754 case LY_TYPE_STRING:
Michal Vasko4c183312015-09-25 10:41:47 +0200755 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf_list *)node)->value.string);
Michal Vasko2d162e12015-09-24 14:33:29 +0200756 break;
757 case LY_TYPE_BITS:
Michal Vasko4c183312015-09-25 10:41:47 +0200758 if (((struct lyd_node_leaf_list *)node)->value.bit) {
759 free(((struct lyd_node_leaf_list *)node)->value.bit);
Michal Vasko2d162e12015-09-24 14:33:29 +0200760 }
761 break;
762 default:
763 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
764 break;
765 }
766 }
767
768 lyd_unlink(node);
Radek Krejci88f29302015-10-30 15:42:33 +0100769 lyd_free_attr(node->schema->module->ctx, node, node->attr, 1);
Michal Vasko2d162e12015-09-24 14:33:29 +0200770 free(node);
771}
772
Michal Vaskoff4c2832015-10-15 13:30:50 +0200773API char *
Michal Vasko1e62a092015-12-01 12:27:20 +0100774lyxml_serialize(const struct lyxml_elem *anyxml)
Michal Vaskoff4c2832015-10-15 13:30:50 +0200775{
776 FILE *stream;
777 char *buf;
778 size_t buf_size;
779
780 if (!anyxml) {
781 ly_errno = LY_EINVAL;
782 return NULL;
783 }
784
785 stream = open_memstream(&buf, &buf_size);
786 if (!stream) {
787 ly_errno = LY_ESYS;
788 return NULL;
789 }
790 if (lyxml_dump(stream, anyxml, 0) == 0) {
791 free(buf);
792 buf = NULL;
793 ly_errno = LY_EINVAL;
794 }
795 fclose(stream);
796
797 return buf;
798}
799
Michal Vasko2d162e12015-09-24 14:33:29 +0200800int
801lyd_compare(struct lyd_node *first, struct lyd_node *second, int unique)
802{
803 struct lys_node_list *slist;
Michal Vasko1e62a092015-12-01 12:27:20 +0100804 const struct lys_node *snode = NULL;
Michal Vasko2d162e12015-09-24 14:33:29 +0200805 struct lyd_node *diter;
806 const char *val1, *val2;
807 int i, j;
808
809 assert(first);
810 assert(second);
811
812 if (first->schema != second->schema) {
813 return 1;
814 }
815
816 switch (first->schema->nodetype) {
817 case LYS_LEAFLIST:
818 /* compare values */
Michal Vasko4c183312015-09-25 10:41:47 +0200819 if (((struct lyd_node_leaf_list *)first)->value_str == ((struct lyd_node_leaf_list *)second)->value_str) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200820 return 0;
821 }
822 return 1;
823 case LYS_LIST:
Michal Vasko4c183312015-09-25 10:41:47 +0200824 slist = (struct lys_node_list *)first->schema;
Michal Vasko2d162e12015-09-24 14:33:29 +0200825
826 if (unique) {
827 /* compare unique leafs */
828 for (i = 0; i < slist->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +0100829 for (j = 0; j < slist->unique[i].expr_size; j++) {
830 /* first */
831 diter = resolve_data_nodeid(slist->unique[i].expr[j], first->child);
832 if (diter) {
833 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
834 } else {
835 /* use default value */
836 resolve_schema_nodeid(slist->unique[i].expr[j], first->schema->child, first->schema->module, LYS_LEAF, &snode);
837 val1 = ((struct lys_node_leaf *)snode)->dflt;
Michal Vasko2d162e12015-09-24 14:33:29 +0200838 }
Radek Krejci581ce772015-11-10 17:22:40 +0100839
840 /* second */
841 diter = resolve_data_nodeid(slist->unique[i].expr[j], second->child);
842 if (diter) {
843 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
844 } else {
845 /* use default value */
846 resolve_schema_nodeid(slist->unique[i].expr[j], second->schema->child, second->schema->module, LYS_LEAF, &snode);
847 val2 = ((struct lys_node_leaf *)snode)->dflt;
Michal Vasko2d162e12015-09-24 14:33:29 +0200848 }
Radek Krejci581ce772015-11-10 17:22:40 +0100849
Michal Vasko2d162e12015-09-24 14:33:29 +0200850 if (val1 != val2) {
851 break;
852 }
853 }
Radek Krejci581ce772015-11-10 17:22:40 +0100854 if (j && j == slist->unique[i].expr_size) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200855 /* all unique leafs are the same in this set */
856 return 0;
857 }
858 }
859 }
860
861 /* compare keys */
862 for (i = 0; i < slist->keys_size; i++) {
863 snode = (struct lys_node *)slist->keys[i];
864 val1 = val2 = NULL;
865 LY_TREE_FOR(first->child, diter) {
866 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200867 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200868 break;
869 }
870 }
871 LY_TREE_FOR(second->child, diter) {
872 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200873 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200874 break;
875 }
876 }
877 if (val1 != val2) {
878 return 1;
879 }
880 }
881
882 return 0;
883 default:
884 /* no additional check is needed */
885 return 0;
886 }
887}
888
889API struct lyd_set *
890lyd_set_new(void)
891{
892 return calloc(1, sizeof(struct lyd_set));
893}
894
895API void
896lyd_set_free(struct lyd_set *set)
897{
898 if (!set) {
899 return;
900 }
901
902 free(set->set);
903 free(set);
904}
905
906API int
907lyd_set_add(struct lyd_set *set, struct lyd_node *node)
908{
909 struct lyd_node **new;
910
911 if (!set) {
912 ly_errno = LY_EINVAL;
913 return EXIT_FAILURE;
914 }
915
916 if (set->size == set->number) {
917 new = realloc(set->set, (set->size + 8) * sizeof *(set->set));
918 if (!new) {
919 LOGMEM;
920 return EXIT_FAILURE;
921 }
922 set->size += 8;
923 set->set = new;
924 }
925
926 set->set[set->number++] = node;
927
928 return EXIT_SUCCESS;
929}