blob: e08fb8500090b3e433cae9f37e8d6ad80c679465 [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
Michal Vasko14d88772015-12-03 10:54:59 +0100214 if ((!parent && !module) || !name) {
Michal Vasko587998f2015-09-29 16:07:53 +0200215 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
Michal Vasko14d88772015-12-03 10:54:59 +0100244 if (val_xml && val_xml[0]) {
245 /* add fake root so we can parse the data */
246 asprintf(&xml, "<root>%s</root>", val_xml);
247 root = lyxml_read(ctx, xml, 0);
248 free(xml);
249 if (!root) {
250 lyd_free((struct lyd_node *)ret);
251 return NULL;
Michal Vasko587998f2015-09-29 16:07:53 +0200252 }
Michal Vasko587998f2015-09-29 16:07:53 +0200253
Michal Vasko14d88772015-12-03 10:54:59 +0100254 /* remove the root */
255 first_child = last_child = NULL;
256 LY_TREE_FOR(root->child, child) {
257 lyxml_unlink_elem(ctx, child, 1);
258 if (!first_child) {
259 first_child = child;
260 last_child = child;
261 } else {
262 last_child->next = child;
263 child->prev = last_child;
264 last_child = child;
265 }
266 }
267 if (first_child) {
268 first_child->prev = last_child;
269 }
270 lyxml_free(ctx, root);
271
272 ret->value = first_child;
273 }
Michal Vasko587998f2015-09-29 16:07:53 +0200274
275 return (struct lyd_node *)ret;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200276}
277
Michal Vasko24337392015-10-16 09:58:16 +0200278API int
279lyd_insert(struct lyd_node *parent, struct lyd_node *node)
Michal Vasko2d162e12015-09-24 14:33:29 +0200280{
281 struct lys_node *sparent;
Michal Vasko24337392015-10-16 09:58:16 +0200282 struct lyd_node *iter;
Michal Vasko2d162e12015-09-24 14:33:29 +0200283
Michal Vasko24337392015-10-16 09:58:16 +0200284 if (!node || !parent) {
285 ly_errno = LY_EINVAL;
286 return EXIT_FAILURE;
Michal Vasko2d162e12015-09-24 14:33:29 +0200287 }
288
289 /* check placing the node to the appropriate place according to the schema */
290 sparent = node->schema->parent;
Radek Krejci8a6794f2015-10-20 17:14:48 +0200291 while (!(sparent->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_NOTIF))) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200292 sparent = sparent->parent;
293 }
294 if (sparent != parent->schema) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200295 return EXIT_FAILURE;
296 }
297
Michal Vasko24337392015-10-16 09:58:16 +0200298 if (node->parent || node->prev->next) {
299 lyd_unlink(node);
300 }
301
Michal Vasko2d162e12015-09-24 14:33:29 +0200302 if (!parent->child) {
303 /* add as the only child of the parent */
304 parent->child = node;
305 } else {
306 /* add as the last child of the parent */
307 parent->child->prev->next = node;
308 node->prev = parent->child->prev;
309 for (iter = node; iter->next; iter = iter->next);
310 parent->child->prev = iter;
311 }
Michal Vasko9cc2d0a2015-10-14 15:49:07 +0200312
Michal Vasko2d162e12015-09-24 14:33:29 +0200313 LY_TREE_FOR(node, iter) {
314 iter->parent = parent;
Michal Vasko2d162e12015-09-24 14:33:29 +0200315 }
316
317 return EXIT_SUCCESS;
318}
319
Michal Vasko02592902015-10-15 12:14:40 +0200320static int
Michal Vasko24337392015-10-16 09:58:16 +0200321lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, int before)
Michal Vasko2d162e12015-09-24 14:33:29 +0200322{
323 struct lys_node *par1, *par2;
Michal Vasko24337392015-10-16 09:58:16 +0200324 struct lyd_node *iter, *last;
Michal Vasko3f7dba12015-10-15 13:09:27 +0200325
326 if (sibling == node) {
327 return EXIT_SUCCESS;
328 }
329
Michal Vasko2d162e12015-09-24 14:33:29 +0200330 /* check placing the node to the appropriate place according to the schema */
331 for (par1 = sibling->schema->parent; par1 && (par1->nodetype & (LYS_CONTAINER | LYS_LIST)); par1 = par1->parent);
332 for (par2 = node->schema->parent; par2 && (par2->nodetype & (LYS_CONTAINER | LYS_LIST)); par2 = par2->parent);
333 if (par1 != par2) {
334 ly_errno = LY_EINVAL;
335 return EXIT_FAILURE;
336 }
337
Michal Vasko24337392015-10-16 09:58:16 +0200338 if (node->parent || node->prev->next) {
339 lyd_unlink(node);
340 }
341
Michal Vasko2d162e12015-09-24 14:33:29 +0200342 LY_TREE_FOR(node, iter) {
343 iter->parent = sibling->parent;
Michal Vasko24337392015-10-16 09:58:16 +0200344 last = iter;
Michal Vasko2d162e12015-09-24 14:33:29 +0200345 }
346
Michal Vasko02592902015-10-15 12:14:40 +0200347 if (before) {
348 if (sibling->prev->next) {
349 /* adding into the list */
350 sibling->prev->next = node;
351 } else if (sibling->parent) {
352 /* at the beginning */
353 sibling->parent->child = node;
Michal Vasko2d162e12015-09-24 14:33:29 +0200354 }
Michal Vasko02592902015-10-15 12:14:40 +0200355 node->prev = sibling->prev;
356 sibling->prev = last;
357 last->next = sibling;
358 } else {
359 if (sibling->next) {
360 /* adding into a middle - fix the prev pointer of the node after inserted nodes */
361 last->next = sibling->next;
362 sibling->next->prev = last;
363 } else {
364 /* at the end - fix the prev pointer of the first node */
365 if (sibling->parent) {
366 sibling->parent->child->prev = last;
367 } else {
368 for (iter = sibling; iter->prev->next; iter = iter->prev);
369 iter->prev = last;
370 }
371 }
372 sibling->next = node;
373 node->prev = sibling;
Michal Vasko2d162e12015-09-24 14:33:29 +0200374 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200375
Michal Vasko24337392015-10-16 09:58:16 +0200376 return EXIT_SUCCESS;
377}
Michal Vasko2d162e12015-09-24 14:33:29 +0200378
Michal Vasko24337392015-10-16 09:58:16 +0200379API int
380lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
381{
382 if (!node || !sibling || lyd_insert_sibling(sibling, node, 1)) {
383 ly_errno = LY_EINVAL;
384 return EXIT_FAILURE;
385 }
386
387 return EXIT_SUCCESS;
388}
389
390API int
391lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
392{
393 if (!node || !sibling || lyd_insert_sibling(sibling, node, 0)) {
394 ly_errno = LY_EINVAL;
395 return EXIT_FAILURE;
396 }
397
398 return EXIT_SUCCESS;
399}
400
401API int
402lyd_validate(struct lyd_node *node, int options)
403{
404 struct lyd_node *next, *iter, *to_free = NULL;
405
406 ly_errno = 0;
407 LY_TREE_DFS_BEGIN(node, next, iter) {
408 if (to_free) {
409 lyd_free(to_free);
410 to_free = NULL;
411 }
412
413 if (lyv_data_content(iter, 0, options, NULL)) {
414 if (ly_errno) {
415 return EXIT_FAILURE;
Michal Vasko2fce5f52015-10-23 10:14:08 +0200416 } else if (iter == node) {
417 /* removing the whole subtree */
418 to_free = node;
419 break;
Michal Vasko24337392015-10-16 09:58:16 +0200420 } else {
421 /* safe deferred removal */
422 to_free = iter;
Michal Vasko3f7dba12015-10-15 13:09:27 +0200423 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200424 }
Michal Vasko24337392015-10-16 09:58:16 +0200425
426 LY_TREE_DFS_END(node, next, iter);
Michal Vasko2d162e12015-09-24 14:33:29 +0200427 }
428
Michal Vasko24337392015-10-16 09:58:16 +0200429 if (to_free) {
430 lyd_free(to_free);
431 to_free = NULL;
Michal Vasko02592902015-10-15 12:14:40 +0200432 }
433
434 return EXIT_SUCCESS;
435}
436
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100437/* create an attribute copy */
Michal Vasko55f60be2015-10-14 13:12:58 +0200438static struct lyd_attr *
439lyd_dup_attr(struct ly_ctx *ctx, struct lyd_node *parent, struct lyd_attr *attr)
440{
441 struct lyd_attr *ret;
442
443 /* allocate new attr */
444 if (!parent->attr) {
445 parent->attr = malloc(sizeof *parent->attr);
446 ret = parent->attr;
447 } else {
448 for (ret = parent->attr; ret->next; ret = ret->next);
449 ret->next = malloc(sizeof *ret);
450 ret = ret->next;
451 }
452
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100453 /* fill new attr except */
Michal Vasko55f60be2015-10-14 13:12:58 +0200454 ret->next = NULL;
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100455 ret->module = attr->module;
Michal Vasko55f60be2015-10-14 13:12:58 +0200456 ret->name = lydict_insert(ctx, attr->name, 0);
457 ret->value = lydict_insert(ctx, attr->value, 0);
458
Michal Vasko55f60be2015-10-14 13:12:58 +0200459 return ret;
460}
461
Michal Vasko2d162e12015-09-24 14:33:29 +0200462API int
463lyd_unlink(struct lyd_node *node)
464{
465 struct lyd_node *iter;
466
467 if (!node) {
468 ly_errno = LY_EINVAL;
469 return EXIT_FAILURE;
470 }
471
472 /* unlink from siblings */
473 if (node->prev->next) {
474 node->prev->next = node->next;
475 }
476 if (node->next) {
477 node->next->prev = node->prev;
478 } else {
479 /* unlinking the last node */
480 iter = node->prev;
481 while (iter->prev != node) {
482 iter = iter->prev;
483 }
484 /* update the "last" pointer from the first node */
485 iter->prev = node->prev;
486 }
487
488 /* unlink from parent */
489 if (node->parent) {
490 if (node->parent->child == node) {
491 /* the node is the first child */
492 node->parent->child = node->next;
493 }
494 node->parent = NULL;
495 }
496
497 node->next = NULL;
498 node->prev = node;
499
500 return EXIT_SUCCESS;
501}
502
Michal Vaskoc0797f82015-10-14 15:51:25 +0200503API struct lyd_node *
Michal Vasko1e62a092015-12-01 12:27:20 +0100504lyd_dup(const struct lyd_node *node, int recursive)
Michal Vaskoc0797f82015-10-14 15:51:25 +0200505{
Michal Vasko1e62a092015-12-01 12:27:20 +0100506 const struct lyd_node *next, *elem;
507 struct lyd_node *ret, *parent, *new_node;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200508 struct lyd_attr *attr;
509 struct lyd_node_leaf_list *new_leaf;
510 struct lyd_node_anyxml *new_axml;
511 struct lys_type *type;
512
513 if (!node) {
514 ly_errno = LY_EINVAL;
515 return NULL;
516 }
517
518 ret = NULL;
519 parent = NULL;
520
521 /* LY_TREE_DFS */
522 for (elem = next = node; elem; elem = next) {
523
524 /* fill specific part */
525 switch (elem->schema->nodetype) {
526 case LYS_LEAF:
527 case LYS_LEAFLIST:
528 new_leaf = malloc(sizeof *new_leaf);
529 new_node = (struct lyd_node *)new_leaf;
530
531 new_leaf->value = ((struct lyd_node_leaf_list *)elem)->value;
532 new_leaf->value_str = lydict_insert(elem->schema->module->ctx,
533 ((struct lyd_node_leaf_list *)elem)->value_str, 0);
534 new_leaf->value_type = ((struct lyd_node_leaf_list *)elem)->value_type;
535 /* bits type must be treated specially */
536 if (new_leaf->value_type == LY_TYPE_BITS) {
537 for (type = &((struct lys_node_leaf *)elem->schema)->type; type->der->module; type = &type->der->type) {
538 if (type->base != LY_TYPE_BITS) {
539 LOGINT;
Michal Vaskod80e6c72015-10-15 09:37:01 +0200540 lyd_free(new_node);
Michal Vaskoc0797f82015-10-14 15:51:25 +0200541 lyd_free(ret);
542 return NULL;
543 }
544 }
545
546 new_leaf->value.bit = malloc(type->info.bits.count * sizeof *new_leaf->value.bit);
547 memcpy(new_leaf->value.bit, ((struct lyd_node_leaf_list *)elem)->value.bit,
548 type->info.bits.count * sizeof *new_leaf->value.bit);
549 }
550 break;
551 case LYS_ANYXML:
552 new_axml = malloc(sizeof *new_axml);
553 new_node = (struct lyd_node *)new_axml;
554
555 new_axml->value = lyxml_dup_elem(elem->schema->module->ctx, ((struct lyd_node_anyxml *)elem)->value,
556 NULL, 1);
557 break;
558 case LYS_CONTAINER:
559 case LYS_LIST:
560 case LYS_NOTIF:
561 case LYS_RPC:
562 new_node = malloc(sizeof *new_node);
563 new_node->child = NULL;
564 break;
565 default:
Michal Vaskoc0797f82015-10-14 15:51:25 +0200566 lyd_free(ret);
Michal Vasko24337392015-10-16 09:58:16 +0200567 LOGINT;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200568 return NULL;
569 }
570
571 /* fill common part */
572 new_node->schema = elem->schema;
573 new_node->attr = NULL;
574 LY_TREE_FOR(elem->attr, attr) {
575 lyd_dup_attr(elem->schema->module->ctx, new_node, attr);
576 }
577 new_node->next = NULL;
578 new_node->prev = new_node;
579 new_node->parent = NULL;
580
581 if (!ret) {
582 ret = new_node;
583 }
584 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200585 if (lyd_insert(parent, new_node)) {
Michal Vaskoc0797f82015-10-14 15:51:25 +0200586 lyd_free(ret);
Michal Vasko24337392015-10-16 09:58:16 +0200587 LOGINT;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200588 return NULL;
589 }
590 }
591
592 if (!recursive) {
593 break;
594 }
595
596 /* LY_TREE_DFS_END */
597 /* select element for the next run - children first */
598 next = elem->child;
599 /* child exception for lyd_node_leaf and lyd_node_leaflist */
600 if (elem->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML)) {
601 next = NULL;
602 }
603 if (!next) {
604 /* no children, so try siblings */
605 next = elem->next;
606 } else {
607 parent = new_node;
608 }
609 while (!next) {
610 /* no siblings, go back through parents */
611 elem = elem->parent;
612 if (elem->parent == node->parent) {
613 break;
614 }
Michal Vasko785b2ad2015-10-15 09:37:15 +0200615 if (!parent) {
Michal Vaskoc8f5d802015-10-23 10:14:39 +0200616 lyd_free(ret);
Michal Vasko785b2ad2015-10-15 09:37:15 +0200617 LOGINT;
Michal Vaskoc8f5d802015-10-23 10:14:39 +0200618 return NULL;
Michal Vasko785b2ad2015-10-15 09:37:15 +0200619 }
Michal Vaskoc0797f82015-10-14 15:51:25 +0200620 parent = parent->parent;
621 /* parent is already processed, go to its sibling */
622 next = elem->next;
623 }
624 }
625
626 return ret;
627}
628
Radek Krejci88f29302015-10-30 15:42:33 +0100629API void
630lyd_free_attr(struct ly_ctx *ctx, struct lyd_node *parent, struct lyd_attr *attr, int recursive)
Michal Vasko2d162e12015-09-24 14:33:29 +0200631{
Radek Krejci88f29302015-10-30 15:42:33 +0100632 struct lyd_attr *iter;
633
634 if (!ctx || !attr) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200635 return;
636 }
637
Radek Krejci88f29302015-10-30 15:42:33 +0100638 if (parent) {
639 if (parent->attr == attr) {
640 if (recursive) {
641 parent->attr = NULL;
642 } else {
643 parent->attr = attr->next;
644 }
645 } else {
646 for (iter = parent->attr; iter->next != attr; iter = iter->next);
647 if (iter->next) {
648 if (recursive) {
649 iter->next = NULL;
650 } else {
651 iter->next = attr->next;
652 }
653 }
654 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200655 }
Radek Krejci88f29302015-10-30 15:42:33 +0100656
657 if (!recursive) {
658 attr->next = NULL;
659 }
660
661 for(iter = attr; iter; ) {
662 attr = iter;
663 iter = iter->next;
664
665 lydict_remove(ctx, attr->name);
666 lydict_remove(ctx, attr->value);
667 free(attr);
668 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200669}
670
Michal Vaskofd76bd12015-09-24 15:49:57 +0200671struct lyd_node *
672lyd_attr_parent(struct lyd_node *root, struct lyd_attr *attr)
673{
674 struct lyd_node *next, *elem;
675 struct lyd_attr *node_attr;
676
677 LY_TREE_DFS_BEGIN(root, next, elem) {
678 for (node_attr = elem->attr; node_attr; node_attr = node_attr->next) {
679 if (node_attr == attr) {
680 return elem;
681 }
682 }
683 LY_TREE_DFS_END(root, next, elem)
684 }
685
686 return NULL;
687}
688
Radek Krejci134610e2015-10-20 17:15:34 +0200689API struct lyd_attr *
690lyd_insert_attr(struct lyd_node *parent, const char *name, const char *value)
691{
Radek Krejci134610e2015-10-20 17:15:34 +0200692 struct lyd_attr *a, *iter;
693 struct ly_ctx *ctx;
Michal Vasko1e62a092015-12-01 12:27:20 +0100694 const struct lys_module *module;
Radek Krejci134610e2015-10-20 17:15:34 +0200695 const char *p;
696 char *aux;
697
698 if (!parent || !name || !value) {
699 return NULL;
700 }
701 ctx = parent->schema->module->ctx;
702
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100703 if ((p = strchr(name, ':'))) {
704 /* search for the namespace */
705 aux = strndup(name, p - name);
706 module = ly_ctx_get_module(ctx, aux, NULL);
707 free(aux);
708 name = p + 1;
Radek Krejci134610e2015-10-20 17:15:34 +0200709
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100710 if (!module) {
711 /* module not found */
Radek Krejcia008ca92015-10-30 15:52:05 +0100712 LOGERR(LY_EINVAL, "Attribute prefix does not match any schema in the context.");
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100713 return NULL;
Radek Krejci134610e2015-10-20 17:15:34 +0200714 }
715 } else {
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100716 /* no prefix -> module is the same as for the parent */
717 module = parent->schema->module;
Radek Krejci134610e2015-10-20 17:15:34 +0200718 }
719
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100720 a = malloc(sizeof *a);
Michal Vasko1e62a092015-12-01 12:27:20 +0100721 a->module = (struct lys_module *)module;
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100722 a->next = NULL;
723 a->name = lydict_insert(ctx, name, 0);
Radek Krejci134610e2015-10-20 17:15:34 +0200724 a->value = lydict_insert(ctx, value, 0);
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100725
Radek Krejci134610e2015-10-20 17:15:34 +0200726 if (!parent->attr) {
727 parent->attr = a;
728 } else {
729 for (iter = parent->attr; iter->next; iter = iter->next);
730 iter->next = a;
731 }
732
733 return a;
734}
735
Michal Vasko2d162e12015-09-24 14:33:29 +0200736API void
737lyd_free(struct lyd_node *node)
738{
739 struct lyd_node *next, *child;
740
741 if (!node) {
742 return;
743 }
744
745 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
746 /* free children */
747 LY_TREE_FOR_SAFE(node->child, next, child) {
748 lyd_free(child);
749 }
750 } else if (node->schema->nodetype == LYS_ANYXML) {
Michal Vasko345da0a2015-12-02 10:35:55 +0100751 lyxml_free(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
Michal Vasko2d162e12015-09-24 14:33:29 +0200752 } else {
753 /* free value */
Michal Vasko4c183312015-09-25 10:41:47 +0200754 switch(((struct lyd_node_leaf_list *)node)->value_type) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200755 case LY_TYPE_BINARY:
756 case LY_TYPE_STRING:
Michal Vasko4c183312015-09-25 10:41:47 +0200757 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf_list *)node)->value.string);
Michal Vasko2d162e12015-09-24 14:33:29 +0200758 break;
759 case LY_TYPE_BITS:
Michal Vasko4c183312015-09-25 10:41:47 +0200760 if (((struct lyd_node_leaf_list *)node)->value.bit) {
761 free(((struct lyd_node_leaf_list *)node)->value.bit);
Michal Vasko2d162e12015-09-24 14:33:29 +0200762 }
763 break;
764 default:
765 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
766 break;
767 }
768 }
769
770 lyd_unlink(node);
Radek Krejci88f29302015-10-30 15:42:33 +0100771 lyd_free_attr(node->schema->module->ctx, node, node->attr, 1);
Michal Vasko2d162e12015-09-24 14:33:29 +0200772 free(node);
773}
774
Michal Vaskoff4c2832015-10-15 13:30:50 +0200775API char *
Michal Vasko1e62a092015-12-01 12:27:20 +0100776lyxml_serialize(const struct lyxml_elem *anyxml)
Michal Vaskoff4c2832015-10-15 13:30:50 +0200777{
778 FILE *stream;
779 char *buf;
780 size_t buf_size;
781
782 if (!anyxml) {
783 ly_errno = LY_EINVAL;
784 return NULL;
785 }
786
787 stream = open_memstream(&buf, &buf_size);
788 if (!stream) {
789 ly_errno = LY_ESYS;
790 return NULL;
791 }
792 if (lyxml_dump(stream, anyxml, 0) == 0) {
793 free(buf);
794 buf = NULL;
795 ly_errno = LY_EINVAL;
796 }
797 fclose(stream);
798
799 return buf;
800}
801
Michal Vasko2d162e12015-09-24 14:33:29 +0200802int
803lyd_compare(struct lyd_node *first, struct lyd_node *second, int unique)
804{
805 struct lys_node_list *slist;
Michal Vasko1e62a092015-12-01 12:27:20 +0100806 const struct lys_node *snode = NULL;
Michal Vasko2d162e12015-09-24 14:33:29 +0200807 struct lyd_node *diter;
808 const char *val1, *val2;
809 int i, j;
810
811 assert(first);
812 assert(second);
813
814 if (first->schema != second->schema) {
815 return 1;
816 }
817
818 switch (first->schema->nodetype) {
819 case LYS_LEAFLIST:
820 /* compare values */
Michal Vasko4c183312015-09-25 10:41:47 +0200821 if (((struct lyd_node_leaf_list *)first)->value_str == ((struct lyd_node_leaf_list *)second)->value_str) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200822 return 0;
823 }
824 return 1;
825 case LYS_LIST:
Michal Vasko4c183312015-09-25 10:41:47 +0200826 slist = (struct lys_node_list *)first->schema;
Michal Vasko2d162e12015-09-24 14:33:29 +0200827
828 if (unique) {
829 /* compare unique leafs */
830 for (i = 0; i < slist->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +0100831 for (j = 0; j < slist->unique[i].expr_size; j++) {
832 /* first */
833 diter = resolve_data_nodeid(slist->unique[i].expr[j], first->child);
834 if (diter) {
835 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
836 } else {
837 /* use default value */
838 resolve_schema_nodeid(slist->unique[i].expr[j], first->schema->child, first->schema->module, LYS_LEAF, &snode);
839 val1 = ((struct lys_node_leaf *)snode)->dflt;
Michal Vasko2d162e12015-09-24 14:33:29 +0200840 }
Radek Krejci581ce772015-11-10 17:22:40 +0100841
842 /* second */
843 diter = resolve_data_nodeid(slist->unique[i].expr[j], second->child);
844 if (diter) {
845 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
846 } else {
847 /* use default value */
848 resolve_schema_nodeid(slist->unique[i].expr[j], second->schema->child, second->schema->module, LYS_LEAF, &snode);
849 val2 = ((struct lys_node_leaf *)snode)->dflt;
Michal Vasko2d162e12015-09-24 14:33:29 +0200850 }
Radek Krejci581ce772015-11-10 17:22:40 +0100851
Michal Vasko2d162e12015-09-24 14:33:29 +0200852 if (val1 != val2) {
853 break;
854 }
855 }
Radek Krejci581ce772015-11-10 17:22:40 +0100856 if (j && j == slist->unique[i].expr_size) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200857 /* all unique leafs are the same in this set */
858 return 0;
859 }
860 }
861 }
862
863 /* compare keys */
864 for (i = 0; i < slist->keys_size; i++) {
865 snode = (struct lys_node *)slist->keys[i];
866 val1 = val2 = NULL;
867 LY_TREE_FOR(first->child, diter) {
868 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200869 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200870 break;
871 }
872 }
873 LY_TREE_FOR(second->child, diter) {
874 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200875 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200876 break;
877 }
878 }
879 if (val1 != val2) {
880 return 1;
881 }
882 }
883
884 return 0;
885 default:
886 /* no additional check is needed */
887 return 0;
888 }
889}
890
891API struct lyd_set *
892lyd_set_new(void)
893{
894 return calloc(1, sizeof(struct lyd_set));
895}
896
897API void
898lyd_set_free(struct lyd_set *set)
899{
900 if (!set) {
901 return;
902 }
903
904 free(set->set);
905 free(set);
906}
907
908API int
909lyd_set_add(struct lyd_set *set, struct lyd_node *node)
910{
911 struct lyd_node **new;
912
913 if (!set) {
914 ly_errno = LY_EINVAL;
915 return EXIT_FAILURE;
916 }
917
918 if (set->size == set->number) {
919 new = realloc(set->set, (set->size + 8) * sizeof *(set->set));
920 if (!new) {
921 LOGMEM;
922 return EXIT_FAILURE;
923 }
924 set->size += 8;
925 set->set = new;
926 }
927
928 set->set[set->number++] = node;
929
930 return EXIT_SUCCESS;
931}