blob: 9ab42ef9bb4fa2b75c8a76994b8671c224afc59d [file] [log] [blame]
Radek Krejcie7b95092019-05-15 11:03:07 +02001/**
Michal Vaskob1b5c262020-03-05 14:29:47 +01002 * @file tree_data.c
Radek Krejcie7b95092019-05-15 11:03:07 +02003 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Schema tree implementation
5 *
6 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#include "common.h"
16
Radek Krejci084289f2019-07-09 17:35:30 +020017#include <assert.h>
Radek Krejcie7b95092019-05-15 11:03:07 +020018#include <ctype.h>
19#include <errno.h>
20#include <fcntl.h>
21#include <stdarg.h>
22#include <stdint.h>
23#include <string.h>
24#include <unistd.h>
25
26#include "log.h"
27#include "tree.h"
28#include "tree_data.h"
29#include "tree_data_internal.h"
Michal Vasko90932a92020-02-12 14:33:03 +010030#include "hash_table.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020031#include "tree_schema.h"
Radek Krejci38d85362019-09-05 16:26:38 +020032#include "plugins_exts_metadata.h"
Michal Vasko90932a92020-02-12 14:33:03 +010033#include "plugins_exts_internal.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020034
Michal Vaskoe444f752020-02-10 12:20:06 +010035struct ly_keys {
36 char *str;
37 struct {
38 const struct lysc_node_leaf *schema;
39 char *value;
Michal Vasko90932a92020-02-12 14:33:03 +010040 struct lyd_value val;
Michal Vaskoe444f752020-02-10 12:20:06 +010041 } *keys;
42 size_t key_count;
43};
44
Radek Krejci084289f2019-07-09 17:35:30 +020045LY_ERR
Michal Vasko90932a92020-02-12 14:33:03 +010046lyd_value_parse(struct lyd_node_term *node, const char *value, size_t value_len, int *dynamic, int second,
Michal Vaskof03ed032020-03-04 13:31:44 +010047 ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +020048{
Michal Vasko90932a92020-02-12 14:33:03 +010049 LY_ERR ret = LY_SUCCESS;
Radek Krejci084289f2019-07-09 17:35:30 +020050 struct ly_err_item *err = NULL;
51 struct ly_ctx *ctx;
52 struct lysc_type *type;
Radek Krejci3c9758d2019-07-11 16:49:10 +020053 int options = LY_TYPE_OPTS_STORE | (second ? LY_TYPE_OPTS_SECOND_CALL : 0) |
Michal Vaskof03ed032020-03-04 13:31:44 +010054 (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci084289f2019-07-09 17:35:30 +020055 assert(node);
56
57 ctx = node->schema->module->ctx;
Radek Krejci084289f2019-07-09 17:35:30 +020058
Radek Krejci73dead22019-07-11 16:46:16 +020059 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci62903c32019-07-15 14:42:05 +020060 if (!second) {
61 node->value.realtype = type;
62 }
Michal Vasko90932a92020-02-12 14:33:03 +010063 ret = type->plugin->store(ctx, type, value, value_len, options, get_prefix, parser, format,
Michal Vaskof03ed032020-03-04 13:31:44 +010064 tree ? (void *)node : (void *)node->schema, tree,
Radek Krejci73dead22019-07-11 16:46:16 +020065 &node->value, NULL, &err);
Michal Vasko90932a92020-02-12 14:33:03 +010066 if (ret && (ret != LY_EINCOMPLETE)) {
Radek Krejci73dead22019-07-11 16:46:16 +020067 if (err) {
68 ly_err_print(err);
69 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
70 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +020071 }
Radek Krejci73dead22019-07-11 16:46:16 +020072 goto error;
Michal Vasko90932a92020-02-12 14:33:03 +010073 } else if (dynamic) {
74 *dynamic = 0;
Radek Krejci084289f2019-07-09 17:35:30 +020075 }
76
77error:
78 return ret;
79}
80
Michal Vasko90932a92020-02-12 14:33:03 +010081/* similar to lyd_value_parse except can be used just to store the value, hence does also not support a second call */
82static LY_ERR
83lyd_value_store(struct lyd_value *val, const struct lysc_node *schema, const char *value, size_t value_len, int *dynamic,
84 ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format)
85{
86 LY_ERR ret = LY_SUCCESS;
87 struct ly_err_item *err = NULL;
88 struct ly_ctx *ctx;
89 struct lysc_type *type;
90 int options = LY_TYPE_OPTS_STORE | LY_TYPE_OPTS_INCOMPLETE_DATA | (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0);
91
92 assert(val && schema && (schema->nodetype & LYD_NODE_TERM));
93
94 ctx = schema->module->ctx;
95 type = ((struct lysc_node_leaf *)schema)->type;
96 val->realtype = type;
97 ret = type->plugin->store(ctx, type, value, value_len, options, get_prefix, parser, format, (void *)schema, NULL,
98 val, NULL, &err);
99 if (ret == LY_EINCOMPLETE) {
100 /* this is fine, we do not need it resolved */
101 ret = LY_SUCCESS;
102 } else if (ret && err) {
103 ly_err_print(err);
104 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
105 ly_err_free(err);
106 }
107 if (!ret && dynamic) {
108 *dynamic = 0;
109 }
110
111 return ret;
112}
113
Radek Krejci38d85362019-09-05 16:26:38 +0200114LY_ERR
Michal Vasko8d544252020-03-02 10:19:52 +0100115lyd_value_parse_attr(struct ly_ctx *ctx, struct lyd_attr *attr, const char *value, size_t value_len, int *dynamic,
116 int second, ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format,
Michal Vaskof03ed032020-03-04 13:31:44 +0100117 const struct lysc_node *ctx_snode, const struct lyd_node *tree)
Radek Krejci38d85362019-09-05 16:26:38 +0200118{
Michal Vasko90932a92020-02-12 14:33:03 +0100119 LY_ERR ret = LY_SUCCESS;
Radek Krejci38d85362019-09-05 16:26:38 +0200120 struct ly_err_item *err = NULL;
Radek Krejci38d85362019-09-05 16:26:38 +0200121 struct lyext_metadata *ant;
122 int options = LY_TYPE_OPTS_STORE | (second ? LY_TYPE_OPTS_SECOND_CALL : 0) |
Michal Vaskof03ed032020-03-04 13:31:44 +0100123 (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci38d85362019-09-05 16:26:38 +0200124
Michal Vaskof03ed032020-03-04 13:31:44 +0100125 assert(ctx && attr && ((tree && attr->parent) || ctx_snode));
Michal Vasko8d544252020-03-02 10:19:52 +0100126
Radek Krejci38d85362019-09-05 16:26:38 +0200127 ant = attr->annotation->data;
128
129 if (!second) {
130 attr->value.realtype = ant->type;
131 }
Michal Vasko90932a92020-02-12 14:33:03 +0100132 ret = ant->type->plugin->store(ctx, ant->type, value, value_len, options, get_prefix, parser, format,
Michal Vaskof03ed032020-03-04 13:31:44 +0100133 tree ? (void *)attr->parent : (void *)ctx_snode, tree, &attr->value, NULL, &err);
Michal Vasko90932a92020-02-12 14:33:03 +0100134 if (ret && (ret != LY_EINCOMPLETE)) {
Radek Krejci38d85362019-09-05 16:26:38 +0200135 if (err) {
136 ly_err_print(err);
137 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
138 ly_err_free(err);
139 }
140 goto error;
Michal Vasko90932a92020-02-12 14:33:03 +0100141 } else if (dynamic) {
142 *dynamic = 0;
Radek Krejci38d85362019-09-05 16:26:38 +0200143 }
144
145error:
146 return ret;
147}
148
Radek Krejci084289f2019-07-09 17:35:30 +0200149API LY_ERR
150lys_value_validate(struct ly_ctx *ctx, const struct lysc_node *node, const char *value, size_t value_len,
151 ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format)
152{
153 LY_ERR rc = LY_SUCCESS;
154 struct ly_err_item *err = NULL;
155 struct lysc_type *type;
Radek Krejci084289f2019-07-09 17:35:30 +0200156
157 LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
158
159 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
160 LOGARG(ctx, node);
161 return LY_EINVAL;
162 }
163
164 type = ((struct lysc_node_leaf*)node)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200165 /* just validate, no storing of enything */
166 rc = type->plugin->store(ctx ? ctx : node->module->ctx, type, value, value_len, LY_TYPE_OPTS_INCOMPLETE_DATA,
167 get_prefix, get_prefix_data, format, node, NULL, NULL, NULL, &err);
168 if (rc == LY_EINCOMPLETE) {
169 /* actually success since we do not provide the context tree and call validation with
170 * LY_TYPE_OPTS_INCOMPLETE_DATA */
171 rc = LY_SUCCESS;
172 } else if (rc && err) {
173 if (ctx) {
174 /* log only in case the ctx was provided as input parameter */
175 ly_err_print(err);
176 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
Radek Krejci084289f2019-07-09 17:35:30 +0200177 }
Radek Krejci73dead22019-07-11 16:46:16 +0200178 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200179 }
180
181 return rc;
182}
183
184API LY_ERR
185lyd_value_validate(struct ly_ctx *ctx, const struct lyd_node_term *node, const char *value, size_t value_len,
Michal Vaskof03ed032020-03-04 13:31:44 +0100186 ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +0200187{
188 LY_ERR rc;
189 struct ly_err_item *err = NULL;
190 struct lysc_type *type;
Michal Vaskof03ed032020-03-04 13:31:44 +0100191 int options = (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci084289f2019-07-09 17:35:30 +0200192
193 LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
194
195 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200196 rc = type->plugin->store(ctx ? ctx : node->schema->module->ctx, type, value, value_len, options,
Michal Vaskof03ed032020-03-04 13:31:44 +0100197 get_prefix, get_prefix_data, format, tree ? (void*)node : (void*)node->schema, tree,
Radek Krejci73dead22019-07-11 16:46:16 +0200198 NULL, NULL, &err);
199 if (rc == LY_EINCOMPLETE) {
200 return rc;
201 } else if (rc) {
202 if (err) {
203 if (ctx) {
204 ly_err_print(err);
205 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
Radek Krejci084289f2019-07-09 17:35:30 +0200206 }
Radek Krejci73dead22019-07-11 16:46:16 +0200207 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200208 }
Radek Krejci73dead22019-07-11 16:46:16 +0200209 return rc;
Radek Krejci084289f2019-07-09 17:35:30 +0200210 }
211
212 return LY_SUCCESS;
213}
214
215API LY_ERR
216lyd_value_compare(const struct lyd_node_term *node, const char *value, size_t value_len,
Michal Vaskof03ed032020-03-04 13:31:44 +0100217 ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +0200218{
219 LY_ERR ret = LY_SUCCESS, rc;
220 struct ly_err_item *err = NULL;
221 struct ly_ctx *ctx;
222 struct lysc_type *type;
Radek Krejci084289f2019-07-09 17:35:30 +0200223 struct lyd_value data = {0};
Michal Vaskof03ed032020-03-04 13:31:44 +0100224 int options = LY_TYPE_OPTS_STORE | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci084289f2019-07-09 17:35:30 +0200225
226 LY_CHECK_ARG_RET(node ? node->schema->module->ctx : NULL, node, value, LY_EINVAL);
227
228 ctx = node->schema->module->ctx;
229 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200230 rc = type->plugin->store(ctx, type, value, value_len, options, get_prefix, get_prefix_data, format, (struct lyd_node*)node,
Michal Vaskof03ed032020-03-04 13:31:44 +0100231 tree, &data, NULL, &err);
Radek Krejci73dead22019-07-11 16:46:16 +0200232 if (rc == LY_EINCOMPLETE) {
233 ret = rc;
234 /* continue with comparing, just remember what to return if storing is ok */
235 } else if (rc) {
236 /* value to compare is invalid */
237 ret = LY_EINVAL;
238 if (err) {
239 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200240 }
Radek Krejci73dead22019-07-11 16:46:16 +0200241 goto cleanup;
Radek Krejci084289f2019-07-09 17:35:30 +0200242 }
243
244 /* compare data */
Radek Krejci5af04842019-07-12 11:32:07 +0200245 if (type->plugin->compare(&node->value, &data)) {
246 /* do not assign it directly from the compare callback to keep possible LY_EINCOMPLETE from validation */
247 ret = LY_EVALID;
248 }
Radek Krejci084289f2019-07-09 17:35:30 +0200249
250cleanup:
Radek Krejci62903c32019-07-15 14:42:05 +0200251 type->plugin->free(ctx, &data);
Radek Krejci084289f2019-07-09 17:35:30 +0200252
253 return ret;
254}
255
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200256API const char *
257lyd_value2str(const struct lyd_node_term *node, int *dynamic)
258{
259 LY_CHECK_ARG_RET(node ? node->schema->module->ctx : NULL, node, dynamic, NULL);
260
261 return node->value.realtype->plugin->print(&node->value, LYD_JSON, json_print_get_prefix, NULL, dynamic);
262}
263
264API const char *
265lyd_attr2str(const struct lyd_attr *attr, int *dynamic)
266{
267 LY_CHECK_ARG_RET(attr ? attr->parent->schema->module->ctx : NULL, attr, dynamic, NULL);
268
269 return attr->value.realtype->plugin->print(&attr->value, LYD_JSON, json_print_get_prefix, NULL, dynamic);
270}
271
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200272API struct lyd_node *
Michal Vaskoa3881362020-01-21 15:57:35 +0100273lyd_parse_mem(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
Radek Krejcie7b95092019-05-15 11:03:07 +0200274{
Radek Krejcie7b95092019-05-15 11:03:07 +0200275 struct lyd_node *result = NULL;
Radek Krejcie92210c2019-05-17 15:53:35 +0200276#if 0
Radek Krejcie7b95092019-05-15 11:03:07 +0200277 const char *yang_data_name = NULL;
Radek Krejcie92210c2019-05-17 15:53:35 +0200278#endif
Radek Krejcie7b95092019-05-15 11:03:07 +0200279
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200280 LY_CHECK_ARG_RET(ctx, ctx, NULL);
281
Michal Vasko5b37a352020-03-06 13:38:33 +0100282 if ((options & LYD_OPT_PARSE_ONLY) && (options & LYD_VALOPT_MASK)) {
283 LOGERR(ctx, LY_EINVAL, "Passing validation flags with LYD_OPT_PARSE_ONLY is not allowed.");
284 return NULL;
285 }
286
Michal Vaskoa3881362020-01-21 15:57:35 +0100287#if 0
Radek Krejcie7b95092019-05-15 11:03:07 +0200288 if (options & LYD_OPT_RPCREPLY) {
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200289 /* first item in trees is mandatory - the RPC/action request */
290 LY_CHECK_ARG_RET(ctx, trees, LY_ARRAY_SIZE(trees) >= 1, NULL);
291 if (!trees[0] || trees[0]->parent || !(trees[0]->schema->nodetype & (LYS_ACTION | LYS_LIST | LYS_CONTAINER))) {
292 LOGERR(ctx, LY_EINVAL, "Data parser invalid argument trees - the first item in the array must be the RPC/action request when parsing %s.",
293 lyd_parse_options_type2str(options));
Radek Krejcie7b95092019-05-15 11:03:07 +0200294 return NULL;
295 }
296 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200297
Radek Krejcie7b95092019-05-15 11:03:07 +0200298 if (options & LYD_OPT_DATA_TEMPLATE) {
299 yang_data_name = va_arg(ap, const char *);
300 }
Radek Krejcie92210c2019-05-17 15:53:35 +0200301#endif
Radek Krejcie7b95092019-05-15 11:03:07 +0200302
303 if (!format) {
304 /* TODO try to detect format from the content */
305 }
306
307 switch (format) {
308 case LYD_XML:
Michal Vaskoa3881362020-01-21 15:57:35 +0100309 lyd_parse_xml(ctx, data, options, &result);
Radek Krejcie7b95092019-05-15 11:03:07 +0200310 break;
311#if 0
312 case LYD_JSON:
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200313 lyd_parse_json(ctx, data, options, trees, &result);
Radek Krejcie7b95092019-05-15 11:03:07 +0200314 break;
315 case LYD_LYB:
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200316 lyd_parse_lyb(ctx, data, options, trees, &result);
Radek Krejcie7b95092019-05-15 11:03:07 +0200317 break;
318#endif
319 case LYD_UNKNOWN:
320 LOGINT(ctx);
321 break;
322 }
323
Radek Krejcie7b95092019-05-15 11:03:07 +0200324 return result;
325}
326
327API struct lyd_node *
Michal Vaskoa3881362020-01-21 15:57:35 +0100328lyd_parse_fd(struct ly_ctx *ctx, int fd, LYD_FORMAT format, int options)
Radek Krejcie7b95092019-05-15 11:03:07 +0200329{
330 struct lyd_node *result;
331 size_t length;
332 char *addr;
333
334 LY_CHECK_ARG_RET(ctx, ctx, NULL);
335 if (fd < 0) {
336 LOGARG(ctx, fd);
337 return NULL;
338 }
339
340 LY_CHECK_RET(ly_mmap(ctx, fd, &length, (void **)&addr), NULL);
Michal Vaskoa3881362020-01-21 15:57:35 +0100341 result = lyd_parse_mem(ctx, addr ? addr : "", format, options);
Radek Krejcidf3da792019-05-17 10:32:24 +0200342 if (addr) {
343 ly_munmap(addr, length);
344 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200345
346 return result;
347}
348
349API struct lyd_node *
Michal Vaskoa3881362020-01-21 15:57:35 +0100350lyd_parse_path(struct ly_ctx *ctx, const char *path, LYD_FORMAT format, int options)
Radek Krejcie7b95092019-05-15 11:03:07 +0200351{
352 int fd;
353 struct lyd_node *result;
354 size_t len;
Radek Krejcie7b95092019-05-15 11:03:07 +0200355
356 LY_CHECK_ARG_RET(ctx, ctx, path, NULL);
357
358 fd = open(path, O_RDONLY);
359 LY_CHECK_ERR_RET(fd == -1, LOGERR(ctx, LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno)), NULL);
360
361 if (!format) {
362 /* unknown format - try to detect it from filename's suffix */
363 len = strlen(path);
364
365 /* ignore trailing whitespaces */
366 for (; len > 0 && isspace(path[len - 1]); len--);
367
368 if (len >= 5 && !strncmp(&path[len - 4], ".xml", 4)) {
369 format = LYD_XML;
370#if 0
371 } else if (len >= 6 && !strncmp(&path[len - 5], ".json", 5)) {
372 format = LYD_JSON;
373 } else if (len >= 5 && !strncmp(&path[len - 4], ".lyb", 4)) {
374 format = LYD_LYB;
375#endif
376 } /* else still unknown, try later to detect it from the content */
377 }
378
Michal Vaskoa3881362020-01-21 15:57:35 +0100379 result = lyd_parse_fd(ctx, fd, format, options);
Radek Krejcie7b95092019-05-15 11:03:07 +0200380 close(fd);
381
382 return result;
383}
Radek Krejci084289f2019-07-09 17:35:30 +0200384
Michal Vasko90932a92020-02-12 14:33:03 +0100385LY_ERR
386lyd_create_term(const struct lysc_node *schema, const char *value, size_t value_len, int *dynamic,
387 ly_clb_resolve_prefix get_prefix, void *prefix_data, LYD_FORMAT format, struct lyd_node **node)
388{
389 LY_ERR ret;
390 struct lyd_node_term *term;
391
Michal Vasko9b368d32020-02-14 13:53:31 +0100392 assert(schema->nodetype & LYD_NODE_TERM);
393
Michal Vasko90932a92020-02-12 14:33:03 +0100394 term = calloc(1, sizeof *term);
395 LY_CHECK_ERR_RET(!term, LOGMEM(schema->module->ctx), LY_EMEM);
396
397 term->schema = schema;
398 term->prev = (struct lyd_node *)term;
Michal Vasko9b368d32020-02-14 13:53:31 +0100399 term->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100400
401 ret = lyd_value_parse(term, value, value_len, dynamic, 0, get_prefix, prefix_data, format, NULL);
402 if (ret && (ret != LY_EINCOMPLETE)) {
403 free(term);
404 return ret;
405 }
Michal Vasko9b368d32020-02-14 13:53:31 +0100406 lyd_hash((struct lyd_node *)term);
407
408 *node = (struct lyd_node *)term;
409 return ret;
410}
411
412LY_ERR
413lyd_create_term2(const struct lysc_node *schema, const struct lyd_value *val, struct lyd_node **node)
414{
415 LY_ERR ret;
416 struct lyd_node_term *term;
417 struct lysc_type *type;
418
419 assert(schema->nodetype & LYD_NODE_TERM);
420
421 term = calloc(1, sizeof *term);
422 LY_CHECK_ERR_RET(!term, LOGMEM(schema->module->ctx), LY_EMEM);
423
424 term->schema = schema;
425 term->prev = (struct lyd_node *)term;
426 term->flags = LYD_NEW;
427
428 type = ((struct lysc_node_leaf *)schema)->type;
429 ret = type->plugin->duplicate(schema->module->ctx, val, &term->value);
430 if (ret) {
431 LOGERR(schema->module->ctx, ret, "Value duplication failed.");
432 free(term);
433 return ret;
434 }
435 lyd_hash((struct lyd_node *)term);
Michal Vasko90932a92020-02-12 14:33:03 +0100436
437 *node = (struct lyd_node *)term;
438 return ret;
439}
440
441LY_ERR
442lyd_create_inner(const struct lysc_node *schema, struct lyd_node **node)
443{
444 struct lyd_node_inner *in;
445
Michal Vasko9b368d32020-02-14 13:53:31 +0100446 assert(schema->nodetype & LYD_NODE_INNER);
447
Michal Vasko90932a92020-02-12 14:33:03 +0100448 in = calloc(1, sizeof *in);
449 LY_CHECK_ERR_RET(!in, LOGMEM(schema->module->ctx), LY_EMEM);
450
451 in->schema = schema;
452 in->prev = (struct lyd_node *)in;
Michal Vasko9b368d32020-02-14 13:53:31 +0100453 in->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100454
Michal Vasko9b368d32020-02-14 13:53:31 +0100455 /* do not hash list with keys, we need them for the hash */
456 if ((schema->nodetype != LYS_LIST) || (schema->flags & LYS_KEYLESS)) {
457 lyd_hash((struct lyd_node *)in);
458 }
Michal Vasko90932a92020-02-12 14:33:03 +0100459
460 *node = (struct lyd_node *)in;
461 return LY_SUCCESS;
462}
463
464static void
465ly_keys_clean(struct ly_keys *keys)
466{
467 size_t i;
468
469 for (i = 0; i < keys->key_count; ++i) {
470 keys->keys[i].schema->type->plugin->free(keys->keys[i].schema->module->ctx, &keys->keys[i].val);
471 }
472 free(keys->str);
473 free(keys->keys);
474}
475
476static char *
477ly_keys_parse_next(char **next_key, char **key_name)
478{
479 char *ptr, *ptr2, *val, quot;
480
481 ptr = *next_key;
482
483 /* "[" */
484 LY_CHECK_GOTO(ptr[0] != '[', error);
485 ++ptr;
486
487 /* key name */
488 ptr2 = strchr(ptr, '=');
489 LY_CHECK_GOTO(!ptr2, error);
490
491 *key_name = ptr;
492 ptr2[0] = '\0';
493
494 /* \0, was '=' */
495 ptr = ptr2 + 1;
496
497 /* quote */
498 LY_CHECK_GOTO((ptr[0] != '\'') && (ptr[0] != '\"'), error);
499 quot = ptr[0];
500 ++ptr;
501
502 /* value, terminate it */
503 val = ptr;
504 ptr2 = strchr(ptr, quot);
505 LY_CHECK_GOTO(!ptr2, error);
506 ptr2[0] = '\0';
507
508 /* \0, was quote */
509 ptr = ptr2 + 1;
510
511 /* "]" */
512 LY_CHECK_GOTO(ptr[0] != ']', error);
513 ++ptr;
514
515 *next_key = ptr;
516 return val;
517
518error:
519 *next_key = ptr;
520 return NULL;
521}
522
523/* fill keys structure; if store is set, fill also each val */
524static LY_ERR
525ly_keys_parse(const struct lysc_node *list, const char *keys_str, size_t keys_len, int store, struct ly_keys *keys)
526{
527 LY_ERR ret = LY_SUCCESS;
528 char *next_key, *name;
529 const struct lysc_node *key;
530 size_t i;
531
532 assert(list->nodetype == LYS_LIST);
533
534 memset(keys, 0, sizeof *keys);
535
Michal Vaskof03ed032020-03-04 13:31:44 +0100536 if (!keys_str) {
537 /* nothing to parse */
538 return LY_SUCCESS;
539 }
540
541 keys->str = strndup(keys_str, keys_len);
Michal Vasko90932a92020-02-12 14:33:03 +0100542 LY_CHECK_ERR_GOTO(!keys->str, LOGMEM(list->module->ctx); ret = LY_EMEM, cleanup);
543
544 next_key = keys->str;
545 while (next_key[0]) {
546 /* new key */
547 keys->keys = ly_realloc(keys->keys, (keys->key_count + 1) * sizeof *keys->keys);
548 LY_CHECK_ERR_GOTO(!keys->keys, LOGMEM(list->module->ctx); ret = LY_EMEM, cleanup);
549
550 /* fill */
551 keys->keys[keys->key_count].value = ly_keys_parse_next(&next_key, &name);
552 if (!keys->keys[keys->key_count].value) {
553 LOGERR(list->module->ctx, LY_EINVAL, "Invalid keys string (at \"%s\").", next_key);
554 ret = LY_EINVAL;
555 goto cleanup;
556 }
557
558 /* find schema node */
559 key = lys_find_child(list, list->module, name, 0, LYS_LEAF, 0);
560 if (!key) {
561 LOGERR(list->module->ctx, LY_EINVAL, "List \"%s\" has no key \"%s\".", list->name, name);
562 ret = LY_EINVAL;
563 goto cleanup;
564 }
565 keys->keys[keys->key_count].schema = (const struct lysc_node_leaf *)key;
566
567 /* check that we do not have it already */
568 for (i = 0; i < keys->key_count; ++i) {
569 if (keys->keys[i].schema == keys->keys[keys->key_count].schema) {
570 LOGERR(list->module->ctx, LY_EINVAL, "Duplicit key \"%s\" value.", name);
571 ret = LY_EINVAL;
572 goto cleanup;
573 }
574 }
575
576 if (store) {
577 /* store the value */
578 ret = lyd_value_store(&keys->keys[keys->key_count].val, key, keys->keys[keys->key_count].value, 0, 0,
579 lydjson_resolve_prefix, NULL, LYD_JSON);
580 LY_CHECK_GOTO(ret, cleanup);
581 }
582
583 /* another valid key */
584 ++keys->key_count;
585 }
586
587cleanup:
588 ly_keys_clean(keys);
589 return ret;
590}
591
592LY_ERR
593lyd_create_list(const struct lysc_node *schema, const char *keys_str, size_t keys_len, struct lyd_node **node)
594{
595 LY_ERR ret = LY_SUCCESS;
596 const struct lysc_node *key_s;
597 struct lyd_node *list = NULL, *key;
598 struct ly_keys keys = {0};
599 size_t i;
600
601 assert((schema->nodetype == LYS_LIST) && !(schema->flags & LYS_KEYLESS));
602
603 /* parse keys */
604 LY_CHECK_GOTO(ret = ly_keys_parse(schema, keys_str, keys_len, 0, &keys), cleanup);
605
606 /* create list */
607 LY_CHECK_GOTO(ret = lyd_create_inner(schema, &list), cleanup);
608
609 /* everything was checked except that all keys are set */
610 i = 0;
611 for (key_s = lysc_node_children(schema, 0); key_s && (key_s->flags & LYS_KEY); key_s = key_s->next) {
612 ++i;
613 }
614 if (i != keys.key_count) {
615 LOGERR(schema->module->ctx, LY_EINVAL, "List \"%s\" is missing some keys.", schema->name);
616 ret = LY_EINVAL;
617 goto cleanup;
618 }
619
620 /* create and insert all the keys */
621 for (i = 0; i < keys.key_count; ++i) {
Michal Vaskof03ed032020-03-04 13:31:44 +0100622 LY_CHECK_GOTO(ret = lyd_create_term((struct lysc_node *)keys.keys[i].schema, keys.keys[i].value,
623 strlen(keys.keys[i].value), NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &key), cleanup);
Michal Vasko90932a92020-02-12 14:33:03 +0100624 lyd_insert_node(list, NULL, key);
625 }
626
Michal Vasko9b368d32020-02-14 13:53:31 +0100627 /* hash having all the keys */
628 lyd_hash(list);
629
Michal Vasko90932a92020-02-12 14:33:03 +0100630 /* success */
631 *node = list;
632 list = NULL;
633
634cleanup:
635 lyd_free_tree(list);
636 ly_keys_clean(&keys);
637 return ret;
638}
639
640LY_ERR
641lyd_create_any(const struct lysc_node *schema, const void *value, LYD_ANYDATA_VALUETYPE value_type, struct lyd_node **node)
642{
643 struct lyd_node_any *any;
644
Michal Vasko9b368d32020-02-14 13:53:31 +0100645 assert(schema->nodetype & LYD_NODE_ANY);
646
Michal Vasko90932a92020-02-12 14:33:03 +0100647 any = calloc(1, sizeof *any);
648 LY_CHECK_ERR_RET(!any, LOGMEM(schema->module->ctx), LY_EMEM);
649
650 any->schema = schema;
651 any->prev = (struct lyd_node *)any;
Michal Vasko9b368d32020-02-14 13:53:31 +0100652 any->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100653
654 any->value.xml = value;
655 any->value_type = value_type;
Michal Vasko9b368d32020-02-14 13:53:31 +0100656 lyd_hash((struct lyd_node *)any);
Michal Vasko90932a92020-02-12 14:33:03 +0100657
658 *node = (struct lyd_node *)any;
659 return LY_SUCCESS;
660}
661
Michal Vasko013a8182020-03-03 10:46:53 +0100662API struct lyd_node *
663lyd_new_inner(struct lyd_node *parent, const struct lys_module *module, const char *name)
664{
665 struct lyd_node *ret = NULL;
666 const struct lysc_node *schema;
667 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
668
669 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
670
Michal Vaskof03ed032020-03-04 13:31:44 +0100671 if (!module) {
672 module = parent->schema->module;
673 }
674
Michal Vasko013a8182020-03-03 10:46:53 +0100675 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_CONTAINER | LYS_NOTIF | LYS_ACTION, 0);
676 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Inner node \"%s\" not found.", name), NULL);
677
678 if (!lyd_create_inner(schema, &ret) && parent) {
679 lyd_insert_node(parent, NULL, ret);
680 }
681 return ret;
682}
683
684API struct lyd_node *
685lyd_new_list(struct lyd_node *parent, const struct lys_module *module, const char *name, ...)
686{
687 struct lyd_node *ret = NULL, *key;
688 const struct lysc_node *schema, *key_s;
689 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
690 va_list ap;
691 const char *key_val;
692 LY_ERR rc = LY_SUCCESS;
693
694 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
695
Michal Vaskof03ed032020-03-04 13:31:44 +0100696 if (!module) {
697 module = parent->schema->module;
698 }
699
Michal Vasko013a8182020-03-03 10:46:53 +0100700 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, 0);
701 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), NULL);
702
703 /* create list inner node */
704 LY_CHECK_RET(lyd_create_inner(schema, &ret), NULL);
705
706 va_start(ap, name);
707
708 /* create and insert all the keys */
709 for (key_s = lysc_node_children(schema, 0); key_s && (key_s->flags & LYS_KEY); key_s = key_s->next) {
710 key_val = va_arg(ap, const char *);
711
Michal Vaskof03ed032020-03-04 13:31:44 +0100712 rc = lyd_create_term(key_s, key_val, key_val ? strlen(key_val) : 0, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &key);
713 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko013a8182020-03-03 10:46:53 +0100714 lyd_insert_node(ret, NULL, key);
715 }
716
717 /* hash having all the keys */
718 lyd_hash(ret);
719
720 if (parent) {
721 lyd_insert_node(parent, NULL, ret);
722 }
723
724cleanup:
725 if (rc) {
726 lyd_free_tree(ret);
727 ret = NULL;
728 }
729 va_end(ap);
730 return ret;
731}
732
733API struct lyd_node *
734lyd_new_list2(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *keys)
735{
736 struct lyd_node *ret = NULL;
737 const struct lysc_node *schema;
738 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
739
740 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
741
Michal Vaskof03ed032020-03-04 13:31:44 +0100742 if (!module) {
743 module = parent->schema->module;
744 }
745
Michal Vasko013a8182020-03-03 10:46:53 +0100746 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, 0);
747 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), NULL);
748
Michal Vaskof03ed032020-03-04 13:31:44 +0100749 if (!lyd_create_list(schema, keys, keys ? strlen(keys) : 0, &ret) && parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100750 lyd_insert_node(parent, NULL, ret);
751 }
752 return ret;
753}
754
755API struct lyd_node *
756lyd_new_term(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str)
757{
758 struct lyd_node *ret = NULL;
759 const struct lysc_node *schema;
760 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
761
762 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
763
Michal Vaskof03ed032020-03-04 13:31:44 +0100764 if (!module) {
765 module = parent->schema->module;
766 }
767
Michal Vasko013a8182020-03-03 10:46:53 +0100768 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_TERM, 0);
769 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Term node \"%s\" not found.", name), NULL);
770
Michal Vaskof03ed032020-03-04 13:31:44 +0100771 if (!lyd_create_term(schema, val_str, val_str ? strlen(val_str) : 0, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &ret)
772 && parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100773 lyd_insert_node(parent, NULL, ret);
774 }
775 return ret;
776}
777
778API struct lyd_node *
779lyd_new_any(struct lyd_node *parent, const struct lys_module *module, const char *name, const void *value,
780 LYD_ANYDATA_VALUETYPE value_type)
781{
782 struct lyd_node *ret = NULL;
783 const struct lysc_node *schema;
784 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
785
786 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
787
Michal Vaskof03ed032020-03-04 13:31:44 +0100788 if (!module) {
789 module = parent->schema->module;
790 }
791
Michal Vasko013a8182020-03-03 10:46:53 +0100792 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_ANY, 0);
793 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Any node \"%s\" not found.", name), NULL);
794
795 if (!lyd_create_any(schema, value, value_type, &ret) && parent) {
796 lyd_insert_node(parent, NULL, ret);
797 }
798 return ret;
799}
800
Michal Vasko90932a92020-02-12 14:33:03 +0100801struct lyd_node *
802lyd_get_prev_key_anchor(const struct lyd_node *first_sibling, const struct lysc_node *new_key)
803{
804 const struct lysc_node *prev_key;
805 struct lyd_node *match = NULL;
806
807 if (!first_sibling) {
808 return NULL;
809 }
810
811 for (prev_key = new_key->prev; !match && prev_key->next; prev_key = prev_key->prev) {
812 lyd_find_sibling_val(first_sibling, prev_key, NULL, 0, &match);
813 }
814
815 return match;
816}
817
818/**
819 * @brief Insert node after a sibling.
820 *
821 * @param[in] sibling Sibling to insert after.
822 * @param[in] node Node to insert.
823 */
824static void
Michal Vaskof03ed032020-03-04 13:31:44 +0100825lyd_insert_after_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +0100826{
Michal Vasko0249f7c2020-03-05 16:36:40 +0100827 struct lyd_node_inner *par;
828
Michal Vasko90932a92020-02-12 14:33:03 +0100829 assert(!node->next && (node->prev == node));
830
831 node->next = sibling->next;
832 node->prev = sibling;
833 sibling->next = node;
834 if (node->next) {
835 /* sibling had a succeeding node */
836 node->next->prev = node;
837 } else {
838 /* sibling was last, find first sibling and change its prev */
839 if (sibling->parent) {
840 sibling = sibling->parent->child;
841 } else {
842 for (; sibling->prev->next != node; sibling = sibling->prev);
843 }
844 sibling->prev = node;
845 }
846 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +0100847
848 if (!(node->flags & LYD_DEFAULT)) {
849 /* remove default flags from NP containers */
850 for (par = node->parent; par && (par->flags & LYD_DEFAULT); par = par->parent) {
851 par->flags &= ~LYD_DEFAULT;
852 }
853 }
854
855 /* insert into hash table */
856 lyd_insert_hash(node);
Michal Vasko90932a92020-02-12 14:33:03 +0100857}
858
859/**
860 * @brief Insert node before a sibling.
861 *
862 * @param[in] sibling Sibling to insert before.
863 * @param[in] node Node to insert.
864 */
865static void
Michal Vaskof03ed032020-03-04 13:31:44 +0100866lyd_insert_before_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +0100867{
Michal Vasko0249f7c2020-03-05 16:36:40 +0100868 struct lyd_node_inner *par;
869
Michal Vasko90932a92020-02-12 14:33:03 +0100870 assert(!node->next && (node->prev == node));
871
872 node->next = sibling;
873 /* covers situation of sibling being first */
874 node->prev = sibling->prev;
875 sibling->prev = node;
876 if (node->prev->next) {
877 /* sibling had a preceding node */
878 node->prev->next = node;
879 } else if (sibling->parent) {
880 /* sibling was first and we must also change parent child pointer */
881 sibling->parent->child = node;
882 }
883 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +0100884
885 if (!(node->flags & LYD_DEFAULT)) {
886 /* remove default flags from NP containers */
887 for (par = node->parent; par && (par->flags & LYD_DEFAULT); par = par->parent) {
888 par->flags &= ~LYD_DEFAULT;
889 }
890 }
891
892 /* insert into hash table */
893 lyd_insert_hash(node);
Michal Vasko90932a92020-02-12 14:33:03 +0100894}
895
896/**
897 * @brief Insert node as the last child of a parent.
898 *
899 * @param[in] parent Parent to insert into.
900 * @param[in] node Node to insert.
901 */
902static void
Michal Vaskof03ed032020-03-04 13:31:44 +0100903lyd_insert_last_node(struct lyd_node *parent, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +0100904{
905 struct lyd_node_inner *par;
906
Michal Vasko0249f7c2020-03-05 16:36:40 +0100907 assert(parent && !node->next && (node->prev == node));
Michal Vasko90932a92020-02-12 14:33:03 +0100908 assert(parent->schema->nodetype & LYD_NODE_INNER);
909
910 par = (struct lyd_node_inner *)parent;
911
912 if (!par->child) {
913 par->child = node;
914 } else {
915 node->prev = par->child->prev;
916 par->child->prev->next = node;
917 par->child->prev = node;
918 }
919 node->parent = par;
Michal Vasko0249f7c2020-03-05 16:36:40 +0100920
921 if (!(node->flags & LYD_DEFAULT)) {
922 /* remove default flags from NP containers */
923 for (; par && (par->flags & LYD_DEFAULT); par = par->parent) {
924 par->flags &= ~LYD_DEFAULT;
925 }
926 }
927
928 /* insert into hash table */
929 lyd_insert_hash(node);
Michal Vasko90932a92020-02-12 14:33:03 +0100930}
931
932void
Michal Vasko9b368d32020-02-14 13:53:31 +0100933lyd_insert_node(struct lyd_node *parent, struct lyd_node **first_sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +0100934{
Michal Vasko9b368d32020-02-14 13:53:31 +0100935 struct lyd_node *anchor;
Michal Vasko90932a92020-02-12 14:33:03 +0100936
Michal Vasko9b368d32020-02-14 13:53:31 +0100937 assert((parent || first_sibling) && node && node->hash);
938
939 if (!parent && first_sibling && (*first_sibling) && (*first_sibling)->parent) {
940 parent = (struct lyd_node *)(*first_sibling)->parent;
941 }
Michal Vasko90932a92020-02-12 14:33:03 +0100942
943 if (parent) {
944 if (node->schema->flags & LYS_KEY) {
945 /* it is key and we need to insert it at the correct place */
Michal Vasko9b368d32020-02-14 13:53:31 +0100946 anchor = lyd_get_prev_key_anchor(lyd_node_children(parent), node->schema);
947 if (anchor) {
Michal Vaskof03ed032020-03-04 13:31:44 +0100948 lyd_insert_after_node(anchor, node);
Michal Vasko90932a92020-02-12 14:33:03 +0100949 } else if (lyd_node_children(parent)) {
Michal Vaskof03ed032020-03-04 13:31:44 +0100950 lyd_insert_before_node((struct lyd_node *)lyd_node_children(parent), node);
Michal Vasko90932a92020-02-12 14:33:03 +0100951 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +0100952 lyd_insert_last_node(parent, node);
Michal Vasko90932a92020-02-12 14:33:03 +0100953 }
954 } else {
955 /* last child */
Michal Vaskof03ed032020-03-04 13:31:44 +0100956 lyd_insert_last_node(parent, node);
Michal Vasko90932a92020-02-12 14:33:03 +0100957 }
Michal Vasko9b368d32020-02-14 13:53:31 +0100958 } else if (*first_sibling) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100959 /* top-level siblings */
Michal Vasko9b368d32020-02-14 13:53:31 +0100960 anchor = (*first_sibling)->prev;
Michal Vaskoc193ce92020-03-06 11:04:48 +0100961 while (anchor->prev->next && (lyd_owner_module(anchor) != lyd_owner_module(node))) {
Michal Vasko9b368d32020-02-14 13:53:31 +0100962 anchor = anchor->prev;
963 }
964
Michal Vaskoc193ce92020-03-06 11:04:48 +0100965 if (lyd_owner_module(anchor) == lyd_owner_module(node)) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100966 /* insert after last sibling from this module */
967 lyd_insert_after_node(anchor, node);
968 } else {
969 /* no data from this module, insert at the last position */
970 lyd_insert_after_node((*first_sibling)->prev, node);
971 }
Michal Vasko90932a92020-02-12 14:33:03 +0100972 } else {
Michal Vasko9b368d32020-02-14 13:53:31 +0100973 /* the only sibling */
974 *first_sibling = node;
Michal Vasko90932a92020-02-12 14:33:03 +0100975 }
Michal Vasko90932a92020-02-12 14:33:03 +0100976}
977
Michal Vaskof03ed032020-03-04 13:31:44 +0100978static LY_ERR
979lyd_insert_check_schema(const struct lysc_node *parent, const struct lysc_node *schema)
980{
981 const struct lysc_node *par2;
982
983 assert(schema);
984
985 /* adjust parent first */
986 while (parent && (parent->nodetype & (LYS_CASE | LYS_CHOICE))) {
987 parent = parent->parent;
988 }
989
990 /* find schema parent */
991 for (par2 = schema->parent; par2 && (par2->nodetype & (LYS_CASE | LYS_CHOICE)); par2 = par2->parent);
992
993 if (parent) {
994 /* inner node */
995 if (par2 != parent) {
996 LOGERR(parent->module->ctx, LY_EINVAL, "Cannot insert, parent of \"%s\" is not \"%s\".", schema->name, parent->name);
997 return LY_EINVAL;
998 }
999 } else {
1000 /* top-level node */
1001 if (par2) {
1002 LOGERR(parent->module->ctx, LY_EINVAL, "Cannot insert, node \"%s\" is not top-level.", schema->name);
1003 return LY_EINVAL;
1004 }
1005 }
1006
1007 return LY_SUCCESS;
1008}
1009
1010API LY_ERR
1011lyd_insert(struct lyd_node *parent, struct lyd_node *node)
1012{
1013 struct lyd_node *iter;
1014
1015 LY_CHECK_ARG_RET(NULL, parent, node, !(parent->schema->nodetype & LYD_NODE_INNER), LY_EINVAL);
1016
1017 LY_CHECK_RET(lyd_insert_check_schema(parent->schema, node->schema));
1018
1019 if (node->schema->flags & LYS_KEY) {
1020 LOGERR(parent->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1021 return LY_EINVAL;
1022 }
1023
1024 if (node->parent || node->prev->next) {
1025 lyd_unlink_tree(node);
1026 }
1027
1028 while (node) {
1029 iter = node->next;
1030 lyd_unlink_tree(node);
1031 lyd_insert_node(parent, NULL, node);
1032 node = iter;
1033 }
1034 return LY_SUCCESS;
1035}
1036
1037API LY_ERR
Michal Vaskob1b5c262020-03-05 14:29:47 +01001038lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node)
1039{
1040 struct lyd_node *iter;
1041
1042 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1043
1044 LY_CHECK_RET(lyd_insert_check_schema(sibling->schema->parent, node->schema));
1045
1046 if (node->schema->flags & LYS_KEY) {
1047 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1048 return LY_EINVAL;
1049 }
1050
1051 if (node->parent || node->prev->next) {
1052 lyd_unlink_tree(node);
1053 }
1054
1055 while (node) {
1056 iter = node->next;
1057 lyd_unlink_tree(node);
1058 lyd_insert_node(NULL, &sibling, node);
1059 node = iter;
1060 }
1061 return LY_SUCCESS;
1062}
1063
Michal Vasko0249f7c2020-03-05 16:36:40 +01001064static LY_ERR
1065lyd_insert_after_check_place(struct lyd_node *anchor, struct lyd_node *sibling, struct lyd_node *node)
1066{
1067 if (sibling->parent) {
1068 /* nested, we do not care for the order */
1069 return LY_SUCCESS;
1070 }
1071
1072 if (anchor) {
Michal Vaskoc193ce92020-03-06 11:04:48 +01001073 if (anchor->next && (lyd_owner_module(anchor) == lyd_owner_module(anchor->next))
1074 && (lyd_owner_module(node) != lyd_owner_module(anchor))) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001075 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert top-level module \"%s\" data into module \"%s\" data.",
Michal Vaskoc193ce92020-03-06 11:04:48 +01001076 lyd_owner_module(node)->name, lyd_owner_module(anchor)->name);
Michal Vasko0249f7c2020-03-05 16:36:40 +01001077 return LY_EINVAL;
1078 }
1079
Michal Vaskoc193ce92020-03-06 11:04:48 +01001080 if ((lyd_owner_module(node) == lyd_owner_module(anchor))
1081 || (anchor->next && (lyd_owner_module(node) == lyd_owner_module(anchor->next)))) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001082 /* inserting before/after its module data */
1083 return LY_SUCCESS;
1084 }
1085 }
1086
1087 /* find first sibling */
1088 while (sibling->prev->next) {
1089 sibling = sibling->prev;
1090 }
1091
1092 if (!anchor) {
Michal Vaskoc193ce92020-03-06 11:04:48 +01001093 if (lyd_owner_module(node) == lyd_owner_module(sibling)) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001094 /* inserting before its module data */
1095 return LY_SUCCESS;
1096 }
1097 }
1098
1099 /* check there are no data of this module */
1100 LY_LIST_FOR(sibling, sibling) {
Michal Vaskoc193ce92020-03-06 11:04:48 +01001101 if (lyd_owner_module(node) == lyd_owner_module(sibling)) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001102 /* some data of this module found */
1103 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Top-level data of module \"%s\" already exist,"
Michal Vaskoc193ce92020-03-06 11:04:48 +01001104 " they must be directly connected.", lyd_owner_module(node)->name);
Michal Vasko0249f7c2020-03-05 16:36:40 +01001105 return LY_EINVAL;
1106 }
1107 }
1108
1109 return LY_SUCCESS;
1110}
1111
Michal Vaskob1b5c262020-03-05 14:29:47 +01001112API LY_ERR
Michal Vaskof03ed032020-03-04 13:31:44 +01001113lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
1114{
1115 struct lyd_node *iter;
1116
1117 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1118
1119 LY_CHECK_RET(lyd_insert_check_schema(sibling->schema->parent, node->schema));
1120
1121 if (node->schema->flags & LYS_KEY) {
1122 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1123 return LY_EINVAL;
1124 } else if (sibling->schema->flags & LYS_KEY) {
1125 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert into keys.");
1126 return LY_EINVAL;
1127 }
1128
Michal Vasko0249f7c2020-03-05 16:36:40 +01001129 LY_CHECK_RET(lyd_insert_after_check_place(sibling->prev->next ? sibling->prev : NULL, sibling, node));
1130
Michal Vaskof03ed032020-03-04 13:31:44 +01001131 if (node->parent || node->prev->next) {
1132 lyd_unlink_tree(node);
1133 }
1134
1135 /* insert in reverse order to get the original order */
1136 node = node->prev;
1137 while (node) {
1138 iter = node->prev;
1139 lyd_unlink_tree(node);
1140
1141 lyd_insert_before_node(sibling, node);
1142 /* move the anchor accordingly */
1143 sibling = node;
1144
1145 node = (iter == node) ? NULL : iter;
1146 }
1147 return LY_SUCCESS;
1148}
1149
1150API LY_ERR
1151lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
1152{
1153 struct lyd_node *iter;
1154
1155 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1156
1157 LY_CHECK_RET(lyd_insert_check_schema(sibling->schema->parent, node->schema));
1158
1159 if (node->schema->flags & LYS_KEY) {
1160 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1161 return LY_EINVAL;
1162 } else if (sibling->next && (sibling->next->schema->flags & LYS_KEY)) {
1163 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert into keys.");
1164 return LY_EINVAL;
1165 }
1166
Michal Vasko0249f7c2020-03-05 16:36:40 +01001167 LY_CHECK_RET(lyd_insert_after_check_place(sibling, sibling, node));
1168
Michal Vaskof03ed032020-03-04 13:31:44 +01001169 if (node->parent || node->prev->next) {
1170 lyd_unlink_tree(node);
1171 }
1172
1173 while (node) {
1174 iter = node->next;
1175 lyd_unlink_tree(node);
1176
1177 lyd_insert_after_node(sibling, node);
1178 /* move the anchor accordingly */
1179 sibling = node;
1180
1181 node = iter;
1182 }
1183 return LY_SUCCESS;
1184}
1185
1186API void
1187lyd_unlink_tree(struct lyd_node *node)
1188{
1189 struct lyd_node *iter;
1190
1191 if (!node) {
1192 return;
1193 }
1194
1195 /* unlink from siblings */
1196 if (node->prev->next) {
1197 node->prev->next = node->next;
1198 }
1199 if (node->next) {
1200 node->next->prev = node->prev;
1201 } else {
1202 /* unlinking the last node */
1203 if (node->parent) {
1204 iter = node->parent->child;
1205 } else {
1206 iter = node->prev;
1207 while (iter->prev != node) {
1208 iter = iter->prev;
1209 }
1210 }
1211 /* update the "last" pointer from the first node */
1212 iter->prev = node->prev;
1213 }
1214
1215 /* unlink from parent */
1216 if (node->parent) {
1217 if (node->parent->child == node) {
1218 /* the node is the first child */
1219 node->parent->child = node->next;
1220 }
1221
1222 lyd_unlink_hash(node);
1223
1224 /* check for keyless list and update its hash */
1225 for (iter = (struct lyd_node *)node->parent; iter; iter = (struct lyd_node *)iter->parent) {
1226 if (iter->schema->flags & LYS_KEYLESS) {
1227 lyd_hash(iter);
1228 }
1229 }
1230
1231 node->parent = NULL;
1232 }
1233
1234 node->next = NULL;
1235 node->prev = node;
1236}
1237
Michal Vasko90932a92020-02-12 14:33:03 +01001238LY_ERR
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001239lyd_create_attr(struct lyd_node *parent, struct lyd_attr **attr, const struct lys_module *mod, const char *name,
1240 size_t name_len, const char *value, size_t value_len, int *dynamic, ly_clb_resolve_prefix get_prefix,
Michal Vasko8d544252020-03-02 10:19:52 +01001241 void *prefix_data, LYD_FORMAT format, const struct lysc_node *ctx_snode)
Michal Vasko90932a92020-02-12 14:33:03 +01001242{
1243 LY_ERR ret;
1244 struct lysc_ext_instance *ant = NULL;
1245 struct lyd_attr *at, *last;
1246 uint32_t v;
1247
Michal Vasko8d544252020-03-02 10:19:52 +01001248 assert((parent || attr) && mod);
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001249
Michal Vasko90932a92020-02-12 14:33:03 +01001250 LY_ARRAY_FOR(mod->compiled->exts, v) {
1251 if (mod->compiled->exts[v].def->plugin == lyext_plugins_internal[LYEXT_PLUGIN_INTERNAL_ANNOTATION].plugin &&
1252 !ly_strncmp(mod->compiled->exts[v].argument, name, name_len)) {
1253 /* we have the annotation definition */
1254 ant = &mod->compiled->exts[v];
1255 break;
1256 }
1257 }
1258 if (!ant) {
1259 /* attribute is not defined as a metadata annotation (RFC 7952) */
1260 LOGERR(mod->ctx, LY_EINVAL, "Annotation definition for attribute \"%s:%.*s\" not found.",
1261 mod->name, name_len, name);
1262 return LY_EINVAL;
1263 }
1264
1265 at = calloc(1, sizeof *at);
1266 LY_CHECK_ERR_RET(!at, LOGMEM(mod->ctx), LY_EMEM);
1267 at->parent = parent;
1268 at->annotation = ant;
Michal Vasko8d544252020-03-02 10:19:52 +01001269 ret = lyd_value_parse_attr(mod->ctx, at, value, value_len, dynamic, 0, get_prefix, prefix_data, format, ctx_snode, NULL);
Michal Vasko90932a92020-02-12 14:33:03 +01001270 if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
1271 free(at);
1272 return ret;
1273 }
1274 at->name = lydict_insert(mod->ctx, name, name_len);
1275
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001276 /* insert as the last attribute */
1277 if (parent) {
1278 if (parent->attr) {
1279 for (last = parent->attr; last->next; last = last->next);
1280 last->next = at;
1281 } else {
1282 parent->attr = at;
1283 }
1284 } else if (*attr) {
1285 for (last = *attr; last->next; last = last->next);
Michal Vasko90932a92020-02-12 14:33:03 +01001286 last->next = at;
Michal Vasko90932a92020-02-12 14:33:03 +01001287 }
1288
1289 /* remove default flags from NP containers */
1290 while (parent && (parent->flags & LYD_DEFAULT)) {
1291 parent->flags &= ~LYD_DEFAULT;
1292 parent = (struct lyd_node *)parent->parent;
1293 }
1294
1295 if (attr) {
1296 *attr = at;
1297 }
1298 return ret;
1299}
1300
Radek Krejci084289f2019-07-09 17:35:30 +02001301API const struct lyd_node_term *
Michal Vaskof03ed032020-03-04 13:31:44 +01001302lyd_target(struct lyd_value_path *path, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +02001303{
Michal Vaskof03ed032020-03-04 13:31:44 +01001304 unsigned int u, x;
Michal Vaskoe444f752020-02-10 12:20:06 +01001305 const struct lyd_node *parent = NULL, *start_search;
1306 struct lyd_node *node = NULL;
Radek Krejci084289f2019-07-09 17:35:30 +02001307 uint64_t pos = 1;
1308
Michal Vaskof03ed032020-03-04 13:31:44 +01001309 LY_CHECK_ARG_RET(NULL, path, tree, NULL);
Radek Krejci084289f2019-07-09 17:35:30 +02001310
1311 LY_ARRAY_FOR(path, u) {
1312 if (parent) {
1313 start_search = lyd_node_children(parent);
1314search_inner:
Michal Vaskoe444f752020-02-10 12:20:06 +01001315 lyd_find_sibling_next(start_search, path[u].node->module, path[u].node->name, 0, NULL, 0, &node);
Radek Krejci084289f2019-07-09 17:35:30 +02001316 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +01001317 start_search = tree;
Radek Krejci084289f2019-07-09 17:35:30 +02001318search_toplevel:
Michal Vaskof03ed032020-03-04 13:31:44 +01001319 /* WARNING! to use search_toplevel label correctly, variable v must be preserved and not changed! */
1320 lyd_find_sibling_next(start_search, path[u].node->module, path[u].node->name, 0, NULL, 0, &node);
Radek Krejci084289f2019-07-09 17:35:30 +02001321 }
1322 if (!node) {
1323 return NULL;
1324 }
1325
1326 /* check predicate if any */
1327 LY_ARRAY_FOR(path[u].predicates, x) {
1328 if (path[u].predicates[x].type == 0) {
1329 /* position predicate */
1330 if (pos != path[u].predicates[x].position) {
1331 pos++;
1332 goto search_repeat;
1333 }
1334 /* done, no more predicates are allowed here */
1335 break;
1336 } else if (path[u].predicates[x].type == 1) {
1337 /* key-predicate */
1338 struct lysc_type *type = ((struct lysc_node_leaf*)path[u].predicates[x].key)->type;
Michal Vaskoe444f752020-02-10 12:20:06 +01001339 struct lyd_node *key;
1340 lyd_find_sibling_next(lyd_node_children(node), path[u].predicates[x].key->module,
1341 path[u].predicates[x].key->name, 0, NULL, 0, &key);
Radek Krejci084289f2019-07-09 17:35:30 +02001342 if (!key) {
1343 /* probably error and we shouldn't be here due to previous checks when creating path */
1344 goto search_repeat;
1345 }
1346 if (type->plugin->compare(&((struct lyd_node_term*)key)->value, path[u].predicates[x].value)) {
1347 goto search_repeat;
1348 }
1349 } else if (path[u].predicates[x].type == 2) {
1350 /* leaf-list-predicate */
1351 struct lysc_type *type = ((struct lysc_node_leaf*)path[u].node)->type;
1352 if (type->plugin->compare(&((struct lyd_node_term*)node)->value, path[u].predicates[x].value)) {
1353 goto search_repeat;
1354 }
1355 } else {
1356 LOGINT(NULL);
1357 }
1358 }
1359
1360 parent = node;
1361 }
1362
1363 return (const struct lyd_node_term*)node;
1364
1365search_repeat:
1366 start_search = node->next;
1367 if (parent) {
1368 goto search_inner;
1369 } else {
1370 goto search_toplevel;
1371 }
1372}
1373
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001374API LY_ERR
1375lyd_compare(const struct lyd_node *node1, const struct lyd_node *node2, int options)
1376{
1377 const struct lyd_node *iter1, *iter2;
1378 struct lyd_node_term *term1, *term2;
1379 struct lyd_node_any *any1, *any2;
1380 struct lysc_type *type;
1381 size_t len1, len2;
Radek Krejci084289f2019-07-09 17:35:30 +02001382
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001383 if (!node1 || !node2) {
1384 if (node1 == node2) {
1385 return LY_SUCCESS;
1386 } else {
1387 return LY_ENOT;
1388 }
1389 }
1390
Michal Vasko14654712020-02-06 08:35:21 +01001391 if (node1->schema->module->ctx != node2->schema->module->ctx || node1->schema != node2->schema) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001392 return LY_ENOT;
1393 }
1394
1395 if (node1->hash != node2->hash) {
1396 return LY_ENOT;
1397 }
1398
1399 /* equal hashes do not mean equal nodes, they can be just in collision so the nodes must be checked explicitly */
1400
1401 switch (node1->schema->nodetype) {
1402 case LYS_LEAF:
1403 case LYS_LEAFLIST:
1404 if (options & LYD_COMPARE_DEFAULTS) {
1405 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
1406 return LY_ENOT;
1407 }
1408 }
1409
1410 term1 = (struct lyd_node_term*)node1;
1411 term2 = (struct lyd_node_term*)node2;
1412 type = ((struct lysc_node_leaf*)node1->schema)->type;
1413
1414 return type->plugin->compare(&term1->value, &term2->value);
1415 case LYS_CONTAINER:
1416 if (options & LYD_COMPARE_DEFAULTS) {
1417 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
1418 return LY_ENOT;
1419 }
1420 }
1421 if (options & LYD_COMPARE_FULL_RECURSION) {
1422 iter1 = ((struct lyd_node_inner*)node1)->child;
1423 iter2 = ((struct lyd_node_inner*)node2)->child;
1424 goto all_children_compare;
1425 }
1426 return LY_SUCCESS;
1427 case LYS_ACTION:
1428 if (options & LYD_COMPARE_FULL_RECURSION) {
1429 /* TODO action/RPC
1430 goto all_children_compare;
1431 */
1432 }
1433 return LY_SUCCESS;
1434 case LYS_NOTIF:
1435 if (options & LYD_COMPARE_FULL_RECURSION) {
1436 /* TODO Notification
1437 goto all_children_compare;
1438 */
1439 }
1440 return LY_SUCCESS;
1441 case LYS_LIST:
1442 iter1 = ((struct lyd_node_inner*)node1)->child;
1443 iter2 = ((struct lyd_node_inner*)node2)->child;
1444
Radek Krejci0fe9b512019-07-26 17:51:05 +02001445 if (!(node1->schema->flags & LYS_KEYLESS) && !(options & LYD_COMPARE_FULL_RECURSION)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001446 /* lists with keys, their equivalence is based on their keys */
Radek Krejci0fe9b512019-07-26 17:51:05 +02001447 for (struct lysc_node *key = ((struct lysc_node_list*)node1->schema)->child;
1448 key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
1449 key = key->next) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001450 if (lyd_compare(iter1, iter2, options)) {
1451 return LY_ENOT;
1452 }
1453 iter1 = iter1->next;
1454 iter2 = iter2->next;
1455 }
1456 } else {
1457 /* lists without keys, their equivalence is based on equivalence of all the children (both direct and indirect) */
1458
1459all_children_compare:
1460 if (!iter1 && !iter2) {
1461 /* no children, nothing to compare */
1462 return LY_SUCCESS;
1463 }
1464
1465 for (; iter1 && iter2; iter1 = iter1->next, iter2 = iter2->next) {
1466 if (lyd_compare(iter1, iter2, options | LYD_COMPARE_FULL_RECURSION)) {
1467 return LY_ENOT;
1468 }
1469 }
1470 if (iter1 || iter2) {
1471 return LY_ENOT;
1472 }
1473 }
1474 return LY_SUCCESS;
1475 case LYS_ANYXML:
1476 case LYS_ANYDATA:
1477 any1 = (struct lyd_node_any*)node1;
1478 any2 = (struct lyd_node_any*)node2;
1479
1480 if (any1->value_type != any2->value_type) {
1481 return LY_ENOT;
1482 }
1483 switch (any1->value_type) {
1484 case LYD_ANYDATA_DATATREE:
1485 iter1 = any1->value.tree;
1486 iter2 = any2->value.tree;
1487 goto all_children_compare;
1488 case LYD_ANYDATA_STRING:
1489 case LYD_ANYDATA_XML:
1490 case LYD_ANYDATA_JSON:
1491 len1 = strlen(any1->value.str);
1492 len2 = strlen(any2->value.str);
1493 if (len1 != len2 || strcmp(any1->value.str, any2->value.str)) {
1494 return LY_ENOT;
1495 }
1496 return LY_SUCCESS;
1497#if 0 /* TODO LYB format */
1498 case LYD_ANYDATA_LYB:
1499 int len1 = lyd_lyb_data_length(any1->value.mem);
1500 int len2 = lyd_lyb_data_length(any2->value.mem);
1501 if (len1 != len2 || memcmp(any1->value.mem, any2->value.mem, len1)) {
1502 return LY_ENOT;
1503 }
1504 return LY_SUCCESS;
1505#endif
1506 }
1507 }
1508
1509 LOGINT(node1->schema->module->ctx);
1510 return LY_EINT;
1511}
Radek Krejci22ebdba2019-07-25 13:59:43 +02001512
1513/**
1514 * @brief Duplicates just a single node and interconnect it into a @p parent (if present) and after the @p prev
1515 * sibling (if present).
1516 *
1517 * Ignores LYD_DUP_WITH_PARENTS and LYD_DUP_WITH_SIBLINGS which are supposed to be handled by lyd_dup().
1518 */
1519static struct lyd_node *
1520lyd_dup_recursive(const struct lyd_node *node, struct lyd_node_inner *parent, struct lyd_node *prev, int options)
1521{
1522 struct ly_ctx *ctx;
1523 struct lyd_node *dup = NULL;
1524
1525 LY_CHECK_ARG_RET(NULL, node, NULL);
1526 ctx = node->schema->module->ctx;
1527
1528 switch (node->schema->nodetype) {
1529 case LYS_ACTION:
1530 case LYS_NOTIF:
1531 case LYS_CONTAINER:
1532 case LYS_LIST:
1533 dup = calloc(1, sizeof(struct lyd_node_inner));
1534 break;
1535 case LYS_LEAF:
1536 case LYS_LEAFLIST:
1537 dup = calloc(1, sizeof(struct lyd_node_term));
1538 break;
1539 case LYS_ANYDATA:
1540 case LYS_ANYXML:
1541 dup = calloc(1, sizeof(struct lyd_node_any));
1542 break;
1543 default:
1544 LOGINT(ctx);
1545 goto error;
1546 }
1547
1548 /* TODO implement LYD_DUP_WITH_WHEN */
1549 dup->flags = node->flags;
1550 dup->schema = node->schema;
1551
1552 /* interconnect the node at the end */
1553 dup->parent = parent;
1554 if (prev) {
1555 dup->prev = prev;
1556 prev->next = dup;
1557 } else {
1558 dup->prev = dup;
1559 if (parent) {
1560 parent->child = dup;
1561 }
1562 }
1563 if (parent) {
1564 parent->child->prev = dup;
1565 } else if (prev) {
1566 struct lyd_node *first;
1567 for (first = prev; first->prev != prev; first = first->prev);
1568 first->prev = dup;
1569 }
1570
1571 /* TODO duplicate attributes, implement LYD_DUP_NO_ATTR */
1572
1573 /* nodetype-specific work */
1574 if (dup->schema->nodetype & LYD_NODE_TERM) {
1575 struct lyd_node_term *term = (struct lyd_node_term*)dup;
1576 struct lyd_node_term *orig = (struct lyd_node_term*)node;
1577
1578 term->hash = orig->hash;
1579 term->value.realtype = orig->value.realtype;
1580 LY_CHECK_ERR_GOTO(term->value.realtype->plugin->duplicate(ctx, &orig->value, &term->value),
1581 LOGERR(ctx, LY_EINT, "Value duplication failed."), error);
1582 } else if (dup->schema->nodetype & LYD_NODE_INNER) {
1583 struct lyd_node_inner *inner = (struct lyd_node_inner*)dup;
1584 struct lyd_node_inner *orig = (struct lyd_node_inner*)node;
1585 struct lyd_node *child, *last = NULL;
1586
1587 if (options & LYD_DUP_RECURSIVE) {
1588 /* duplicate all the children */
1589 LY_LIST_FOR(orig->child, child) {
1590 last = lyd_dup_recursive(child, inner, last, options);
1591 LY_CHECK_GOTO(!last, error);
1592 }
Radek Krejci0fe9b512019-07-26 17:51:05 +02001593 } else if (dup->schema->nodetype == LYS_LIST && !(dup->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001594 /* always duplicate keys of a list */
Radek Krejci22ebdba2019-07-25 13:59:43 +02001595 child = orig->child;
Radek Krejci0fe9b512019-07-26 17:51:05 +02001596 for (struct lysc_node *key = ((struct lysc_node_list*)dup->schema)->child;
1597 key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
1598 key = key->next) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001599 if (!child) {
1600 /* possibly not keys are present in filtered tree */
1601 break;
Radek Krejci0fe9b512019-07-26 17:51:05 +02001602 } else if (child->schema != key) {
1603 /* possibly not all keys are present in filtered tree,
1604 * but there can be also some non-key nodes */
1605 continue;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001606 }
1607 last = lyd_dup_recursive(child, inner, last, options);
1608 child = child->next;
1609 }
1610 }
1611 lyd_hash(dup);
1612 } else if (dup->schema->nodetype & LYD_NODE_ANY) {
1613 struct lyd_node_any *any = (struct lyd_node_any*)dup;
1614 struct lyd_node_any *orig = (struct lyd_node_any*)node;
1615
1616 any->hash = orig->hash;
1617 any->value_type = orig->value_type;
1618 switch (any->value_type) {
1619 case LYD_ANYDATA_DATATREE:
1620 if (orig->value.tree) {
1621 any->value.tree = lyd_dup(orig->value.tree, NULL, LYD_DUP_RECURSIVE | LYD_DUP_WITH_SIBLINGS);
1622 LY_CHECK_GOTO(!any->value.tree, error);
1623 }
1624 break;
1625 case LYD_ANYDATA_STRING:
1626 case LYD_ANYDATA_XML:
1627 case LYD_ANYDATA_JSON:
1628 if (orig->value.str) {
1629 any->value.str = lydict_insert(ctx, orig->value.str, strlen(orig->value.str));
1630 }
1631 break;
1632 }
1633 }
1634
1635 lyd_insert_hash(dup);
1636 return dup;
1637
1638error:
1639 if (!parent && !prev) {
1640 lyd_free_tree(dup);
1641 }
1642 return NULL;
1643}
1644
1645API struct lyd_node *
1646lyd_dup(const struct lyd_node *node, struct lyd_node_inner *parent, int options)
1647{
1648 struct ly_ctx *ctx;
1649 const struct lyd_node *orig; /* original node to be duplicated */
1650 struct lyd_node *first = NULL; /* the first duplicated node, this is returned */
1651 struct lyd_node *last = NULL; /* the last sibling of the duplicated nodes */
1652 struct lyd_node *top = NULL; /* the most higher created node */
1653 struct lyd_node_inner *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
1654 int keyless_parent_list = 0;
1655
1656 LY_CHECK_ARG_RET(NULL, node, NULL);
1657 ctx = node->schema->module->ctx;
1658
1659 if (options & LYD_DUP_WITH_PARENTS) {
1660 struct lyd_node_inner *orig_parent, *iter;
1661 int repeat = 1;
1662 for (top = NULL, orig_parent = node->parent; repeat && orig_parent; orig_parent = orig_parent->parent) {
1663 if (parent && parent->schema == orig_parent->schema) {
1664 /* stop creating parents, connect what we have into the provided parent */
1665 iter = parent;
1666 repeat = 0;
1667 /* get know if there is a keyless list which we will have to rehash */
1668 for (struct lyd_node_inner *piter = parent; piter; piter = piter->parent) {
Radek Krejci0fe9b512019-07-26 17:51:05 +02001669 if (piter->schema->nodetype == LYS_LIST && (piter->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001670 keyless_parent_list = 1;
1671 break;
1672 }
1673 }
1674 } else {
1675 iter = (struct lyd_node_inner*)lyd_dup_recursive((struct lyd_node*)orig_parent, NULL, NULL, 0);
1676 LY_CHECK_GOTO(!iter, error);
1677 }
1678 if (!local_parent) {
1679 local_parent = iter;
1680 }
1681 if (iter->child) {
1682 /* 1) list - add after keys
1683 * 2) provided parent with some children */
1684 iter->child->prev->next = top;
1685 if (top) {
1686 top->prev = iter->child->prev;
1687 iter->child->prev = top;
1688 }
1689 } else {
1690 iter->child = top;
1691 if (iter->schema->nodetype == LYS_LIST) {
1692 /* keyless list - we will need to rehash it since we are going to add nodes into it */
1693 keyless_parent_list = 1;
1694 }
1695 }
1696 if (top) {
1697 top->parent = iter;
1698 }
1699 top = (struct lyd_node*)iter;
1700 }
1701 if (repeat && parent) {
1702 /* given parent and created parents chain actually do not interconnect */
1703 LOGERR(ctx, LY_EINVAL, "Invalid argument parent (%s()) - does not interconnect with the created node's parents chain.", __func__);
1704 goto error;
1705 }
1706 } else {
1707 local_parent = parent;
1708 }
1709
1710 if (local_parent && local_parent->child) {
1711 last = local_parent->child->prev;
1712 }
1713
1714 LY_LIST_FOR(node, orig) {
1715 last = lyd_dup_recursive(orig, local_parent, last, options);
1716 LY_CHECK_GOTO(!last, error);
1717 if (!first) {
1718 first = last;
1719 }
1720
1721 if (!(options & LYD_DUP_WITH_SIBLINGS)) {
1722 break;
1723 }
1724 }
1725 if (keyless_parent_list) {
1726 /* rehash */
1727 for (; local_parent; local_parent = local_parent->parent) {
Radek Krejci0fe9b512019-07-26 17:51:05 +02001728 if (local_parent->schema->nodetype == LYS_LIST && (local_parent->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001729 lyd_hash((struct lyd_node*)local_parent);
1730 }
1731 }
1732 }
1733 return first;
1734
1735error:
1736 if (top) {
1737 lyd_free_tree(top);
1738 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +01001739 lyd_free_siblings(first);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001740 }
1741 return NULL;
1742}
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001743
1744static LY_ERR
1745lyd_path_str_enlarge(char **buffer, size_t *buflen, size_t reqlen, int is_static)
1746{
Michal Vasko14654712020-02-06 08:35:21 +01001747 /* ending \0 */
1748 ++reqlen;
1749
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001750 if (reqlen > *buflen) {
1751 if (is_static) {
1752 return LY_EINCOMPLETE;
1753 }
1754
1755 *buffer = ly_realloc(*buffer, reqlen * sizeof **buffer);
1756 if (!*buffer) {
1757 return LY_EMEM;
1758 }
1759
1760 *buflen = reqlen;
1761 }
1762
1763 return LY_SUCCESS;
1764}
1765
1766/**
1767 * @brief Append all list key predicates to path.
1768 *
1769 * @param[in] node Node with keys to print.
1770 * @param[in,out] buffer Buffer to print to.
1771 * @param[in,out] buflen Current buffer length.
1772 * @param[in,out] bufused Current number of characters used in @p buffer.
1773 * @param[in] is_static Whether buffer is static or can be reallocated.
1774 * @return LY_ERR
1775 */
1776static LY_ERR
1777lyd_path_list_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
1778{
1779 const struct lyd_node *key;
1780 int dynamic = 0;
1781 size_t len;
1782 const char *val;
1783 char quot;
1784 LY_ERR rc;
1785
Michal Vasko14654712020-02-06 08:35:21 +01001786 for (key = lyd_node_children(node); key && (key->schema->flags & LYS_KEY); key = key->next) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001787 val = lyd_value2str((struct lyd_node_term *)key, &dynamic);
1788 len = 1 + strlen(key->schema->name) + 2 + strlen(val) + 2;
1789 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
1790 if (rc != LY_SUCCESS) {
1791 if (dynamic) {
1792 free((char *)val);
1793 }
1794 return rc;
1795 }
1796
1797 quot = '\'';
1798 if (strchr(val, '\'')) {
1799 quot = '"';
1800 }
1801 *bufused += sprintf(*buffer + *bufused, "[%s=%c%s%c]", key->schema->name, quot, val, quot);
1802
1803 if (dynamic) {
1804 free((char *)val);
1805 }
1806 }
1807
1808 return LY_SUCCESS;
1809}
1810
1811/**
1812 * @brief Append leaf-list value predicate to path.
1813 *
1814 * @param[in] node Node to print.
1815 * @param[in,out] buffer Buffer to print to.
1816 * @param[in,out] buflen Current buffer length.
1817 * @param[in,out] bufused Current number of characters used in @p buffer.
1818 * @param[in] is_static Whether buffer is static or can be reallocated.
1819 * @return LY_ERR
1820 */
1821static LY_ERR
1822lyd_path_leaflist_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
1823{
1824 int dynamic = 0;
1825 size_t len;
1826 const char *val;
1827 char quot;
1828 LY_ERR rc;
1829
1830 val = lyd_value2str((struct lyd_node_term *)node, &dynamic);
1831 len = 4 + strlen(val) + 2;
1832 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
1833 if (rc != LY_SUCCESS) {
1834 goto cleanup;
1835 }
1836
1837 quot = '\'';
1838 if (strchr(val, '\'')) {
1839 quot = '"';
1840 }
1841 *bufused += sprintf(*buffer + *bufused, "[.=%c%s%c]", quot, val, quot);
1842
1843cleanup:
1844 if (dynamic) {
1845 free((char *)val);
1846 }
1847 return rc;
1848}
1849
1850/**
1851 * @brief Append node position (relative to its other instances) predicate to path.
1852 *
1853 * @param[in] node Node to print.
1854 * @param[in,out] buffer Buffer to print to.
1855 * @param[in,out] buflen Current buffer length.
1856 * @param[in,out] bufused Current number of characters used in @p buffer.
1857 * @param[in] is_static Whether buffer is static or can be reallocated.
1858 * @return LY_ERR
1859 */
1860static LY_ERR
1861lyd_path_position_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
1862{
1863 const struct lyd_node *first, *iter;
1864 size_t len;
1865 int pos;
1866 char *val = NULL;
1867 LY_ERR rc;
1868
1869 if (node->parent) {
1870 first = node->parent->child;
1871 } else {
1872 for (first = node; node->prev->next; node = node->prev);
1873 }
1874 pos = 1;
1875 for (iter = first; iter != node; iter = iter->next) {
1876 if (iter->schema == node->schema) {
1877 ++pos;
1878 }
1879 }
1880 if (asprintf(&val, "%d", pos) == -1) {
1881 return LY_EMEM;
1882 }
1883
1884 len = 1 + strlen(val) + 1;
1885 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
1886 if (rc != LY_SUCCESS) {
1887 goto cleanup;
1888 }
1889
1890 *bufused += sprintf(*buffer + *bufused, "[%s]", val);
1891
1892cleanup:
1893 free(val);
1894 return rc;
1895}
1896
1897API char *
1898lyd_path(const struct lyd_node *node, LYD_PATH_TYPE pathtype, char *buffer, size_t buflen)
1899{
Michal Vasko14654712020-02-06 08:35:21 +01001900 int is_static = 0, i, depth;
1901 size_t bufused = 0, len;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001902 const struct lyd_node *iter;
1903 const struct lys_module *mod;
1904 LY_ERR rc;
1905
1906 LY_CHECK_ARG_RET(NULL, node, NULL);
1907 if (buffer) {
1908 LY_CHECK_ARG_RET(node->schema->module->ctx, buflen > 1, NULL);
1909 is_static = 1;
Michal Vasko14654712020-02-06 08:35:21 +01001910 } else {
1911 buflen = 0;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001912 }
1913
1914 switch (pathtype) {
Michal Vasko14654712020-02-06 08:35:21 +01001915 case LYD_PATH_LOG:
1916 depth = 1;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001917 for (iter = node; iter->parent; iter = (const struct lyd_node *)iter->parent) {
1918 ++depth;
1919 }
1920
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001921 goto iter_print;
Michal Vasko14654712020-02-06 08:35:21 +01001922 while (depth) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001923 /* find the right node */
Michal Vasko14654712020-02-06 08:35:21 +01001924 for (iter = node, i = 1; i < depth; iter = (const struct lyd_node *)iter->parent, ++i);
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001925iter_print:
1926 /* print prefix and name */
1927 mod = NULL;
1928 if (!iter->parent || (iter->schema->module != iter->parent->schema->module)) {
1929 mod = iter->schema->module;
1930 }
1931
1932 /* realloc string */
1933 len = 1 + (mod ? strlen(mod->name) + 1 : 0) + strlen(iter->schema->name);
1934 rc = lyd_path_str_enlarge(&buffer, &buflen, bufused + len, is_static);
1935 if (rc != LY_SUCCESS) {
1936 break;
1937 }
1938
1939 /* print next node */
1940 bufused += sprintf(buffer + bufused, "/%s%s%s", mod ? mod->name : "", mod ? ":" : "", iter->schema->name);
1941
1942 switch (iter->schema->nodetype) {
1943 case LYS_LIST:
1944 if (iter->schema->flags & LYS_KEYLESS) {
1945 /* print its position */
1946 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
1947 } else {
1948 /* print all list keys in predicates */
1949 rc = lyd_path_list_predicate(iter, &buffer, &buflen, &bufused, is_static);
1950 }
1951 break;
1952 case LYS_LEAFLIST:
1953 if (iter->schema->flags & LYS_CONFIG_W) {
1954 /* print leaf-list value */
1955 rc = lyd_path_leaflist_predicate(iter, &buffer, &buflen, &bufused, is_static);
1956 } else {
1957 /* print its position */
1958 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
1959 }
1960 break;
1961 default:
1962 /* nothing to print more */
1963 rc = LY_SUCCESS;
1964 break;
1965 }
1966 if (rc != LY_SUCCESS) {
1967 break;
1968 }
1969
Michal Vasko14654712020-02-06 08:35:21 +01001970 --depth;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001971 }
1972 break;
1973 }
1974
1975 return buffer;
1976}
Michal Vaskoe444f752020-02-10 12:20:06 +01001977
Michal Vasko9b368d32020-02-14 13:53:31 +01001978LY_ERR
1979lyd_find_sibling_next2(const struct lyd_node *first, const struct lysc_node *schema, const char *key_or_value,
1980 size_t val_len, struct lyd_node **match)
Michal Vaskoe444f752020-02-10 12:20:06 +01001981{
1982 LY_ERR rc;
1983 const struct lyd_node *node = NULL;
1984 struct lyd_node_term *term;
Michal Vaskoe444f752020-02-10 12:20:06 +01001985 struct ly_keys keys = {0};
Michal Vasko90932a92020-02-12 14:33:03 +01001986 struct lyd_value val = {0};
Michal Vaskoe444f752020-02-10 12:20:06 +01001987 size_t i;
Michal Vaskoe444f752020-02-10 12:20:06 +01001988
Michal Vasko9b368d32020-02-14 13:53:31 +01001989 LY_CHECK_ARG_RET(NULL, schema, LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01001990
1991 if (!first) {
1992 /* no data */
Michal Vasko9b368d32020-02-14 13:53:31 +01001993 if (match) {
1994 *match = NULL;
1995 }
Michal Vaskoe444f752020-02-10 12:20:06 +01001996 return LY_ENOTFOUND;
1997 }
1998
Michal Vaskoe444f752020-02-10 12:20:06 +01001999 if (key_or_value && !val_len) {
2000 val_len = strlen(key_or_value);
2001 }
2002
2003 if (key_or_value && (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko90932a92020-02-12 14:33:03 +01002004 /* store the value */
Michal Vasko9b368d32020-02-14 13:53:31 +01002005 LY_CHECK_GOTO(rc = lyd_value_store(&val, schema, key_or_value, val_len, 0, lydjson_resolve_prefix, NULL, LYD_JSON), cleanup);
Michal Vaskoe444f752020-02-10 12:20:06 +01002006 } else if (key_or_value && (schema->nodetype == LYS_LIST)) {
2007 /* parse keys into canonical values */
2008 LY_CHECK_GOTO(rc = ly_keys_parse(schema, key_or_value, val_len, 1, &keys), cleanup);
2009 }
2010
2011 /* find first matching value */
2012 LY_LIST_FOR(first, node) {
2013 if (node->schema != schema) {
2014 continue;
2015 }
2016
2017 if ((schema->nodetype == LYS_LIST) && keys.str) {
2018 /* compare all set keys */
2019 for (i = 0; i < keys.key_count; ++i) {
2020 /* find key */
2021 rc = lyd_find_sibling_val(lyd_node_children(node), (struct lysc_node *)keys.keys[i].schema, NULL, 0,
2022 (struct lyd_node **)&term);
2023 if (rc == LY_ENOTFOUND) {
2024 /* all keys must always exist */
Michal Vasko9b368d32020-02-14 13:53:31 +01002025 LOGINT_RET(schema->module->ctx);
Michal Vaskoe444f752020-02-10 12:20:06 +01002026 }
2027 LY_CHECK_GOTO(rc, cleanup);
2028
2029 /* compare values */
Michal Vasko90932a92020-02-12 14:33:03 +01002030 if (!term->value.realtype->plugin->compare(&term->value, &keys.keys[i].val)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002031 break;
2032 }
2033 }
2034
2035 if (i < keys.key_count) {
2036 /* not a match */
2037 continue;
2038 }
Michal Vasko90932a92020-02-12 14:33:03 +01002039 } else if ((schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && val.realtype) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002040 term = (struct lyd_node_term *)node;
2041
2042 /* compare values */
Michal Vasko90932a92020-02-12 14:33:03 +01002043 if (!term->value.realtype->plugin->compare(&term->value, &val)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002044 /* not a match */
2045 continue;
2046 }
2047 }
2048
2049 /* all criteria passed */
2050 break;
2051 }
2052
2053 if (!node) {
2054 rc = LY_ENOTFOUND;
Michal Vasko9b368d32020-02-14 13:53:31 +01002055 if (match) {
2056 *match = NULL;
2057 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002058 goto cleanup;
2059 }
2060
2061 /* success */
Michal Vasko9b368d32020-02-14 13:53:31 +01002062 if (match) {
2063 *match = (struct lyd_node *)node;
2064 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002065 rc = LY_SUCCESS;
2066
2067cleanup:
2068 ly_keys_clean(&keys);
Michal Vasko90932a92020-02-12 14:33:03 +01002069 if (val.realtype) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002070 val.realtype->plugin->free(schema->module->ctx, &val);
Michal Vasko90932a92020-02-12 14:33:03 +01002071 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002072 return rc;
2073}
2074
2075API LY_ERR
Michal Vasko9b368d32020-02-14 13:53:31 +01002076lyd_find_sibling_next(const struct lyd_node *first, const struct lys_module *module, const char *name, size_t name_len,
2077 const char *key_or_value, size_t val_len, struct lyd_node **match)
2078{
2079 const struct lysc_node *schema;
2080
2081 LY_CHECK_ARG_RET(NULL, module, name, match, LY_EINVAL);
2082
2083 if (!first) {
2084 /* no data */
2085 *match = NULL;
2086 return LY_ENOTFOUND;
2087 }
2088
2089 /* find schema */
2090 schema = lys_find_child(first->parent ? first->parent->schema : NULL, module, name, name_len, 0, 0);
2091 if (!schema) {
2092 LOGERR(module->ctx, LY_EINVAL, "Schema node not found.");
2093 return LY_EINVAL;
2094 }
2095
2096 return lyd_find_sibling_next2(first, schema, key_or_value, val_len, match);
2097}
2098
2099API LY_ERR
Michal Vaskoe444f752020-02-10 12:20:06 +01002100lyd_find_sibling_first(const struct lyd_node *siblings, const struct lyd_node *target, struct lyd_node **match)
2101{
2102 struct lyd_node **match_p;
2103 struct lyd_node_inner *parent;
2104
Michal Vaskof03ed032020-03-04 13:31:44 +01002105 LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01002106
2107 if (!siblings) {
2108 /* no data */
Michal Vasko9b368d32020-02-14 13:53:31 +01002109 if (match) {
2110 *match = NULL;
2111 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002112 return LY_ENOTFOUND;
2113 }
2114
2115 /* find first sibling */
2116 if (siblings->parent) {
2117 siblings = siblings->parent->child;
2118 } else {
2119 while (siblings->prev->next) {
2120 siblings = siblings->prev;
2121 }
2122 }
2123
2124 parent = (struct lyd_node_inner *)siblings->parent;
2125 if (parent && parent->children_ht) {
2126 assert(target->hash);
2127
2128 /* find by hash */
2129 if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
2130 siblings = *match_p;
2131 } else {
2132 /* not found */
2133 siblings = NULL;
2134 }
2135 } else {
2136 /* no children hash table */
2137 for (; siblings; siblings = siblings->next) {
2138 if (!lyd_compare(siblings, target, 0)) {
2139 break;
2140 }
2141 }
2142 }
2143
2144 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002145 if (match) {
2146 *match = NULL;
2147 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002148 return LY_ENOTFOUND;
2149 }
2150
Michal Vasko9b368d32020-02-14 13:53:31 +01002151 if (match) {
2152 *match = (struct lyd_node *)siblings;
2153 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002154 return LY_SUCCESS;
2155}
2156
2157API LY_ERR
2158lyd_find_sibling_set(const struct lyd_node *siblings, const struct lyd_node *target, struct ly_set **set)
2159{
2160 struct lyd_node_inner *parent;
2161 struct lyd_node *match;
2162 struct lyd_node **match_p;
2163 struct ly_set *ret;
2164
2165 LY_CHECK_ARG_RET(NULL, target, set, LY_EINVAL);
2166
2167 if (!siblings) {
2168 /* no data */
2169 return LY_ENOTFOUND;
2170 }
2171
2172 ret = ly_set_new();
2173 LY_CHECK_ERR_RET(!ret, LOGMEM(target->schema->module->ctx), LY_EMEM);
2174
2175 /* find first sibling */
2176 if (siblings->parent) {
2177 siblings = siblings->parent->child;
2178 } else {
2179 while (siblings->prev->next) {
2180 siblings = siblings->prev;
2181 }
2182 }
2183
2184 parent = (struct lyd_node_inner *)siblings->parent;
2185 if (parent && parent->children_ht) {
2186 assert(target->hash);
2187
2188 /* find by hash */
2189 if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
2190 match = *match_p;
2191 } else {
2192 /* not found */
2193 match = NULL;
2194 }
2195 while (match) {
2196 /* add all found nodes into the return set */
2197 if (ly_set_add(ret, match, LY_SET_OPT_USEASLIST) == -1) {
2198 goto error;
2199 }
2200
2201 /* find next instance */
2202 if (lyht_find_next(parent->children_ht, &match, match->hash, (void **)&match_p)) {
2203 match = NULL;
2204 } else {
2205 match = *match_p;
2206 }
2207 }
2208 } else {
2209 /* no children hash table */
2210 for (; siblings; siblings = siblings->next) {
2211 if (!lyd_compare(siblings, target, 0)) {
2212 /* a match */
2213 if (ly_set_add(ret, (struct lyd_node *)siblings, LY_SET_OPT_USEASLIST) == -1) {
2214 goto error;
2215 }
2216 }
2217 }
2218 }
2219
2220 if (!ret->count) {
2221 ly_set_free(ret, NULL);
2222 return LY_ENOTFOUND;
2223 }
2224
2225 *set = ret;
2226 return LY_SUCCESS;
2227
2228error:
2229 ly_set_free(ret, NULL);
2230 return LY_EMEM;
2231}
2232
Michal Vasko90932a92020-02-12 14:33:03 +01002233static int
2234lyd_hash_table_schema_val_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *UNUSED(cb_data))
2235{
2236 struct lysc_node *val1;
2237 struct lyd_node *val2;
2238
2239 val1 = *((struct lysc_node **)val1_p);
2240 val2 = *((struct lyd_node **)val2_p);
2241
2242 assert(val1->nodetype & (LYD_NODE_INNER | LYS_LEAF));
2243
2244 if (val1 == val2->schema) {
2245 /* schema match is enough */
2246 return 1;
2247 } else {
2248 return 0;
2249 }
2250}
2251
2252static LY_ERR
2253lyd_find_sibling_schema(const struct lyd_node *siblings, const struct lysc_node *schema, struct lyd_node **match)
2254{
2255 struct lyd_node **match_p;
2256 struct lyd_node_inner *parent;
2257 uint32_t hash;
2258 values_equal_cb ht_cb;
2259
2260 assert(siblings && schema && (schema->nodetype & (LYD_NODE_INNER | LYS_LEAF)));
2261
2262 /* find first sibling */
2263 if (siblings->parent) {
2264 siblings = siblings->parent->child;
2265 } else {
2266 while (siblings->prev->next) {
2267 siblings = siblings->prev;
2268 }
2269 }
2270
2271 parent = (struct lyd_node_inner *)siblings->parent;
2272 if (parent && parent->children_ht) {
2273 /* calculate our hash */
2274 hash = dict_hash_multi(0, schema->module->name, strlen(schema->module->name));
2275 hash = dict_hash_multi(hash, schema->name, strlen(schema->name));
2276 hash = dict_hash_multi(hash, NULL, 0);
2277
2278 /* use special hash table function */
2279 ht_cb = lyht_set_cb(parent->children_ht, lyd_hash_table_schema_val_equal);
2280
2281 /* find by hash */
2282 if (!lyht_find(parent->children_ht, &schema, hash, (void **)&match_p)) {
2283 siblings = *match_p;
2284 } else {
2285 /* not found */
2286 siblings = NULL;
2287 }
2288
2289 /* set the original hash table compare function back */
2290 lyht_set_cb(parent->children_ht, ht_cb);
2291 } else {
2292 /* no children hash table */
2293 for (; siblings; siblings = siblings->next) {
2294 if (siblings->schema == schema) {
2295 /* schema match is enough */
2296 break;
2297 }
2298 }
2299 }
2300
2301 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002302 if (match) {
2303 *match = NULL;
2304 }
Michal Vasko90932a92020-02-12 14:33:03 +01002305 return LY_ENOTFOUND;
2306 }
2307
Michal Vasko9b368d32020-02-14 13:53:31 +01002308 if (match) {
2309 *match = (struct lyd_node *)siblings;
2310 }
Michal Vasko90932a92020-02-12 14:33:03 +01002311 return LY_SUCCESS;
2312}
2313
Michal Vaskoe444f752020-02-10 12:20:06 +01002314API LY_ERR
2315lyd_find_sibling_val(const struct lyd_node *siblings, const struct lysc_node *schema, const char *key_or_value,
2316 size_t val_len, struct lyd_node **match)
2317{
2318 LY_ERR rc;
2319 struct lyd_node *target = NULL;
2320
2321 LY_CHECK_ARG_RET(NULL, schema, LY_EINVAL);
2322 if ((schema->nodetype == LYS_LIST) && schema->flags & LYS_KEYLESS) {
2323 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - key-less list (%s()).", __func__);
2324 return LY_EINVAL;
2325 } else if ((schema->nodetype & (LYS_LEAFLIST | LYS_LIST)) && !key_or_value) {
2326 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - no value/keys for a (leaf-)list (%s()).", __func__);
2327 return LY_EINVAL;
2328 } else if (schema->nodetype & (LYS_CHOICE | LYS_CASE)) {
2329 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - schema type %s (%s()).",
2330 lys_nodetype2str(schema->nodetype), __func__);
2331 return LY_EINVAL;
2332 }
2333
2334 if (!siblings) {
2335 /* no data */
Michal Vasko9b368d32020-02-14 13:53:31 +01002336 if (match) {
2337 *match = NULL;
2338 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002339 return LY_ENOTFOUND;
2340 }
2341
Michal Vaskof03ed032020-03-04 13:31:44 +01002342 if (key_or_value && !val_len) {
2343 val_len = strlen(key_or_value);
2344 }
2345
Michal Vasko90932a92020-02-12 14:33:03 +01002346 /* create data node if needed and find it */
Michal Vaskoe444f752020-02-10 12:20:06 +01002347 switch (schema->nodetype) {
2348 case LYS_CONTAINER:
2349 case LYS_ANYXML:
2350 case LYS_ANYDATA:
2351 case LYS_NOTIF:
Michal Vasko9b368d32020-02-14 13:53:31 +01002352 case LYS_ACTION:
Michal Vaskoe444f752020-02-10 12:20:06 +01002353 case LYS_LEAF:
Michal Vasko90932a92020-02-12 14:33:03 +01002354 /* find it based on schema only */
2355 rc = lyd_find_sibling_schema(siblings, schema, match);
Michal Vaskoe444f752020-02-10 12:20:06 +01002356 break;
2357 case LYS_LEAFLIST:
2358 /* target used attributes: schema, hash, value */
Michal Vasko90932a92020-02-12 14:33:03 +01002359 LY_CHECK_RET(lyd_create_term(schema, key_or_value, val_len, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &target));
Michal Vasko90932a92020-02-12 14:33:03 +01002360 /* fallthrough */
Michal Vaskoe444f752020-02-10 12:20:06 +01002361 case LYS_LIST:
Michal Vasko90932a92020-02-12 14:33:03 +01002362 if (schema->nodetype == LYS_LIST) {
2363 /* target used attributes: schema, hash, child (all keys) */
2364 LY_CHECK_RET(lyd_create_list(schema, key_or_value, val_len, &target));
Michal Vasko90932a92020-02-12 14:33:03 +01002365 }
2366
2367 /* find it */
2368 rc = lyd_find_sibling_first(siblings, target, match);
Michal Vaskoe444f752020-02-10 12:20:06 +01002369 break;
2370 default:
2371 /* unreachable */
2372 LOGINT(schema->module->ctx);
2373 return LY_EINT;
2374 }
2375
Michal Vaskoe444f752020-02-10 12:20:06 +01002376 lyd_free_tree(target);
2377 return rc;
2378}