blob: d65f56afcdabed09e2fec645b42532c1707c7a49 [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"
Michal Vasko52927e22020-03-16 17:26:14 +010032#include "xml.h"
Radek Krejci38d85362019-09-05 16:26:38 +020033#include "plugins_exts_metadata.h"
Michal Vasko90932a92020-02-12 14:33:03 +010034#include "plugins_exts_internal.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020035
Michal Vaskoe444f752020-02-10 12:20:06 +010036struct ly_keys {
37 char *str;
38 struct {
39 const struct lysc_node_leaf *schema;
40 char *value;
Michal Vasko90932a92020-02-12 14:33:03 +010041 struct lyd_value val;
Michal Vaskoe444f752020-02-10 12:20:06 +010042 } *keys;
43 size_t key_count;
44};
45
Radek Krejci084289f2019-07-09 17:35:30 +020046LY_ERR
Michal Vasko90932a92020-02-12 14:33:03 +010047lyd_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 +010048 ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +020049{
Michal Vasko90932a92020-02-12 14:33:03 +010050 LY_ERR ret = LY_SUCCESS;
Radek Krejci084289f2019-07-09 17:35:30 +020051 struct ly_err_item *err = NULL;
52 struct ly_ctx *ctx;
53 struct lysc_type *type;
Radek Krejci3c9758d2019-07-11 16:49:10 +020054 int options = LY_TYPE_OPTS_STORE | (second ? LY_TYPE_OPTS_SECOND_CALL : 0) |
Michal Vaskof03ed032020-03-04 13:31:44 +010055 (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci084289f2019-07-09 17:35:30 +020056 assert(node);
57
58 ctx = node->schema->module->ctx;
Radek Krejci084289f2019-07-09 17:35:30 +020059
Radek Krejci73dead22019-07-11 16:46:16 +020060 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci62903c32019-07-15 14:42:05 +020061 if (!second) {
62 node->value.realtype = type;
63 }
Michal Vasko90932a92020-02-12 14:33:03 +010064 ret = type->plugin->store(ctx, type, value, value_len, options, get_prefix, parser, format,
Michal Vaskof03ed032020-03-04 13:31:44 +010065 tree ? (void *)node : (void *)node->schema, tree,
Radek Krejci73dead22019-07-11 16:46:16 +020066 &node->value, NULL, &err);
Michal Vasko90932a92020-02-12 14:33:03 +010067 if (ret && (ret != LY_EINCOMPLETE)) {
Radek Krejci73dead22019-07-11 16:46:16 +020068 if (err) {
69 ly_err_print(err);
70 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
71 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +020072 }
Radek Krejci73dead22019-07-11 16:46:16 +020073 goto error;
Michal Vasko90932a92020-02-12 14:33:03 +010074 } else if (dynamic) {
75 *dynamic = 0;
Radek Krejci084289f2019-07-09 17:35:30 +020076 }
77
78error:
79 return ret;
80}
81
Michal Vasko90932a92020-02-12 14:33:03 +010082/* similar to lyd_value_parse except can be used just to store the value, hence does also not support a second call */
83static LY_ERR
84lyd_value_store(struct lyd_value *val, const struct lysc_node *schema, const char *value, size_t value_len, int *dynamic,
85 ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format)
86{
87 LY_ERR ret = LY_SUCCESS;
88 struct ly_err_item *err = NULL;
89 struct ly_ctx *ctx;
90 struct lysc_type *type;
91 int options = LY_TYPE_OPTS_STORE | LY_TYPE_OPTS_INCOMPLETE_DATA | (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0);
92
93 assert(val && schema && (schema->nodetype & LYD_NODE_TERM));
94
95 ctx = schema->module->ctx;
96 type = ((struct lysc_node_leaf *)schema)->type;
97 val->realtype = type;
98 ret = type->plugin->store(ctx, type, value, value_len, options, get_prefix, parser, format, (void *)schema, NULL,
99 val, NULL, &err);
100 if (ret == LY_EINCOMPLETE) {
101 /* this is fine, we do not need it resolved */
102 ret = LY_SUCCESS;
103 } else if (ret && err) {
104 ly_err_print(err);
105 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
106 ly_err_free(err);
107 }
108 if (!ret && dynamic) {
109 *dynamic = 0;
110 }
111
112 return ret;
113}
114
Radek Krejci38d85362019-09-05 16:26:38 +0200115LY_ERR
Michal Vasko9f96a052020-03-10 09:41:45 +0100116lyd_value_parse_meta(struct ly_ctx *ctx, struct lyd_meta *meta, const char *value, size_t value_len, int *dynamic,
Michal Vasko8d544252020-03-02 10:19:52 +0100117 int second, ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format,
Michal Vaskof03ed032020-03-04 13:31:44 +0100118 const struct lysc_node *ctx_snode, const struct lyd_node *tree)
Radek Krejci38d85362019-09-05 16:26:38 +0200119{
Michal Vasko90932a92020-02-12 14:33:03 +0100120 LY_ERR ret = LY_SUCCESS;
Radek Krejci38d85362019-09-05 16:26:38 +0200121 struct ly_err_item *err = NULL;
Radek Krejci38d85362019-09-05 16:26:38 +0200122 struct lyext_metadata *ant;
123 int options = LY_TYPE_OPTS_STORE | (second ? LY_TYPE_OPTS_SECOND_CALL : 0) |
Michal Vaskof03ed032020-03-04 13:31:44 +0100124 (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci38d85362019-09-05 16:26:38 +0200125
Michal Vasko9f96a052020-03-10 09:41:45 +0100126 assert(ctx && meta && ((tree && meta->parent) || ctx_snode));
Michal Vasko8d544252020-03-02 10:19:52 +0100127
Michal Vasko9f96a052020-03-10 09:41:45 +0100128 ant = meta->annotation->data;
Radek Krejci38d85362019-09-05 16:26:38 +0200129
130 if (!second) {
Michal Vasko9f96a052020-03-10 09:41:45 +0100131 meta->value.realtype = ant->type;
Radek Krejci38d85362019-09-05 16:26:38 +0200132 }
Michal Vasko90932a92020-02-12 14:33:03 +0100133 ret = ant->type->plugin->store(ctx, ant->type, value, value_len, options, get_prefix, parser, format,
Michal Vasko9f96a052020-03-10 09:41:45 +0100134 tree ? (void *)meta->parent : (void *)ctx_snode, tree, &meta->value, NULL, &err);
Michal Vasko90932a92020-02-12 14:33:03 +0100135 if (ret && (ret != LY_EINCOMPLETE)) {
Radek Krejci38d85362019-09-05 16:26:38 +0200136 if (err) {
137 ly_err_print(err);
138 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
139 ly_err_free(err);
140 }
141 goto error;
Michal Vasko90932a92020-02-12 14:33:03 +0100142 } else if (dynamic) {
143 *dynamic = 0;
Radek Krejci38d85362019-09-05 16:26:38 +0200144 }
145
146error:
147 return ret;
148}
149
Radek Krejci084289f2019-07-09 17:35:30 +0200150API LY_ERR
Michal Vasko44685da2020-03-17 15:38:06 +0100151lys_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const char *value, size_t value_len,
Radek Krejci084289f2019-07-09 17:35:30 +0200152 ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format)
153{
154 LY_ERR rc = LY_SUCCESS;
155 struct ly_err_item *err = NULL;
156 struct lysc_type *type;
Radek Krejci084289f2019-07-09 17:35:30 +0200157
158 LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
159
160 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
161 LOGARG(ctx, node);
162 return LY_EINVAL;
163 }
164
165 type = ((struct lysc_node_leaf*)node)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200166 /* just validate, no storing of enything */
167 rc = type->plugin->store(ctx ? ctx : node->module->ctx, type, value, value_len, LY_TYPE_OPTS_INCOMPLETE_DATA,
168 get_prefix, get_prefix_data, format, node, NULL, NULL, NULL, &err);
169 if (rc == LY_EINCOMPLETE) {
170 /* actually success since we do not provide the context tree and call validation with
171 * LY_TYPE_OPTS_INCOMPLETE_DATA */
172 rc = LY_SUCCESS;
173 } else if (rc && err) {
174 if (ctx) {
175 /* log only in case the ctx was provided as input parameter */
176 ly_err_print(err);
177 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
Radek Krejci084289f2019-07-09 17:35:30 +0200178 }
Radek Krejci73dead22019-07-11 16:46:16 +0200179 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200180 }
181
182 return rc;
183}
184
185API LY_ERR
Michal Vasko44685da2020-03-17 15:38:06 +0100186lyd_value_validate(const struct ly_ctx *ctx, const struct lyd_node_term *node, const char *value, size_t value_len,
Michal Vaskof03ed032020-03-04 13:31:44 +0100187 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 +0200188{
189 LY_ERR rc;
190 struct ly_err_item *err = NULL;
191 struct lysc_type *type;
Michal Vaskof03ed032020-03-04 13:31:44 +0100192 int options = (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci084289f2019-07-09 17:35:30 +0200193
194 LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
195
196 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200197 rc = type->plugin->store(ctx ? ctx : node->schema->module->ctx, type, value, value_len, options,
Michal Vaskof03ed032020-03-04 13:31:44 +0100198 get_prefix, get_prefix_data, format, tree ? (void*)node : (void*)node->schema, tree,
Radek Krejci73dead22019-07-11 16:46:16 +0200199 NULL, NULL, &err);
200 if (rc == LY_EINCOMPLETE) {
201 return rc;
202 } else if (rc) {
203 if (err) {
204 if (ctx) {
205 ly_err_print(err);
206 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
Radek Krejci084289f2019-07-09 17:35:30 +0200207 }
Radek Krejci73dead22019-07-11 16:46:16 +0200208 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200209 }
Radek Krejci73dead22019-07-11 16:46:16 +0200210 return rc;
Radek Krejci084289f2019-07-09 17:35:30 +0200211 }
212
213 return LY_SUCCESS;
214}
215
216API LY_ERR
217lyd_value_compare(const struct lyd_node_term *node, const char *value, size_t value_len,
Michal Vaskof03ed032020-03-04 13:31:44 +0100218 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 +0200219{
220 LY_ERR ret = LY_SUCCESS, rc;
221 struct ly_err_item *err = NULL;
222 struct ly_ctx *ctx;
223 struct lysc_type *type;
Radek Krejci084289f2019-07-09 17:35:30 +0200224 struct lyd_value data = {0};
Michal Vaskof03ed032020-03-04 13:31:44 +0100225 int options = LY_TYPE_OPTS_STORE | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci084289f2019-07-09 17:35:30 +0200226
227 LY_CHECK_ARG_RET(node ? node->schema->module->ctx : NULL, node, value, LY_EINVAL);
228
229 ctx = node->schema->module->ctx;
230 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200231 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 +0100232 tree, &data, NULL, &err);
Radek Krejci73dead22019-07-11 16:46:16 +0200233 if (rc == LY_EINCOMPLETE) {
234 ret = rc;
235 /* continue with comparing, just remember what to return if storing is ok */
236 } else if (rc) {
237 /* value to compare is invalid */
238 ret = LY_EINVAL;
239 if (err) {
240 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200241 }
Radek Krejci73dead22019-07-11 16:46:16 +0200242 goto cleanup;
Radek Krejci084289f2019-07-09 17:35:30 +0200243 }
244
245 /* compare data */
Radek Krejci5af04842019-07-12 11:32:07 +0200246 if (type->plugin->compare(&node->value, &data)) {
247 /* do not assign it directly from the compare callback to keep possible LY_EINCOMPLETE from validation */
248 ret = LY_EVALID;
249 }
Radek Krejci084289f2019-07-09 17:35:30 +0200250
251cleanup:
Radek Krejci62903c32019-07-15 14:42:05 +0200252 type->plugin->free(ctx, &data);
Radek Krejci084289f2019-07-09 17:35:30 +0200253
254 return ret;
255}
256
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200257API const char *
258lyd_value2str(const struct lyd_node_term *node, int *dynamic)
259{
260 LY_CHECK_ARG_RET(node ? node->schema->module->ctx : NULL, node, dynamic, NULL);
261
262 return node->value.realtype->plugin->print(&node->value, LYD_JSON, json_print_get_prefix, NULL, dynamic);
263}
264
265API const char *
Michal Vasko9f96a052020-03-10 09:41:45 +0100266lyd_meta2str(const struct lyd_meta *meta, int *dynamic)
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200267{
Michal Vasko9f96a052020-03-10 09:41:45 +0100268 LY_CHECK_ARG_RET(meta ? meta->parent->schema->module->ctx : NULL, meta, dynamic, NULL);
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200269
Michal Vasko9f96a052020-03-10 09:41:45 +0100270 return meta->value.realtype->plugin->print(&meta->value, LYD_JSON, json_print_get_prefix, NULL, dynamic);
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200271}
272
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200273API struct lyd_node *
Michal Vaskoa3881362020-01-21 15:57:35 +0100274lyd_parse_mem(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
Radek Krejcie7b95092019-05-15 11:03:07 +0200275{
Radek Krejcie7b95092019-05-15 11:03:07 +0200276 struct lyd_node *result = NULL;
Radek Krejcie92210c2019-05-17 15:53:35 +0200277#if 0
Radek Krejcie7b95092019-05-15 11:03:07 +0200278 const char *yang_data_name = NULL;
Radek Krejcie92210c2019-05-17 15:53:35 +0200279#endif
Radek Krejcie7b95092019-05-15 11:03:07 +0200280
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200281 LY_CHECK_ARG_RET(ctx, ctx, NULL);
282
Michal Vasko5b37a352020-03-06 13:38:33 +0100283 if ((options & LYD_OPT_PARSE_ONLY) && (options & LYD_VALOPT_MASK)) {
284 LOGERR(ctx, LY_EINVAL, "Passing validation flags with LYD_OPT_PARSE_ONLY is not allowed.");
285 return NULL;
286 }
287
Michal Vaskoa3881362020-01-21 15:57:35 +0100288#if 0
Radek Krejcie7b95092019-05-15 11:03:07 +0200289 if (options & LYD_OPT_RPCREPLY) {
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200290 /* first item in trees is mandatory - the RPC/action request */
291 LY_CHECK_ARG_RET(ctx, trees, LY_ARRAY_SIZE(trees) >= 1, NULL);
292 if (!trees[0] || trees[0]->parent || !(trees[0]->schema->nodetype & (LYS_ACTION | LYS_LIST | LYS_CONTAINER))) {
293 LOGERR(ctx, LY_EINVAL, "Data parser invalid argument trees - the first item in the array must be the RPC/action request when parsing %s.",
294 lyd_parse_options_type2str(options));
Radek Krejcie7b95092019-05-15 11:03:07 +0200295 return NULL;
296 }
297 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200298
Radek Krejcie7b95092019-05-15 11:03:07 +0200299 if (options & LYD_OPT_DATA_TEMPLATE) {
300 yang_data_name = va_arg(ap, const char *);
301 }
Radek Krejcie92210c2019-05-17 15:53:35 +0200302#endif
Radek Krejcie7b95092019-05-15 11:03:07 +0200303
304 if (!format) {
305 /* TODO try to detect format from the content */
306 }
307
308 switch (format) {
309 case LYD_XML:
Michal Vasko9f96a052020-03-10 09:41:45 +0100310 lyd_parse_xml_data(ctx, data, options, &result);
Radek Krejcie7b95092019-05-15 11:03:07 +0200311 break;
312#if 0
313 case LYD_JSON:
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200314 lyd_parse_json(ctx, data, options, trees, &result);
Radek Krejcie7b95092019-05-15 11:03:07 +0200315 break;
316 case LYD_LYB:
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200317 lyd_parse_lyb(ctx, data, options, trees, &result);
Radek Krejcie7b95092019-05-15 11:03:07 +0200318 break;
319#endif
Michal Vasko52927e22020-03-16 17:26:14 +0100320 case LYD_SCHEMA:
Radek Krejcie7b95092019-05-15 11:03:07 +0200321 LOGINT(ctx);
322 break;
323 }
324
Radek Krejcie7b95092019-05-15 11:03:07 +0200325 return result;
326}
327
328API struct lyd_node *
Michal Vaskoa3881362020-01-21 15:57:35 +0100329lyd_parse_fd(struct ly_ctx *ctx, int fd, LYD_FORMAT format, int options)
Radek Krejcie7b95092019-05-15 11:03:07 +0200330{
331 struct lyd_node *result;
332 size_t length;
333 char *addr;
334
335 LY_CHECK_ARG_RET(ctx, ctx, NULL);
336 if (fd < 0) {
337 LOGARG(ctx, fd);
338 return NULL;
339 }
340
341 LY_CHECK_RET(ly_mmap(ctx, fd, &length, (void **)&addr), NULL);
Michal Vaskoa3881362020-01-21 15:57:35 +0100342 result = lyd_parse_mem(ctx, addr ? addr : "", format, options);
Radek Krejcidf3da792019-05-17 10:32:24 +0200343 if (addr) {
344 ly_munmap(addr, length);
345 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200346
347 return result;
348}
349
350API struct lyd_node *
Michal Vaskoa3881362020-01-21 15:57:35 +0100351lyd_parse_path(struct ly_ctx *ctx, const char *path, LYD_FORMAT format, int options)
Radek Krejcie7b95092019-05-15 11:03:07 +0200352{
353 int fd;
354 struct lyd_node *result;
355 size_t len;
Radek Krejcie7b95092019-05-15 11:03:07 +0200356
357 LY_CHECK_ARG_RET(ctx, ctx, path, NULL);
358
359 fd = open(path, O_RDONLY);
360 LY_CHECK_ERR_RET(fd == -1, LOGERR(ctx, LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno)), NULL);
361
362 if (!format) {
363 /* unknown format - try to detect it from filename's suffix */
364 len = strlen(path);
365
366 /* ignore trailing whitespaces */
367 for (; len > 0 && isspace(path[len - 1]); len--);
368
369 if (len >= 5 && !strncmp(&path[len - 4], ".xml", 4)) {
370 format = LYD_XML;
371#if 0
372 } else if (len >= 6 && !strncmp(&path[len - 5], ".json", 5)) {
373 format = LYD_JSON;
374 } else if (len >= 5 && !strncmp(&path[len - 4], ".lyb", 4)) {
375 format = LYD_LYB;
376#endif
377 } /* else still unknown, try later to detect it from the content */
378 }
379
Michal Vaskoa3881362020-01-21 15:57:35 +0100380 result = lyd_parse_fd(ctx, fd, format, options);
Radek Krejcie7b95092019-05-15 11:03:07 +0200381 close(fd);
382
383 return result;
384}
Radek Krejci084289f2019-07-09 17:35:30 +0200385
Michal Vasko90932a92020-02-12 14:33:03 +0100386LY_ERR
387lyd_create_term(const struct lysc_node *schema, const char *value, size_t value_len, int *dynamic,
388 ly_clb_resolve_prefix get_prefix, void *prefix_data, LYD_FORMAT format, struct lyd_node **node)
389{
390 LY_ERR ret;
391 struct lyd_node_term *term;
392
Michal Vasko9b368d32020-02-14 13:53:31 +0100393 assert(schema->nodetype & LYD_NODE_TERM);
394
Michal Vasko90932a92020-02-12 14:33:03 +0100395 term = calloc(1, sizeof *term);
396 LY_CHECK_ERR_RET(!term, LOGMEM(schema->module->ctx), LY_EMEM);
397
398 term->schema = schema;
399 term->prev = (struct lyd_node *)term;
Michal Vasko9b368d32020-02-14 13:53:31 +0100400 term->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100401
402 ret = lyd_value_parse(term, value, value_len, dynamic, 0, get_prefix, prefix_data, format, NULL);
403 if (ret && (ret != LY_EINCOMPLETE)) {
404 free(term);
405 return ret;
406 }
Michal Vasko9b368d32020-02-14 13:53:31 +0100407 lyd_hash((struct lyd_node *)term);
408
409 *node = (struct lyd_node *)term;
410 return ret;
411}
412
413LY_ERR
414lyd_create_term2(const struct lysc_node *schema, const struct lyd_value *val, struct lyd_node **node)
415{
416 LY_ERR ret;
417 struct lyd_node_term *term;
418 struct lysc_type *type;
419
420 assert(schema->nodetype & LYD_NODE_TERM);
421
422 term = calloc(1, sizeof *term);
423 LY_CHECK_ERR_RET(!term, LOGMEM(schema->module->ctx), LY_EMEM);
424
425 term->schema = schema;
426 term->prev = (struct lyd_node *)term;
427 term->flags = LYD_NEW;
428
429 type = ((struct lysc_node_leaf *)schema)->type;
430 ret = type->plugin->duplicate(schema->module->ctx, val, &term->value);
431 if (ret) {
432 LOGERR(schema->module->ctx, ret, "Value duplication failed.");
433 free(term);
434 return ret;
435 }
436 lyd_hash((struct lyd_node *)term);
Michal Vasko90932a92020-02-12 14:33:03 +0100437
438 *node = (struct lyd_node *)term;
439 return ret;
440}
441
442LY_ERR
443lyd_create_inner(const struct lysc_node *schema, struct lyd_node **node)
444{
445 struct lyd_node_inner *in;
446
Michal Vasko9b368d32020-02-14 13:53:31 +0100447 assert(schema->nodetype & LYD_NODE_INNER);
448
Michal Vasko90932a92020-02-12 14:33:03 +0100449 in = calloc(1, sizeof *in);
450 LY_CHECK_ERR_RET(!in, LOGMEM(schema->module->ctx), LY_EMEM);
451
452 in->schema = schema;
453 in->prev = (struct lyd_node *)in;
Michal Vasko9b368d32020-02-14 13:53:31 +0100454 in->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100455
Michal Vasko9b368d32020-02-14 13:53:31 +0100456 /* do not hash list with keys, we need them for the hash */
457 if ((schema->nodetype != LYS_LIST) || (schema->flags & LYS_KEYLESS)) {
458 lyd_hash((struct lyd_node *)in);
459 }
Michal Vasko90932a92020-02-12 14:33:03 +0100460
461 *node = (struct lyd_node *)in;
462 return LY_SUCCESS;
463}
464
465static void
466ly_keys_clean(struct ly_keys *keys)
467{
468 size_t i;
469
470 for (i = 0; i < keys->key_count; ++i) {
471 keys->keys[i].schema->type->plugin->free(keys->keys[i].schema->module->ctx, &keys->keys[i].val);
472 }
473 free(keys->str);
474 free(keys->keys);
475}
476
477static char *
478ly_keys_parse_next(char **next_key, char **key_name)
479{
480 char *ptr, *ptr2, *val, quot;
481
482 ptr = *next_key;
483
484 /* "[" */
485 LY_CHECK_GOTO(ptr[0] != '[', error);
486 ++ptr;
487
488 /* key name */
489 ptr2 = strchr(ptr, '=');
490 LY_CHECK_GOTO(!ptr2, error);
491
492 *key_name = ptr;
493 ptr2[0] = '\0';
494
495 /* \0, was '=' */
496 ptr = ptr2 + 1;
497
498 /* quote */
499 LY_CHECK_GOTO((ptr[0] != '\'') && (ptr[0] != '\"'), error);
500 quot = ptr[0];
501 ++ptr;
502
503 /* value, terminate it */
504 val = ptr;
505 ptr2 = strchr(ptr, quot);
506 LY_CHECK_GOTO(!ptr2, error);
507 ptr2[0] = '\0';
508
509 /* \0, was quote */
510 ptr = ptr2 + 1;
511
512 /* "]" */
513 LY_CHECK_GOTO(ptr[0] != ']', error);
514 ++ptr;
515
516 *next_key = ptr;
517 return val;
518
519error:
520 *next_key = ptr;
521 return NULL;
522}
523
524/* fill keys structure; if store is set, fill also each val */
525static LY_ERR
526ly_keys_parse(const struct lysc_node *list, const char *keys_str, size_t keys_len, int store, struct ly_keys *keys)
527{
528 LY_ERR ret = LY_SUCCESS;
529 char *next_key, *name;
530 const struct lysc_node *key;
531 size_t i;
532
533 assert(list->nodetype == LYS_LIST);
534
535 memset(keys, 0, sizeof *keys);
536
Michal Vaskof03ed032020-03-04 13:31:44 +0100537 if (!keys_str) {
538 /* nothing to parse */
539 return LY_SUCCESS;
540 }
541
542 keys->str = strndup(keys_str, keys_len);
Michal Vasko90932a92020-02-12 14:33:03 +0100543 LY_CHECK_ERR_GOTO(!keys->str, LOGMEM(list->module->ctx); ret = LY_EMEM, cleanup);
544
545 next_key = keys->str;
546 while (next_key[0]) {
547 /* new key */
548 keys->keys = ly_realloc(keys->keys, (keys->key_count + 1) * sizeof *keys->keys);
549 LY_CHECK_ERR_GOTO(!keys->keys, LOGMEM(list->module->ctx); ret = LY_EMEM, cleanup);
550
551 /* fill */
552 keys->keys[keys->key_count].value = ly_keys_parse_next(&next_key, &name);
553 if (!keys->keys[keys->key_count].value) {
554 LOGERR(list->module->ctx, LY_EINVAL, "Invalid keys string (at \"%s\").", next_key);
555 ret = LY_EINVAL;
556 goto cleanup;
557 }
558
559 /* find schema node */
560 key = lys_find_child(list, list->module, name, 0, LYS_LEAF, 0);
561 if (!key) {
562 LOGERR(list->module->ctx, LY_EINVAL, "List \"%s\" has no key \"%s\".", list->name, name);
563 ret = LY_EINVAL;
564 goto cleanup;
565 }
566 keys->keys[keys->key_count].schema = (const struct lysc_node_leaf *)key;
567
568 /* check that we do not have it already */
569 for (i = 0; i < keys->key_count; ++i) {
570 if (keys->keys[i].schema == keys->keys[keys->key_count].schema) {
571 LOGERR(list->module->ctx, LY_EINVAL, "Duplicit key \"%s\" value.", name);
572 ret = LY_EINVAL;
573 goto cleanup;
574 }
575 }
576
577 if (store) {
578 /* store the value */
579 ret = lyd_value_store(&keys->keys[keys->key_count].val, key, keys->keys[keys->key_count].value, 0, 0,
580 lydjson_resolve_prefix, NULL, LYD_JSON);
581 LY_CHECK_GOTO(ret, cleanup);
582 }
583
584 /* another valid key */
585 ++keys->key_count;
586 }
587
588cleanup:
589 ly_keys_clean(keys);
590 return ret;
591}
592
593LY_ERR
594lyd_create_list(const struct lysc_node *schema, const char *keys_str, size_t keys_len, struct lyd_node **node)
595{
596 LY_ERR ret = LY_SUCCESS;
597 const struct lysc_node *key_s;
598 struct lyd_node *list = NULL, *key;
599 struct ly_keys keys = {0};
600 size_t i;
601
602 assert((schema->nodetype == LYS_LIST) && !(schema->flags & LYS_KEYLESS));
603
604 /* parse keys */
605 LY_CHECK_GOTO(ret = ly_keys_parse(schema, keys_str, keys_len, 0, &keys), cleanup);
606
607 /* create list */
608 LY_CHECK_GOTO(ret = lyd_create_inner(schema, &list), cleanup);
609
610 /* everything was checked except that all keys are set */
611 i = 0;
612 for (key_s = lysc_node_children(schema, 0); key_s && (key_s->flags & LYS_KEY); key_s = key_s->next) {
613 ++i;
614 }
615 if (i != keys.key_count) {
616 LOGERR(schema->module->ctx, LY_EINVAL, "List \"%s\" is missing some keys.", schema->name);
617 ret = LY_EINVAL;
618 goto cleanup;
619 }
620
621 /* create and insert all the keys */
622 for (i = 0; i < keys.key_count; ++i) {
Michal Vaskof03ed032020-03-04 13:31:44 +0100623 LY_CHECK_GOTO(ret = lyd_create_term((struct lysc_node *)keys.keys[i].schema, keys.keys[i].value,
624 strlen(keys.keys[i].value), NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &key), cleanup);
Michal Vasko90932a92020-02-12 14:33:03 +0100625 lyd_insert_node(list, NULL, key);
626 }
627
Michal Vasko9b368d32020-02-14 13:53:31 +0100628 /* hash having all the keys */
629 lyd_hash(list);
630
Michal Vasko90932a92020-02-12 14:33:03 +0100631 /* success */
632 *node = list;
633 list = NULL;
634
635cleanup:
636 lyd_free_tree(list);
637 ly_keys_clean(&keys);
638 return ret;
639}
640
641LY_ERR
642lyd_create_any(const struct lysc_node *schema, const void *value, LYD_ANYDATA_VALUETYPE value_type, struct lyd_node **node)
643{
644 struct lyd_node_any *any;
645
Michal Vasko9b368d32020-02-14 13:53:31 +0100646 assert(schema->nodetype & LYD_NODE_ANY);
647
Michal Vasko90932a92020-02-12 14:33:03 +0100648 any = calloc(1, sizeof *any);
649 LY_CHECK_ERR_RET(!any, LOGMEM(schema->module->ctx), LY_EMEM);
650
651 any->schema = schema;
652 any->prev = (struct lyd_node *)any;
Michal Vasko9b368d32020-02-14 13:53:31 +0100653 any->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100654
655 any->value.xml = value;
656 any->value_type = value_type;
Michal Vasko9b368d32020-02-14 13:53:31 +0100657 lyd_hash((struct lyd_node *)any);
Michal Vasko90932a92020-02-12 14:33:03 +0100658
659 *node = (struct lyd_node *)any;
660 return LY_SUCCESS;
661}
662
Michal Vasko52927e22020-03-16 17:26:14 +0100663LY_ERR
664lyd_create_opaq(const struct ly_ctx *ctx, const char *name, size_t name_len, const char *value, size_t value_len,
665 int *dynamic, LYD_FORMAT format, struct ly_prefix *val_prefs, const char *prefix, size_t pref_len,
666 const char *ns, struct lyd_node **node)
667{
668 struct lyd_node_opaq *opaq;
669
670 assert(ctx && name && name_len && ns);
671
672 if (!value_len) {
673 value = "";
674 }
675
676 opaq = calloc(1, sizeof *opaq);
677 LY_CHECK_ERR_RET(!opaq, LOGMEM(ctx), LY_EMEM);
678
679 opaq->prev = (struct lyd_node *)opaq;
680
681 opaq->name = lydict_insert(ctx, name, name_len);
682 opaq->format = format;
683 if (pref_len) {
684 opaq->prefix.pref = lydict_insert(ctx, prefix, pref_len);
685 }
686 opaq->prefix.ns = lydict_insert(ctx, ns, 0);
687 opaq->val_prefs = val_prefs;
688 if (dynamic && *dynamic) {
689 opaq->value = lydict_insert_zc(ctx, (char *)value);
690 *dynamic = 0;
691 } else {
692 opaq->value = lydict_insert(ctx, value, value_len);
693 }
694 opaq->ctx = ctx;
695
696 *node = (struct lyd_node *)opaq;
697 return LY_SUCCESS;
698}
699
Michal Vasko013a8182020-03-03 10:46:53 +0100700API struct lyd_node *
701lyd_new_inner(struct lyd_node *parent, const struct lys_module *module, const char *name)
702{
703 struct lyd_node *ret = NULL;
704 const struct lysc_node *schema;
705 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
706
707 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
708
Michal Vaskof03ed032020-03-04 13:31:44 +0100709 if (!module) {
710 module = parent->schema->module;
711 }
712
Michal Vasko1bf09392020-03-27 12:38:10 +0100713 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_CONTAINER | LYS_NOTIF | LYS_RPC | LYS_ACTION, 0);
Michal Vasko013a8182020-03-03 10:46:53 +0100714 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Inner node \"%s\" not found.", name), NULL);
715
716 if (!lyd_create_inner(schema, &ret) && parent) {
717 lyd_insert_node(parent, NULL, ret);
718 }
719 return ret;
720}
721
722API struct lyd_node *
723lyd_new_list(struct lyd_node *parent, const struct lys_module *module, const char *name, ...)
724{
725 struct lyd_node *ret = NULL, *key;
726 const struct lysc_node *schema, *key_s;
727 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
728 va_list ap;
729 const char *key_val;
730 LY_ERR rc = LY_SUCCESS;
731
732 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
733
Michal Vaskof03ed032020-03-04 13:31:44 +0100734 if (!module) {
735 module = parent->schema->module;
736 }
737
Michal Vasko013a8182020-03-03 10:46:53 +0100738 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, 0);
739 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), NULL);
740
741 /* create list inner node */
742 LY_CHECK_RET(lyd_create_inner(schema, &ret), NULL);
743
744 va_start(ap, name);
745
746 /* create and insert all the keys */
747 for (key_s = lysc_node_children(schema, 0); key_s && (key_s->flags & LYS_KEY); key_s = key_s->next) {
748 key_val = va_arg(ap, const char *);
749
Michal Vaskof03ed032020-03-04 13:31:44 +0100750 rc = lyd_create_term(key_s, key_val, key_val ? strlen(key_val) : 0, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &key);
751 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko013a8182020-03-03 10:46:53 +0100752 lyd_insert_node(ret, NULL, key);
753 }
754
755 /* hash having all the keys */
756 lyd_hash(ret);
757
758 if (parent) {
759 lyd_insert_node(parent, NULL, ret);
760 }
761
762cleanup:
763 if (rc) {
764 lyd_free_tree(ret);
765 ret = NULL;
766 }
767 va_end(ap);
768 return ret;
769}
770
771API struct lyd_node *
772lyd_new_list2(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *keys)
773{
774 struct lyd_node *ret = NULL;
775 const struct lysc_node *schema;
776 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
777
778 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
779
Michal Vaskof03ed032020-03-04 13:31:44 +0100780 if (!module) {
781 module = parent->schema->module;
782 }
783
Michal Vasko013a8182020-03-03 10:46:53 +0100784 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, 0);
785 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), NULL);
786
Michal Vaskof03ed032020-03-04 13:31:44 +0100787 if (!lyd_create_list(schema, keys, keys ? strlen(keys) : 0, &ret) && parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100788 lyd_insert_node(parent, NULL, ret);
789 }
790 return ret;
791}
792
793API struct lyd_node *
794lyd_new_term(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str)
795{
796 struct lyd_node *ret = NULL;
797 const struct lysc_node *schema;
798 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
799
800 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
801
Michal Vaskof03ed032020-03-04 13:31:44 +0100802 if (!module) {
803 module = parent->schema->module;
804 }
805
Michal Vasko013a8182020-03-03 10:46:53 +0100806 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_TERM, 0);
807 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Term node \"%s\" not found.", name), NULL);
808
Michal Vaskof03ed032020-03-04 13:31:44 +0100809 if (!lyd_create_term(schema, val_str, val_str ? strlen(val_str) : 0, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &ret)
810 && parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100811 lyd_insert_node(parent, NULL, ret);
812 }
813 return ret;
814}
815
816API struct lyd_node *
817lyd_new_any(struct lyd_node *parent, const struct lys_module *module, const char *name, const void *value,
818 LYD_ANYDATA_VALUETYPE value_type)
819{
820 struct lyd_node *ret = NULL;
821 const struct lysc_node *schema;
822 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
823
824 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
825
Michal Vaskof03ed032020-03-04 13:31:44 +0100826 if (!module) {
827 module = parent->schema->module;
828 }
829
Michal Vasko013a8182020-03-03 10:46:53 +0100830 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_ANY, 0);
831 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Any node \"%s\" not found.", name), NULL);
832
833 if (!lyd_create_any(schema, value, value_type, &ret) && parent) {
834 lyd_insert_node(parent, NULL, ret);
835 }
836 return ret;
837}
838
Michal Vasko90932a92020-02-12 14:33:03 +0100839struct lyd_node *
840lyd_get_prev_key_anchor(const struct lyd_node *first_sibling, const struct lysc_node *new_key)
841{
842 const struct lysc_node *prev_key;
843 struct lyd_node *match = NULL;
844
845 if (!first_sibling) {
846 return NULL;
847 }
848
849 for (prev_key = new_key->prev; !match && prev_key->next; prev_key = prev_key->prev) {
850 lyd_find_sibling_val(first_sibling, prev_key, NULL, 0, &match);
851 }
852
853 return match;
854}
855
856/**
857 * @brief Insert node after a sibling.
858 *
Michal Vasko9f96a052020-03-10 09:41:45 +0100859 * Handles inserting into NP containers and key-less lists.
860 *
Michal Vasko90932a92020-02-12 14:33:03 +0100861 * @param[in] sibling Sibling to insert after.
862 * @param[in] node Node to insert.
863 */
864static void
Michal Vaskof03ed032020-03-04 13:31:44 +0100865lyd_insert_after_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +0100866{
Michal Vasko0249f7c2020-03-05 16:36:40 +0100867 struct lyd_node_inner *par;
868
Michal Vasko90932a92020-02-12 14:33:03 +0100869 assert(!node->next && (node->prev == node));
870
871 node->next = sibling->next;
872 node->prev = sibling;
873 sibling->next = node;
874 if (node->next) {
875 /* sibling had a succeeding node */
876 node->next->prev = node;
877 } else {
878 /* sibling was last, find first sibling and change its prev */
879 if (sibling->parent) {
880 sibling = sibling->parent->child;
881 } else {
882 for (; sibling->prev->next != node; sibling = sibling->prev);
883 }
884 sibling->prev = node;
885 }
886 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +0100887
Michal Vasko9f96a052020-03-10 09:41:45 +0100888 for (par = node->parent; par; par = par->parent) {
889 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
890 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +0100891 par->flags &= ~LYD_DEFAULT;
892 }
Michal Vasko9f96a052020-03-10 09:41:45 +0100893 if ((par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
894 /* rehash key-less list */
895 lyd_hash((struct lyd_node *)par);
896 }
Michal Vasko0249f7c2020-03-05 16:36:40 +0100897 }
898
899 /* insert into hash table */
900 lyd_insert_hash(node);
Michal Vasko90932a92020-02-12 14:33:03 +0100901}
902
903/**
904 * @brief Insert node before a sibling.
905 *
Michal Vasko9f96a052020-03-10 09:41:45 +0100906 * Handles inserting into NP containers and key-less lists.
907 *
Michal Vasko90932a92020-02-12 14:33:03 +0100908 * @param[in] sibling Sibling to insert before.
909 * @param[in] node Node to insert.
910 */
911static void
Michal Vaskof03ed032020-03-04 13:31:44 +0100912lyd_insert_before_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +0100913{
Michal Vasko0249f7c2020-03-05 16:36:40 +0100914 struct lyd_node_inner *par;
915
Michal Vasko90932a92020-02-12 14:33:03 +0100916 assert(!node->next && (node->prev == node));
917
918 node->next = sibling;
919 /* covers situation of sibling being first */
920 node->prev = sibling->prev;
921 sibling->prev = node;
922 if (node->prev->next) {
923 /* sibling had a preceding node */
924 node->prev->next = node;
925 } else if (sibling->parent) {
926 /* sibling was first and we must also change parent child pointer */
927 sibling->parent->child = node;
928 }
929 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +0100930
Michal Vasko9f96a052020-03-10 09:41:45 +0100931 for (par = node->parent; par; par = par->parent) {
932 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
933 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +0100934 par->flags &= ~LYD_DEFAULT;
935 }
Michal Vasko9f96a052020-03-10 09:41:45 +0100936 if ((par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
937 /* rehash key-less list */
938 lyd_hash((struct lyd_node *)par);
939 }
Michal Vasko0249f7c2020-03-05 16:36:40 +0100940 }
941
942 /* insert into hash table */
943 lyd_insert_hash(node);
Michal Vasko90932a92020-02-12 14:33:03 +0100944}
945
946/**
947 * @brief Insert node as the last child of a parent.
948 *
Michal Vasko9f96a052020-03-10 09:41:45 +0100949 * Handles inserting into NP containers and key-less lists.
950 *
Michal Vasko90932a92020-02-12 14:33:03 +0100951 * @param[in] parent Parent to insert into.
952 * @param[in] node Node to insert.
953 */
954static void
Michal Vaskof03ed032020-03-04 13:31:44 +0100955lyd_insert_last_node(struct lyd_node *parent, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +0100956{
957 struct lyd_node_inner *par;
958
Michal Vasko0249f7c2020-03-05 16:36:40 +0100959 assert(parent && !node->next && (node->prev == node));
Michal Vasko52927e22020-03-16 17:26:14 +0100960 assert(!parent->schema || (parent->schema->nodetype & LYD_NODE_INNER));
Michal Vasko90932a92020-02-12 14:33:03 +0100961
962 par = (struct lyd_node_inner *)parent;
963
964 if (!par->child) {
965 par->child = node;
966 } else {
967 node->prev = par->child->prev;
968 par->child->prev->next = node;
969 par->child->prev = node;
970 }
971 node->parent = par;
Michal Vasko0249f7c2020-03-05 16:36:40 +0100972
Michal Vasko9f96a052020-03-10 09:41:45 +0100973 for (; par; par = par->parent) {
974 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
975 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +0100976 par->flags &= ~LYD_DEFAULT;
977 }
Michal Vasko52927e22020-03-16 17:26:14 +0100978 if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
Michal Vasko9f96a052020-03-10 09:41:45 +0100979 /* rehash key-less list */
980 lyd_hash((struct lyd_node *)par);
981 }
Michal Vasko0249f7c2020-03-05 16:36:40 +0100982 }
983
984 /* insert into hash table */
985 lyd_insert_hash(node);
Michal Vasko90932a92020-02-12 14:33:03 +0100986}
987
988void
Michal Vasko9b368d32020-02-14 13:53:31 +0100989lyd_insert_node(struct lyd_node *parent, struct lyd_node **first_sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +0100990{
Michal Vasko9b368d32020-02-14 13:53:31 +0100991 struct lyd_node *anchor;
Michal Vasko9f96a052020-03-10 09:41:45 +0100992 const struct lysc_node *skey = NULL;
993 int has_keys;
Michal Vasko90932a92020-02-12 14:33:03 +0100994
Michal Vasko52927e22020-03-16 17:26:14 +0100995 assert((parent || first_sibling) && node && (node->hash || !node->schema));
Michal Vasko9b368d32020-02-14 13:53:31 +0100996
997 if (!parent && first_sibling && (*first_sibling) && (*first_sibling)->parent) {
998 parent = (struct lyd_node *)(*first_sibling)->parent;
999 }
Michal Vasko90932a92020-02-12 14:33:03 +01001000
1001 if (parent) {
Michal Vasko52927e22020-03-16 17:26:14 +01001002 if (node->schema && (node->schema->flags & LYS_KEY)) {
Michal Vasko90932a92020-02-12 14:33:03 +01001003 /* it is key and we need to insert it at the correct place */
Michal Vasko9b368d32020-02-14 13:53:31 +01001004 anchor = lyd_get_prev_key_anchor(lyd_node_children(parent), node->schema);
1005 if (anchor) {
Michal Vaskof03ed032020-03-04 13:31:44 +01001006 lyd_insert_after_node(anchor, node);
Michal Vasko90932a92020-02-12 14:33:03 +01001007 } else if (lyd_node_children(parent)) {
Michal Vaskof03ed032020-03-04 13:31:44 +01001008 lyd_insert_before_node((struct lyd_node *)lyd_node_children(parent), node);
Michal Vasko90932a92020-02-12 14:33:03 +01001009 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +01001010 lyd_insert_last_node(parent, node);
Michal Vasko90932a92020-02-12 14:33:03 +01001011 }
Michal Vasko9f96a052020-03-10 09:41:45 +01001012
1013 /* hash list if all its keys were added */
1014 assert(parent->schema->nodetype == LYS_LIST);
1015 anchor = (struct lyd_node *)lyd_node_children(parent);
1016 has_keys = 1;
1017 while ((skey = lys_getnext(skey, parent->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
1018 if (!anchor || (anchor->schema != skey)) {
1019 /* key missing */
1020 has_keys = 0;
1021 break;
1022 }
1023
1024 anchor = anchor->next;
1025 }
1026 if (has_keys) {
1027 lyd_hash(parent);
1028 }
1029
Michal Vasko90932a92020-02-12 14:33:03 +01001030 } else {
1031 /* last child */
Michal Vaskof03ed032020-03-04 13:31:44 +01001032 lyd_insert_last_node(parent, node);
Michal Vasko90932a92020-02-12 14:33:03 +01001033 }
Michal Vasko9b368d32020-02-14 13:53:31 +01001034 } else if (*first_sibling) {
Michal Vaskob1b5c262020-03-05 14:29:47 +01001035 /* top-level siblings */
Michal Vasko9b368d32020-02-14 13:53:31 +01001036 anchor = (*first_sibling)->prev;
Michal Vaskoc193ce92020-03-06 11:04:48 +01001037 while (anchor->prev->next && (lyd_owner_module(anchor) != lyd_owner_module(node))) {
Michal Vasko9b368d32020-02-14 13:53:31 +01001038 anchor = anchor->prev;
1039 }
1040
Michal Vaskoc193ce92020-03-06 11:04:48 +01001041 if (lyd_owner_module(anchor) == lyd_owner_module(node)) {
Michal Vaskob1b5c262020-03-05 14:29:47 +01001042 /* insert after last sibling from this module */
1043 lyd_insert_after_node(anchor, node);
1044 } else {
1045 /* no data from this module, insert at the last position */
1046 lyd_insert_after_node((*first_sibling)->prev, node);
1047 }
Michal Vasko90932a92020-02-12 14:33:03 +01001048 } else {
Michal Vasko9b368d32020-02-14 13:53:31 +01001049 /* the only sibling */
1050 *first_sibling = node;
Michal Vasko90932a92020-02-12 14:33:03 +01001051 }
Michal Vasko90932a92020-02-12 14:33:03 +01001052}
1053
Michal Vaskof03ed032020-03-04 13:31:44 +01001054static LY_ERR
1055lyd_insert_check_schema(const struct lysc_node *parent, const struct lysc_node *schema)
1056{
1057 const struct lysc_node *par2;
1058
1059 assert(schema);
1060
1061 /* adjust parent first */
1062 while (parent && (parent->nodetype & (LYS_CASE | LYS_CHOICE))) {
1063 parent = parent->parent;
1064 }
1065
1066 /* find schema parent */
1067 for (par2 = schema->parent; par2 && (par2->nodetype & (LYS_CASE | LYS_CHOICE)); par2 = par2->parent);
1068
1069 if (parent) {
1070 /* inner node */
1071 if (par2 != parent) {
1072 LOGERR(parent->module->ctx, LY_EINVAL, "Cannot insert, parent of \"%s\" is not \"%s\".", schema->name, parent->name);
1073 return LY_EINVAL;
1074 }
1075 } else {
1076 /* top-level node */
1077 if (par2) {
1078 LOGERR(parent->module->ctx, LY_EINVAL, "Cannot insert, node \"%s\" is not top-level.", schema->name);
1079 return LY_EINVAL;
1080 }
1081 }
1082
1083 return LY_SUCCESS;
1084}
1085
1086API LY_ERR
1087lyd_insert(struct lyd_node *parent, struct lyd_node *node)
1088{
1089 struct lyd_node *iter;
1090
1091 LY_CHECK_ARG_RET(NULL, parent, node, !(parent->schema->nodetype & LYD_NODE_INNER), LY_EINVAL);
1092
1093 LY_CHECK_RET(lyd_insert_check_schema(parent->schema, node->schema));
1094
1095 if (node->schema->flags & LYS_KEY) {
1096 LOGERR(parent->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1097 return LY_EINVAL;
1098 }
1099
1100 if (node->parent || node->prev->next) {
1101 lyd_unlink_tree(node);
1102 }
1103
1104 while (node) {
1105 iter = node->next;
1106 lyd_unlink_tree(node);
1107 lyd_insert_node(parent, NULL, node);
1108 node = iter;
1109 }
1110 return LY_SUCCESS;
1111}
1112
1113API LY_ERR
Michal Vaskob1b5c262020-03-05 14:29:47 +01001114lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node)
1115{
1116 struct lyd_node *iter;
1117
1118 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1119
1120 LY_CHECK_RET(lyd_insert_check_schema(sibling->schema->parent, node->schema));
1121
1122 if (node->schema->flags & LYS_KEY) {
1123 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1124 return LY_EINVAL;
1125 }
1126
1127 if (node->parent || node->prev->next) {
1128 lyd_unlink_tree(node);
1129 }
1130
1131 while (node) {
1132 iter = node->next;
1133 lyd_unlink_tree(node);
1134 lyd_insert_node(NULL, &sibling, node);
1135 node = iter;
1136 }
1137 return LY_SUCCESS;
1138}
1139
Michal Vasko0249f7c2020-03-05 16:36:40 +01001140static LY_ERR
1141lyd_insert_after_check_place(struct lyd_node *anchor, struct lyd_node *sibling, struct lyd_node *node)
1142{
1143 if (sibling->parent) {
1144 /* nested, we do not care for the order */
1145 return LY_SUCCESS;
1146 }
1147
1148 if (anchor) {
Michal Vaskoc193ce92020-03-06 11:04:48 +01001149 if (anchor->next && (lyd_owner_module(anchor) == lyd_owner_module(anchor->next))
1150 && (lyd_owner_module(node) != lyd_owner_module(anchor))) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001151 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 +01001152 lyd_owner_module(node)->name, lyd_owner_module(anchor)->name);
Michal Vasko0249f7c2020-03-05 16:36:40 +01001153 return LY_EINVAL;
1154 }
1155
Michal Vaskoc193ce92020-03-06 11:04:48 +01001156 if ((lyd_owner_module(node) == lyd_owner_module(anchor))
1157 || (anchor->next && (lyd_owner_module(node) == lyd_owner_module(anchor->next)))) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001158 /* inserting before/after its module data */
1159 return LY_SUCCESS;
1160 }
1161 }
1162
1163 /* find first sibling */
1164 while (sibling->prev->next) {
1165 sibling = sibling->prev;
1166 }
1167
1168 if (!anchor) {
Michal Vaskoc193ce92020-03-06 11:04:48 +01001169 if (lyd_owner_module(node) == lyd_owner_module(sibling)) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001170 /* inserting before its module data */
1171 return LY_SUCCESS;
1172 }
1173 }
1174
1175 /* check there are no data of this module */
1176 LY_LIST_FOR(sibling, sibling) {
Michal Vaskoc193ce92020-03-06 11:04:48 +01001177 if (lyd_owner_module(node) == lyd_owner_module(sibling)) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001178 /* some data of this module found */
1179 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Top-level data of module \"%s\" already exist,"
Michal Vaskoc193ce92020-03-06 11:04:48 +01001180 " they must be directly connected.", lyd_owner_module(node)->name);
Michal Vasko0249f7c2020-03-05 16:36:40 +01001181 return LY_EINVAL;
1182 }
1183 }
1184
1185 return LY_SUCCESS;
1186}
1187
Michal Vaskob1b5c262020-03-05 14:29:47 +01001188API LY_ERR
Michal Vaskof03ed032020-03-04 13:31:44 +01001189lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
1190{
1191 struct lyd_node *iter;
1192
1193 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1194
1195 LY_CHECK_RET(lyd_insert_check_schema(sibling->schema->parent, node->schema));
1196
1197 if (node->schema->flags & LYS_KEY) {
1198 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1199 return LY_EINVAL;
1200 } else if (sibling->schema->flags & LYS_KEY) {
1201 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert into keys.");
1202 return LY_EINVAL;
1203 }
1204
Michal Vasko0249f7c2020-03-05 16:36:40 +01001205 LY_CHECK_RET(lyd_insert_after_check_place(sibling->prev->next ? sibling->prev : NULL, sibling, node));
1206
Michal Vaskof03ed032020-03-04 13:31:44 +01001207 if (node->parent || node->prev->next) {
1208 lyd_unlink_tree(node);
1209 }
1210
1211 /* insert in reverse order to get the original order */
1212 node = node->prev;
1213 while (node) {
1214 iter = node->prev;
1215 lyd_unlink_tree(node);
1216
1217 lyd_insert_before_node(sibling, node);
1218 /* move the anchor accordingly */
1219 sibling = node;
1220
1221 node = (iter == node) ? NULL : iter;
1222 }
1223 return LY_SUCCESS;
1224}
1225
1226API LY_ERR
1227lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
1228{
1229 struct lyd_node *iter;
1230
1231 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1232
1233 LY_CHECK_RET(lyd_insert_check_schema(sibling->schema->parent, node->schema));
1234
1235 if (node->schema->flags & LYS_KEY) {
1236 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1237 return LY_EINVAL;
1238 } else if (sibling->next && (sibling->next->schema->flags & LYS_KEY)) {
1239 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert into keys.");
1240 return LY_EINVAL;
1241 }
1242
Michal Vasko0249f7c2020-03-05 16:36:40 +01001243 LY_CHECK_RET(lyd_insert_after_check_place(sibling, sibling, node));
1244
Michal Vaskof03ed032020-03-04 13:31:44 +01001245 if (node->parent || node->prev->next) {
1246 lyd_unlink_tree(node);
1247 }
1248
1249 while (node) {
1250 iter = node->next;
1251 lyd_unlink_tree(node);
1252
1253 lyd_insert_after_node(sibling, node);
1254 /* move the anchor accordingly */
1255 sibling = node;
1256
1257 node = iter;
1258 }
1259 return LY_SUCCESS;
1260}
1261
1262API void
1263lyd_unlink_tree(struct lyd_node *node)
1264{
1265 struct lyd_node *iter;
1266
1267 if (!node) {
1268 return;
1269 }
1270
1271 /* unlink from siblings */
1272 if (node->prev->next) {
1273 node->prev->next = node->next;
1274 }
1275 if (node->next) {
1276 node->next->prev = node->prev;
1277 } else {
1278 /* unlinking the last node */
1279 if (node->parent) {
1280 iter = node->parent->child;
1281 } else {
1282 iter = node->prev;
1283 while (iter->prev != node) {
1284 iter = iter->prev;
1285 }
1286 }
1287 /* update the "last" pointer from the first node */
1288 iter->prev = node->prev;
1289 }
1290
1291 /* unlink from parent */
1292 if (node->parent) {
1293 if (node->parent->child == node) {
1294 /* the node is the first child */
1295 node->parent->child = node->next;
1296 }
1297
1298 lyd_unlink_hash(node);
1299
1300 /* check for keyless list and update its hash */
1301 for (iter = (struct lyd_node *)node->parent; iter; iter = (struct lyd_node *)iter->parent) {
1302 if (iter->schema->flags & LYS_KEYLESS) {
1303 lyd_hash(iter);
1304 }
1305 }
1306
1307 node->parent = NULL;
1308 }
1309
1310 node->next = NULL;
1311 node->prev = node;
1312}
1313
Michal Vasko90932a92020-02-12 14:33:03 +01001314LY_ERR
Michal Vasko9f96a052020-03-10 09:41:45 +01001315lyd_create_meta(struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod, const char *name,
Michal Vasko52927e22020-03-16 17:26:14 +01001316 size_t name_len, const char *value, size_t value_len, int *dynamic, ly_clb_resolve_prefix resolve_prefix,
Michal Vasko8d544252020-03-02 10:19:52 +01001317 void *prefix_data, LYD_FORMAT format, const struct lysc_node *ctx_snode)
Michal Vasko90932a92020-02-12 14:33:03 +01001318{
1319 LY_ERR ret;
1320 struct lysc_ext_instance *ant = NULL;
Michal Vasko9f96a052020-03-10 09:41:45 +01001321 struct lyd_meta *mt, *last;
Michal Vasko90932a92020-02-12 14:33:03 +01001322 uint32_t v;
1323
Michal Vasko9f96a052020-03-10 09:41:45 +01001324 assert((parent || meta) && mod);
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001325
Michal Vasko90932a92020-02-12 14:33:03 +01001326 LY_ARRAY_FOR(mod->compiled->exts, v) {
1327 if (mod->compiled->exts[v].def->plugin == lyext_plugins_internal[LYEXT_PLUGIN_INTERNAL_ANNOTATION].plugin &&
1328 !ly_strncmp(mod->compiled->exts[v].argument, name, name_len)) {
1329 /* we have the annotation definition */
1330 ant = &mod->compiled->exts[v];
1331 break;
1332 }
1333 }
1334 if (!ant) {
1335 /* attribute is not defined as a metadata annotation (RFC 7952) */
1336 LOGERR(mod->ctx, LY_EINVAL, "Annotation definition for attribute \"%s:%.*s\" not found.",
1337 mod->name, name_len, name);
1338 return LY_EINVAL;
1339 }
1340
Michal Vasko9f96a052020-03-10 09:41:45 +01001341 mt = calloc(1, sizeof *mt);
1342 LY_CHECK_ERR_RET(!mt, LOGMEM(mod->ctx), LY_EMEM);
1343 mt->parent = parent;
1344 mt->annotation = ant;
Michal Vasko52927e22020-03-16 17:26:14 +01001345 ret = lyd_value_parse_meta(mod->ctx, mt, value, value_len, dynamic, 0, resolve_prefix, prefix_data, format, ctx_snode, NULL);
Michal Vasko90932a92020-02-12 14:33:03 +01001346 if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001347 free(mt);
Michal Vasko90932a92020-02-12 14:33:03 +01001348 return ret;
1349 }
Michal Vasko9f96a052020-03-10 09:41:45 +01001350 mt->name = lydict_insert(mod->ctx, name, name_len);
Michal Vasko90932a92020-02-12 14:33:03 +01001351
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001352 /* insert as the last attribute */
1353 if (parent) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001354 if (parent->meta) {
1355 for (last = parent->meta; last->next; last = last->next);
1356 last->next = mt;
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001357 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +01001358 parent->meta = mt;
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001359 }
Michal Vasko9f96a052020-03-10 09:41:45 +01001360 } else if (*meta) {
1361 for (last = *meta; last->next; last = last->next);
1362 last->next = mt;
Michal Vasko90932a92020-02-12 14:33:03 +01001363 }
1364
1365 /* remove default flags from NP containers */
1366 while (parent && (parent->flags & LYD_DEFAULT)) {
1367 parent->flags &= ~LYD_DEFAULT;
1368 parent = (struct lyd_node *)parent->parent;
1369 }
1370
Michal Vasko9f96a052020-03-10 09:41:45 +01001371 if (meta) {
1372 *meta = mt;
Michal Vasko90932a92020-02-12 14:33:03 +01001373 }
1374 return ret;
1375}
1376
Michal Vasko52927e22020-03-16 17:26:14 +01001377LY_ERR
1378ly_create_attr(struct lyd_node *parent, struct ly_attr **attr, const struct ly_ctx *ctx, const char *name,
1379 size_t name_len, const char *value, size_t value_len, int *dynamic, LYD_FORMAT format,
1380 struct ly_prefix *val_prefs, const char *prefix, size_t prefix_len, const char *ns)
1381{
1382 struct ly_attr *at, *last;
1383 struct lyd_node_opaq *opaq;
1384
1385 assert(ctx && (parent || attr) && (!parent || !parent->schema));
1386 assert(name && name_len);
1387 assert((prefix_len && ns) || (!prefix_len && !ns));
1388
1389 if (!value_len) {
1390 value = "";
1391 }
1392
1393 at = calloc(1, sizeof *at);
1394 LY_CHECK_ERR_RET(!at, LOGMEM(ctx), LY_EMEM);
1395 at->parent = (struct lyd_node_opaq *)parent;
1396 at->name = lydict_insert(ctx, name, name_len);
1397 if (dynamic && *dynamic) {
1398 at->value = lydict_insert_zc(ctx, (char *)value);
1399 *dynamic = 0;
1400 } else {
1401 at->value = lydict_insert(ctx, value, value_len);
1402 }
1403
1404 at->format = format;
1405 at->val_prefs = val_prefs;
1406 if (ns) {
1407 at->prefix.pref = lydict_insert(ctx, prefix, prefix_len);
1408 at->prefix.ns = lydict_insert(ctx, ns, 0);
1409 }
1410
1411 /* insert as the last attribute */
1412 if (parent) {
1413 opaq = (struct lyd_node_opaq *)parent;
1414 if (opaq->attr) {
1415 for (last = opaq->attr; last->next; last = last->next);
1416 last->next = at;
1417 } else {
1418 opaq->attr = at;
1419 }
1420 } else if (*attr) {
1421 for (last = *attr; last->next; last = last->next);
1422 last->next = at;
1423 }
1424
1425 if (attr) {
1426 *attr = at;
1427 }
1428 return LY_SUCCESS;
1429}
1430
Radek Krejci084289f2019-07-09 17:35:30 +02001431API const struct lyd_node_term *
Michal Vaskof03ed032020-03-04 13:31:44 +01001432lyd_target(struct lyd_value_path *path, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +02001433{
Michal Vaskof03ed032020-03-04 13:31:44 +01001434 unsigned int u, x;
Michal Vaskoe444f752020-02-10 12:20:06 +01001435 const struct lyd_node *parent = NULL, *start_search;
1436 struct lyd_node *node = NULL;
Radek Krejci084289f2019-07-09 17:35:30 +02001437 uint64_t pos = 1;
1438
Michal Vaskof03ed032020-03-04 13:31:44 +01001439 LY_CHECK_ARG_RET(NULL, path, tree, NULL);
Radek Krejci084289f2019-07-09 17:35:30 +02001440
1441 LY_ARRAY_FOR(path, u) {
1442 if (parent) {
1443 start_search = lyd_node_children(parent);
1444search_inner:
Michal Vaskoe444f752020-02-10 12:20:06 +01001445 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 +02001446 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +01001447 start_search = tree;
Radek Krejci084289f2019-07-09 17:35:30 +02001448search_toplevel:
Michal Vaskof03ed032020-03-04 13:31:44 +01001449 /* WARNING! to use search_toplevel label correctly, variable v must be preserved and not changed! */
1450 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 +02001451 }
1452 if (!node) {
1453 return NULL;
1454 }
1455
1456 /* check predicate if any */
1457 LY_ARRAY_FOR(path[u].predicates, x) {
1458 if (path[u].predicates[x].type == 0) {
1459 /* position predicate */
1460 if (pos != path[u].predicates[x].position) {
1461 pos++;
1462 goto search_repeat;
1463 }
1464 /* done, no more predicates are allowed here */
1465 break;
1466 } else if (path[u].predicates[x].type == 1) {
1467 /* key-predicate */
1468 struct lysc_type *type = ((struct lysc_node_leaf*)path[u].predicates[x].key)->type;
Michal Vaskoe444f752020-02-10 12:20:06 +01001469 struct lyd_node *key;
1470 lyd_find_sibling_next(lyd_node_children(node), path[u].predicates[x].key->module,
1471 path[u].predicates[x].key->name, 0, NULL, 0, &key);
Radek Krejci084289f2019-07-09 17:35:30 +02001472 if (!key) {
1473 /* probably error and we shouldn't be here due to previous checks when creating path */
1474 goto search_repeat;
1475 }
1476 if (type->plugin->compare(&((struct lyd_node_term*)key)->value, path[u].predicates[x].value)) {
1477 goto search_repeat;
1478 }
1479 } else if (path[u].predicates[x].type == 2) {
1480 /* leaf-list-predicate */
1481 struct lysc_type *type = ((struct lysc_node_leaf*)path[u].node)->type;
1482 if (type->plugin->compare(&((struct lyd_node_term*)node)->value, path[u].predicates[x].value)) {
1483 goto search_repeat;
1484 }
1485 } else {
1486 LOGINT(NULL);
1487 }
1488 }
1489
1490 parent = node;
1491 }
1492
1493 return (const struct lyd_node_term*)node;
1494
1495search_repeat:
1496 start_search = node->next;
1497 if (parent) {
1498 goto search_inner;
1499 } else {
1500 goto search_toplevel;
1501 }
1502}
1503
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001504API LY_ERR
1505lyd_compare(const struct lyd_node *node1, const struct lyd_node *node2, int options)
1506{
1507 const struct lyd_node *iter1, *iter2;
1508 struct lyd_node_term *term1, *term2;
1509 struct lyd_node_any *any1, *any2;
Michal Vasko52927e22020-03-16 17:26:14 +01001510 struct lyd_node_opaq *opaq1, *opaq2;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001511 struct lysc_type *type;
1512 size_t len1, len2;
Radek Krejci084289f2019-07-09 17:35:30 +02001513
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001514 if (!node1 || !node2) {
1515 if (node1 == node2) {
1516 return LY_SUCCESS;
1517 } else {
1518 return LY_ENOT;
1519 }
1520 }
1521
Michal Vasko52927e22020-03-16 17:26:14 +01001522 if ((LYD_NODE_CTX(node1) != LYD_NODE_CTX(node2)) || (node1->schema != node2->schema)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001523 return LY_ENOT;
1524 }
1525
1526 if (node1->hash != node2->hash) {
1527 return LY_ENOT;
1528 }
Michal Vasko52927e22020-03-16 17:26:14 +01001529 /* equal hashes do not mean equal nodes, they can be just in collision (or both be 0) so the nodes must be checked explicitly */
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001530
Michal Vasko52927e22020-03-16 17:26:14 +01001531 if (!node1->schema) {
1532 opaq1 = (struct lyd_node_opaq *)node1;
1533 opaq2 = (struct lyd_node_opaq *)node2;
1534 if ((opaq1->name != opaq2->name) || (opaq1->prefix.ns != opaq2->prefix.ns) || (opaq1->format != opaq2->format)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001535 return LY_ENOT;
1536 }
Michal Vasko52927e22020-03-16 17:26:14 +01001537 switch (opaq1->format) {
1538 case LYD_XML:
1539 if (lyxml_value_compare(opaq1->value, opaq1->val_prefs, opaq2->value, opaq2->val_prefs)) {
1540 return LY_ENOT;
1541 }
1542 break;
1543 case LYD_SCHEMA:
1544 /* not allowed */
1545 LOGINT(LYD_NODE_CTX(node1));
1546 return LY_EINT;
1547 }
1548 if (options & LYD_COMPARE_FULL_RECURSION) {
1549 iter1 = opaq1->child;
1550 iter2 = opaq2->child;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001551 goto all_children_compare;
Michal Vasko52927e22020-03-16 17:26:14 +01001552 }
1553 return LY_SUCCESS;
1554 } else {
1555 switch (node1->schema->nodetype) {
1556 case LYS_LEAF:
1557 case LYS_LEAFLIST:
1558 if (options & LYD_COMPARE_DEFAULTS) {
1559 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
1560 return LY_ENOT;
1561 }
1562 }
1563
1564 term1 = (struct lyd_node_term*)node1;
1565 term2 = (struct lyd_node_term*)node2;
1566 type = ((struct lysc_node_leaf*)node1->schema)->type;
1567
1568 return type->plugin->compare(&term1->value, &term2->value);
1569 case LYS_CONTAINER:
1570 if (options & LYD_COMPARE_DEFAULTS) {
1571 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
1572 return LY_ENOT;
1573 }
1574 }
1575 if (options & LYD_COMPARE_FULL_RECURSION) {
1576 iter1 = ((struct lyd_node_inner*)node1)->child;
1577 iter2 = ((struct lyd_node_inner*)node2)->child;
1578 goto all_children_compare;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001579 }
1580 return LY_SUCCESS;
Michal Vasko1bf09392020-03-27 12:38:10 +01001581 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01001582 case LYS_ACTION:
1583 if (options & LYD_COMPARE_FULL_RECURSION) {
1584 /* TODO action/RPC
1585 goto all_children_compare;
1586 */
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001587 }
1588 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01001589 case LYS_NOTIF:
1590 if (options & LYD_COMPARE_FULL_RECURSION) {
1591 /* TODO Notification
1592 goto all_children_compare;
1593 */
1594 }
1595 return LY_SUCCESS;
1596 case LYS_LIST:
1597 iter1 = ((struct lyd_node_inner*)node1)->child;
1598 iter2 = ((struct lyd_node_inner*)node2)->child;
1599
1600 if (!(node1->schema->flags & LYS_KEYLESS) && !(options & LYD_COMPARE_FULL_RECURSION)) {
1601 /* lists with keys, their equivalence is based on their keys */
1602 for (struct lysc_node *key = ((struct lysc_node_list*)node1->schema)->child;
1603 key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
1604 key = key->next) {
1605 if (lyd_compare(iter1, iter2, options)) {
1606 return LY_ENOT;
1607 }
1608 iter1 = iter1->next;
1609 iter2 = iter2->next;
1610 }
1611 } else {
1612 /* lists without keys, their equivalence is based on equivalence of all the children (both direct and indirect) */
1613
1614 all_children_compare:
1615 if (!iter1 && !iter2) {
1616 /* no children, nothing to compare */
1617 return LY_SUCCESS;
1618 }
1619
1620 for (; iter1 && iter2; iter1 = iter1->next, iter2 = iter2->next) {
1621 if (lyd_compare(iter1, iter2, options | LYD_COMPARE_FULL_RECURSION)) {
1622 return LY_ENOT;
1623 }
1624 }
1625 if (iter1 || iter2) {
1626 return LY_ENOT;
1627 }
1628 }
1629 return LY_SUCCESS;
1630 case LYS_ANYXML:
1631 case LYS_ANYDATA:
1632 any1 = (struct lyd_node_any*)node1;
1633 any2 = (struct lyd_node_any*)node2;
1634
1635 if (any1->value_type != any2->value_type) {
1636 return LY_ENOT;
1637 }
1638 switch (any1->value_type) {
1639 case LYD_ANYDATA_DATATREE:
1640 iter1 = any1->value.tree;
1641 iter2 = any2->value.tree;
1642 goto all_children_compare;
1643 case LYD_ANYDATA_STRING:
1644 case LYD_ANYDATA_XML:
1645 case LYD_ANYDATA_JSON:
1646 len1 = strlen(any1->value.str);
1647 len2 = strlen(any2->value.str);
1648 if (len1 != len2 || strcmp(any1->value.str, any2->value.str)) {
1649 return LY_ENOT;
1650 }
1651 return LY_SUCCESS;
1652 #if 0 /* TODO LYB format */
1653 case LYD_ANYDATA_LYB:
1654 int len1 = lyd_lyb_data_length(any1->value.mem);
1655 int len2 = lyd_lyb_data_length(any2->value.mem);
1656 if (len1 != len2 || memcmp(any1->value.mem, any2->value.mem, len1)) {
1657 return LY_ENOT;
1658 }
1659 return LY_SUCCESS;
1660 #endif
1661 }
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001662 }
1663 }
1664
Michal Vasko52927e22020-03-16 17:26:14 +01001665 LOGINT(LYD_NODE_CTX(node1));
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001666 return LY_EINT;
1667}
Radek Krejci22ebdba2019-07-25 13:59:43 +02001668
1669/**
Michal Vasko52927e22020-03-16 17:26:14 +01001670 * @brief Duplicate a single node and connect it into @p parent (if present) or last of @p first siblings.
Radek Krejci22ebdba2019-07-25 13:59:43 +02001671 *
1672 * Ignores LYD_DUP_WITH_PARENTS and LYD_DUP_WITH_SIBLINGS which are supposed to be handled by lyd_dup().
1673 */
Michal Vasko52927e22020-03-16 17:26:14 +01001674static LY_ERR
1675lyd_dup_recursive(const struct lyd_node *node, struct lyd_node *parent, struct lyd_node **first, int options,
1676 struct lyd_node **dup_p)
Radek Krejci22ebdba2019-07-25 13:59:43 +02001677{
Michal Vasko52927e22020-03-16 17:26:14 +01001678 LY_ERR ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001679 struct lyd_node *dup = NULL;
Michal Vasko52927e22020-03-16 17:26:14 +01001680 uint32_t u;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001681
Michal Vasko52927e22020-03-16 17:26:14 +01001682 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001683
Michal Vasko52927e22020-03-16 17:26:14 +01001684 if (!node->schema) {
1685 dup = calloc(1, sizeof(struct lyd_node_opaq));
1686 } else {
1687 switch (node->schema->nodetype) {
Michal Vasko1bf09392020-03-27 12:38:10 +01001688 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01001689 case LYS_ACTION:
1690 case LYS_NOTIF:
1691 case LYS_CONTAINER:
1692 case LYS_LIST:
1693 dup = calloc(1, sizeof(struct lyd_node_inner));
1694 break;
1695 case LYS_LEAF:
1696 case LYS_LEAFLIST:
1697 dup = calloc(1, sizeof(struct lyd_node_term));
1698 break;
1699 case LYS_ANYDATA:
1700 case LYS_ANYXML:
1701 dup = calloc(1, sizeof(struct lyd_node_any));
1702 break;
1703 default:
1704 LOGINT(LYD_NODE_CTX(node));
1705 ret = LY_EINT;
1706 goto error;
1707 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02001708 }
Michal Vasko52927e22020-03-16 17:26:14 +01001709 LY_CHECK_ERR_GOTO(!dup, LOGMEM(LYD_NODE_CTX(node)); ret = LY_EMEM, error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001710
1711 /* TODO implement LYD_DUP_WITH_WHEN */
1712 dup->flags = node->flags;
1713 dup->schema = node->schema;
Michal Vasko52927e22020-03-16 17:26:14 +01001714 dup->prev = dup;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001715
1716 /* TODO duplicate attributes, implement LYD_DUP_NO_ATTR */
1717
1718 /* nodetype-specific work */
Michal Vasko52927e22020-03-16 17:26:14 +01001719 if (!dup->schema) {
1720 struct lyd_node_opaq *opaq = (struct lyd_node_opaq *)dup;
1721 struct lyd_node_opaq *orig = (struct lyd_node_opaq *)node;
1722 struct lyd_node *child;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001723
1724 if (options & LYD_DUP_RECURSIVE) {
1725 /* duplicate all the children */
1726 LY_LIST_FOR(orig->child, child) {
Michal Vasko52927e22020-03-16 17:26:14 +01001727 LY_CHECK_GOTO(ret = lyd_dup_recursive(child, dup, NULL, options, NULL), error);
1728 }
1729 }
1730 opaq->name = lydict_insert(LYD_NODE_CTX(node), orig->name, 0);
1731 opaq->format = orig->format;
1732 if (orig->prefix.pref) {
1733 opaq->prefix.pref = lydict_insert(LYD_NODE_CTX(node), orig->prefix.pref, 0);
1734 }
1735 if (orig->prefix.ns) {
1736 opaq->prefix.ns = lydict_insert(LYD_NODE_CTX(node), orig->prefix.ns, 0);
1737 }
1738 if (orig->val_prefs) {
1739 LY_ARRAY_CREATE_GOTO(LYD_NODE_CTX(node), opaq->val_prefs, LY_ARRAY_SIZE(orig->val_prefs), ret, error);
1740 LY_ARRAY_FOR(orig->val_prefs, u) {
1741 opaq->val_prefs[u].pref = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].pref, 0);
1742 opaq->val_prefs[u].ns = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].ns, 0);
1743 LY_ARRAY_INCREMENT(opaq->val_prefs);
1744 }
1745 }
1746 opaq->value = lydict_insert(LYD_NODE_CTX(node), orig->value, 0);
1747 opaq->ctx = orig->ctx;
1748 } else if (dup->schema->nodetype & LYD_NODE_TERM) {
1749 struct lyd_node_term *term = (struct lyd_node_term *)dup;
1750 struct lyd_node_term *orig = (struct lyd_node_term *)node;
1751
1752 term->hash = orig->hash;
1753 term->value.realtype = orig->value.realtype;
1754 LY_CHECK_ERR_GOTO(term->value.realtype->plugin->duplicate(LYD_NODE_CTX(node), &orig->value, &term->value),
1755 LOGERR(LYD_NODE_CTX(node), LY_EINT, "Value duplication failed."); ret = LY_EINT, error);
1756 } else if (dup->schema->nodetype & LYD_NODE_INNER) {
1757 struct lyd_node_inner *orig = (struct lyd_node_inner *)node;
1758 struct lyd_node *child;
1759
1760 if (options & LYD_DUP_RECURSIVE) {
1761 /* duplicate all the children */
1762 LY_LIST_FOR(orig->child, child) {
1763 LY_CHECK_GOTO(ret = lyd_dup_recursive(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001764 }
Radek Krejci0fe9b512019-07-26 17:51:05 +02001765 } else if (dup->schema->nodetype == LYS_LIST && !(dup->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001766 /* always duplicate keys of a list */
Radek Krejci22ebdba2019-07-25 13:59:43 +02001767 child = orig->child;
Michal Vasko52927e22020-03-16 17:26:14 +01001768 for (struct lysc_node *key = ((struct lysc_node_list *)dup->schema)->child;
Radek Krejci0fe9b512019-07-26 17:51:05 +02001769 key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
1770 key = key->next) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001771 if (!child) {
1772 /* possibly not keys are present in filtered tree */
1773 break;
Radek Krejci0fe9b512019-07-26 17:51:05 +02001774 } else if (child->schema != key) {
1775 /* possibly not all keys are present in filtered tree,
1776 * but there can be also some non-key nodes */
1777 continue;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001778 }
Michal Vasko52927e22020-03-16 17:26:14 +01001779 LY_CHECK_GOTO(ret = lyd_dup_recursive(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001780 child = child->next;
1781 }
1782 }
1783 lyd_hash(dup);
1784 } else if (dup->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko52927e22020-03-16 17:26:14 +01001785 struct lyd_node_any *any = (struct lyd_node_any *)dup;
1786 struct lyd_node_any *orig = (struct lyd_node_any *)node;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001787
1788 any->hash = orig->hash;
1789 any->value_type = orig->value_type;
1790 switch (any->value_type) {
1791 case LYD_ANYDATA_DATATREE:
1792 if (orig->value.tree) {
1793 any->value.tree = lyd_dup(orig->value.tree, NULL, LYD_DUP_RECURSIVE | LYD_DUP_WITH_SIBLINGS);
1794 LY_CHECK_GOTO(!any->value.tree, error);
1795 }
1796 break;
1797 case LYD_ANYDATA_STRING:
1798 case LYD_ANYDATA_XML:
1799 case LYD_ANYDATA_JSON:
1800 if (orig->value.str) {
Michal Vasko52927e22020-03-16 17:26:14 +01001801 any->value.str = lydict_insert(LYD_NODE_CTX(node), orig->value.str, strlen(orig->value.str));
Radek Krejci22ebdba2019-07-25 13:59:43 +02001802 }
1803 break;
1804 }
1805 }
1806
Michal Vasko52927e22020-03-16 17:26:14 +01001807 /* insert */
1808 lyd_insert_node(parent, first, dup);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001809 lyd_insert_hash(dup);
Michal Vasko52927e22020-03-16 17:26:14 +01001810
1811 if (dup_p) {
1812 *dup_p = dup;
1813 }
1814 return LY_SUCCESS;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001815
1816error:
Michal Vasko52927e22020-03-16 17:26:14 +01001817 lyd_free_tree(dup);
1818 return ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001819}
1820
1821API struct lyd_node *
1822lyd_dup(const struct lyd_node *node, struct lyd_node_inner *parent, int options)
1823{
1824 struct ly_ctx *ctx;
1825 const struct lyd_node *orig; /* original node to be duplicated */
1826 struct lyd_node *first = NULL; /* the first duplicated node, this is returned */
Radek Krejci22ebdba2019-07-25 13:59:43 +02001827 struct lyd_node *top = NULL; /* the most higher created node */
1828 struct lyd_node_inner *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
1829 int keyless_parent_list = 0;
1830
1831 LY_CHECK_ARG_RET(NULL, node, NULL);
1832 ctx = node->schema->module->ctx;
1833
1834 if (options & LYD_DUP_WITH_PARENTS) {
1835 struct lyd_node_inner *orig_parent, *iter;
1836 int repeat = 1;
1837 for (top = NULL, orig_parent = node->parent; repeat && orig_parent; orig_parent = orig_parent->parent) {
1838 if (parent && parent->schema == orig_parent->schema) {
1839 /* stop creating parents, connect what we have into the provided parent */
1840 iter = parent;
1841 repeat = 0;
1842 /* get know if there is a keyless list which we will have to rehash */
1843 for (struct lyd_node_inner *piter = parent; piter; piter = piter->parent) {
Radek Krejci0fe9b512019-07-26 17:51:05 +02001844 if (piter->schema->nodetype == LYS_LIST && (piter->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001845 keyless_parent_list = 1;
1846 break;
1847 }
1848 }
1849 } else {
Michal Vasko52927e22020-03-16 17:26:14 +01001850 iter = NULL;
1851 LY_CHECK_GOTO(lyd_dup_recursive((struct lyd_node *)orig_parent, NULL, (struct lyd_node **)&iter, 0,
1852 (struct lyd_node **)&iter), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001853 }
1854 if (!local_parent) {
1855 local_parent = iter;
1856 }
1857 if (iter->child) {
1858 /* 1) list - add after keys
1859 * 2) provided parent with some children */
1860 iter->child->prev->next = top;
1861 if (top) {
1862 top->prev = iter->child->prev;
1863 iter->child->prev = top;
1864 }
1865 } else {
1866 iter->child = top;
1867 if (iter->schema->nodetype == LYS_LIST) {
1868 /* keyless list - we will need to rehash it since we are going to add nodes into it */
1869 keyless_parent_list = 1;
1870 }
1871 }
1872 if (top) {
1873 top->parent = iter;
1874 }
1875 top = (struct lyd_node*)iter;
1876 }
1877 if (repeat && parent) {
1878 /* given parent and created parents chain actually do not interconnect */
1879 LOGERR(ctx, LY_EINVAL, "Invalid argument parent (%s()) - does not interconnect with the created node's parents chain.", __func__);
1880 goto error;
1881 }
1882 } else {
1883 local_parent = parent;
1884 }
1885
Radek Krejci22ebdba2019-07-25 13:59:43 +02001886 LY_LIST_FOR(node, orig) {
Michal Vasko52927e22020-03-16 17:26:14 +01001887 /* if there is no local parent, it will be inserted into first */
1888 LY_CHECK_GOTO(lyd_dup_recursive(orig, (struct lyd_node *)local_parent, &first, options, first ? NULL : &first), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001889 if (!(options & LYD_DUP_WITH_SIBLINGS)) {
1890 break;
1891 }
1892 }
1893 if (keyless_parent_list) {
1894 /* rehash */
1895 for (; local_parent; local_parent = local_parent->parent) {
Radek Krejci0fe9b512019-07-26 17:51:05 +02001896 if (local_parent->schema->nodetype == LYS_LIST && (local_parent->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001897 lyd_hash((struct lyd_node*)local_parent);
1898 }
1899 }
1900 }
1901 return first;
1902
1903error:
1904 if (top) {
1905 lyd_free_tree(top);
1906 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +01001907 lyd_free_siblings(first);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001908 }
1909 return NULL;
1910}
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001911
1912static LY_ERR
1913lyd_path_str_enlarge(char **buffer, size_t *buflen, size_t reqlen, int is_static)
1914{
Michal Vasko14654712020-02-06 08:35:21 +01001915 /* ending \0 */
1916 ++reqlen;
1917
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001918 if (reqlen > *buflen) {
1919 if (is_static) {
1920 return LY_EINCOMPLETE;
1921 }
1922
1923 *buffer = ly_realloc(*buffer, reqlen * sizeof **buffer);
1924 if (!*buffer) {
1925 return LY_EMEM;
1926 }
1927
1928 *buflen = reqlen;
1929 }
1930
1931 return LY_SUCCESS;
1932}
1933
1934/**
1935 * @brief Append all list key predicates to path.
1936 *
1937 * @param[in] node Node with keys to print.
1938 * @param[in,out] buffer Buffer to print to.
1939 * @param[in,out] buflen Current buffer length.
1940 * @param[in,out] bufused Current number of characters used in @p buffer.
1941 * @param[in] is_static Whether buffer is static or can be reallocated.
1942 * @return LY_ERR
1943 */
1944static LY_ERR
1945lyd_path_list_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
1946{
1947 const struct lyd_node *key;
1948 int dynamic = 0;
1949 size_t len;
1950 const char *val;
1951 char quot;
1952 LY_ERR rc;
1953
Michal Vasko14654712020-02-06 08:35:21 +01001954 for (key = lyd_node_children(node); key && (key->schema->flags & LYS_KEY); key = key->next) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001955 val = lyd_value2str((struct lyd_node_term *)key, &dynamic);
1956 len = 1 + strlen(key->schema->name) + 2 + strlen(val) + 2;
1957 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
1958 if (rc != LY_SUCCESS) {
1959 if (dynamic) {
1960 free((char *)val);
1961 }
1962 return rc;
1963 }
1964
1965 quot = '\'';
1966 if (strchr(val, '\'')) {
1967 quot = '"';
1968 }
1969 *bufused += sprintf(*buffer + *bufused, "[%s=%c%s%c]", key->schema->name, quot, val, quot);
1970
1971 if (dynamic) {
1972 free((char *)val);
1973 }
1974 }
1975
1976 return LY_SUCCESS;
1977}
1978
1979/**
1980 * @brief Append leaf-list value predicate to path.
1981 *
1982 * @param[in] node Node to print.
1983 * @param[in,out] buffer Buffer to print to.
1984 * @param[in,out] buflen Current buffer length.
1985 * @param[in,out] bufused Current number of characters used in @p buffer.
1986 * @param[in] is_static Whether buffer is static or can be reallocated.
1987 * @return LY_ERR
1988 */
1989static LY_ERR
1990lyd_path_leaflist_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
1991{
1992 int dynamic = 0;
1993 size_t len;
1994 const char *val;
1995 char quot;
1996 LY_ERR rc;
1997
1998 val = lyd_value2str((struct lyd_node_term *)node, &dynamic);
1999 len = 4 + strlen(val) + 2;
2000 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2001 if (rc != LY_SUCCESS) {
2002 goto cleanup;
2003 }
2004
2005 quot = '\'';
2006 if (strchr(val, '\'')) {
2007 quot = '"';
2008 }
2009 *bufused += sprintf(*buffer + *bufused, "[.=%c%s%c]", quot, val, quot);
2010
2011cleanup:
2012 if (dynamic) {
2013 free((char *)val);
2014 }
2015 return rc;
2016}
2017
2018/**
2019 * @brief Append node position (relative to its other instances) predicate to path.
2020 *
2021 * @param[in] node Node to print.
2022 * @param[in,out] buffer Buffer to print to.
2023 * @param[in,out] buflen Current buffer length.
2024 * @param[in,out] bufused Current number of characters used in @p buffer.
2025 * @param[in] is_static Whether buffer is static or can be reallocated.
2026 * @return LY_ERR
2027 */
2028static LY_ERR
2029lyd_path_position_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2030{
2031 const struct lyd_node *first, *iter;
2032 size_t len;
2033 int pos;
2034 char *val = NULL;
2035 LY_ERR rc;
2036
2037 if (node->parent) {
2038 first = node->parent->child;
2039 } else {
2040 for (first = node; node->prev->next; node = node->prev);
2041 }
2042 pos = 1;
2043 for (iter = first; iter != node; iter = iter->next) {
2044 if (iter->schema == node->schema) {
2045 ++pos;
2046 }
2047 }
2048 if (asprintf(&val, "%d", pos) == -1) {
2049 return LY_EMEM;
2050 }
2051
2052 len = 1 + strlen(val) + 1;
2053 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2054 if (rc != LY_SUCCESS) {
2055 goto cleanup;
2056 }
2057
2058 *bufused += sprintf(*buffer + *bufused, "[%s]", val);
2059
2060cleanup:
2061 free(val);
2062 return rc;
2063}
2064
2065API char *
2066lyd_path(const struct lyd_node *node, LYD_PATH_TYPE pathtype, char *buffer, size_t buflen)
2067{
Michal Vasko14654712020-02-06 08:35:21 +01002068 int is_static = 0, i, depth;
2069 size_t bufused = 0, len;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002070 const struct lyd_node *iter;
2071 const struct lys_module *mod;
2072 LY_ERR rc;
2073
2074 LY_CHECK_ARG_RET(NULL, node, NULL);
2075 if (buffer) {
2076 LY_CHECK_ARG_RET(node->schema->module->ctx, buflen > 1, NULL);
2077 is_static = 1;
Michal Vasko14654712020-02-06 08:35:21 +01002078 } else {
2079 buflen = 0;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002080 }
2081
2082 switch (pathtype) {
Michal Vasko14654712020-02-06 08:35:21 +01002083 case LYD_PATH_LOG:
2084 depth = 1;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002085 for (iter = node; iter->parent; iter = (const struct lyd_node *)iter->parent) {
2086 ++depth;
2087 }
2088
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002089 goto iter_print;
Michal Vasko14654712020-02-06 08:35:21 +01002090 while (depth) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002091 /* find the right node */
Michal Vasko14654712020-02-06 08:35:21 +01002092 for (iter = node, i = 1; i < depth; iter = (const struct lyd_node *)iter->parent, ++i);
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002093iter_print:
2094 /* print prefix and name */
2095 mod = NULL;
2096 if (!iter->parent || (iter->schema->module != iter->parent->schema->module)) {
2097 mod = iter->schema->module;
2098 }
2099
2100 /* realloc string */
2101 len = 1 + (mod ? strlen(mod->name) + 1 : 0) + strlen(iter->schema->name);
2102 rc = lyd_path_str_enlarge(&buffer, &buflen, bufused + len, is_static);
2103 if (rc != LY_SUCCESS) {
2104 break;
2105 }
2106
2107 /* print next node */
2108 bufused += sprintf(buffer + bufused, "/%s%s%s", mod ? mod->name : "", mod ? ":" : "", iter->schema->name);
2109
2110 switch (iter->schema->nodetype) {
2111 case LYS_LIST:
2112 if (iter->schema->flags & LYS_KEYLESS) {
2113 /* print its position */
2114 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2115 } else {
2116 /* print all list keys in predicates */
2117 rc = lyd_path_list_predicate(iter, &buffer, &buflen, &bufused, is_static);
2118 }
2119 break;
2120 case LYS_LEAFLIST:
2121 if (iter->schema->flags & LYS_CONFIG_W) {
2122 /* print leaf-list value */
2123 rc = lyd_path_leaflist_predicate(iter, &buffer, &buflen, &bufused, is_static);
2124 } else {
2125 /* print its position */
2126 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2127 }
2128 break;
2129 default:
2130 /* nothing to print more */
2131 rc = LY_SUCCESS;
2132 break;
2133 }
2134 if (rc != LY_SUCCESS) {
2135 break;
2136 }
2137
Michal Vasko14654712020-02-06 08:35:21 +01002138 --depth;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002139 }
2140 break;
2141 }
2142
2143 return buffer;
2144}
Michal Vaskoe444f752020-02-10 12:20:06 +01002145
Michal Vasko9b368d32020-02-14 13:53:31 +01002146LY_ERR
2147lyd_find_sibling_next2(const struct lyd_node *first, const struct lysc_node *schema, const char *key_or_value,
2148 size_t val_len, struct lyd_node **match)
Michal Vaskoe444f752020-02-10 12:20:06 +01002149{
2150 LY_ERR rc;
2151 const struct lyd_node *node = NULL;
2152 struct lyd_node_term *term;
Michal Vaskoe444f752020-02-10 12:20:06 +01002153 struct ly_keys keys = {0};
Michal Vasko90932a92020-02-12 14:33:03 +01002154 struct lyd_value val = {0};
Michal Vaskoe444f752020-02-10 12:20:06 +01002155 size_t i;
Michal Vaskoe444f752020-02-10 12:20:06 +01002156
Michal Vasko9b368d32020-02-14 13:53:31 +01002157 LY_CHECK_ARG_RET(NULL, schema, LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01002158
2159 if (!first) {
2160 /* no data */
Michal Vasko9b368d32020-02-14 13:53:31 +01002161 if (match) {
2162 *match = NULL;
2163 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002164 return LY_ENOTFOUND;
2165 }
2166
Michal Vaskoe444f752020-02-10 12:20:06 +01002167 if (key_or_value && !val_len) {
2168 val_len = strlen(key_or_value);
2169 }
2170
2171 if (key_or_value && (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko90932a92020-02-12 14:33:03 +01002172 /* store the value */
Michal Vasko9b368d32020-02-14 13:53:31 +01002173 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 +01002174 } else if (key_or_value && (schema->nodetype == LYS_LIST)) {
2175 /* parse keys into canonical values */
2176 LY_CHECK_GOTO(rc = ly_keys_parse(schema, key_or_value, val_len, 1, &keys), cleanup);
2177 }
2178
2179 /* find first matching value */
2180 LY_LIST_FOR(first, node) {
2181 if (node->schema != schema) {
2182 continue;
2183 }
2184
2185 if ((schema->nodetype == LYS_LIST) && keys.str) {
2186 /* compare all set keys */
2187 for (i = 0; i < keys.key_count; ++i) {
2188 /* find key */
2189 rc = lyd_find_sibling_val(lyd_node_children(node), (struct lysc_node *)keys.keys[i].schema, NULL, 0,
2190 (struct lyd_node **)&term);
2191 if (rc == LY_ENOTFOUND) {
2192 /* all keys must always exist */
Michal Vasko9b368d32020-02-14 13:53:31 +01002193 LOGINT_RET(schema->module->ctx);
Michal Vaskoe444f752020-02-10 12:20:06 +01002194 }
2195 LY_CHECK_GOTO(rc, cleanup);
2196
2197 /* compare values */
Michal Vasko90932a92020-02-12 14:33:03 +01002198 if (!term->value.realtype->plugin->compare(&term->value, &keys.keys[i].val)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002199 break;
2200 }
2201 }
2202
2203 if (i < keys.key_count) {
2204 /* not a match */
2205 continue;
2206 }
Michal Vasko90932a92020-02-12 14:33:03 +01002207 } else if ((schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && val.realtype) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002208 term = (struct lyd_node_term *)node;
2209
2210 /* compare values */
Michal Vasko90932a92020-02-12 14:33:03 +01002211 if (!term->value.realtype->plugin->compare(&term->value, &val)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002212 /* not a match */
2213 continue;
2214 }
2215 }
2216
2217 /* all criteria passed */
2218 break;
2219 }
2220
2221 if (!node) {
2222 rc = LY_ENOTFOUND;
Michal Vasko9b368d32020-02-14 13:53:31 +01002223 if (match) {
2224 *match = NULL;
2225 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002226 goto cleanup;
2227 }
2228
2229 /* success */
Michal Vasko9b368d32020-02-14 13:53:31 +01002230 if (match) {
2231 *match = (struct lyd_node *)node;
2232 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002233 rc = LY_SUCCESS;
2234
2235cleanup:
2236 ly_keys_clean(&keys);
Michal Vasko90932a92020-02-12 14:33:03 +01002237 if (val.realtype) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002238 val.realtype->plugin->free(schema->module->ctx, &val);
Michal Vasko90932a92020-02-12 14:33:03 +01002239 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002240 return rc;
2241}
2242
2243API LY_ERR
Michal Vasko9b368d32020-02-14 13:53:31 +01002244lyd_find_sibling_next(const struct lyd_node *first, const struct lys_module *module, const char *name, size_t name_len,
2245 const char *key_or_value, size_t val_len, struct lyd_node **match)
2246{
2247 const struct lysc_node *schema;
2248
2249 LY_CHECK_ARG_RET(NULL, module, name, match, LY_EINVAL);
2250
2251 if (!first) {
2252 /* no data */
2253 *match = NULL;
2254 return LY_ENOTFOUND;
2255 }
2256
2257 /* find schema */
2258 schema = lys_find_child(first->parent ? first->parent->schema : NULL, module, name, name_len, 0, 0);
2259 if (!schema) {
2260 LOGERR(module->ctx, LY_EINVAL, "Schema node not found.");
2261 return LY_EINVAL;
2262 }
2263
2264 return lyd_find_sibling_next2(first, schema, key_or_value, val_len, match);
2265}
2266
2267API LY_ERR
Michal Vaskoe444f752020-02-10 12:20:06 +01002268lyd_find_sibling_first(const struct lyd_node *siblings, const struct lyd_node *target, struct lyd_node **match)
2269{
2270 struct lyd_node **match_p;
2271 struct lyd_node_inner *parent;
2272
Michal Vaskof03ed032020-03-04 13:31:44 +01002273 LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01002274
2275 if (!siblings) {
2276 /* no data */
Michal Vasko9b368d32020-02-14 13:53:31 +01002277 if (match) {
2278 *match = NULL;
2279 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002280 return LY_ENOTFOUND;
2281 }
2282
2283 /* find first sibling */
2284 if (siblings->parent) {
2285 siblings = siblings->parent->child;
2286 } else {
2287 while (siblings->prev->next) {
2288 siblings = siblings->prev;
2289 }
2290 }
2291
2292 parent = (struct lyd_node_inner *)siblings->parent;
2293 if (parent && parent->children_ht) {
2294 assert(target->hash);
2295
2296 /* find by hash */
2297 if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
2298 siblings = *match_p;
2299 } else {
2300 /* not found */
2301 siblings = NULL;
2302 }
2303 } else {
2304 /* no children hash table */
2305 for (; siblings; siblings = siblings->next) {
2306 if (!lyd_compare(siblings, target, 0)) {
2307 break;
2308 }
2309 }
2310 }
2311
2312 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002313 if (match) {
2314 *match = NULL;
2315 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002316 return LY_ENOTFOUND;
2317 }
2318
Michal Vasko9b368d32020-02-14 13:53:31 +01002319 if (match) {
2320 *match = (struct lyd_node *)siblings;
2321 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002322 return LY_SUCCESS;
2323}
2324
2325API LY_ERR
2326lyd_find_sibling_set(const struct lyd_node *siblings, const struct lyd_node *target, struct ly_set **set)
2327{
2328 struct lyd_node_inner *parent;
2329 struct lyd_node *match;
2330 struct lyd_node **match_p;
2331 struct ly_set *ret;
2332
2333 LY_CHECK_ARG_RET(NULL, target, set, LY_EINVAL);
2334
2335 if (!siblings) {
2336 /* no data */
2337 return LY_ENOTFOUND;
2338 }
2339
2340 ret = ly_set_new();
2341 LY_CHECK_ERR_RET(!ret, LOGMEM(target->schema->module->ctx), LY_EMEM);
2342
2343 /* find first sibling */
2344 if (siblings->parent) {
2345 siblings = siblings->parent->child;
2346 } else {
2347 while (siblings->prev->next) {
2348 siblings = siblings->prev;
2349 }
2350 }
2351
2352 parent = (struct lyd_node_inner *)siblings->parent;
2353 if (parent && parent->children_ht) {
2354 assert(target->hash);
2355
2356 /* find by hash */
2357 if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
2358 match = *match_p;
2359 } else {
2360 /* not found */
2361 match = NULL;
2362 }
2363 while (match) {
2364 /* add all found nodes into the return set */
2365 if (ly_set_add(ret, match, LY_SET_OPT_USEASLIST) == -1) {
2366 goto error;
2367 }
2368
2369 /* find next instance */
2370 if (lyht_find_next(parent->children_ht, &match, match->hash, (void **)&match_p)) {
2371 match = NULL;
2372 } else {
2373 match = *match_p;
2374 }
2375 }
2376 } else {
2377 /* no children hash table */
2378 for (; siblings; siblings = siblings->next) {
2379 if (!lyd_compare(siblings, target, 0)) {
2380 /* a match */
2381 if (ly_set_add(ret, (struct lyd_node *)siblings, LY_SET_OPT_USEASLIST) == -1) {
2382 goto error;
2383 }
2384 }
2385 }
2386 }
2387
2388 if (!ret->count) {
2389 ly_set_free(ret, NULL);
2390 return LY_ENOTFOUND;
2391 }
2392
2393 *set = ret;
2394 return LY_SUCCESS;
2395
2396error:
2397 ly_set_free(ret, NULL);
2398 return LY_EMEM;
2399}
2400
Michal Vasko90932a92020-02-12 14:33:03 +01002401static int
2402lyd_hash_table_schema_val_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *UNUSED(cb_data))
2403{
2404 struct lysc_node *val1;
2405 struct lyd_node *val2;
2406
2407 val1 = *((struct lysc_node **)val1_p);
2408 val2 = *((struct lyd_node **)val2_p);
2409
2410 assert(val1->nodetype & (LYD_NODE_INNER | LYS_LEAF));
2411
2412 if (val1 == val2->schema) {
2413 /* schema match is enough */
2414 return 1;
2415 } else {
2416 return 0;
2417 }
2418}
2419
2420static LY_ERR
2421lyd_find_sibling_schema(const struct lyd_node *siblings, const struct lysc_node *schema, struct lyd_node **match)
2422{
2423 struct lyd_node **match_p;
2424 struct lyd_node_inner *parent;
2425 uint32_t hash;
2426 values_equal_cb ht_cb;
2427
2428 assert(siblings && schema && (schema->nodetype & (LYD_NODE_INNER | LYS_LEAF)));
2429
2430 /* find first sibling */
2431 if (siblings->parent) {
2432 siblings = siblings->parent->child;
2433 } else {
2434 while (siblings->prev->next) {
2435 siblings = siblings->prev;
2436 }
2437 }
2438
2439 parent = (struct lyd_node_inner *)siblings->parent;
2440 if (parent && parent->children_ht) {
2441 /* calculate our hash */
2442 hash = dict_hash_multi(0, schema->module->name, strlen(schema->module->name));
2443 hash = dict_hash_multi(hash, schema->name, strlen(schema->name));
2444 hash = dict_hash_multi(hash, NULL, 0);
2445
2446 /* use special hash table function */
2447 ht_cb = lyht_set_cb(parent->children_ht, lyd_hash_table_schema_val_equal);
2448
2449 /* find by hash */
2450 if (!lyht_find(parent->children_ht, &schema, hash, (void **)&match_p)) {
2451 siblings = *match_p;
2452 } else {
2453 /* not found */
2454 siblings = NULL;
2455 }
2456
2457 /* set the original hash table compare function back */
2458 lyht_set_cb(parent->children_ht, ht_cb);
2459 } else {
2460 /* no children hash table */
2461 for (; siblings; siblings = siblings->next) {
2462 if (siblings->schema == schema) {
2463 /* schema match is enough */
2464 break;
2465 }
2466 }
2467 }
2468
2469 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002470 if (match) {
2471 *match = NULL;
2472 }
Michal Vasko90932a92020-02-12 14:33:03 +01002473 return LY_ENOTFOUND;
2474 }
2475
Michal Vasko9b368d32020-02-14 13:53:31 +01002476 if (match) {
2477 *match = (struct lyd_node *)siblings;
2478 }
Michal Vasko90932a92020-02-12 14:33:03 +01002479 return LY_SUCCESS;
2480}
2481
Michal Vaskoe444f752020-02-10 12:20:06 +01002482API LY_ERR
2483lyd_find_sibling_val(const struct lyd_node *siblings, const struct lysc_node *schema, const char *key_or_value,
2484 size_t val_len, struct lyd_node **match)
2485{
2486 LY_ERR rc;
2487 struct lyd_node *target = NULL;
2488
2489 LY_CHECK_ARG_RET(NULL, schema, LY_EINVAL);
2490 if ((schema->nodetype == LYS_LIST) && schema->flags & LYS_KEYLESS) {
2491 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - key-less list (%s()).", __func__);
2492 return LY_EINVAL;
2493 } else if ((schema->nodetype & (LYS_LEAFLIST | LYS_LIST)) && !key_or_value) {
2494 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - no value/keys for a (leaf-)list (%s()).", __func__);
2495 return LY_EINVAL;
2496 } else if (schema->nodetype & (LYS_CHOICE | LYS_CASE)) {
2497 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - schema type %s (%s()).",
2498 lys_nodetype2str(schema->nodetype), __func__);
2499 return LY_EINVAL;
2500 }
2501
2502 if (!siblings) {
2503 /* no data */
Michal Vasko9b368d32020-02-14 13:53:31 +01002504 if (match) {
2505 *match = NULL;
2506 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002507 return LY_ENOTFOUND;
2508 }
2509
Michal Vaskof03ed032020-03-04 13:31:44 +01002510 if (key_or_value && !val_len) {
2511 val_len = strlen(key_or_value);
2512 }
2513
Michal Vasko90932a92020-02-12 14:33:03 +01002514 /* create data node if needed and find it */
Michal Vaskoe444f752020-02-10 12:20:06 +01002515 switch (schema->nodetype) {
2516 case LYS_CONTAINER:
2517 case LYS_ANYXML:
2518 case LYS_ANYDATA:
2519 case LYS_NOTIF:
Michal Vasko1bf09392020-03-27 12:38:10 +01002520 case LYS_RPC:
Michal Vasko9b368d32020-02-14 13:53:31 +01002521 case LYS_ACTION:
Michal Vaskoe444f752020-02-10 12:20:06 +01002522 case LYS_LEAF:
Michal Vasko90932a92020-02-12 14:33:03 +01002523 /* find it based on schema only */
2524 rc = lyd_find_sibling_schema(siblings, schema, match);
Michal Vaskoe444f752020-02-10 12:20:06 +01002525 break;
2526 case LYS_LEAFLIST:
2527 /* target used attributes: schema, hash, value */
Michal Vasko90932a92020-02-12 14:33:03 +01002528 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 +01002529 /* fallthrough */
Michal Vaskoe444f752020-02-10 12:20:06 +01002530 case LYS_LIST:
Michal Vasko90932a92020-02-12 14:33:03 +01002531 if (schema->nodetype == LYS_LIST) {
2532 /* target used attributes: schema, hash, child (all keys) */
2533 LY_CHECK_RET(lyd_create_list(schema, key_or_value, val_len, &target));
Michal Vasko90932a92020-02-12 14:33:03 +01002534 }
2535
2536 /* find it */
2537 rc = lyd_find_sibling_first(siblings, target, match);
Michal Vaskoe444f752020-02-10 12:20:06 +01002538 break;
2539 default:
2540 /* unreachable */
2541 LOGINT(schema->module->ctx);
2542 return LY_EINT;
2543 }
2544
Michal Vaskoe444f752020-02-10 12:20:06 +01002545 lyd_free_tree(target);
2546 return rc;
2547}