blob: 35bf86a1f2f322321d5935ada65c11416379182b [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 +0200450static int
Michal Vasko6faee332015-10-15 12:13:59 +0200451lyd_insert_parent(struct lyd_node *parent, struct lyd_node *node, int options, int validate)
Michal Vasko2d162e12015-09-24 14:33:29 +0200452{
453 struct lys_node *sparent;
Michal Vasko6faee332015-10-15 12:13:59 +0200454 struct lyd_node *next, *iter, *last;
Michal Vasko2d162e12015-09-24 14:33:29 +0200455
456 if (node->parent || node->prev->next) {
457 lyd_unlink(node);
458 }
459
460 /* check placing the node to the appropriate place according to the schema */
461 sparent = node->schema->parent;
462 while (!(sparent->nodetype & (LYS_CONTAINER | LYS_LIST))) {
463 sparent = sparent->parent;
464 }
465 if (sparent != parent->schema) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200466 return EXIT_FAILURE;
467 }
468
469 if (!parent->child) {
470 /* add as the only child of the parent */
471 parent->child = node;
472 } else {
473 /* add as the last child of the parent */
474 parent->child->prev->next = node;
475 node->prev = parent->child->prev;
476 for (iter = node; iter->next; iter = iter->next);
477 parent->child->prev = iter;
478 }
Michal Vasko9cc2d0a2015-10-14 15:49:07 +0200479
Michal Vasko2d162e12015-09-24 14:33:29 +0200480 LY_TREE_FOR(node, iter) {
481 iter->parent = parent;
Michal Vasko6faee332015-10-15 12:13:59 +0200482 last = iter; /* remember the last of the inserted nodes */
Michal Vasko9cc2d0a2015-10-14 15:49:07 +0200483 }
484
Michal Vasko6faee332015-10-15 12:13:59 +0200485 if (validate) {
486 ly_errno = 0;
487 LY_TREE_FOR_SAFE(node, next, iter) {
488 /* various validation checks */
489 if (lyv_data_content(iter, 0, options, NULL)) {
490 if (ly_errno) {
491 return EXIT_FAILURE;
492 } else {
493 lyd_free(iter);
494 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200495 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200496
Michal Vasko6faee332015-10-15 12:13:59 +0200497 if (iter == last) {
498 /* we are done - checking only the inserted nodes */
499 break;
500 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200501 }
502 }
503
504 return EXIT_SUCCESS;
505}
506
Michal Vasko02592902015-10-15 12:14:40 +0200507static int
508lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, int options, int before)
Michal Vasko2d162e12015-09-24 14:33:29 +0200509{
510 struct lys_node *par1, *par2;
511 struct lyd_node *iter, *next, *last;
512
Michal Vasko2d162e12015-09-24 14:33:29 +0200513 if (node->parent || node->prev->next) {
514 lyd_unlink(node);
515 }
516
517 /* check placing the node to the appropriate place according to the schema */
518 for (par1 = sibling->schema->parent; par1 && (par1->nodetype & (LYS_CONTAINER | LYS_LIST)); par1 = par1->parent);
519 for (par2 = node->schema->parent; par2 && (par2->nodetype & (LYS_CONTAINER | LYS_LIST)); par2 = par2->parent);
520 if (par1 != par2) {
521 ly_errno = LY_EINVAL;
522 return EXIT_FAILURE;
523 }
524
525 LY_TREE_FOR(node, iter) {
526 iter->parent = sibling->parent;
527 last = iter; /* remember the last of the inserted nodes */
528 }
529
Michal Vasko02592902015-10-15 12:14:40 +0200530 if (before) {
531 if (sibling->prev->next) {
532 /* adding into the list */
533 sibling->prev->next = node;
534 } else if (sibling->parent) {
535 /* at the beginning */
536 sibling->parent->child = node;
Michal Vasko2d162e12015-09-24 14:33:29 +0200537 }
Michal Vasko02592902015-10-15 12:14:40 +0200538 node->prev = sibling->prev;
539 sibling->prev = last;
540 last->next = sibling;
541 } else {
542 if (sibling->next) {
543 /* adding into a middle - fix the prev pointer of the node after inserted nodes */
544 last->next = sibling->next;
545 sibling->next->prev = last;
546 } else {
547 /* at the end - fix the prev pointer of the first node */
548 if (sibling->parent) {
549 sibling->parent->child->prev = last;
550 } else {
551 for (iter = sibling; iter->prev->next; iter = iter->prev);
552 iter->prev = last;
553 }
554 }
555 sibling->next = node;
556 node->prev = sibling;
Michal Vasko2d162e12015-09-24 14:33:29 +0200557 }
Michal Vasko2d162e12015-09-24 14:33:29 +0200558
559 ly_errno = 0;
560 LY_TREE_FOR_SAFE(node, next, iter) {
561 /* various validation checks */
Michal Vaskocf024702015-10-08 15:01:42 +0200562 if (lyv_data_content(iter, 0, options, NULL)) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200563 if (ly_errno) {
564 return EXIT_FAILURE;
565 } else {
566 lyd_free(iter);
567 }
568 }
569
570 if (iter == last) {
571 /* we are done - checking only the inserted nodes */
572 break;
573 }
574 }
575
576 return EXIT_SUCCESS;
577}
578
Michal Vasko6faee332015-10-15 12:13:59 +0200579API int
580lyd_insert(struct lyd_node *parent, struct lyd_node *node, int options)
581{
582 if (!node || !parent || lyd_insert_parent(parent, node, options, 1)) {
583 ly_errno = LY_EINVAL;
584 return EXIT_FAILURE;
585 }
586
587 return EXIT_SUCCESS;
588}
589
Michal Vasko02592902015-10-15 12:14:40 +0200590API int
591lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node, int options)
592{
593 if (!node || !sibling || lyd_insert_sibling(sibling, node, options, 1)) {
594 ly_errno = LY_EINVAL;
595 return EXIT_FAILURE;
596 }
597
598 return EXIT_SUCCESS;
599}
600
601API int
602lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node, int options)
603{
604 if (!node || !sibling || lyd_insert_sibling(sibling, node, options, 0)) {
605 ly_errno = LY_EINVAL;
606 return EXIT_FAILURE;
607 }
608
609 return EXIT_SUCCESS;
610}
611
Michal Vasko55f60be2015-10-14 13:12:58 +0200612/* return matching namespace in node or any of it's parents */
613static struct lyd_ns *
614lyd_find_ns(struct lyd_node *node, const char *prefix, const char *value)
615{
616 int pref_match, val_match;
617 struct lyd_attr *attr;
618
619 if (!node) {
620 return NULL;
621 }
622
623 for (; node; node = node->parent) {
624 for (attr = node->attr; attr; attr = attr->next) {
625 if (attr->type != LYD_ATTR_NS) {
626 continue;
627 }
628
629 pref_match = 0;
630 if (!prefix && !attr->name) {
631 pref_match = 1;
632 }
633 if (prefix && attr->name && !strcmp(attr->name, prefix)) {
634 pref_match = 1;
635 }
636
637 val_match = 0;
638 if (!value && !attr->value) {
639 val_match = 1;
640 }
641 if (value && attr->value && !strcmp(attr->value, value)) {
642 val_match = 1;
643 }
644
645 if (pref_match && val_match) {
646 return (struct lyd_ns *)attr;
647 }
648 }
649 }
650
651 return NULL;
652}
653
654/* create an attribute copy including correct namespace if used */
655static struct lyd_attr *
656lyd_dup_attr(struct ly_ctx *ctx, struct lyd_node *parent, struct lyd_attr *attr)
657{
658 struct lyd_attr *ret;
659
660 /* allocate new attr */
661 if (!parent->attr) {
662 parent->attr = malloc(sizeof *parent->attr);
663 ret = parent->attr;
664 } else {
665 for (ret = parent->attr; ret->next; ret = ret->next);
666 ret->next = malloc(sizeof *ret);
667 ret = ret->next;
668 }
669
670 /* fill new attr except ns/parent */
671 ret->type = attr->type;
672 ret->next = NULL;
673 ret->name = lydict_insert(ctx, attr->name, 0);
674 ret->value = lydict_insert(ctx, attr->value, 0);
675
676 if (ret->type == LYD_ATTR_NS) {
677 /* fill parent in a NS */
678 ((struct lyd_ns *)ret)->parent = parent;
679 } else if (attr->ns) {
680 /* attr has a namespace */
681
682 /* perhaps the namespace was already copied over? */
683 ret->ns = lyd_find_ns(parent, attr->ns->prefix, attr->ns->value);
684 if (!ret->ns) {
685 /* nope, it wasn't */
686 ret->ns = (struct lyd_ns *)lyd_dup_attr(ctx, parent, (struct lyd_attr *)attr->ns);
687 }
688 } else {
689 /* there is no namespace */
690 ret->ns = NULL;
691 }
692
693 return ret;
694}
695
696/* correct namespaces in the attributes of subtree nodes of node */
697static void
698lyd_correct_ns(struct lyd_node *node)
699{
700 const struct lyd_ns *attr_ns;
701 struct lyd_attr *attr;
702 struct lyd_node *node_root, *ns_root, *tmp;
703
704 /* find the root of node */
705 for (node_root = node; node_root->parent; node_root = node_root->parent);
706
707 LY_TREE_DFS_BEGIN(node, tmp, node) {
708 for (attr = node->attr; attr; attr = attr->next) {
709 if ((attr->type != LYD_ATTR_STD) || !attr->ns) {
710 continue;
711 }
712
713 /* find the root of attr NS */
714 for (ns_root = attr->ns->parent; ns_root->parent; ns_root = ns_root->parent);
715
716 /* attr NS is defined outside node subtree */
717 if (ns_root != node_root) {
718 attr_ns = attr->ns;
719 /* we may have already copied the NS over? */
720 attr->ns = lyd_find_ns(node, attr_ns->prefix, attr_ns->value);
721
722 /* we haven't copied it over, copy it now */
723 if (!attr->ns) {
724 attr->ns = (struct lyd_ns *)lyd_dup_attr(node->schema->module->ctx, node,
725 (struct lyd_attr *)attr_ns);
726 }
727 }
728 }
729 LY_TREE_DFS_END(node, tmp, node);
730 }
731}
732
Michal Vasko2d162e12015-09-24 14:33:29 +0200733API int
734lyd_unlink(struct lyd_node *node)
735{
736 struct lyd_node *iter;
737
738 if (!node) {
739 ly_errno = LY_EINVAL;
740 return EXIT_FAILURE;
741 }
742
743 /* unlink from siblings */
744 if (node->prev->next) {
745 node->prev->next = node->next;
746 }
747 if (node->next) {
748 node->next->prev = node->prev;
749 } else {
750 /* unlinking the last node */
751 iter = node->prev;
752 while (iter->prev != node) {
753 iter = iter->prev;
754 }
755 /* update the "last" pointer from the first node */
756 iter->prev = node->prev;
757 }
758
759 /* unlink from parent */
760 if (node->parent) {
761 if (node->parent->child == node) {
762 /* the node is the first child */
763 node->parent->child = node->next;
764 }
765 node->parent = NULL;
766 }
767
768 node->next = NULL;
769 node->prev = node;
770
Michal Vasko55f60be2015-10-14 13:12:58 +0200771 lyd_correct_ns(node);
Michal Vasko2d162e12015-09-24 14:33:29 +0200772 return EXIT_SUCCESS;
773}
774
Michal Vaskoc0797f82015-10-14 15:51:25 +0200775API struct lyd_node *
776lyd_dup(struct lyd_node *node, int recursive)
777{
778 struct lyd_node *next, *elem, *ret, *parent, *new_node;
779 struct lyd_attr *attr;
780 struct lyd_node_leaf_list *new_leaf;
781 struct lyd_node_anyxml *new_axml;
782 struct lys_type *type;
783
784 if (!node) {
785 ly_errno = LY_EINVAL;
786 return NULL;
787 }
788
789 ret = NULL;
790 parent = NULL;
791
792 /* LY_TREE_DFS */
793 for (elem = next = node; elem; elem = next) {
794
795 /* fill specific part */
796 switch (elem->schema->nodetype) {
797 case LYS_LEAF:
798 case LYS_LEAFLIST:
799 new_leaf = malloc(sizeof *new_leaf);
800 new_node = (struct lyd_node *)new_leaf;
801
802 new_leaf->value = ((struct lyd_node_leaf_list *)elem)->value;
803 new_leaf->value_str = lydict_insert(elem->schema->module->ctx,
804 ((struct lyd_node_leaf_list *)elem)->value_str, 0);
805 new_leaf->value_type = ((struct lyd_node_leaf_list *)elem)->value_type;
806 /* bits type must be treated specially */
807 if (new_leaf->value_type == LY_TYPE_BITS) {
808 for (type = &((struct lys_node_leaf *)elem->schema)->type; type->der->module; type = &type->der->type) {
809 if (type->base != LY_TYPE_BITS) {
810 LOGINT;
Michal Vaskod80e6c72015-10-15 09:37:01 +0200811 lyd_free(new_node);
Michal Vaskoc0797f82015-10-14 15:51:25 +0200812 lyd_free(ret);
813 return NULL;
814 }
815 }
816
817 new_leaf->value.bit = malloc(type->info.bits.count * sizeof *new_leaf->value.bit);
818 memcpy(new_leaf->value.bit, ((struct lyd_node_leaf_list *)elem)->value.bit,
819 type->info.bits.count * sizeof *new_leaf->value.bit);
820 }
821 break;
822 case LYS_ANYXML:
823 new_axml = malloc(sizeof *new_axml);
824 new_node = (struct lyd_node *)new_axml;
825
826 new_axml->value = lyxml_dup_elem(elem->schema->module->ctx, ((struct lyd_node_anyxml *)elem)->value,
827 NULL, 1);
828 break;
829 case LYS_CONTAINER:
830 case LYS_LIST:
831 case LYS_NOTIF:
832 case LYS_RPC:
833 new_node = malloc(sizeof *new_node);
834 new_node->child = NULL;
835 break;
836 default:
837 LOGINT;
838 lyd_free(ret);
839 return NULL;
840 }
841
842 /* fill common part */
843 new_node->schema = elem->schema;
844 new_node->attr = NULL;
845 LY_TREE_FOR(elem->attr, attr) {
846 lyd_dup_attr(elem->schema->module->ctx, new_node, attr);
847 }
848 new_node->next = NULL;
849 new_node->prev = new_node;
850 new_node->parent = NULL;
851
852 if (!ret) {
853 ret = new_node;
854 }
855 if (parent) {
Michal Vasko6faee332015-10-15 12:13:59 +0200856 if (lyd_insert_parent(parent, new_node, 0, 0)) {
Michal Vaskoc0797f82015-10-14 15:51:25 +0200857 LOGINT;
858 lyd_free(ret);
859 return NULL;
860 }
861 }
862
863 if (!recursive) {
864 break;
865 }
866
867 /* LY_TREE_DFS_END */
868 /* select element for the next run - children first */
869 next = elem->child;
870 /* child exception for lyd_node_leaf and lyd_node_leaflist */
871 if (elem->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML)) {
872 next = NULL;
873 }
874 if (!next) {
875 /* no children, so try siblings */
876 next = elem->next;
877 } else {
878 parent = new_node;
879 }
880 while (!next) {
881 /* no siblings, go back through parents */
882 elem = elem->parent;
883 if (elem->parent == node->parent) {
884 break;
885 }
Michal Vasko785b2ad2015-10-15 09:37:15 +0200886 if (!parent) {
887 LOGINT;
888 }
Michal Vaskoc0797f82015-10-14 15:51:25 +0200889 parent = parent->parent;
890 /* parent is already processed, go to its sibling */
891 next = elem->next;
892 }
893 }
894
895 return ret;
896}
897
Michal Vasko2d162e12015-09-24 14:33:29 +0200898static void
899lyd_attr_free(struct ly_ctx *ctx, struct lyd_attr *attr)
900{
901 if (!attr) {
902 return;
903 }
904
905 if (attr->next) {
906 lyd_attr_free(ctx, attr->next);
907 }
908 lydict_remove(ctx, attr->name);
909 lydict_remove(ctx, attr->value);
910 free(attr);
911}
912
Michal Vaskofd76bd12015-09-24 15:49:57 +0200913struct lyd_node *
914lyd_attr_parent(struct lyd_node *root, struct lyd_attr *attr)
915{
916 struct lyd_node *next, *elem;
917 struct lyd_attr *node_attr;
918
919 LY_TREE_DFS_BEGIN(root, next, elem) {
920 for (node_attr = elem->attr; node_attr; node_attr = node_attr->next) {
921 if (node_attr == attr) {
922 return elem;
923 }
924 }
925 LY_TREE_DFS_END(root, next, elem)
926 }
927
928 return NULL;
929}
930
Michal Vasko2d162e12015-09-24 14:33:29 +0200931API void
932lyd_free(struct lyd_node *node)
933{
934 struct lyd_node *next, *child;
935
936 if (!node) {
937 return;
938 }
939
940 if (!(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML))) {
941 /* free children */
942 LY_TREE_FOR_SAFE(node->child, next, child) {
943 lyd_free(child);
944 }
945 } else if (node->schema->nodetype == LYS_ANYXML) {
946 lyxml_free_elem(node->schema->module->ctx, ((struct lyd_node_anyxml *)node)->value);
947 } else {
948 /* free value */
Michal Vasko4c183312015-09-25 10:41:47 +0200949 switch(((struct lyd_node_leaf_list *)node)->value_type) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200950 case LY_TYPE_BINARY:
951 case LY_TYPE_STRING:
Michal Vasko4c183312015-09-25 10:41:47 +0200952 lydict_remove(node->schema->module->ctx, ((struct lyd_node_leaf_list *)node)->value.string);
Michal Vasko2d162e12015-09-24 14:33:29 +0200953 break;
954 case LY_TYPE_BITS:
Michal Vasko4c183312015-09-25 10:41:47 +0200955 if (((struct lyd_node_leaf_list *)node)->value.bit) {
956 free(((struct lyd_node_leaf_list *)node)->value.bit);
Michal Vasko2d162e12015-09-24 14:33:29 +0200957 }
958 break;
959 default:
960 /* TODO nothing needed : LY_TYPE_BOOL, LY_TYPE_DEC64*/
961 break;
962 }
963 }
964
965 lyd_unlink(node);
966 lyd_attr_free(node->schema->module->ctx, node->attr);
967 free(node);
968}
969
970int
971lyd_compare(struct lyd_node *first, struct lyd_node *second, int unique)
972{
973 struct lys_node_list *slist;
974 struct lys_node *snode;
975 struct lyd_node *diter;
976 const char *val1, *val2;
977 int i, j;
978
979 assert(first);
980 assert(second);
981
982 if (first->schema != second->schema) {
983 return 1;
984 }
985
986 switch (first->schema->nodetype) {
987 case LYS_LEAFLIST:
988 /* compare values */
Michal Vasko4c183312015-09-25 10:41:47 +0200989 if (((struct lyd_node_leaf_list *)first)->value_str == ((struct lyd_node_leaf_list *)second)->value_str) {
Michal Vasko2d162e12015-09-24 14:33:29 +0200990 return 0;
991 }
992 return 1;
993 case LYS_LIST:
Michal Vasko4c183312015-09-25 10:41:47 +0200994 slist = (struct lys_node_list *)first->schema;
Michal Vasko2d162e12015-09-24 14:33:29 +0200995
996 if (unique) {
997 /* compare unique leafs */
998 for (i = 0; i < slist->unique_size; i++) {
999 for (j = 0; j < slist->unique[i].leafs_size; j++) {
1000 snode = (struct lys_node *)slist->unique[i].leafs[j];
1001 /* use default values if the instances of unique leafs are not present */
1002 val1 = val2 = ((struct lys_node_leaf *)snode)->dflt;
1003 LY_TREE_FOR(first->child, diter) {
1004 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001005 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001006 break;
1007 }
1008 }
1009 LY_TREE_FOR(second->child, diter) {
1010 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001011 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001012 break;
1013 }
1014 }
1015 if (val1 != val2) {
1016 break;
1017 }
1018 }
1019 if (j && j == slist->unique[i].leafs_size) {
1020 /* all unique leafs are the same in this set */
1021 return 0;
1022 }
1023 }
1024 }
1025
1026 /* compare keys */
1027 for (i = 0; i < slist->keys_size; i++) {
1028 snode = (struct lys_node *)slist->keys[i];
1029 val1 = val2 = NULL;
1030 LY_TREE_FOR(first->child, diter) {
1031 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001032 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001033 break;
1034 }
1035 }
1036 LY_TREE_FOR(second->child, diter) {
1037 if (diter->schema == snode) {
Michal Vasko4c183312015-09-25 10:41:47 +02001038 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
Michal Vasko2d162e12015-09-24 14:33:29 +02001039 break;
1040 }
1041 }
1042 if (val1 != val2) {
1043 return 1;
1044 }
1045 }
1046
1047 return 0;
1048 default:
1049 /* no additional check is needed */
1050 return 0;
1051 }
1052}
1053
1054API struct lyd_set *
1055lyd_set_new(void)
1056{
1057 return calloc(1, sizeof(struct lyd_set));
1058}
1059
1060API void
1061lyd_set_free(struct lyd_set *set)
1062{
1063 if (!set) {
1064 return;
1065 }
1066
1067 free(set->set);
1068 free(set);
1069}
1070
1071API int
1072lyd_set_add(struct lyd_set *set, struct lyd_node *node)
1073{
1074 struct lyd_node **new;
1075
1076 if (!set) {
1077 ly_errno = LY_EINVAL;
1078 return EXIT_FAILURE;
1079 }
1080
1081 if (set->size == set->number) {
1082 new = realloc(set->set, (set->size + 8) * sizeof *(set->set));
1083 if (!new) {
1084 LOGMEM;
1085 return EXIT_FAILURE;
1086 }
1087 set->size += 8;
1088 set->set = new;
1089 }
1090
1091 set->set[set->number++] = node;
1092
1093 return EXIT_SUCCESS;
1094}