blob: 110f535ccc77bb3f05134419d2f770fb288d88b6 [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
23
24#include <assert.h>
25#include <ctype.h>
26#include <stdlib.h>
27#include <sys/mman.h>
28#include <sys/stat.h>
29#include <string.h>
30
31#include "common.h"
32#include "context.h"
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020033#include "tree_data.h"
Michal Vasko2d162e12015-09-24 14:33:29 +020034#include "parser.h"
35#include "resolve.h"
Radek Krejcic6704c82015-10-06 11:12:45 +020036#include "xml_private.h"
Michal Vasko2d162e12015-09-24 14:33:29 +020037#include "tree_internal.h"
38#include "validation.h"
39
40API struct lyd_node *
41lyd_parse(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
42{
Radek Krejci5974c1f2015-10-09 09:53:24 +020043 struct lyxml_elem *xml;
44 struct lyd_node *result = NULL;
45
Michal Vasko2d162e12015-09-24 14:33:29 +020046 if (!ctx || !data) {
47 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
48 return NULL;
49 }
50
51 switch (format) {
52 case LYD_XML:
Radek Krejci452fb952015-10-02 16:07:46 +020053 case LYD_XML_FORMAT:
Radek Krejci5974c1f2015-10-09 09:53:24 +020054 xml = lyxml_read(ctx, data, 0);
55 result = lyd_parse_xml(ctx, xml, options);
56 lyxml_free_elem(ctx, xml);
57 break;
Michal Vasko2d162e12015-09-24 14:33:29 +020058 case LYD_JSON:
59 default:
60 /* TODO */
61 return NULL;
62 }
63
Radek Krejci5974c1f2015-10-09 09:53:24 +020064 return result;
Michal Vasko2d162e12015-09-24 14:33:29 +020065}
66
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020067API struct lyd_node *
68lyd_new(struct lyd_node *parent, struct lys_module *module, const char *name)
69{
70 struct lyd_node *ret;
71 struct lys_node *snode = NULL, *siblings;
72
73 if ((!parent && !module) || !name) {
74 ly_errno = LY_EINVAL;
75 return NULL;
76 }
77
78 if (!parent) {
79 siblings = module->data;
80 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +020081 if (!parent->schema) {
82 return NULL;
83 }
84 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +020085 }
86
87 if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_CONTAINER | LYS_INPUT | LYS_OUTPUT
88 | LYS_NOTIF | LYS_RPC, &snode) || !snode) {
89 return NULL;
90 }
91
92 ret = calloc(1, sizeof *ret);
93 ret->schema = snode;
94 ret->prev = ret;
95 if (parent) {
96 if (lyd_insert(parent, ret, 0)) {
97 free(ret);
98 return NULL;
99 }
100 }
101
102 return ret;
103}
104
105API struct lyd_node *
106lyd_new_leaf_val(struct lyd_node *parent, struct lys_module *module, const char *name, LY_DATA_TYPE type,
Michal Vasko0e3c8722015-09-29 16:06:08 +0200107 lyd_val value)
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200108{
109 struct lyd_node_leaf_list *ret;
110 struct lys_node *snode = NULL, *siblings;
Radek Krejcie4e4d722015-10-05 16:53:50 +0200111 struct lys_type *stype = NULL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200112 struct lys_module *src_mod, *dst_mod;
113 char *val_str = NULL, str_num[22];
Radek Krejcie4e4d722015-10-05 16:53:50 +0200114 const char *prefix = NULL;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200115 int i, str_len = 0, prev_len;
116 uint64_t exp;
117
Michal Vasko0e3c8722015-09-29 16:06:08 +0200118 if ((!parent && !module) || !name) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200119 ly_errno = LY_EINVAL;
120 return NULL;
121 }
122
123 if (!parent) {
124 siblings = module->data;
125 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200126 if (!parent->schema) {
127 return NULL;
128 }
129 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200130 }
131
132 if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_LEAFLIST | LYS_LEAF, &snode)
133 || !snode) {
134 return NULL;
135 }
136
137 switch (type) {
138 case LY_TYPE_BINARY:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200139 val_str = (char *)lydict_insert(snode->module->ctx, value.binary, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200140 break;
141
142 case LY_TYPE_BITS:
143 /* find the type definition */
144 for (stype = &((struct lys_node_leaf *)snode)->type; stype->der->module; stype = &stype->der->type) {
145 if (stype->base != LY_TYPE_BITS) {
146 LOGINT;
147 return NULL;
148 }
149 }
150
151 /* concatenate set bits */
152 for (i = 0; i < stype->info.bits.count; ++i) {
Michal Vasko0e3c8722015-09-29 16:06:08 +0200153 if (!value.bit[i]) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200154 continue;
155 }
156
157 prev_len = str_len;
Michal Vasko0e3c8722015-09-29 16:06:08 +0200158 str_len += strlen(value.bit[i]->name) + 1;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200159 val_str = realloc((char *)val_str, str_len * sizeof(char));
160
161 if (prev_len) {
162 val_str[prev_len] = ' ';
163 ++prev_len;
164 }
Michal Vasko0e3c8722015-09-29 16:06:08 +0200165 strcpy(val_str + prev_len, value.bit[i]->name);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200166 }
167
168 val_str = (char *)lydict_insert_zc(snode->module->ctx, val_str);
169 break;
170
171 case LY_TYPE_BOOL:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200172 if (value.bool) {
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200173 val_str = (char *)lydict_insert(snode->module->ctx, "true", 4);
174 } else {
175 val_str = (char *)lydict_insert(snode->module->ctx, "false", 5);
176 }
177 break;
178
179 case LY_TYPE_DEC64:
180 /* find the type definition */
181 for (stype = &((struct lys_node_leaf *)snode)->type; stype->der->module; stype = &stype->der->type) {
182 if (stype->base != LY_TYPE_DEC64) {
183 LOGINT;
184 return NULL;
185 }
186 }
187
188 for (i = 0, exp = 1; i < stype->info.dec64.dig; ++i, exp *= 10);
Michal Vasko0e3c8722015-09-29 16:06:08 +0200189 sprintf(str_num, "%01.1Lf", ((long double)value.dec64) / exp);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200190 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
191 break;
192
193 case LY_TYPE_EMPTY:
194 break;
195
196 case LY_TYPE_ENUM:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200197 val_str = (char *)lydict_insert(snode->module->ctx, value.enm->name, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200198 break;
199
200 case LY_TYPE_IDENT:
201 /* TODO move to function if used somewhere else (module -> import prefix) */
Michal Vasko0e3c8722015-09-29 16:06:08 +0200202 src_mod = value.ident->module;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200203 if (src_mod->type) {
204 src_mod = ((struct lys_submodule *)src_mod)->belongsto;
205 }
206 dst_mod = snode->module;
207 if (dst_mod->type) {
208 dst_mod = ((struct lys_submodule *)dst_mod)->belongsto;
209 }
210 if (src_mod != dst_mod) {
211 for (i = 0; i < src_mod->imp_size; ++i) {
212 if (src_mod->imp[i].module == dst_mod) {
213 prefix = src_mod->imp[i].prefix;
214 break;
215 }
216 }
217 if (!prefix) {
218 LOGINT;
219 return NULL;
220 }
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200221 }
222
223 if (!prefix) {
Michal Vasko0e3c8722015-09-29 16:06:08 +0200224 val_str = (char *)lydict_insert(snode->module->ctx, value.ident->name, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200225 } else {
Michal Vasko0e3c8722015-09-29 16:06:08 +0200226 val_str = malloc((strlen(prefix) + 1 + strlen(value.ident->name) + 1) * sizeof(char));
227 sprintf(val_str, "%s:%s", prefix, value.ident->name);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200228 val_str = (char *)lydict_insert_zc(snode->module->ctx, val_str);
229 }
230 break;
231
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200232 case LY_TYPE_LEAFREF:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200233 val_str = (char *)lydict_insert(snode->module->ctx, ((struct lyd_node_leaf_list *)value.leafref)->value_str, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200234 break;
235
236 case LY_TYPE_STRING:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200237 val_str = (char *)lydict_insert(snode->module->ctx, value.string, 0);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200238 break;
239
240 case LY_TYPE_INT8:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200241 sprintf(str_num, "%hhd", value.int8);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200242 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
243 break;
244
245 case LY_TYPE_INT16:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200246 sprintf(str_num, "%hd", value.int16);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200247 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
248 break;
249
250 case LY_TYPE_INT32:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200251 sprintf(str_num, "%d", value.int32);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200252 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
253 break;
254
255 case LY_TYPE_INT64:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200256 sprintf(str_num, "%ld", value.int64);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200257 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
258 break;
259
260 case LY_TYPE_UINT8:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200261 sprintf(str_num, "%hhu", value.uint8);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200262 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
263 break;
264
265 case LY_TYPE_UINT16:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200266 sprintf(str_num, "%hu", value.uint16);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200267 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
268 break;
269
270 case LY_TYPE_UINT32:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200271 sprintf(str_num, "%u", value.uint32);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200272 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
273 break;
274
275 case LY_TYPE_UINT64:
Michal Vasko0e3c8722015-09-29 16:06:08 +0200276 sprintf(str_num, "%lu", value.uint64);
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200277 val_str = (char *)lydict_insert(snode->module->ctx, str_num, 0);
278 break;
279
Michal Vasko14580182015-10-09 14:49:00 +0200280 default: /* LY_TYPE_INST */
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200281 LOGINT;
282 return NULL;
283 }
284
285 ret = calloc(1, sizeof *ret);
286 ret->schema = snode;
287 ret->prev = (struct lyd_node *)ret;
288 if (parent) {
289 if (lyd_insert(parent, (struct lyd_node *)ret, 0)) {
290 free(ret);
291 lydict_remove(snode->module->ctx, val_str);
292 return NULL;
293 }
294 }
Michal Vasko81eef2c2015-10-02 15:37:25 +0200295
296 if (type == LY_TYPE_BINARY) {
297 ret->value.binary = val_str;
298 } else if (type == LY_TYPE_STRING) {
299 ret->value.string = val_str;
300 } else if (type == LY_TYPE_BITS) {
301 /* stype is left with the bits type definition */
302 ret->value.bit = malloc(stype->info.bits.count * sizeof *ret->value.bit);
303 memcpy(ret->value.bit, value.bit, stype->info.bits.count * sizeof *ret->value.bit);
304 } else {
305 ret->value = value;
306 }
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200307 ret->value_str = val_str;
308 ret->value_type = type;
309
310 return (struct lyd_node *)ret;
311}
312
313API struct lyd_node *
314lyd_new_leaf_str(struct lyd_node *parent, struct lys_module *module, const char *name, LY_DATA_TYPE type,
315 const char *val_str)
316{
317 struct lyd_node_leaf_list *ret;
318 struct lys_node *snode = NULL, *siblings;
319 struct lys_type *stype, *utype;
320 int found;
321
322 if ((!parent && !module) || !name) {
323 ly_errno = LY_EINVAL;
324 return NULL;
325 }
326
327 if (!parent) {
328 siblings = module->data;
329 } else {
Michal Vaskoa5ef4d72015-09-29 16:05:21 +0200330 if (!parent->schema) {
331 return NULL;
332 }
333 siblings = parent->schema->child;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200334 }
335
336 if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_LEAFLIST | LYS_LEAF, &snode)
337 || !snode) {
338 return NULL;
339 }
340
341 ret = calloc(1, sizeof *ret);
342 ret->schema = snode;
343 ret->prev = (struct lyd_node *)ret;
344 if (parent) {
345 if (lyd_insert(parent, (struct lyd_node *)ret, 0)) {
346 free(ret);
347 return NULL;
348 }
349 }
350 ret->value_str = val_str;
351 ret->value_type = type;
352
353 /* get the correct type struct */
354 stype = &((struct lys_node_leaf *)snode)->type;
355 if (stype->base == LY_TYPE_UNION) {
356 found = 0;
357 utype = stype;
358 stype = lyp_get_next_union_type(utype, NULL, &found);
359 while (stype && (stype->base != type)) {
360 found = 0;
361 stype = lyp_get_next_union_type(utype, stype, &found);
362 }
363 if (!stype) {
364 free(ret);
365 return NULL;
366 }
367 }
368
369 if (lyp_parse_value(ret, stype, 1, NULL, 0)) {
370 free(ret);
371 return NULL;
372 }
373
374 return (struct lyd_node *)ret;
375
376}
377
378API struct lyd_node *
379lyd_new_anyxml(struct lyd_node *parent, struct lys_module *module, const char *name, const char *val_xml)
380{
Michal Vasko587998f2015-09-29 16:07:53 +0200381 struct lyd_node_anyxml *ret;
382 struct lys_node *siblings, *snode;
383 struct lyxml_elem *root, *first_child, *last_child, *child;
384 struct ly_ctx *ctx;
385 char *xml;
386
387 if ((!parent && !module) || !name || !val_xml) {
388 ly_errno = LY_EINVAL;
389 return NULL;
390 }
391
392 if (!parent) {
393 siblings = module->data;
394 ctx = module->ctx;
395 } else {
396 if (!parent->schema) {
397 return NULL;
398 }
399 siblings = parent->schema->child;
400 ctx = parent->schema->module->ctx;
401 }
402
403 if (resolve_sibling(module, siblings, NULL, 0, name, strlen(name), LYS_ANYXML, &snode)
404 || !snode) {
405 return NULL;
406 }
407
408 ret = calloc(1, sizeof *ret);
409 ret->schema = snode;
410 ret->prev = (struct lyd_node *)ret;
411 if (parent) {
412 if (lyd_insert(parent, (struct lyd_node *)ret, 0)) {
413 free(ret);
414 return NULL;
415 }
416 }
417
418 /* add fake root so we can parse the data */
419 asprintf(&xml, "<root>%s</root>", val_xml);
420 root = lyxml_read(ctx, xml, 0);
421 free(xml);
Michal Vasko5b6e78d2015-10-09 15:01:10 +0200422 if (!root) {
423 free(ret);
424 return NULL;
425 }
Michal Vasko587998f2015-09-29 16:07:53 +0200426
427 /* remove the root */
Radek Krejcie4e4d722015-10-05 16:53:50 +0200428 first_child = last_child = NULL;
Michal Vasko587998f2015-09-29 16:07:53 +0200429 LY_TREE_FOR(root->child, child) {
430 lyxml_unlink_elem(ctx, child, 1);
431 if (!first_child) {
432 first_child = child;
433 last_child = child;
434 } else {
435 last_child->next = child;
436 child->prev = last_child;
437 last_child = child;
438 }
439 }
Radek Krejcie4e4d722015-10-05 16:53:50 +0200440 if (first_child) {
441 first_child->prev = last_child;
442 }
Michal Vasko587998f2015-09-29 16:07:53 +0200443 lyxml_free_elem(ctx, root);
444
445 ret->value = first_child;
446
447 return (struct lyd_node *)ret;
Michal Vasko8ea2b7f2015-09-29 14:30:53 +0200448}
449
Michal Vasko9cc2d0a2015-10-14 15:49:07 +0200450/* last - optional, points to the last inserted node */
451static int
452lyd_insert_schema_check_only(struct lyd_node *parent, struct lyd_node *node, struct lyd_node **last)
Michal Vasko2d162e12015-09-24 14:33:29 +0200453{
454 struct lys_node *sparent;
Michal Vasko9cc2d0a2015-10-14 15:49:07 +0200455 struct lyd_node *iter;
Michal Vasko2d162e12015-09-24 14:33:29 +0200456
457 if (node->parent || node->prev->next) {
458 lyd_unlink(node);
459 }
460
461 /* check placing the node to the appropriate place according to the schema */
462 sparent = node->schema->parent;
463 while (!(sparent->nodetype & (LYS_CONTAINER | LYS_LIST))) {
464 sparent = sparent->parent;
465 }
466 if (sparent != parent->schema) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200467 return EXIT_FAILURE;
468 }
469
470 if (!parent->child) {
471 /* add as the only child of the parent */
472 parent->child = node;
473 } else {
474 /* add as the last child of the parent */
475 parent->child->prev->next = node;
476 node->prev = parent->child->prev;
477 for (iter = node; iter->next; iter = iter->next);
478 parent->child->prev = iter;
479 }
Michal Vasko9cc2d0a2015-10-14 15:49:07 +0200480
Michal Vasko2d162e12015-09-24 14:33:29 +0200481 LY_TREE_FOR(node, iter) {
482 iter->parent = parent;
Michal Vasko9cc2d0a2015-10-14 15:49:07 +0200483 if (last) {
484 *last = iter; /* remember the last of the inserted nodes */
485 }
486 }
487
488 return EXIT_SUCCESS;
489}
490
491API int
492lyd_insert(struct lyd_node *parent, struct lyd_node *node, int options)
493{
494 struct lyd_node *iter, *next, *last;
495
496 if (!node || !parent) {
497 ly_errno = LY_EINVAL;
498 return EXIT_FAILURE;
499 }
500
501 if (lyd_insert_schema_check_only(parent, node, &last)) {
502 ly_errno = LY_EINVAL;
503 return EXIT_FAILURE;
Michal Vasko2d162e12015-09-24 14:33:29 +0200504 }
505
506 ly_errno = 0;
507 LY_TREE_FOR_SAFE(node, next, iter) {
508 /* various validation checks */
Michal Vaskocf024702015-10-08 15:01:42 +0200509 if (lyv_data_content(iter, 0, options, NULL)) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200510 if (ly_errno) {
511 return EXIT_FAILURE;
512 } else {
513 lyd_free(iter);
514 }
515 }
516
517 if (iter == last) {
518 /* we are done - checking only the inserted nodes */
519 break;
520 }
521 }
522
523 return EXIT_SUCCESS;
524}
525
526API int
527lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node, int options)
528{
529 struct lys_node *par1, *par2;
530 struct lyd_node *iter, *next, *last;
531
532 if (!node || !sibling) {
533 ly_errno = LY_EINVAL;
534 return EXIT_FAILURE;
535 }
536
537 if (node->parent || node->prev->next) {
538 lyd_unlink(node);
539 }
540
541 /* check placing the node to the appropriate place according to the schema */
542 for (par1 = sibling->schema->parent; par1 && (par1->nodetype & (LYS_CONTAINER | LYS_LIST)); par1 = par1->parent);
543 for (par2 = node->schema->parent; par2 && (par2->nodetype & (LYS_CONTAINER | LYS_LIST)); par2 = par2->parent);
544 if (par1 != par2) {
545 ly_errno = LY_EINVAL;
546 return EXIT_FAILURE;
547 }
548
549 LY_TREE_FOR(node, iter) {
550 iter->parent = sibling->parent;
551 last = iter; /* remember the last of the inserted nodes */
552 }
553
554 if (sibling->next) {
555 /* adding into a middle - fix the prev pointer of the node after inserted nodes */
556 last->next = sibling->next;
557 sibling->next->prev = last;
558 } else {
559 /* at the end - fix the prev pointer of the first node */
560 if (sibling->parent) {
561 sibling->parent->child->prev = last;
562 } else {
563 for (iter = sibling; iter->prev->next; iter = iter->prev);
564 iter->prev = last;
565 }
566 }
567 sibling->next = node;
568 node->prev = sibling;
569
570 ly_errno = 0;
571 LY_TREE_FOR_SAFE(node, next, iter) {
572 /* various validation checks */
Michal Vaskocf024702015-10-08 15:01:42 +0200573 if (lyv_data_content(iter, 0, options, NULL)) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200574 if (ly_errno) {
575 return EXIT_FAILURE;
576 } else {
577 lyd_free(iter);
578 }
579 }
580
581 if (iter == last) {
582 /* we are done - checking only the inserted nodes */
583 break;
584 }
585 }
586
587 return EXIT_SUCCESS;
588}
589
Michal Vasko55f60be2015-10-14 13:12:58 +0200590/* return matching namespace in node or any of it's parents */
591static struct lyd_ns *
592lyd_find_ns(struct lyd_node *node, const char *prefix, const char *value)
593{
594 int pref_match, val_match;
595 struct lyd_attr *attr;
596
597 if (!node) {
598 return NULL;
599 }
600
601 for (; node; node = node->parent) {
602 for (attr = node->attr; attr; attr = attr->next) {
603 if (attr->type != LYD_ATTR_NS) {
604 continue;
605 }
606
607 pref_match = 0;
608 if (!prefix && !attr->name) {
609 pref_match = 1;
610 }
611 if (prefix && attr->name && !strcmp(attr->name, prefix)) {
612 pref_match = 1;
613 }
614
615 val_match = 0;
616 if (!value && !attr->value) {
617 val_match = 1;
618 }
619 if (value && attr->value && !strcmp(attr->value, value)) {
620 val_match = 1;
621 }
622
623 if (pref_match && val_match) {
624 return (struct lyd_ns *)attr;
625 }
626 }
627 }
628
629 return NULL;
630}
631
632/* create an attribute copy including correct namespace if used */
633static struct lyd_attr *
634lyd_dup_attr(struct ly_ctx *ctx, struct lyd_node *parent, struct lyd_attr *attr)
635{
636 struct lyd_attr *ret;
637
638 /* allocate new attr */
639 if (!parent->attr) {
640 parent->attr = malloc(sizeof *parent->attr);
641 ret = parent->attr;
642 } else {
643 for (ret = parent->attr; ret->next; ret = ret->next);
644 ret->next = malloc(sizeof *ret);
645 ret = ret->next;
646 }
647
648 /* fill new attr except ns/parent */
649 ret->type = attr->type;
650 ret->next = NULL;
651 ret->name = lydict_insert(ctx, attr->name, 0);
652 ret->value = lydict_insert(ctx, attr->value, 0);
653
654 if (ret->type == LYD_ATTR_NS) {
655 /* fill parent in a NS */
656 ((struct lyd_ns *)ret)->parent = parent;
657 } else if (attr->ns) {
658 /* attr has a namespace */
659
660 /* perhaps the namespace was already copied over? */
661 ret->ns = lyd_find_ns(parent, attr->ns->prefix, attr->ns->value);
662 if (!ret->ns) {
663 /* nope, it wasn't */
664 ret->ns = (struct lyd_ns *)lyd_dup_attr(ctx, parent, (struct lyd_attr *)attr->ns);
665 }
666 } else {
667 /* there is no namespace */
668 ret->ns = NULL;
669 }
670
671 return ret;
672}
673
674/* correct namespaces in the attributes of subtree nodes of node */
675static void
676lyd_correct_ns(struct lyd_node *node)
677{
678 const struct lyd_ns *attr_ns;
679 struct lyd_attr *attr;
680 struct lyd_node *node_root, *ns_root, *tmp;
681
682 /* find the root of node */
683 for (node_root = node; node_root->parent; node_root = node_root->parent);
684
685 LY_TREE_DFS_BEGIN(node, tmp, node) {
686 for (attr = node->attr; attr; attr = attr->next) {
687 if ((attr->type != LYD_ATTR_STD) || !attr->ns) {
688 continue;
689 }
690
691 /* find the root of attr NS */
692 for (ns_root = attr->ns->parent; ns_root->parent; ns_root = ns_root->parent);
693
694 /* attr NS is defined outside node subtree */
695 if (ns_root != node_root) {
696 attr_ns = attr->ns;
697 /* we may have already copied the NS over? */
698 attr->ns = lyd_find_ns(node, attr_ns->prefix, attr_ns->value);
699
700 /* we haven't copied it over, copy it now */
701 if (!attr->ns) {
702 attr->ns = (struct lyd_ns *)lyd_dup_attr(node->schema->module->ctx, node,
703 (struct lyd_attr *)attr_ns);
704 }
705 }
706 }
707 LY_TREE_DFS_END(node, tmp, node);
708 }
709}
710
Michal Vasko2d162e12015-09-24 14:33:29 +0200711API int
712lyd_unlink(struct lyd_node *node)
713{
714 struct lyd_node *iter;
715
716 if (!node) {
717 ly_errno = LY_EINVAL;
718 return EXIT_FAILURE;
719 }
720
721 /* unlink from siblings */
722 if (node->prev->next) {
723 node->prev->next = node->next;
724 }
725 if (node->next) {
726 node->next->prev = node->prev;
727 } else {
728 /* unlinking the last node */
729 iter = node->prev;
730 while (iter->prev != node) {
731 iter = iter->prev;
732 }
733 /* update the "last" pointer from the first node */
734 iter->prev = node->prev;
735 }
736
737 /* unlink from parent */
738 if (node->parent) {
739 if (node->parent->child == node) {
740 /* the node is the first child */
741 node->parent->child = node->next;
742 }
743 node->parent = NULL;
744 }
745
746 node->next = NULL;
747 node->prev = node;
748
Michal Vasko55f60be2015-10-14 13:12:58 +0200749 lyd_correct_ns(node);
Michal Vasko2d162e12015-09-24 14:33:29 +0200750 return EXIT_SUCCESS;
751}
752
Michal Vaskoc0797f82015-10-14 15:51:25 +0200753API struct lyd_node *
754lyd_dup(struct lyd_node *node, int recursive)
755{
756 struct lyd_node *next, *elem, *ret, *parent, *new_node;
757 struct lyd_attr *attr;
758 struct lyd_node_leaf_list *new_leaf;
759 struct lyd_node_anyxml *new_axml;
760 struct lys_type *type;
761
762 if (!node) {
763 ly_errno = LY_EINVAL;
764 return NULL;
765 }
766
767 ret = NULL;
768 parent = NULL;
769
770 /* LY_TREE_DFS */
771 for (elem = next = node; elem; elem = next) {
772
773 /* fill specific part */
774 switch (elem->schema->nodetype) {
775 case LYS_LEAF:
776 case LYS_LEAFLIST:
777 new_leaf = malloc(sizeof *new_leaf);
778 new_node = (struct lyd_node *)new_leaf;
779
780 new_leaf->value = ((struct lyd_node_leaf_list *)elem)->value;
781 new_leaf->value_str = lydict_insert(elem->schema->module->ctx,
782 ((struct lyd_node_leaf_list *)elem)->value_str, 0);
783 new_leaf->value_type = ((struct lyd_node_leaf_list *)elem)->value_type;
784 /* bits type must be treated specially */
785 if (new_leaf->value_type == LY_TYPE_BITS) {
786 for (type = &((struct lys_node_leaf *)elem->schema)->type; type->der->module; type = &type->der->type) {
787 if (type->base != LY_TYPE_BITS) {
788 LOGINT;
Michal Vaskod80e6c72015-10-15 09:37:01 +0200789 lyd_free(new_node);
Michal Vaskoc0797f82015-10-14 15:51:25 +0200790 lyd_free(ret);
791 return NULL;
792 }
793 }
794
795 new_leaf->value.bit = malloc(type->info.bits.count * sizeof *new_leaf->value.bit);
796 memcpy(new_leaf->value.bit, ((struct lyd_node_leaf_list *)elem)->value.bit,
797 type->info.bits.count * sizeof *new_leaf->value.bit);
798 }
799 break;
800 case LYS_ANYXML:
801 new_axml = malloc(sizeof *new_axml);
802 new_node = (struct lyd_node *)new_axml;
803
804 new_axml->value = lyxml_dup_elem(elem->schema->module->ctx, ((struct lyd_node_anyxml *)elem)->value,
805 NULL, 1);
806 break;
807 case LYS_CONTAINER:
808 case LYS_LIST:
809 case LYS_NOTIF:
810 case LYS_RPC:
811 new_node = malloc(sizeof *new_node);
812 new_node->child = NULL;
813 break;
814 default:
815 LOGINT;
816 lyd_free(ret);
817 return NULL;
818 }
819
820 /* fill common part */
821 new_node->schema = elem->schema;
822 new_node->attr = NULL;
823 LY_TREE_FOR(elem->attr, attr) {
824 lyd_dup_attr(elem->schema->module->ctx, new_node, attr);
825 }
826 new_node->next = NULL;
827 new_node->prev = new_node;
828 new_node->parent = NULL;
829
830 if (!ret) {
831 ret = new_node;
832 }
833 if (parent) {
834 if (lyd_insert_schema_check_only(parent, new_node, NULL)) {
835 LOGINT;
836 lyd_free(ret);
837 return NULL;
838 }
839 }
840
841 if (!recursive) {
842 break;
843 }
844
845 /* LY_TREE_DFS_END */
846 /* select element for the next run - children first */
847 next = elem->child;
848 /* child exception for lyd_node_leaf and lyd_node_leaflist */
849 if (elem->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML)) {
850 next = NULL;
851 }
852 if (!next) {
853 /* no children, so try siblings */
854 next = elem->next;
855 } else {
856 parent = new_node;
857 }
858 while (!next) {
859 /* no siblings, go back through parents */
860 elem = elem->parent;
861 if (elem->parent == node->parent) {
862 break;
863 }
Michal Vasko785b2ad2015-10-15 09:37:15 +0200864 if (!parent) {
865 LOGINT;
866 }
Michal Vaskoc0797f82015-10-14 15:51:25 +0200867 parent = parent->parent;
868 /* parent is already processed, go to its sibling */
869 next = elem->next;
870 }
871 }
872
873 return ret;
874}
875
Michal Vasko2d162e12015-09-24 14:33:29 +0200876static void
877lyd_attr_free(struct ly_ctx *ctx, struct lyd_attr *attr)
878{
879 if (!attr) {
880 return;
881 }
882
883 if (attr->next) {
884 lyd_attr_free(ctx, attr->next);
885 }
886 lydict_remove(ctx, attr->name);
887 lydict_remove(ctx, attr->value);
888 free(attr);
889}
890
Michal Vaskofd76bd12015-09-24 15:49:57 +0200891struct lyd_node *
892lyd_attr_parent(struct lyd_node *root, struct lyd_attr *attr)
893{
894 struct lyd_node *next, *elem;
895 struct lyd_attr *node_attr;
896
897 LY_TREE_DFS_BEGIN(root, next, elem) {
898 for (node_attr = elem->attr; node_attr; node_attr = node_attr->next) {
899 if (node_attr == attr) {
900 return elem;
901 }
902 }
903 LY_TREE_DFS_END(root, next, elem)
904 }
905
906 return NULL;
907}
908
Michal Vasko2d162e12015-09-24 14:33:29 +0200909API void
910lyd_free(struct lyd_node *node)
911{
912 struct lyd_node *next, *child;
913
914 if (!node) {
915 return;
916 }
917
918 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
919 /* free children */
920 LY_TREE_FOR_SAFE(node->child, next, child) {
921 lyd_free(child);
922 }
923 } else if (node->schema->nodetype == LYS_ANYXML) {
924 lyxml_free_elem(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
925 } else {
926 /* free value */
Michal Vasko4c183312015-09-25 10:41:47 +0200927 switch(((struct lyd_node_leaf_list *)node)->value_type) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200928 case LY_TYPE_BINARY:
929 case LY_TYPE_STRING:
Michal Vasko4c183312015-09-25 10:41:47 +0200930 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf_list *)node)->value.string);
Michal Vasko2d162e12015-09-24 14:33:29 +0200931 break;
932 case LY_TYPE_BITS:
Michal Vasko4c183312015-09-25 10:41:47 +0200933 if (((struct lyd_node_leaf_list *)node)->value.bit) {
934 free(((struct lyd_node_leaf_list *)node)->value.bit);
Michal Vasko2d162e12015-09-24 14:33:29 +0200935 }
936 break;
937 default:
938 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
939 break;
940 }
941 }
942
943 lyd_unlink(node);
944 lyd_attr_free(node->schema->module->ctx, node->attr);
945 free(node);
946}
947
948int
949lyd_compare(struct lyd_node *first, struct lyd_node *second, int unique)
950{
951 struct lys_node_list *slist;
952 struct lys_node *snode;
953 struct lyd_node *diter;
954 const char *val1, *val2;
955 int i, j;
956
957 assert(first);
958 assert(second);
959
960 if (first->schema != second->schema) {
961 return 1;
962 }
963
964 switch (first->schema->nodetype) {
965 case LYS_LEAFLIST:
966 /* compare values */
Michal Vasko4c183312015-09-25 10:41:47 +0200967 if (((struct lyd_node_leaf_list *)first)->value_str == ((struct lyd_node_leaf_list *)second)->value_str) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200968 return 0;
969 }
970 return 1;
971 case LYS_LIST:
Michal Vasko4c183312015-09-25 10:41:47 +0200972 slist = (struct lys_node_list *)first->schema;
Michal Vasko2d162e12015-09-24 14:33:29 +0200973
974 if (unique) {
975 /* compare unique leafs */
976 for (i = 0; i < slist->unique_size; i++) {
977 for (j = 0; j < slist->unique[i].leafs_size; j++) {
978 snode = (struct lys_node *)slist->unique[i].leafs[j];
979 /* use default values if the instances of unique leafs are not present */
980 val1 = val2 = ((struct lys_node_leaf *)snode)->dflt;
981 LY_TREE_FOR(first->child, diter) {
982 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200983 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200984 break;
985 }
986 }
987 LY_TREE_FOR(second->child, diter) {
988 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +0200989 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +0200990 break;
991 }
992 }
993 if (val1 != val2) {
994 break;
995 }
996 }
997 if (j && j == slist->unique[i].leafs_size) {
998 /* all unique leafs are the same in this set */
999 return 0;
1000 }
1001 }
1002 }
1003
1004 /* compare keys */
1005 for (i = 0; i < slist->keys_size; i++) {
1006 snode = (struct lys_node *)slist->keys[i];
1007 val1 = val2 = NULL;
1008 LY_TREE_FOR(first->child, diter) {
1009 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001010 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001011 break;
1012 }
1013 }
1014 LY_TREE_FOR(second->child, diter) {
1015 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001016 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001017 break;
1018 }
1019 }
1020 if (val1 != val2) {
1021 return 1;
1022 }
1023 }
1024
1025 return 0;
1026 default:
1027 /* no additional check is needed */
1028 return 0;
1029 }
1030}
1031
1032API struct lyd_set *
1033lyd_set_new(void)
1034{
1035 return calloc(1, sizeof(struct lyd_set));
1036}
1037
1038API void
1039lyd_set_free(struct lyd_set *set)
1040{
1041 if (!set) {
1042 return;
1043 }
1044
1045 free(set->set);
1046 free(set);
1047}
1048
1049API int
1050lyd_set_add(struct lyd_set *set, struct lyd_node *node)
1051{
1052 struct lyd_node **new;
1053
1054 if (!set) {
1055 ly_errno = LY_EINVAL;
1056 return EXIT_FAILURE;
1057 }
1058
1059 if (set->size == set->number) {
1060 new = realloc(set->set, (set->size + 8) * sizeof *(set->set));
1061 if (!new) {
1062 LOGMEM;
1063 return EXIT_FAILURE;
1064 }
1065 set->size += 8;
1066 set->set = new;
1067 }
1068
1069 set->set[set->number++] = node;
1070
1071 return EXIT_SUCCESS;
1072}