blob: a14efbe9d8c1e9f1fe92ae31518048165c42b7da [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 */
Radek Krejci2b7bb492015-12-02 15:46:29 +0100288 for(sparent = node->schema->parent;
289 sparent && !(sparent->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF));
290 sparent = sparent->parent);
Michal Vasko2d162e12015-09-24 14:33:29 +0200291 if (sparent != parent->schema) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200292 return EXIT_FAILURE;
293 }
294
Michal Vasko24337392015-10-16 09:58:16 +0200295 if (node->parent || node->prev->next) {
296 lyd_unlink(node);
297 }
298
Michal Vasko2d162e12015-09-24 14:33:29 +0200299 if (!parent->child) {
300 /* add as the only child of the parent */
301 parent->child = node;
302 } else {
303 /* add as the last child of the parent */
304 parent->child->prev->next = node;
305 node->prev = parent->child->prev;
306 for (iter = node; iter->next; iter = iter->next);
307 parent->child->prev = iter;
308 }
Michal Vasko9cc2d0a2015-10-14 15:49:07 +0200309
Michal Vasko2d162e12015-09-24 14:33:29 +0200310 LY_TREE_FOR(node, iter) {
311 iter->parent = parent;
Michal Vasko2d162e12015-09-24 14:33:29 +0200312 }
313
314 return EXIT_SUCCESS;
315}
316
Michal Vasko02592902015-10-15 12:14:40 +0200317static int
Michal Vasko24337392015-10-16 09:58:16 +0200318lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, int before)
Michal Vasko2d162e12015-09-24 14:33:29 +0200319{
320 struct lys_node *par1, *par2;
Michal Vasko24337392015-10-16 09:58:16 +0200321 struct lyd_node *iter, *last;
Michal Vasko3f7dba12015-10-15 13:09:27 +0200322
323 if (sibling == node) {
324 return EXIT_SUCCESS;
325 }
326
Michal Vasko2d162e12015-09-24 14:33:29 +0200327 /* check placing the node to the appropriate place according to the schema */
Radek Krejci2b7bb492015-12-02 15:46:29 +0100328 for (par1 = sibling->schema->parent;
329 par1 && !(par1->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF));
330 par1 = par1->parent);
331 for (par2 = node->schema->parent;
332 par2 && !(par2->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF));
333 par2 = par2->parent);
Michal Vasko2d162e12015-09-24 14:33:29 +0200334 if (par1 != par2) {
335 ly_errno = LY_EINVAL;
336 return EXIT_FAILURE;
337 }
338
Michal Vasko24337392015-10-16 09:58:16 +0200339 if (node->parent || node->prev->next) {
340 lyd_unlink(node);
341 }
342
Michal Vasko2d162e12015-09-24 14:33:29 +0200343 LY_TREE_FOR(node, iter) {
344 iter->parent = sibling->parent;
Michal Vasko24337392015-10-16 09:58:16 +0200345 last = iter;
Michal Vasko2d162e12015-09-24 14:33:29 +0200346 }
347
Michal Vasko02592902015-10-15 12:14:40 +0200348 if (before) {
349 if (sibling->prev->next) {
350 /* adding into the list */
351 sibling->prev->next = node;
352 } else if (sibling->parent) {
353 /* at the beginning */
354 sibling->parent->child = node;
Michal Vasko2d162e12015-09-24 14:33:29 +0200355 }
Michal Vasko02592902015-10-15 12:14:40 +0200356 node->prev = sibling->prev;
357 sibling->prev = last;
358 last->next = sibling;
359 } else {
360 if (sibling->next) {
361 /* adding into a middle - fix the prev pointer of the node after inserted nodes */
362 last->next = sibling->next;
363 sibling->next->prev = last;
364 } else {
365 /* at the end - fix the prev pointer of the first node */
366 if (sibling->parent) {
367 sibling->parent->child->prev = last;
368 } else {
369 for (iter = sibling; iter->prev->next; iter = iter->prev);
370 iter->prev = last;
371 }
372 }
373 sibling->next = node;
374 node->prev = sibling;
Michal Vasko2d162e12015-09-24 14:33:29 +0200375 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200376
Michal Vasko24337392015-10-16 09:58:16 +0200377 return EXIT_SUCCESS;
378}
Michal Vasko2d162e12015-09-24 14:33:29 +0200379
Michal Vasko24337392015-10-16 09:58:16 +0200380API int
381lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
382{
383 if (!node || !sibling || lyd_insert_sibling(sibling, node, 1)) {
384 ly_errno = LY_EINVAL;
385 return EXIT_FAILURE;
386 }
387
388 return EXIT_SUCCESS;
389}
390
391API int
392lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
393{
394 if (!node || !sibling || lyd_insert_sibling(sibling, node, 0)) {
395 ly_errno = LY_EINVAL;
396 return EXIT_FAILURE;
397 }
398
399 return EXIT_SUCCESS;
400}
401
402API int
403lyd_validate(struct lyd_node *node, int options)
404{
405 struct lyd_node *next, *iter, *to_free = NULL;
406
407 ly_errno = 0;
408 LY_TREE_DFS_BEGIN(node, next, iter) {
409 if (to_free) {
410 lyd_free(to_free);
411 to_free = NULL;
412 }
413
414 if (lyv_data_content(iter, 0, options, NULL)) {
415 if (ly_errno) {
416 return EXIT_FAILURE;
Michal Vasko2fce5f52015-10-23 10:14:08 +0200417 } else if (iter == node) {
418 /* removing the whole subtree */
419 to_free = node;
420 break;
Michal Vasko24337392015-10-16 09:58:16 +0200421 } else {
422 /* safe deferred removal */
423 to_free = iter;
Michal Vasko3f7dba12015-10-15 13:09:27 +0200424 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200425 }
Michal Vasko24337392015-10-16 09:58:16 +0200426
427 LY_TREE_DFS_END(node, next, iter);
Michal Vasko2d162e12015-09-24 14:33:29 +0200428 }
429
Michal Vasko24337392015-10-16 09:58:16 +0200430 if (to_free) {
431 lyd_free(to_free);
432 to_free = NULL;
Michal Vasko02592902015-10-15 12:14:40 +0200433 }
434
435 return EXIT_SUCCESS;
436}
437
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100438/* create an attribute copy */
Michal Vasko55f60be2015-10-14 13:12:58 +0200439static struct lyd_attr *
440lyd_dup_attr(struct ly_ctx *ctx, struct lyd_node *parent, struct lyd_attr *attr)
441{
442 struct lyd_attr *ret;
443
444 /* allocate new attr */
445 if (!parent->attr) {
446 parent->attr = malloc(sizeof *parent->attr);
447 ret = parent->attr;
448 } else {
449 for (ret = parent->attr; ret->next; ret = ret->next);
450 ret->next = malloc(sizeof *ret);
451 ret = ret->next;
452 }
453
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100454 /* fill new attr except */
Michal Vasko55f60be2015-10-14 13:12:58 +0200455 ret->next = NULL;
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100456 ret->module = attr->module;
Michal Vasko55f60be2015-10-14 13:12:58 +0200457 ret->name = lydict_insert(ctx, attr->name, 0);
458 ret->value = lydict_insert(ctx, attr->value, 0);
459
Michal Vasko55f60be2015-10-14 13:12:58 +0200460 return ret;
461}
462
Michal Vasko2d162e12015-09-24 14:33:29 +0200463API int
464lyd_unlink(struct lyd_node *node)
465{
466 struct lyd_node *iter;
467
468 if (!node) {
469 ly_errno = LY_EINVAL;
470 return EXIT_FAILURE;
471 }
472
473 /* unlink from siblings */
474 if (node->prev->next) {
475 node->prev->next = node->next;
476 }
477 if (node->next) {
478 node->next->prev = node->prev;
479 } else {
480 /* unlinking the last node */
481 iter = node->prev;
482 while (iter->prev != node) {
483 iter = iter->prev;
484 }
485 /* update the "last" pointer from the first node */
486 iter->prev = node->prev;
487 }
488
489 /* unlink from parent */
490 if (node->parent) {
491 if (node->parent->child == node) {
492 /* the node is the first child */
493 node->parent->child = node->next;
494 }
495 node->parent = NULL;
496 }
497
498 node->next = NULL;
499 node->prev = node;
500
501 return EXIT_SUCCESS;
502}
503
Michal Vaskoc0797f82015-10-14 15:51:25 +0200504API struct lyd_node *
Michal Vasko1e62a092015-12-01 12:27:20 +0100505lyd_dup(const struct lyd_node *node, int recursive)
Michal Vaskoc0797f82015-10-14 15:51:25 +0200506{
Michal Vasko1e62a092015-12-01 12:27:20 +0100507 const struct lyd_node *next, *elem;
508 struct lyd_node *ret, *parent, *new_node;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200509 struct lyd_attr *attr;
510 struct lyd_node_leaf_list *new_leaf;
511 struct lyd_node_anyxml *new_axml;
512 struct lys_type *type;
513
514 if (!node) {
515 ly_errno = LY_EINVAL;
516 return NULL;
517 }
518
519 ret = NULL;
520 parent = NULL;
521
522 /* LY_TREE_DFS */
523 for (elem = next = node; elem; elem = next) {
524
525 /* fill specific part */
526 switch (elem->schema->nodetype) {
527 case LYS_LEAF:
528 case LYS_LEAFLIST:
529 new_leaf = malloc(sizeof *new_leaf);
530 new_node = (struct lyd_node *)new_leaf;
531
532 new_leaf->value = ((struct lyd_node_leaf_list *)elem)->value;
533 new_leaf->value_str = lydict_insert(elem->schema->module->ctx,
534 ((struct lyd_node_leaf_list *)elem)->value_str, 0);
535 new_leaf->value_type = ((struct lyd_node_leaf_list *)elem)->value_type;
536 /* bits type must be treated specially */
537 if (new_leaf->value_type == LY_TYPE_BITS) {
538 for (type = &((struct lys_node_leaf *)elem->schema)->type; type->der->module; type = &type->der->type) {
539 if (type->base != LY_TYPE_BITS) {
540 LOGINT;
Michal Vaskod80e6c72015-10-15 09:37:01 +0200541 lyd_free(new_node);
Michal Vaskoc0797f82015-10-14 15:51:25 +0200542 lyd_free(ret);
543 return NULL;
544 }
545 }
546
547 new_leaf->value.bit = malloc(type->info.bits.count * sizeof *new_leaf->value.bit);
548 memcpy(new_leaf->value.bit, ((struct lyd_node_leaf_list *)elem)->value.bit,
549 type->info.bits.count * sizeof *new_leaf->value.bit);
550 }
551 break;
552 case LYS_ANYXML:
553 new_axml = malloc(sizeof *new_axml);
554 new_node = (struct lyd_node *)new_axml;
555
556 new_axml->value = lyxml_dup_elem(elem->schema->module->ctx, ((struct lyd_node_anyxml *)elem)->value,
557 NULL, 1);
558 break;
559 case LYS_CONTAINER:
560 case LYS_LIST:
561 case LYS_NOTIF:
562 case LYS_RPC:
563 new_node = malloc(sizeof *new_node);
564 new_node->child = NULL;
565 break;
566 default:
Michal Vaskoc0797f82015-10-14 15:51:25 +0200567 lyd_free(ret);
Michal Vasko24337392015-10-16 09:58:16 +0200568 LOGINT;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200569 return NULL;
570 }
571
572 /* fill common part */
573 new_node->schema = elem->schema;
574 new_node->attr = NULL;
575 LY_TREE_FOR(elem->attr, attr) {
576 lyd_dup_attr(elem->schema->module->ctx, new_node, attr);
577 }
578 new_node->next = NULL;
579 new_node->prev = new_node;
580 new_node->parent = NULL;
581
582 if (!ret) {
583 ret = new_node;
584 }
585 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200586 if (lyd_insert(parent, new_node)) {
Michal Vaskoc0797f82015-10-14 15:51:25 +0200587 lyd_free(ret);
Michal Vasko24337392015-10-16 09:58:16 +0200588 LOGINT;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200589 return NULL;
590 }
591 }
592
593 if (!recursive) {
594 break;
595 }
596
597 /* LY_TREE_DFS_END */
598 /* select element for the next run - children first */
599 next = elem->child;
600 /* child exception for lyd_node_leaf and lyd_node_leaflist */
601 if (elem->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML)) {
602 next = NULL;
603 }
604 if (!next) {
605 /* no children, so try siblings */
606 next = elem->next;
607 } else {
608 parent = new_node;
609 }
610 while (!next) {
611 /* no siblings, go back through parents */
612 elem = elem->parent;
613 if (elem->parent == node->parent) {
614 break;
615 }
Michal Vasko785b2ad2015-10-15 09:37:15 +0200616 if (!parent) {
Michal Vaskoc8f5d802015-10-23 10:14:39 +0200617 lyd_free(ret);
Michal Vasko785b2ad2015-10-15 09:37:15 +0200618 LOGINT;
Michal Vaskoc8f5d802015-10-23 10:14:39 +0200619 return NULL;
Michal Vasko785b2ad2015-10-15 09:37:15 +0200620 }
Michal Vaskoc0797f82015-10-14 15:51:25 +0200621 parent = parent->parent;
622 /* parent is already processed, go to its sibling */
623 next = elem->next;
624 }
625 }
626
627 return ret;
628}
629
Radek Krejci88f29302015-10-30 15:42:33 +0100630API void
631lyd_free_attr(struct ly_ctx *ctx, struct lyd_node *parent, struct lyd_attr *attr, int recursive)
Michal Vasko2d162e12015-09-24 14:33:29 +0200632{
Radek Krejci88f29302015-10-30 15:42:33 +0100633 struct lyd_attr *iter;
634
635 if (!ctx || !attr) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200636 return;
637 }
638
Radek Krejci88f29302015-10-30 15:42:33 +0100639 if (parent) {
640 if (parent->attr == attr) {
641 if (recursive) {
642 parent->attr = NULL;
643 } else {
644 parent->attr = attr->next;
645 }
646 } else {
647 for (iter = parent->attr; iter->next != attr; iter = iter->next);
648 if (iter->next) {
649 if (recursive) {
650 iter->next = NULL;
651 } else {
652 iter->next = attr->next;
653 }
654 }
655 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200656 }
Radek Krejci88f29302015-10-30 15:42:33 +0100657
658 if (!recursive) {
659 attr->next = NULL;
660 }
661
662 for(iter = attr; iter; ) {
663 attr = iter;
664 iter = iter->next;
665
666 lydict_remove(ctx, attr->name);
667 lydict_remove(ctx, attr->value);
668 free(attr);
669 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200670}
671
Michal Vaskofd76bd12015-09-24 15:49:57 +0200672struct lyd_node *
673lyd_attr_parent(struct lyd_node *root, struct lyd_attr *attr)
674{
675 struct lyd_node *next, *elem;
676 struct lyd_attr *node_attr;
677
678 LY_TREE_DFS_BEGIN(root, next, elem) {
679 for (node_attr = elem->attr; node_attr; node_attr = node_attr->next) {
680 if (node_attr == attr) {
681 return elem;
682 }
683 }
684 LY_TREE_DFS_END(root, next, elem)
685 }
686
687 return NULL;
688}
689
Radek Krejci134610e2015-10-20 17:15:34 +0200690API struct lyd_attr *
691lyd_insert_attr(struct lyd_node *parent, const char *name, const char *value)
692{
Radek Krejci134610e2015-10-20 17:15:34 +0200693 struct lyd_attr *a, *iter;
694 struct ly_ctx *ctx;
Michal Vasko1e62a092015-12-01 12:27:20 +0100695 const struct lys_module *module;
Radek Krejci134610e2015-10-20 17:15:34 +0200696 const char *p;
697 char *aux;
698
699 if (!parent || !name || !value) {
700 return NULL;
701 }
702 ctx = parent->schema->module->ctx;
703
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100704 if ((p = strchr(name, ':'))) {
705 /* search for the namespace */
706 aux = strndup(name, p - name);
707 module = ly_ctx_get_module(ctx, aux, NULL);
708 free(aux);
709 name = p + 1;
Radek Krejci134610e2015-10-20 17:15:34 +0200710
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100711 if (!module) {
712 /* module not found */
Radek Krejcia008ca92015-10-30 15:52:05 +0100713 LOGERR(LY_EINVAL, "Attribute prefix does not match any schema in the context.");
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100714 return NULL;
Radek Krejci134610e2015-10-20 17:15:34 +0200715 }
716 } else {
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100717 /* no prefix -> module is the same as for the parent */
718 module = parent->schema->module;
Radek Krejci134610e2015-10-20 17:15:34 +0200719 }
720
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100721 a = malloc(sizeof *a);
Michal Vasko1e62a092015-12-01 12:27:20 +0100722 a->module = (struct lys_module *)module;
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100723 a->next = NULL;
724 a->name = lydict_insert(ctx, name, 0);
Radek Krejci134610e2015-10-20 17:15:34 +0200725 a->value = lydict_insert(ctx, value, 0);
Radek Krejci5f9e8c92015-10-30 10:01:06 +0100726
Radek Krejci134610e2015-10-20 17:15:34 +0200727 if (!parent->attr) {
728 parent->attr = a;
729 } else {
730 for (iter = parent->attr; iter->next; iter = iter->next);
731 iter->next = a;
732 }
733
734 return a;
735}
736
Michal Vasko2d162e12015-09-24 14:33:29 +0200737API void
738lyd_free(struct lyd_node *node)
739{
740 struct lyd_node *next, *child;
741
742 if (!node) {
743 return;
744 }
745
746 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
747 /* free children */
748 LY_TREE_FOR_SAFE(node->child, next, child) {
749 lyd_free(child);
750 }
751 } else if (node->schema->nodetype == LYS_ANYXML) {
Michal Vasko345da0a2015-12-02 10:35:55 +0100752 lyxml_free(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
Michal Vasko2d162e12015-09-24 14:33:29 +0200753 } else {
754 /* free value */
Michal Vasko4c183312015-09-25 10:41:47 +0200755 switch(((struct lyd_node_leaf_list *)node)->value_type) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200756 case LY_TYPE_BINARY:
757 case LY_TYPE_STRING:
Michal Vasko4c183312015-09-25 10:41:47 +0200758 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf_list *)node)->value.string);
Michal Vasko2d162e12015-09-24 14:33:29 +0200759 break;
760 case LY_TYPE_BITS:
Michal Vasko4c183312015-09-25 10:41:47 +0200761 if (((struct lyd_node_leaf_list *)node)->value.bit) {
762 free(((struct lyd_node_leaf_list *)node)->value.bit);
Michal Vasko2d162e12015-09-24 14:33:29 +0200763 }
764 break;
765 default:
766 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
767 break;
768 }
769 }
770
771 lyd_unlink(node);
Radek Krejci88f29302015-10-30 15:42:33 +0100772 lyd_free_attr(node->schema->module->ctx, node, node->attr, 1);
Michal Vasko2d162e12015-09-24 14:33:29 +0200773 free(node);
774}
775
Michal Vaskoff4c2832015-10-15 13:30:50 +0200776API char *
Michal Vasko1e62a092015-12-01 12:27:20 +0100777lyxml_serialize(const struct lyxml_elem *anyxml)
Michal Vaskoff4c2832015-10-15 13:30:50 +0200778{
779 FILE *stream;
780 char *buf;
781 size_t buf_size;
782
783 if (!anyxml) {
784 ly_errno = LY_EINVAL;
785 return NULL;
786 }
787
788 stream = open_memstream(&buf, &buf_size);
789 if (!stream) {
790 ly_errno = LY_ESYS;
791 return NULL;
792 }
793 if (lyxml_dump(stream, anyxml, 0) == 0) {
794 free(buf);
795 buf = NULL;
796 ly_errno = LY_EINVAL;
797 }
798 fclose(stream);
799
800 return buf;
801}
802
Michal Vasko2d162e12015-09-24 14:33:29 +0200803int
804lyd_compare(struct lyd_node *first, struct lyd_node *second, int unique)
805{
806 struct lys_node_list *slist;
Michal Vasko1e62a092015-12-01 12:27:20 +0100807 const struct lys_node *snode = NULL;
Michal Vasko2d162e12015-09-24 14:33:29 +0200808 struct lyd_node *diter;
809 const char *val1, *val2;
810 int i, j;
811
812 assert(first);
813 assert(second);
814
815 if (first->schema != second->schema) {
816 return 1;
817 }
818
819 switch (first->schema->nodetype) {
820 case LYS_LEAFLIST:
821 /* compare values */
Michal Vasko4c183312015-09-25 10:41:47 +0200822 if (((struct lyd_node_leaf_list *)first)->value_str == ((struct lyd_node_leaf_list *)second)->value_str) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200823 return 0;
824 }
825 return 1;
826 case LYS_LIST:
Michal Vasko4c183312015-09-25 10:41:47 +0200827 slist = (struct lys_node_list *)first->schema;
Michal Vasko2d162e12015-09-24 14:33:29 +0200828
829 if (unique) {
830 /* compare unique leafs */
831 for (i = 0; i < slist->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +0100832 for (j = 0; j < slist->unique[i].expr_size; j++) {
833 /* first */
834 diter = resolve_data_nodeid(slist->unique[i].expr[j], first->child);
835 if (diter) {
836 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
837 } else {
838 /* use default value */
839 resolve_schema_nodeid(slist->unique[i].expr[j], first->schema->child, first->schema->module, LYS_LEAF, &snode);
840 val1 = ((struct lys_node_leaf *)snode)->dflt;
Michal Vasko2d162e12015-09-24 14:33:29 +0200841 }
Radek Krejci581ce772015-11-10 17:22:40 +0100842
843 /* second */
844 diter = resolve_data_nodeid(slist->unique[i].expr[j], second->child);
845 if (diter) {
846 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
847 } else {
848 /* use default value */
849 resolve_schema_nodeid(slist->unique[i].expr[j], second->schema->child, second->schema->module, LYS_LEAF, &snode);
850 val2 = ((struct lys_node_leaf *)snode)->dflt;
Michal Vasko2d162e12015-09-24 14:33:29 +0200851 }
Radek Krejci581ce772015-11-10 17:22:40 +0100852
Michal Vasko2d162e12015-09-24 14:33:29 +0200853 if (val1 != val2) {
854 break;
855 }
856 }
Radek Krejci581ce772015-11-10 17:22:40 +0100857 if (j && j == slist->unique[i].expr_size) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200858 /* all unique leafs are the same in this set */
859 return 0;
860 }
861 }
862 }
863
864 /* compare keys */
865 for (i = 0; i < slist->keys_size; i++) {
866 snode = (struct lys_node *)slist->keys[i];
867 val1 = val2 = NULL;
868 LY_TREE_FOR(first->child, diter) {
869 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200870 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200871 break;
872 }
873 }
874 LY_TREE_FOR(second->child, diter) {
875 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200876 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200877 break;
878 }
879 }
880 if (val1 != val2) {
881 return 1;
882 }
883 }
884
885 return 0;
886 default:
887 /* no additional check is needed */
888 return 0;
889 }
890}
891
892API struct lyd_set *
893lyd_set_new(void)
894{
895 return calloc(1, sizeof(struct lyd_set));
896}
897
898API void
899lyd_set_free(struct lyd_set *set)
900{
901 if (!set) {
902 return;
903 }
904
905 free(set->set);
906 free(set);
907}
908
909API int
910lyd_set_add(struct lyd_set *set, struct lyd_node *node)
911{
912 struct lyd_node **new;
913
914 if (!set) {
915 ly_errno = LY_EINVAL;
916 return EXIT_FAILURE;
917 }
918
919 if (set->size == set->number) {
920 new = realloc(set->set, (set->size + 8) * sizeof *(set->set));
921 if (!new) {
922 LOGMEM;
923 return EXIT_FAILURE;
924 }
925 set->size += 8;
926 set->set = new;
927 }
928
929 set->set[set->number++] = node;
930
931 return EXIT_SUCCESS;
932}