blob: eb97cdacc2240cacf31eb603d7a291b5c1167f2a [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
42API struct lyd_node *
43lyd_parse(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
44{
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);
57 result = lyd_parse_xml(ctx, xml, options);
58 lyxml_free_elem(ctx, xml);
59 break;
Michal Vasko2d162e12015-09-24 14:33:29 +020060 case LYD_JSON:
61 default:
62 /* TODO */
63 return NULL;
64 }
65
Radek Krejci5974c1f2015-10-09 09:53:24 +020066 return result;
Michal Vasko2d162e12015-09-24 14:33:29 +020067}
68
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020069API struct lyd_node *
70lyd_new(struct lyd_node *parent, struct lys_module *module, const char *name)
71{
72 struct lyd_node *ret;
73 struct lys_node *snode = NULL, *siblings;
74
75 if ((!parent && !module) || !name) {
76 ly_errno = LY_EINVAL;
77 return NULL;
78 }
79
80 if (!parent) {
81 siblings = module->data;
82 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +020083 if (!parent->schema) {
84 return NULL;
85 }
86 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020087 }
88
Michal Vaskoa45cf2b2015-10-23 09:45:36 +020089 if (lys_get_data_sibling(module, siblings, name, LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC, &snode)
90 || !snode) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020091 return NULL;
92 }
93
94 ret = calloc(1, sizeof *ret);
95 ret->schema = snode;
96 ret->prev = ret;
97 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +020098 if (lyd_insert(parent, ret)) {
99 lyd_free(ret);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200100 return NULL;
101 }
102 }
103
104 return ret;
105}
106
107API struct lyd_node *
Michal Vasko3e671b52015-10-23 16:23:15 +0200108lyd_new_leaf(struct lyd_node *parent, struct lys_module *module, const char *name, const char *val_str)
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200109{
110 struct lyd_node_leaf_list *ret;
111 struct lys_node *snode = NULL, *siblings;
Michal Vasko3e671b52015-10-23 16:23:15 +0200112 struct lys_type *stype, *type;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200113 int found;
114
115 if ((!parent && !module) || !name) {
116 ly_errno = LY_EINVAL;
117 return NULL;
118 }
119
120 if (!parent) {
121 siblings = module->data;
122 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200123 if (!parent->schema) {
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200124 ly_errno = LY_EINVAL;
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200125 return NULL;
126 }
127 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200128 }
129
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200130 if (lys_get_data_sibling(module, siblings, name, LYS_LEAFLIST | LYS_LEAF, &snode) || !snode) {
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200131 ly_errno = LY_EINVAL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200132 return NULL;
133 }
134
Michal Vasko3e671b52015-10-23 16:23:15 +0200135 /* create the new leaf */
136 ret = calloc(1, sizeof *ret);
137 ret->schema = snode;
138 ret->prev = (struct lyd_node *)ret;
139 ret->value_str = lydict_insert((module ? module->ctx : parent->schema->module->ctx), val_str, 0);
140
141 /* resolve the type correctly */
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200142 stype = &((struct lys_node_leaf *)snode)->type;
143 if (stype->base == LY_TYPE_UNION) {
144 found = 0;
Michal Vasko3e671b52015-10-23 16:23:15 +0200145 type = lyp_get_next_union_type(stype, NULL, &found);
146 do {
147 ret->value_type = type->base;
148 if (!lyp_parse_value(ret, type, 1, NULL, UINT_MAX)) {
149 /* success! */
150 break;
151 }
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200152 found = 0;
Michal Vasko3e671b52015-10-23 16:23:15 +0200153 } while ((type = lyp_get_next_union_type(stype, type, &found)));
154
155 if (!type) {
156 /* fail */
157 ly_errno = LY_EINVAL;
158 lyd_free((struct lyd_node *)ret);
159 return NULL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200160 }
Michal Vasko3e671b52015-10-23 16:23:15 +0200161 } else {
162 ret->value_type = stype->base;
163 if (lyp_parse_value(ret, stype, 1, NULL, 0)) {
164 lyd_free((struct lyd_node *)ret);
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200165 ly_errno = LY_EINVAL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200166 return NULL;
167 }
168 }
169
Michal Vasko3e671b52015-10-23 16:23:15 +0200170 /* connect to parent */
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200171 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200172 if (lyd_insert(parent, (struct lyd_node *)ret)) {
173 lyd_free((struct lyd_node *)ret);
Michal Vasko6a9dd1f2015-10-15 15:09:11 +0200174 return NULL;
175 }
176 }
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200177
178 return (struct lyd_node *)ret;
179
180}
181
182API struct lyd_node *
183lyd_new_anyxml(struct lyd_node *parent, struct lys_module *module, const char *name, const char *val_xml)
184{
Michal Vasko587998f2015-09-29 16:07:53 +0200185 struct lyd_node_anyxml *ret;
186 struct lys_node *siblings, *snode;
187 struct lyxml_elem *root, *first_child, *last_child, *child;
188 struct ly_ctx *ctx;
189 char *xml;
190
191 if ((!parent && !module) || !name || !val_xml) {
192 ly_errno = LY_EINVAL;
193 return NULL;
194 }
195
196 if (!parent) {
197 siblings = module->data;
198 ctx = module->ctx;
199 } else {
200 if (!parent->schema) {
201 return NULL;
202 }
203 siblings = parent->schema->child;
204 ctx = parent->schema->module->ctx;
205 }
206
Michal Vaskoa45cf2b2015-10-23 09:45:36 +0200207 if (lys_get_data_sibling(module, siblings, name, LYS_ANYXML, &snode) || !snode) {
Michal Vasko587998f2015-09-29 16:07:53 +0200208 return NULL;
209 }
210
211 ret = calloc(1, sizeof *ret);
212 ret->schema = snode;
213 ret->prev = (struct lyd_node *)ret;
214 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200215 if (lyd_insert(parent, (struct lyd_node *)ret)) {
216 lyd_free((struct lyd_node *)ret);
Michal Vasko587998f2015-09-29 16:07:53 +0200217 return NULL;
218 }
219 }
220
221 /* add fake root so we can parse the data */
222 asprintf(&xml, "<root>%s</root>", val_xml);
223 root = lyxml_read(ctx, xml, 0);
224 free(xml);
Michal Vasko5b6e78d2015-10-09 15:01:10 +0200225 if (!root) {
Michal Vasko24337392015-10-16 09:58:16 +0200226 lyd_free((struct lyd_node *)ret);
Michal Vasko5b6e78d2015-10-09 15:01:10 +0200227 return NULL;
228 }
Michal Vasko587998f2015-09-29 16:07:53 +0200229
230 /* remove the root */
Radek Krejcie4e4d722015-10-05 16:53:50 +0200231 first_child = last_child = NULL;
Michal Vasko587998f2015-09-29 16:07:53 +0200232 LY_TREE_FOR(root->child, child) {
233 lyxml_unlink_elem(ctx, child, 1);
234 if (!first_child) {
235 first_child = child;
236 last_child = child;
237 } else {
238 last_child->next = child;
239 child->prev = last_child;
240 last_child = child;
241 }
242 }
Radek Krejcie4e4d722015-10-05 16:53:50 +0200243 if (first_child) {
244 first_child->prev = last_child;
245 }
Michal Vasko587998f2015-09-29 16:07:53 +0200246 lyxml_free_elem(ctx, root);
247
248 ret->value = first_child;
249
250 return (struct lyd_node *)ret;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200251}
252
Michal Vasko24337392015-10-16 09:58:16 +0200253API int
254lyd_insert(struct lyd_node *parent, struct lyd_node *node)
Michal Vasko2d162e12015-09-24 14:33:29 +0200255{
256 struct lys_node *sparent;
Michal Vasko24337392015-10-16 09:58:16 +0200257 struct lyd_node *iter;
Michal Vasko2d162e12015-09-24 14:33:29 +0200258
Michal Vasko24337392015-10-16 09:58:16 +0200259 if (!node || !parent) {
260 ly_errno = LY_EINVAL;
261 return EXIT_FAILURE;
Michal Vasko2d162e12015-09-24 14:33:29 +0200262 }
263
264 /* check placing the node to the appropriate place according to the schema */
265 sparent = node->schema->parent;
Radek Krejci8a6794f2015-10-20 17:14:48 +0200266 while (!(sparent->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_NOTIF))) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200267 sparent = sparent->parent;
268 }
269 if (sparent != parent->schema) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200270 return EXIT_FAILURE;
271 }
272
Michal Vasko24337392015-10-16 09:58:16 +0200273 if (node->parent || node->prev->next) {
274 lyd_unlink(node);
275 }
276
Michal Vasko2d162e12015-09-24 14:33:29 +0200277 if (!parent->child) {
278 /* add as the only child of the parent */
279 parent->child = node;
280 } else {
281 /* add as the last child of the parent */
282 parent->child->prev->next = node;
283 node->prev = parent->child->prev;
284 for (iter = node; iter->next; iter = iter->next);
285 parent->child->prev = iter;
286 }
Michal Vasko9cc2d0a2015-10-14 15:49:07 +0200287
Michal Vasko2d162e12015-09-24 14:33:29 +0200288 LY_TREE_FOR(node, iter) {
289 iter->parent = parent;
Michal Vasko2d162e12015-09-24 14:33:29 +0200290 }
291
292 return EXIT_SUCCESS;
293}
294
Michal Vasko02592902015-10-15 12:14:40 +0200295static int
Michal Vasko24337392015-10-16 09:58:16 +0200296lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, int before)
Michal Vasko2d162e12015-09-24 14:33:29 +0200297{
298 struct lys_node *par1, *par2;
Michal Vasko24337392015-10-16 09:58:16 +0200299 struct lyd_node *iter, *last;
Michal Vasko3f7dba12015-10-15 13:09:27 +0200300
301 if (sibling == node) {
302 return EXIT_SUCCESS;
303 }
304
Michal Vasko2d162e12015-09-24 14:33:29 +0200305 /* check placing the node to the appropriate place according to the schema */
306 for (par1 = sibling->schema->parent; par1 && (par1->nodetype & (LYS_CONTAINER | LYS_LIST)); par1 = par1->parent);
307 for (par2 = node->schema->parent; par2 && (par2->nodetype & (LYS_CONTAINER | LYS_LIST)); par2 = par2->parent);
308 if (par1 != par2) {
309 ly_errno = LY_EINVAL;
310 return EXIT_FAILURE;
311 }
312
Michal Vasko24337392015-10-16 09:58:16 +0200313 if (node->parent || node->prev->next) {
314 lyd_unlink(node);
315 }
316
Michal Vasko2d162e12015-09-24 14:33:29 +0200317 LY_TREE_FOR(node, iter) {
318 iter->parent = sibling->parent;
Michal Vasko24337392015-10-16 09:58:16 +0200319 last = iter;
Michal Vasko2d162e12015-09-24 14:33:29 +0200320 }
321
Michal Vasko02592902015-10-15 12:14:40 +0200322 if (before) {
323 if (sibling->prev->next) {
324 /* adding into the list */
325 sibling->prev->next = node;
326 } else if (sibling->parent) {
327 /* at the beginning */
328 sibling->parent->child = node;
Michal Vasko2d162e12015-09-24 14:33:29 +0200329 }
Michal Vasko02592902015-10-15 12:14:40 +0200330 node->prev = sibling->prev;
331 sibling->prev = last;
332 last->next = sibling;
333 } else {
334 if (sibling->next) {
335 /* adding into a middle - fix the prev pointer of the node after inserted nodes */
336 last->next = sibling->next;
337 sibling->next->prev = last;
338 } else {
339 /* at the end - fix the prev pointer of the first node */
340 if (sibling->parent) {
341 sibling->parent->child->prev = last;
342 } else {
343 for (iter = sibling; iter->prev->next; iter = iter->prev);
344 iter->prev = last;
345 }
346 }
347 sibling->next = node;
348 node->prev = sibling;
Michal Vasko2d162e12015-09-24 14:33:29 +0200349 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200350
Michal Vasko24337392015-10-16 09:58:16 +0200351 return EXIT_SUCCESS;
352}
Michal Vasko2d162e12015-09-24 14:33:29 +0200353
Michal Vasko24337392015-10-16 09:58:16 +0200354API int
355lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
356{
357 if (!node || !sibling || lyd_insert_sibling(sibling, node, 1)) {
358 ly_errno = LY_EINVAL;
359 return EXIT_FAILURE;
360 }
361
362 return EXIT_SUCCESS;
363}
364
365API int
366lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
367{
368 if (!node || !sibling || lyd_insert_sibling(sibling, node, 0)) {
369 ly_errno = LY_EINVAL;
370 return EXIT_FAILURE;
371 }
372
373 return EXIT_SUCCESS;
374}
375
376API int
377lyd_validate(struct lyd_node *node, int options)
378{
379 struct lyd_node *next, *iter, *to_free = NULL;
380
381 ly_errno = 0;
382 LY_TREE_DFS_BEGIN(node, next, iter) {
383 if (to_free) {
384 lyd_free(to_free);
385 to_free = NULL;
386 }
387
388 if (lyv_data_content(iter, 0, options, NULL)) {
389 if (ly_errno) {
390 return EXIT_FAILURE;
Michal Vasko2fce5f52015-10-23 10:14:08 +0200391 } else if (iter == node) {
392 /* removing the whole subtree */
393 to_free = node;
394 break;
Michal Vasko24337392015-10-16 09:58:16 +0200395 } else {
396 /* safe deferred removal */
397 to_free = iter;
Michal Vasko3f7dba12015-10-15 13:09:27 +0200398 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200399 }
Michal Vasko24337392015-10-16 09:58:16 +0200400
401 LY_TREE_DFS_END(node, next, iter);
Michal Vasko2d162e12015-09-24 14:33:29 +0200402 }
403
Michal Vasko24337392015-10-16 09:58:16 +0200404 if (to_free) {
405 lyd_free(to_free);
406 to_free = NULL;
Michal Vasko02592902015-10-15 12:14:40 +0200407 }
408
409 return EXIT_SUCCESS;
410}
411
Michal Vasko55f60be2015-10-14 13:12:58 +0200412/* return matching namespace in node or any of it's parents */
413static struct lyd_ns *
414lyd_find_ns(struct lyd_node *node, const char *prefix, const char *value)
415{
416 int pref_match, val_match;
417 struct lyd_attr *attr;
418
419 if (!node) {
420 return NULL;
421 }
422
423 for (; node; node = node->parent) {
424 for (attr = node->attr; attr; attr = attr->next) {
425 if (attr->type != LYD_ATTR_NS) {
426 continue;
427 }
428
429 pref_match = 0;
430 if (!prefix && !attr->name) {
431 pref_match = 1;
432 }
433 if (prefix && attr->name && !strcmp(attr->name, prefix)) {
434 pref_match = 1;
435 }
436
437 val_match = 0;
438 if (!value && !attr->value) {
439 val_match = 1;
440 }
441 if (value && attr->value && !strcmp(attr->value, value)) {
442 val_match = 1;
443 }
444
445 if (pref_match && val_match) {
446 return (struct lyd_ns *)attr;
447 }
448 }
449 }
450
451 return NULL;
452}
453
454/* create an attribute copy including correct namespace if used */
455static struct lyd_attr *
456lyd_dup_attr(struct ly_ctx *ctx, struct lyd_node *parent, struct lyd_attr *attr)
457{
458 struct lyd_attr *ret;
459
460 /* allocate new attr */
461 if (!parent->attr) {
462 parent->attr = malloc(sizeof *parent->attr);
463 ret = parent->attr;
464 } else {
465 for (ret = parent->attr; ret->next; ret = ret->next);
466 ret->next = malloc(sizeof *ret);
467 ret = ret->next;
468 }
469
470 /* fill new attr except ns/parent */
471 ret->type = attr->type;
472 ret->next = NULL;
473 ret->name = lydict_insert(ctx, attr->name, 0);
474 ret->value = lydict_insert(ctx, attr->value, 0);
475
476 if (ret->type == LYD_ATTR_NS) {
477 /* fill parent in a NS */
478 ((struct lyd_ns *)ret)->parent = parent;
479 } else if (attr->ns) {
480 /* attr has a namespace */
481
482 /* perhaps the namespace was already copied over? */
483 ret->ns = lyd_find_ns(parent, attr->ns->prefix, attr->ns->value);
484 if (!ret->ns) {
485 /* nope, it wasn't */
486 ret->ns = (struct lyd_ns *)lyd_dup_attr(ctx, parent, (struct lyd_attr *)attr->ns);
487 }
488 } else {
489 /* there is no namespace */
490 ret->ns = NULL;
491 }
492
493 return ret;
494}
495
496/* correct namespaces in the attributes of subtree nodes of node */
497static void
498lyd_correct_ns(struct lyd_node *node)
499{
500 const struct lyd_ns *attr_ns;
501 struct lyd_attr *attr;
502 struct lyd_node *node_root, *ns_root, *tmp;
503
504 /* find the root of node */
505 for (node_root = node; node_root->parent; node_root = node_root->parent);
506
507 LY_TREE_DFS_BEGIN(node, tmp, node) {
508 for (attr = node->attr; attr; attr = attr->next) {
509 if ((attr->type != LYD_ATTR_STD) || !attr->ns) {
510 continue;
511 }
512
513 /* find the root of attr NS */
514 for (ns_root = attr->ns->parent; ns_root->parent; ns_root = ns_root->parent);
515
516 /* attr NS is defined outside node subtree */
517 if (ns_root != node_root) {
518 attr_ns = attr->ns;
519 /* we may have already copied the NS over? */
520 attr->ns = lyd_find_ns(node, attr_ns->prefix, attr_ns->value);
521
522 /* we haven't copied it over, copy it now */
523 if (!attr->ns) {
524 attr->ns = (struct lyd_ns *)lyd_dup_attr(node->schema->module->ctx, node,
525 (struct lyd_attr *)attr_ns);
526 }
527 }
528 }
529 LY_TREE_DFS_END(node, tmp, node);
530 }
531}
532
Michal Vasko2d162e12015-09-24 14:33:29 +0200533API int
534lyd_unlink(struct lyd_node *node)
535{
536 struct lyd_node *iter;
537
538 if (!node) {
539 ly_errno = LY_EINVAL;
540 return EXIT_FAILURE;
541 }
542
543 /* unlink from siblings */
544 if (node->prev->next) {
545 node->prev->next = node->next;
546 }
547 if (node->next) {
548 node->next->prev = node->prev;
549 } else {
550 /* unlinking the last node */
551 iter = node->prev;
552 while (iter->prev != node) {
553 iter = iter->prev;
554 }
555 /* update the "last" pointer from the first node */
556 iter->prev = node->prev;
557 }
558
559 /* unlink from parent */
560 if (node->parent) {
561 if (node->parent->child == node) {
562 /* the node is the first child */
563 node->parent->child = node->next;
564 }
565 node->parent = NULL;
566 }
567
568 node->next = NULL;
569 node->prev = node;
570
Michal Vasko55f60be2015-10-14 13:12:58 +0200571 lyd_correct_ns(node);
Michal Vasko2d162e12015-09-24 14:33:29 +0200572 return EXIT_SUCCESS;
573}
574
Michal Vaskoc0797f82015-10-14 15:51:25 +0200575API struct lyd_node *
576lyd_dup(struct lyd_node *node, int recursive)
577{
578 struct lyd_node *next, *elem, *ret, *parent, *new_node;
579 struct lyd_attr *attr;
580 struct lyd_node_leaf_list *new_leaf;
581 struct lyd_node_anyxml *new_axml;
582 struct lys_type *type;
583
584 if (!node) {
585 ly_errno = LY_EINVAL;
586 return NULL;
587 }
588
589 ret = NULL;
590 parent = NULL;
591
592 /* LY_TREE_DFS */
593 for (elem = next = node; elem; elem = next) {
594
595 /* fill specific part */
596 switch (elem->schema->nodetype) {
597 case LYS_LEAF:
598 case LYS_LEAFLIST:
599 new_leaf = malloc(sizeof *new_leaf);
600 new_node = (struct lyd_node *)new_leaf;
601
602 new_leaf->value = ((struct lyd_node_leaf_list *)elem)->value;
603 new_leaf->value_str = lydict_insert(elem->schema->module->ctx,
604 ((struct lyd_node_leaf_list *)elem)->value_str, 0);
605 new_leaf->value_type = ((struct lyd_node_leaf_list *)elem)->value_type;
606 /* bits type must be treated specially */
607 if (new_leaf->value_type == LY_TYPE_BITS) {
608 for (type = &((struct lys_node_leaf *)elem->schema)->type; type->der->module; type = &type->der->type) {
609 if (type->base != LY_TYPE_BITS) {
610 LOGINT;
Michal Vaskod80e6c72015-10-15 09:37:01 +0200611 lyd_free(new_node);
Michal Vaskoc0797f82015-10-14 15:51:25 +0200612 lyd_free(ret);
613 return NULL;
614 }
615 }
616
617 new_leaf->value.bit = malloc(type->info.bits.count * sizeof *new_leaf->value.bit);
618 memcpy(new_leaf->value.bit, ((struct lyd_node_leaf_list *)elem)->value.bit,
619 type->info.bits.count * sizeof *new_leaf->value.bit);
620 }
621 break;
622 case LYS_ANYXML:
623 new_axml = malloc(sizeof *new_axml);
624 new_node = (struct lyd_node *)new_axml;
625
626 new_axml->value = lyxml_dup_elem(elem->schema->module->ctx, ((struct lyd_node_anyxml *)elem)->value,
627 NULL, 1);
628 break;
629 case LYS_CONTAINER:
630 case LYS_LIST:
631 case LYS_NOTIF:
632 case LYS_RPC:
633 new_node = malloc(sizeof *new_node);
634 new_node->child = NULL;
635 break;
636 default:
Michal Vaskoc0797f82015-10-14 15:51:25 +0200637 lyd_free(ret);
Michal Vasko24337392015-10-16 09:58:16 +0200638 LOGINT;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200639 return NULL;
640 }
641
642 /* fill common part */
643 new_node->schema = elem->schema;
644 new_node->attr = NULL;
645 LY_TREE_FOR(elem->attr, attr) {
646 lyd_dup_attr(elem->schema->module->ctx, new_node, attr);
647 }
648 new_node->next = NULL;
649 new_node->prev = new_node;
650 new_node->parent = NULL;
651
652 if (!ret) {
653 ret = new_node;
654 }
655 if (parent) {
Michal Vasko24337392015-10-16 09:58:16 +0200656 if (lyd_insert(parent, new_node)) {
Michal Vaskoc0797f82015-10-14 15:51:25 +0200657 lyd_free(ret);
Michal Vasko24337392015-10-16 09:58:16 +0200658 LOGINT;
Michal Vaskoc0797f82015-10-14 15:51:25 +0200659 return NULL;
660 }
661 }
662
663 if (!recursive) {
664 break;
665 }
666
667 /* LY_TREE_DFS_END */
668 /* select element for the next run - children first */
669 next = elem->child;
670 /* child exception for lyd_node_leaf and lyd_node_leaflist */
671 if (elem->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML)) {
672 next = NULL;
673 }
674 if (!next) {
675 /* no children, so try siblings */
676 next = elem->next;
677 } else {
678 parent = new_node;
679 }
680 while (!next) {
681 /* no siblings, go back through parents */
682 elem = elem->parent;
683 if (elem->parent == node->parent) {
684 break;
685 }
Michal Vasko785b2ad2015-10-15 09:37:15 +0200686 if (!parent) {
Michal Vaskoc8f5d802015-10-23 10:14:39 +0200687 lyd_free(ret);
Michal Vasko785b2ad2015-10-15 09:37:15 +0200688 LOGINT;
Michal Vaskoc8f5d802015-10-23 10:14:39 +0200689 return NULL;
Michal Vasko785b2ad2015-10-15 09:37:15 +0200690 }
Michal Vaskoc0797f82015-10-14 15:51:25 +0200691 parent = parent->parent;
692 /* parent is already processed, go to its sibling */
693 next = elem->next;
694 }
695 }
696
697 return ret;
698}
699
Michal Vasko2d162e12015-09-24 14:33:29 +0200700static void
701lyd_attr_free(struct ly_ctx *ctx, struct lyd_attr *attr)
702{
703 if (!attr) {
704 return;
705 }
706
707 if (attr->next) {
708 lyd_attr_free(ctx, attr->next);
709 }
710 lydict_remove(ctx, attr->name);
711 lydict_remove(ctx, attr->value);
712 free(attr);
713}
714
Michal Vaskofd76bd12015-09-24 15:49:57 +0200715struct lyd_node *
716lyd_attr_parent(struct lyd_node *root, struct lyd_attr *attr)
717{
718 struct lyd_node *next, *elem;
719 struct lyd_attr *node_attr;
720
721 LY_TREE_DFS_BEGIN(root, next, elem) {
722 for (node_attr = elem->attr; node_attr; node_attr = node_attr->next) {
723 if (node_attr == attr) {
724 return elem;
725 }
726 }
727 LY_TREE_DFS_END(root, next, elem)
728 }
729
730 return NULL;
731}
732
Radek Krejci134610e2015-10-20 17:15:34 +0200733static struct lyd_ns *
734lyd_get_attr_ns(struct lyd_node *node, const char *prefix)
735{
736 struct lyd_attr *attr;
737 int len;
738
739 while(node) {
740
741 if (!prefix) {
742 len = 0;
743 } else {
744 len = strlen(prefix) + 1;
745 }
746
747 for (attr = node->attr; attr; attr = attr->next) {
748 if (attr->type != LYD_ATTR_NS) {
749 continue;
750 }
751 if (!attr->name) {
752 if (!len) {
753 /* default namespace found */
754 if (!attr->value) {
755 /* empty default namespace -> no default namespace */
756 return NULL;
757 }
758 return (struct lyd_ns *)attr;
759 }
760 } else if (len && !memcmp(attr->name, prefix, len)) {
761 /* prefix found */
762 return (struct lyd_ns *)attr;
763 }
764 }
765 node = node->parent;
766 }
767
768 return NULL;
769}
770
771API struct lyd_attr *
772lyd_insert_attr(struct lyd_node *parent, const char *name, const char *value)
773{
774 struct lyd_ns *ns;
775 struct lyd_attr *a, *iter;
776 struct ly_ctx *ctx;
777 const char *p;
778 char *aux;
779
780 if (!parent || !name || !value) {
781 return NULL;
782 }
783 ctx = parent->schema->module->ctx;
784
785 a = calloc(1, sizeof *a);
786
787 if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || !name[5])) {
788 ns = (struct lyd_ns *)a;
789 ns->type = LYD_ATTR_NS;
790 ns->parent = parent;
791 if (name[5]) {
792 ns->prefix = lydict_insert(ctx, &(name[6]), 0);
793 }
794 } else {
795 a->type = LYD_ATTR_STD;
796 if ((p = strchr(name, ':'))) {
797 /* search for the namespace */
798 aux = strndup(name, p - name);
799 a->ns = lyd_get_attr_ns(parent, aux);
800 free(aux);
801
802 if (!a->ns) {
803 /* namespace not found */
804 free(a);
805 return NULL;
806 }
807 } else {
808 /* no prefix -> no namespace */
809 a->name = name;
810 }
811 }
812
813 a->value = lydict_insert(ctx, value, 0);
814 if (!parent->attr) {
815 parent->attr = a;
816 } else {
817 for (iter = parent->attr; iter->next; iter = iter->next);
818 iter->next = a;
819 }
820
821 return a;
822}
823
Michal Vasko2d162e12015-09-24 14:33:29 +0200824API void
825lyd_free(struct lyd_node *node)
826{
827 struct lyd_node *next, *child;
828
829 if (!node) {
830 return;
831 }
832
833 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
834 /* free children */
835 LY_TREE_FOR_SAFE(node->child, next, child) {
836 lyd_free(child);
837 }
838 } else if (node->schema->nodetype == LYS_ANYXML) {
839 lyxml_free_elem(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
840 } else {
841 /* free value */
Michal Vasko4c183312015-09-25 10:41:47 +0200842 switch(((struct lyd_node_leaf_list *)node)->value_type) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200843 case LY_TYPE_BINARY:
844 case LY_TYPE_STRING:
Michal Vasko4c183312015-09-25 10:41:47 +0200845 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf_list *)node)->value.string);
Michal Vasko2d162e12015-09-24 14:33:29 +0200846 break;
847 case LY_TYPE_BITS:
Michal Vasko4c183312015-09-25 10:41:47 +0200848 if (((struct lyd_node_leaf_list *)node)->value.bit) {
849 free(((struct lyd_node_leaf_list *)node)->value.bit);
Michal Vasko2d162e12015-09-24 14:33:29 +0200850 }
851 break;
852 default:
853 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
854 break;
855 }
856 }
857
858 lyd_unlink(node);
859 lyd_attr_free(node->schema->module->ctx, node->attr);
860 free(node);
861}
862
Michal Vaskoff4c2832015-10-15 13:30:50 +0200863API char *
864lyxml_serialize(struct lyxml_elem *anyxml)
865{
866 FILE *stream;
867 char *buf;
868 size_t buf_size;
869
870 if (!anyxml) {
871 ly_errno = LY_EINVAL;
872 return NULL;
873 }
874
875 stream = open_memstream(&buf, &buf_size);
876 if (!stream) {
877 ly_errno = LY_ESYS;
878 return NULL;
879 }
880 if (lyxml_dump(stream, anyxml, 0) == 0) {
881 free(buf);
882 buf = NULL;
883 ly_errno = LY_EINVAL;
884 }
885 fclose(stream);
886
887 return buf;
888}
889
Michal Vasko2d162e12015-09-24 14:33:29 +0200890int
891lyd_compare(struct lyd_node *first, struct lyd_node *second, int unique)
892{
893 struct lys_node_list *slist;
894 struct lys_node *snode;
895 struct lyd_node *diter;
896 const char *val1, *val2;
897 int i, j;
898
899 assert(first);
900 assert(second);
901
902 if (first->schema != second->schema) {
903 return 1;
904 }
905
906 switch (first->schema->nodetype) {
907 case LYS_LEAFLIST:
908 /* compare values */
Michal Vasko4c183312015-09-25 10:41:47 +0200909 if (((struct lyd_node_leaf_list *)first)->value_str == ((struct lyd_node_leaf_list *)second)->value_str) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200910 return 0;
911 }
912 return 1;
913 case LYS_LIST:
Michal Vasko4c183312015-09-25 10:41:47 +0200914 slist = (struct lys_node_list *)first->schema;
Michal Vasko2d162e12015-09-24 14:33:29 +0200915
916 if (unique) {
917 /* compare unique leafs */
918 for (i = 0; i < slist->unique_size; i++) {
919 for (j = 0; j < slist->unique[i].leafs_size; j++) {
920 snode = (struct lys_node *)slist->unique[i].leafs[j];
921 /* use default values if the instances of unique leafs are not present */
922 val1 = val2 = ((struct lys_node_leaf *)snode)->dflt;
923 LY_TREE_FOR(first->child, diter) {
924 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200925 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200926 break;
927 }
928 }
929 LY_TREE_FOR(second->child, diter) {
930 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200931 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200932 break;
933 }
934 }
935 if (val1 != val2) {
936 break;
937 }
938 }
939 if (j && j == slist->unique[i].leafs_size) {
940 /* all unique leafs are the same in this set */
941 return 0;
942 }
943 }
944 }
945
946 /* compare keys */
947 for (i = 0; i < slist->keys_size; i++) {
948 snode = (struct lys_node *)slist->keys[i];
949 val1 = val2 = NULL;
950 LY_TREE_FOR(first->child, diter) {
951 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200952 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200953 break;
954 }
955 }
956 LY_TREE_FOR(second->child, diter) {
957 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200958 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200959 break;
960 }
961 }
962 if (val1 != val2) {
963 return 1;
964 }
965 }
966
967 return 0;
968 default:
969 /* no additional check is needed */
970 return 0;
971 }
972}
973
974API struct lyd_set *
975lyd_set_new(void)
976{
977 return calloc(1, sizeof(struct lyd_set));
978}
979
980API void
981lyd_set_free(struct lyd_set *set)
982{
983 if (!set) {
984 return;
985 }
986
987 free(set->set);
988 free(set);
989}
990
991API int
992lyd_set_add(struct lyd_set *set, struct lyd_node *node)
993{
994 struct lyd_node **new;
995
996 if (!set) {
997 ly_errno = LY_EINVAL;
998 return EXIT_FAILURE;
999 }
1000
1001 if (set->size == set->number) {
1002 new = realloc(set->set, (set->size + 8) * sizeof *(set->set));
1003 if (!new) {
1004 LOGMEM;
1005 return EXIT_FAILURE;
1006 }
1007 set->size += 8;
1008 set->set = new;
1009 }
1010
1011 set->set[set->number++] = node;
1012
1013 return EXIT_SUCCESS;
1014}