blob: ae5818f0515af1fcf4085b3ccd44628ca3c4c80c [file] [log] [blame]
Radek Krejcie7b95092019-05-15 11:03:07 +02001/**
Michal Vaskob1b5c262020-03-05 14:29:47 +01002 * @file tree_data.c
Radek Krejcie7b95092019-05-15 11:03:07 +02003 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Schema tree implementation
5 *
6 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#include "common.h"
16
Radek Krejci084289f2019-07-09 17:35:30 +020017#include <assert.h>
Radek Krejcie7b95092019-05-15 11:03:07 +020018#include <ctype.h>
19#include <errno.h>
20#include <fcntl.h>
21#include <stdarg.h>
22#include <stdint.h>
23#include <string.h>
24#include <unistd.h>
25
26#include "log.h"
27#include "tree.h"
28#include "tree_data.h"
29#include "tree_data_internal.h"
Michal Vasko90932a92020-02-12 14:33:03 +010030#include "hash_table.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020031#include "tree_schema.h"
Radek Krejci38d85362019-09-05 16:26:38 +020032#include "plugins_exts_metadata.h"
Michal Vasko90932a92020-02-12 14:33:03 +010033#include "plugins_exts_internal.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020034
Michal Vaskoe444f752020-02-10 12:20:06 +010035struct ly_keys {
36 char *str;
37 struct {
38 const struct lysc_node_leaf *schema;
39 char *value;
Michal Vasko90932a92020-02-12 14:33:03 +010040 struct lyd_value val;
Michal Vaskoe444f752020-02-10 12:20:06 +010041 } *keys;
42 size_t key_count;
43};
44
Radek Krejci084289f2019-07-09 17:35:30 +020045LY_ERR
Michal Vasko90932a92020-02-12 14:33:03 +010046lyd_value_parse(struct lyd_node_term *node, const char *value, size_t value_len, int *dynamic, int second,
Michal Vaskof03ed032020-03-04 13:31:44 +010047 ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +020048{
Michal Vasko90932a92020-02-12 14:33:03 +010049 LY_ERR ret = LY_SUCCESS;
Radek Krejci084289f2019-07-09 17:35:30 +020050 struct ly_err_item *err = NULL;
51 struct ly_ctx *ctx;
52 struct lysc_type *type;
Radek Krejci3c9758d2019-07-11 16:49:10 +020053 int options = LY_TYPE_OPTS_STORE | (second ? LY_TYPE_OPTS_SECOND_CALL : 0) |
Michal Vaskof03ed032020-03-04 13:31:44 +010054 (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci084289f2019-07-09 17:35:30 +020055 assert(node);
56
57 ctx = node->schema->module->ctx;
Radek Krejci084289f2019-07-09 17:35:30 +020058
Radek Krejci73dead22019-07-11 16:46:16 +020059 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci62903c32019-07-15 14:42:05 +020060 if (!second) {
61 node->value.realtype = type;
62 }
Michal Vasko90932a92020-02-12 14:33:03 +010063 ret = type->plugin->store(ctx, type, value, value_len, options, get_prefix, parser, format,
Michal Vaskof03ed032020-03-04 13:31:44 +010064 tree ? (void *)node : (void *)node->schema, tree,
Radek Krejci73dead22019-07-11 16:46:16 +020065 &node->value, NULL, &err);
Michal Vasko90932a92020-02-12 14:33:03 +010066 if (ret && (ret != LY_EINCOMPLETE)) {
Radek Krejci73dead22019-07-11 16:46:16 +020067 if (err) {
68 ly_err_print(err);
69 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
70 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +020071 }
Radek Krejci73dead22019-07-11 16:46:16 +020072 goto error;
Michal Vasko90932a92020-02-12 14:33:03 +010073 } else if (dynamic) {
74 *dynamic = 0;
Radek Krejci084289f2019-07-09 17:35:30 +020075 }
76
77error:
78 return ret;
79}
80
Michal Vasko90932a92020-02-12 14:33:03 +010081/* similar to lyd_value_parse except can be used just to store the value, hence does also not support a second call */
82static LY_ERR
83lyd_value_store(struct lyd_value *val, const struct lysc_node *schema, const char *value, size_t value_len, int *dynamic,
84 ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format)
85{
86 LY_ERR ret = LY_SUCCESS;
87 struct ly_err_item *err = NULL;
88 struct ly_ctx *ctx;
89 struct lysc_type *type;
90 int options = LY_TYPE_OPTS_STORE | LY_TYPE_OPTS_INCOMPLETE_DATA | (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0);
91
92 assert(val && schema && (schema->nodetype & LYD_NODE_TERM));
93
94 ctx = schema->module->ctx;
95 type = ((struct lysc_node_leaf *)schema)->type;
96 val->realtype = type;
97 ret = type->plugin->store(ctx, type, value, value_len, options, get_prefix, parser, format, (void *)schema, NULL,
98 val, NULL, &err);
99 if (ret == LY_EINCOMPLETE) {
100 /* this is fine, we do not need it resolved */
101 ret = LY_SUCCESS;
102 } else if (ret && err) {
103 ly_err_print(err);
104 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
105 ly_err_free(err);
106 }
107 if (!ret && dynamic) {
108 *dynamic = 0;
109 }
110
111 return ret;
112}
113
Radek Krejci38d85362019-09-05 16:26:38 +0200114LY_ERR
Michal Vasko8d544252020-03-02 10:19:52 +0100115lyd_value_parse_attr(struct ly_ctx *ctx, struct lyd_attr *attr, const char *value, size_t value_len, int *dynamic,
116 int second, ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format,
Michal Vaskof03ed032020-03-04 13:31:44 +0100117 const struct lysc_node *ctx_snode, const struct lyd_node *tree)
Radek Krejci38d85362019-09-05 16:26:38 +0200118{
Michal Vasko90932a92020-02-12 14:33:03 +0100119 LY_ERR ret = LY_SUCCESS;
Radek Krejci38d85362019-09-05 16:26:38 +0200120 struct ly_err_item *err = NULL;
Radek Krejci38d85362019-09-05 16:26:38 +0200121 struct lyext_metadata *ant;
122 int options = LY_TYPE_OPTS_STORE | (second ? LY_TYPE_OPTS_SECOND_CALL : 0) |
Michal Vaskof03ed032020-03-04 13:31:44 +0100123 (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci38d85362019-09-05 16:26:38 +0200124
Michal Vaskof03ed032020-03-04 13:31:44 +0100125 assert(ctx && attr && ((tree && attr->parent) || ctx_snode));
Michal Vasko8d544252020-03-02 10:19:52 +0100126
Radek Krejci38d85362019-09-05 16:26:38 +0200127 ant = attr->annotation->data;
128
129 if (!second) {
130 attr->value.realtype = ant->type;
131 }
Michal Vasko90932a92020-02-12 14:33:03 +0100132 ret = ant->type->plugin->store(ctx, ant->type, value, value_len, options, get_prefix, parser, format,
Michal Vaskof03ed032020-03-04 13:31:44 +0100133 tree ? (void *)attr->parent : (void *)ctx_snode, tree, &attr->value, NULL, &err);
Michal Vasko90932a92020-02-12 14:33:03 +0100134 if (ret && (ret != LY_EINCOMPLETE)) {
Radek Krejci38d85362019-09-05 16:26:38 +0200135 if (err) {
136 ly_err_print(err);
137 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
138 ly_err_free(err);
139 }
140 goto error;
Michal Vasko90932a92020-02-12 14:33:03 +0100141 } else if (dynamic) {
142 *dynamic = 0;
Radek Krejci38d85362019-09-05 16:26:38 +0200143 }
144
145error:
146 return ret;
147}
148
Radek Krejci084289f2019-07-09 17:35:30 +0200149API LY_ERR
150lys_value_validate(struct ly_ctx *ctx, const struct lysc_node *node, const char *value, size_t value_len,
151 ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format)
152{
153 LY_ERR rc = LY_SUCCESS;
154 struct ly_err_item *err = NULL;
155 struct lysc_type *type;
Radek Krejci084289f2019-07-09 17:35:30 +0200156
157 LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
158
159 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
160 LOGARG(ctx, node);
161 return LY_EINVAL;
162 }
163
164 type = ((struct lysc_node_leaf*)node)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200165 /* just validate, no storing of enything */
166 rc = type->plugin->store(ctx ? ctx : node->module->ctx, type, value, value_len, LY_TYPE_OPTS_INCOMPLETE_DATA,
167 get_prefix, get_prefix_data, format, node, NULL, NULL, NULL, &err);
168 if (rc == LY_EINCOMPLETE) {
169 /* actually success since we do not provide the context tree and call validation with
170 * LY_TYPE_OPTS_INCOMPLETE_DATA */
171 rc = LY_SUCCESS;
172 } else if (rc && err) {
173 if (ctx) {
174 /* log only in case the ctx was provided as input parameter */
175 ly_err_print(err);
176 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
Radek Krejci084289f2019-07-09 17:35:30 +0200177 }
Radek Krejci73dead22019-07-11 16:46:16 +0200178 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200179 }
180
181 return rc;
182}
183
184API LY_ERR
185lyd_value_validate(struct ly_ctx *ctx, const struct lyd_node_term *node, const char *value, size_t value_len,
Michal Vaskof03ed032020-03-04 13:31:44 +0100186 ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +0200187{
188 LY_ERR rc;
189 struct ly_err_item *err = NULL;
190 struct lysc_type *type;
Michal Vaskof03ed032020-03-04 13:31:44 +0100191 int options = (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci084289f2019-07-09 17:35:30 +0200192
193 LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
194
195 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200196 rc = type->plugin->store(ctx ? ctx : node->schema->module->ctx, type, value, value_len, options,
Michal Vaskof03ed032020-03-04 13:31:44 +0100197 get_prefix, get_prefix_data, format, tree ? (void*)node : (void*)node->schema, tree,
Radek Krejci73dead22019-07-11 16:46:16 +0200198 NULL, NULL, &err);
199 if (rc == LY_EINCOMPLETE) {
200 return rc;
201 } else if (rc) {
202 if (err) {
203 if (ctx) {
204 ly_err_print(err);
205 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
Radek Krejci084289f2019-07-09 17:35:30 +0200206 }
Radek Krejci73dead22019-07-11 16:46:16 +0200207 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200208 }
Radek Krejci73dead22019-07-11 16:46:16 +0200209 return rc;
Radek Krejci084289f2019-07-09 17:35:30 +0200210 }
211
212 return LY_SUCCESS;
213}
214
215API LY_ERR
216lyd_value_compare(const struct lyd_node_term *node, const char *value, size_t value_len,
Michal Vaskof03ed032020-03-04 13:31:44 +0100217 ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +0200218{
219 LY_ERR ret = LY_SUCCESS, rc;
220 struct ly_err_item *err = NULL;
221 struct ly_ctx *ctx;
222 struct lysc_type *type;
Radek Krejci084289f2019-07-09 17:35:30 +0200223 struct lyd_value data = {0};
Michal Vaskof03ed032020-03-04 13:31:44 +0100224 int options = LY_TYPE_OPTS_STORE | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci084289f2019-07-09 17:35:30 +0200225
226 LY_CHECK_ARG_RET(node ? node->schema->module->ctx : NULL, node, value, LY_EINVAL);
227
228 ctx = node->schema->module->ctx;
229 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200230 rc = type->plugin->store(ctx, type, value, value_len, options, get_prefix, get_prefix_data, format, (struct lyd_node*)node,
Michal Vaskof03ed032020-03-04 13:31:44 +0100231 tree, &data, NULL, &err);
Radek Krejci73dead22019-07-11 16:46:16 +0200232 if (rc == LY_EINCOMPLETE) {
233 ret = rc;
234 /* continue with comparing, just remember what to return if storing is ok */
235 } else if (rc) {
236 /* value to compare is invalid */
237 ret = LY_EINVAL;
238 if (err) {
239 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200240 }
Radek Krejci73dead22019-07-11 16:46:16 +0200241 goto cleanup;
Radek Krejci084289f2019-07-09 17:35:30 +0200242 }
243
244 /* compare data */
Radek Krejci5af04842019-07-12 11:32:07 +0200245 if (type->plugin->compare(&node->value, &data)) {
246 /* do not assign it directly from the compare callback to keep possible LY_EINCOMPLETE from validation */
247 ret = LY_EVALID;
248 }
Radek Krejci084289f2019-07-09 17:35:30 +0200249
250cleanup:
Radek Krejci62903c32019-07-15 14:42:05 +0200251 type->plugin->free(ctx, &data);
Radek Krejci084289f2019-07-09 17:35:30 +0200252
253 return ret;
254}
255
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200256API const char *
257lyd_value2str(const struct lyd_node_term *node, int *dynamic)
258{
259 LY_CHECK_ARG_RET(node ? node->schema->module->ctx : NULL, node, dynamic, NULL);
260
261 return node->value.realtype->plugin->print(&node->value, LYD_JSON, json_print_get_prefix, NULL, dynamic);
262}
263
264API const char *
265lyd_attr2str(const struct lyd_attr *attr, int *dynamic)
266{
267 LY_CHECK_ARG_RET(attr ? attr->parent->schema->module->ctx : NULL, attr, dynamic, NULL);
268
269 return attr->value.realtype->plugin->print(&attr->value, LYD_JSON, json_print_get_prefix, NULL, dynamic);
270}
271
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200272API struct lyd_node *
Michal Vaskoa3881362020-01-21 15:57:35 +0100273lyd_parse_mem(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
Radek Krejcie7b95092019-05-15 11:03:07 +0200274{
Radek Krejcie7b95092019-05-15 11:03:07 +0200275 struct lyd_node *result = NULL;
Radek Krejcie92210c2019-05-17 15:53:35 +0200276#if 0
Radek Krejcie7b95092019-05-15 11:03:07 +0200277 const char *yang_data_name = NULL;
Radek Krejcie92210c2019-05-17 15:53:35 +0200278#endif
Radek Krejcie7b95092019-05-15 11:03:07 +0200279
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200280 LY_CHECK_ARG_RET(ctx, ctx, NULL);
281
Michal Vaskoa3881362020-01-21 15:57:35 +0100282#if 0
Radek Krejcie7b95092019-05-15 11:03:07 +0200283 if (options & LYD_OPT_RPCREPLY) {
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200284 /* first item in trees is mandatory - the RPC/action request */
285 LY_CHECK_ARG_RET(ctx, trees, LY_ARRAY_SIZE(trees) >= 1, NULL);
286 if (!trees[0] || trees[0]->parent || !(trees[0]->schema->nodetype & (LYS_ACTION | LYS_LIST | LYS_CONTAINER))) {
287 LOGERR(ctx, LY_EINVAL, "Data parser invalid argument trees - the first item in the array must be the RPC/action request when parsing %s.",
288 lyd_parse_options_type2str(options));
Radek Krejcie7b95092019-05-15 11:03:07 +0200289 return NULL;
290 }
291 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200292
Radek Krejcie7b95092019-05-15 11:03:07 +0200293 if (options & LYD_OPT_DATA_TEMPLATE) {
294 yang_data_name = va_arg(ap, const char *);
295 }
Radek Krejcie92210c2019-05-17 15:53:35 +0200296#endif
Radek Krejcie7b95092019-05-15 11:03:07 +0200297
298 if (!format) {
299 /* TODO try to detect format from the content */
300 }
301
302 switch (format) {
303 case LYD_XML:
Michal Vaskoa3881362020-01-21 15:57:35 +0100304 lyd_parse_xml(ctx, data, options, &result);
Radek Krejcie7b95092019-05-15 11:03:07 +0200305 break;
306#if 0
307 case LYD_JSON:
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200308 lyd_parse_json(ctx, data, options, trees, &result);
Radek Krejcie7b95092019-05-15 11:03:07 +0200309 break;
310 case LYD_LYB:
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200311 lyd_parse_lyb(ctx, data, options, trees, &result);
Radek Krejcie7b95092019-05-15 11:03:07 +0200312 break;
313#endif
314 case LYD_UNKNOWN:
315 LOGINT(ctx);
316 break;
317 }
318
Radek Krejcie7b95092019-05-15 11:03:07 +0200319 return result;
320}
321
322API struct lyd_node *
Michal Vaskoa3881362020-01-21 15:57:35 +0100323lyd_parse_fd(struct ly_ctx *ctx, int fd, LYD_FORMAT format, int options)
Radek Krejcie7b95092019-05-15 11:03:07 +0200324{
325 struct lyd_node *result;
326 size_t length;
327 char *addr;
328
329 LY_CHECK_ARG_RET(ctx, ctx, NULL);
330 if (fd < 0) {
331 LOGARG(ctx, fd);
332 return NULL;
333 }
334
335 LY_CHECK_RET(ly_mmap(ctx, fd, &length, (void **)&addr), NULL);
Michal Vaskoa3881362020-01-21 15:57:35 +0100336 result = lyd_parse_mem(ctx, addr ? addr : "", format, options);
Radek Krejcidf3da792019-05-17 10:32:24 +0200337 if (addr) {
338 ly_munmap(addr, length);
339 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200340
341 return result;
342}
343
344API struct lyd_node *
Michal Vaskoa3881362020-01-21 15:57:35 +0100345lyd_parse_path(struct ly_ctx *ctx, const char *path, LYD_FORMAT format, int options)
Radek Krejcie7b95092019-05-15 11:03:07 +0200346{
347 int fd;
348 struct lyd_node *result;
349 size_t len;
Radek Krejcie7b95092019-05-15 11:03:07 +0200350
351 LY_CHECK_ARG_RET(ctx, ctx, path, NULL);
352
353 fd = open(path, O_RDONLY);
354 LY_CHECK_ERR_RET(fd == -1, LOGERR(ctx, LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno)), NULL);
355
356 if (!format) {
357 /* unknown format - try to detect it from filename's suffix */
358 len = strlen(path);
359
360 /* ignore trailing whitespaces */
361 for (; len > 0 && isspace(path[len - 1]); len--);
362
363 if (len >= 5 && !strncmp(&path[len - 4], ".xml", 4)) {
364 format = LYD_XML;
365#if 0
366 } else if (len >= 6 && !strncmp(&path[len - 5], ".json", 5)) {
367 format = LYD_JSON;
368 } else if (len >= 5 && !strncmp(&path[len - 4], ".lyb", 4)) {
369 format = LYD_LYB;
370#endif
371 } /* else still unknown, try later to detect it from the content */
372 }
373
Michal Vaskoa3881362020-01-21 15:57:35 +0100374 result = lyd_parse_fd(ctx, fd, format, options);
Radek Krejcie7b95092019-05-15 11:03:07 +0200375 close(fd);
376
377 return result;
378}
Radek Krejci084289f2019-07-09 17:35:30 +0200379
Michal Vasko90932a92020-02-12 14:33:03 +0100380LY_ERR
381lyd_create_term(const struct lysc_node *schema, const char *value, size_t value_len, int *dynamic,
382 ly_clb_resolve_prefix get_prefix, void *prefix_data, LYD_FORMAT format, struct lyd_node **node)
383{
384 LY_ERR ret;
385 struct lyd_node_term *term;
386
Michal Vasko9b368d32020-02-14 13:53:31 +0100387 assert(schema->nodetype & LYD_NODE_TERM);
388
Michal Vasko90932a92020-02-12 14:33:03 +0100389 term = calloc(1, sizeof *term);
390 LY_CHECK_ERR_RET(!term, LOGMEM(schema->module->ctx), LY_EMEM);
391
392 term->schema = schema;
393 term->prev = (struct lyd_node *)term;
Michal Vasko9b368d32020-02-14 13:53:31 +0100394 term->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100395
396 ret = lyd_value_parse(term, value, value_len, dynamic, 0, get_prefix, prefix_data, format, NULL);
397 if (ret && (ret != LY_EINCOMPLETE)) {
398 free(term);
399 return ret;
400 }
Michal Vasko9b368d32020-02-14 13:53:31 +0100401 lyd_hash((struct lyd_node *)term);
402
403 *node = (struct lyd_node *)term;
404 return ret;
405}
406
407LY_ERR
408lyd_create_term2(const struct lysc_node *schema, const struct lyd_value *val, struct lyd_node **node)
409{
410 LY_ERR ret;
411 struct lyd_node_term *term;
412 struct lysc_type *type;
413
414 assert(schema->nodetype & LYD_NODE_TERM);
415
416 term = calloc(1, sizeof *term);
417 LY_CHECK_ERR_RET(!term, LOGMEM(schema->module->ctx), LY_EMEM);
418
419 term->schema = schema;
420 term->prev = (struct lyd_node *)term;
421 term->flags = LYD_NEW;
422
423 type = ((struct lysc_node_leaf *)schema)->type;
424 ret = type->plugin->duplicate(schema->module->ctx, val, &term->value);
425 if (ret) {
426 LOGERR(schema->module->ctx, ret, "Value duplication failed.");
427 free(term);
428 return ret;
429 }
430 lyd_hash((struct lyd_node *)term);
Michal Vasko90932a92020-02-12 14:33:03 +0100431
432 *node = (struct lyd_node *)term;
433 return ret;
434}
435
436LY_ERR
437lyd_create_inner(const struct lysc_node *schema, struct lyd_node **node)
438{
439 struct lyd_node_inner *in;
440
Michal Vasko9b368d32020-02-14 13:53:31 +0100441 assert(schema->nodetype & LYD_NODE_INNER);
442
Michal Vasko90932a92020-02-12 14:33:03 +0100443 in = calloc(1, sizeof *in);
444 LY_CHECK_ERR_RET(!in, LOGMEM(schema->module->ctx), LY_EMEM);
445
446 in->schema = schema;
447 in->prev = (struct lyd_node *)in;
Michal Vasko9b368d32020-02-14 13:53:31 +0100448 in->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100449
Michal Vasko9b368d32020-02-14 13:53:31 +0100450 /* do not hash list with keys, we need them for the hash */
451 if ((schema->nodetype != LYS_LIST) || (schema->flags & LYS_KEYLESS)) {
452 lyd_hash((struct lyd_node *)in);
453 }
Michal Vasko90932a92020-02-12 14:33:03 +0100454
455 *node = (struct lyd_node *)in;
456 return LY_SUCCESS;
457}
458
459static void
460ly_keys_clean(struct ly_keys *keys)
461{
462 size_t i;
463
464 for (i = 0; i < keys->key_count; ++i) {
465 keys->keys[i].schema->type->plugin->free(keys->keys[i].schema->module->ctx, &keys->keys[i].val);
466 }
467 free(keys->str);
468 free(keys->keys);
469}
470
471static char *
472ly_keys_parse_next(char **next_key, char **key_name)
473{
474 char *ptr, *ptr2, *val, quot;
475
476 ptr = *next_key;
477
478 /* "[" */
479 LY_CHECK_GOTO(ptr[0] != '[', error);
480 ++ptr;
481
482 /* key name */
483 ptr2 = strchr(ptr, '=');
484 LY_CHECK_GOTO(!ptr2, error);
485
486 *key_name = ptr;
487 ptr2[0] = '\0';
488
489 /* \0, was '=' */
490 ptr = ptr2 + 1;
491
492 /* quote */
493 LY_CHECK_GOTO((ptr[0] != '\'') && (ptr[0] != '\"'), error);
494 quot = ptr[0];
495 ++ptr;
496
497 /* value, terminate it */
498 val = ptr;
499 ptr2 = strchr(ptr, quot);
500 LY_CHECK_GOTO(!ptr2, error);
501 ptr2[0] = '\0';
502
503 /* \0, was quote */
504 ptr = ptr2 + 1;
505
506 /* "]" */
507 LY_CHECK_GOTO(ptr[0] != ']', error);
508 ++ptr;
509
510 *next_key = ptr;
511 return val;
512
513error:
514 *next_key = ptr;
515 return NULL;
516}
517
518/* fill keys structure; if store is set, fill also each val */
519static LY_ERR
520ly_keys_parse(const struct lysc_node *list, const char *keys_str, size_t keys_len, int store, struct ly_keys *keys)
521{
522 LY_ERR ret = LY_SUCCESS;
523 char *next_key, *name;
524 const struct lysc_node *key;
525 size_t i;
526
527 assert(list->nodetype == LYS_LIST);
528
529 memset(keys, 0, sizeof *keys);
530
Michal Vaskof03ed032020-03-04 13:31:44 +0100531 if (!keys_str) {
532 /* nothing to parse */
533 return LY_SUCCESS;
534 }
535
536 keys->str = strndup(keys_str, keys_len);
Michal Vasko90932a92020-02-12 14:33:03 +0100537 LY_CHECK_ERR_GOTO(!keys->str, LOGMEM(list->module->ctx); ret = LY_EMEM, cleanup);
538
539 next_key = keys->str;
540 while (next_key[0]) {
541 /* new key */
542 keys->keys = ly_realloc(keys->keys, (keys->key_count + 1) * sizeof *keys->keys);
543 LY_CHECK_ERR_GOTO(!keys->keys, LOGMEM(list->module->ctx); ret = LY_EMEM, cleanup);
544
545 /* fill */
546 keys->keys[keys->key_count].value = ly_keys_parse_next(&next_key, &name);
547 if (!keys->keys[keys->key_count].value) {
548 LOGERR(list->module->ctx, LY_EINVAL, "Invalid keys string (at \"%s\").", next_key);
549 ret = LY_EINVAL;
550 goto cleanup;
551 }
552
553 /* find schema node */
554 key = lys_find_child(list, list->module, name, 0, LYS_LEAF, 0);
555 if (!key) {
556 LOGERR(list->module->ctx, LY_EINVAL, "List \"%s\" has no key \"%s\".", list->name, name);
557 ret = LY_EINVAL;
558 goto cleanup;
559 }
560 keys->keys[keys->key_count].schema = (const struct lysc_node_leaf *)key;
561
562 /* check that we do not have it already */
563 for (i = 0; i < keys->key_count; ++i) {
564 if (keys->keys[i].schema == keys->keys[keys->key_count].schema) {
565 LOGERR(list->module->ctx, LY_EINVAL, "Duplicit key \"%s\" value.", name);
566 ret = LY_EINVAL;
567 goto cleanup;
568 }
569 }
570
571 if (store) {
572 /* store the value */
573 ret = lyd_value_store(&keys->keys[keys->key_count].val, key, keys->keys[keys->key_count].value, 0, 0,
574 lydjson_resolve_prefix, NULL, LYD_JSON);
575 LY_CHECK_GOTO(ret, cleanup);
576 }
577
578 /* another valid key */
579 ++keys->key_count;
580 }
581
582cleanup:
583 ly_keys_clean(keys);
584 return ret;
585}
586
587LY_ERR
588lyd_create_list(const struct lysc_node *schema, const char *keys_str, size_t keys_len, struct lyd_node **node)
589{
590 LY_ERR ret = LY_SUCCESS;
591 const struct lysc_node *key_s;
592 struct lyd_node *list = NULL, *key;
593 struct ly_keys keys = {0};
594 size_t i;
595
596 assert((schema->nodetype == LYS_LIST) && !(schema->flags & LYS_KEYLESS));
597
598 /* parse keys */
599 LY_CHECK_GOTO(ret = ly_keys_parse(schema, keys_str, keys_len, 0, &keys), cleanup);
600
601 /* create list */
602 LY_CHECK_GOTO(ret = lyd_create_inner(schema, &list), cleanup);
603
604 /* everything was checked except that all keys are set */
605 i = 0;
606 for (key_s = lysc_node_children(schema, 0); key_s && (key_s->flags & LYS_KEY); key_s = key_s->next) {
607 ++i;
608 }
609 if (i != keys.key_count) {
610 LOGERR(schema->module->ctx, LY_EINVAL, "List \"%s\" is missing some keys.", schema->name);
611 ret = LY_EINVAL;
612 goto cleanup;
613 }
614
615 /* create and insert all the keys */
616 for (i = 0; i < keys.key_count; ++i) {
Michal Vaskof03ed032020-03-04 13:31:44 +0100617 LY_CHECK_GOTO(ret = lyd_create_term((struct lysc_node *)keys.keys[i].schema, keys.keys[i].value,
618 strlen(keys.keys[i].value), NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &key), cleanup);
Michal Vasko90932a92020-02-12 14:33:03 +0100619 lyd_insert_node(list, NULL, key);
620 }
621
Michal Vasko9b368d32020-02-14 13:53:31 +0100622 /* hash having all the keys */
623 lyd_hash(list);
624
Michal Vasko90932a92020-02-12 14:33:03 +0100625 /* success */
626 *node = list;
627 list = NULL;
628
629cleanup:
630 lyd_free_tree(list);
631 ly_keys_clean(&keys);
632 return ret;
633}
634
635LY_ERR
636lyd_create_any(const struct lysc_node *schema, const void *value, LYD_ANYDATA_VALUETYPE value_type, struct lyd_node **node)
637{
638 struct lyd_node_any *any;
639
Michal Vasko9b368d32020-02-14 13:53:31 +0100640 assert(schema->nodetype & LYD_NODE_ANY);
641
Michal Vasko90932a92020-02-12 14:33:03 +0100642 any = calloc(1, sizeof *any);
643 LY_CHECK_ERR_RET(!any, LOGMEM(schema->module->ctx), LY_EMEM);
644
645 any->schema = schema;
646 any->prev = (struct lyd_node *)any;
Michal Vasko9b368d32020-02-14 13:53:31 +0100647 any->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100648
649 any->value.xml = value;
650 any->value_type = value_type;
Michal Vasko9b368d32020-02-14 13:53:31 +0100651 lyd_hash((struct lyd_node *)any);
Michal Vasko90932a92020-02-12 14:33:03 +0100652
653 *node = (struct lyd_node *)any;
654 return LY_SUCCESS;
655}
656
Michal Vasko013a8182020-03-03 10:46:53 +0100657API struct lyd_node *
658lyd_new_inner(struct lyd_node *parent, const struct lys_module *module, const char *name)
659{
660 struct lyd_node *ret = NULL;
661 const struct lysc_node *schema;
662 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
663
664 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
665
Michal Vaskof03ed032020-03-04 13:31:44 +0100666 if (!module) {
667 module = parent->schema->module;
668 }
669
Michal Vasko013a8182020-03-03 10:46:53 +0100670 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_CONTAINER | LYS_NOTIF | LYS_ACTION, 0);
671 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Inner node \"%s\" not found.", name), NULL);
672
673 if (!lyd_create_inner(schema, &ret) && parent) {
674 lyd_insert_node(parent, NULL, ret);
675 }
676 return ret;
677}
678
679API struct lyd_node *
680lyd_new_list(struct lyd_node *parent, const struct lys_module *module, const char *name, ...)
681{
682 struct lyd_node *ret = NULL, *key;
683 const struct lysc_node *schema, *key_s;
684 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
685 va_list ap;
686 const char *key_val;
687 LY_ERR rc = LY_SUCCESS;
688
689 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
690
Michal Vaskof03ed032020-03-04 13:31:44 +0100691 if (!module) {
692 module = parent->schema->module;
693 }
694
Michal Vasko013a8182020-03-03 10:46:53 +0100695 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, 0);
696 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), NULL);
697
698 /* create list inner node */
699 LY_CHECK_RET(lyd_create_inner(schema, &ret), NULL);
700
701 va_start(ap, name);
702
703 /* create and insert all the keys */
704 for (key_s = lysc_node_children(schema, 0); key_s && (key_s->flags & LYS_KEY); key_s = key_s->next) {
705 key_val = va_arg(ap, const char *);
706
Michal Vaskof03ed032020-03-04 13:31:44 +0100707 rc = lyd_create_term(key_s, key_val, key_val ? strlen(key_val) : 0, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &key);
708 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko013a8182020-03-03 10:46:53 +0100709 lyd_insert_node(ret, NULL, key);
710 }
711
712 /* hash having all the keys */
713 lyd_hash(ret);
714
715 if (parent) {
716 lyd_insert_node(parent, NULL, ret);
717 }
718
719cleanup:
720 if (rc) {
721 lyd_free_tree(ret);
722 ret = NULL;
723 }
724 va_end(ap);
725 return ret;
726}
727
728API struct lyd_node *
729lyd_new_list2(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *keys)
730{
731 struct lyd_node *ret = NULL;
732 const struct lysc_node *schema;
733 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
734
735 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
736
Michal Vaskof03ed032020-03-04 13:31:44 +0100737 if (!module) {
738 module = parent->schema->module;
739 }
740
Michal Vasko013a8182020-03-03 10:46:53 +0100741 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, 0);
742 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), NULL);
743
Michal Vaskof03ed032020-03-04 13:31:44 +0100744 if (!lyd_create_list(schema, keys, keys ? strlen(keys) : 0, &ret) && parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100745 lyd_insert_node(parent, NULL, ret);
746 }
747 return ret;
748}
749
750API struct lyd_node *
751lyd_new_term(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str)
752{
753 struct lyd_node *ret = NULL;
754 const struct lysc_node *schema;
755 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
756
757 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
758
Michal Vaskof03ed032020-03-04 13:31:44 +0100759 if (!module) {
760 module = parent->schema->module;
761 }
762
Michal Vasko013a8182020-03-03 10:46:53 +0100763 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_TERM, 0);
764 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Term node \"%s\" not found.", name), NULL);
765
Michal Vaskof03ed032020-03-04 13:31:44 +0100766 if (!lyd_create_term(schema, val_str, val_str ? strlen(val_str) : 0, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &ret)
767 && parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100768 lyd_insert_node(parent, NULL, ret);
769 }
770 return ret;
771}
772
773API struct lyd_node *
774lyd_new_any(struct lyd_node *parent, const struct lys_module *module, const char *name, const void *value,
775 LYD_ANYDATA_VALUETYPE value_type)
776{
777 struct lyd_node *ret = NULL;
778 const struct lysc_node *schema;
779 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
780
781 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
782
Michal Vaskof03ed032020-03-04 13:31:44 +0100783 if (!module) {
784 module = parent->schema->module;
785 }
786
Michal Vasko013a8182020-03-03 10:46:53 +0100787 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_ANY, 0);
788 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Any node \"%s\" not found.", name), NULL);
789
790 if (!lyd_create_any(schema, value, value_type, &ret) && parent) {
791 lyd_insert_node(parent, NULL, ret);
792 }
793 return ret;
794}
795
Michal Vasko90932a92020-02-12 14:33:03 +0100796struct lyd_node *
797lyd_get_prev_key_anchor(const struct lyd_node *first_sibling, const struct lysc_node *new_key)
798{
799 const struct lysc_node *prev_key;
800 struct lyd_node *match = NULL;
801
802 if (!first_sibling) {
803 return NULL;
804 }
805
806 for (prev_key = new_key->prev; !match && prev_key->next; prev_key = prev_key->prev) {
807 lyd_find_sibling_val(first_sibling, prev_key, NULL, 0, &match);
808 }
809
810 return match;
811}
812
813/**
814 * @brief Insert node after a sibling.
815 *
816 * @param[in] sibling Sibling to insert after.
817 * @param[in] node Node to insert.
818 */
819static void
Michal Vaskof03ed032020-03-04 13:31:44 +0100820lyd_insert_after_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +0100821{
822 assert(!node->next && (node->prev == node));
823
824 node->next = sibling->next;
825 node->prev = sibling;
826 sibling->next = node;
827 if (node->next) {
828 /* sibling had a succeeding node */
829 node->next->prev = node;
830 } else {
831 /* sibling was last, find first sibling and change its prev */
832 if (sibling->parent) {
833 sibling = sibling->parent->child;
834 } else {
835 for (; sibling->prev->next != node; sibling = sibling->prev);
836 }
837 sibling->prev = node;
838 }
839 node->parent = sibling->parent;
840}
841
842/**
843 * @brief Insert node before a sibling.
844 *
845 * @param[in] sibling Sibling to insert before.
846 * @param[in] node Node to insert.
847 */
848static void
Michal Vaskof03ed032020-03-04 13:31:44 +0100849lyd_insert_before_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +0100850{
851 assert(!node->next && (node->prev == node));
852
853 node->next = sibling;
854 /* covers situation of sibling being first */
855 node->prev = sibling->prev;
856 sibling->prev = node;
857 if (node->prev->next) {
858 /* sibling had a preceding node */
859 node->prev->next = node;
860 } else if (sibling->parent) {
861 /* sibling was first and we must also change parent child pointer */
862 sibling->parent->child = node;
863 }
864 node->parent = sibling->parent;
865}
866
867/**
868 * @brief Insert node as the last child of a parent.
869 *
870 * @param[in] parent Parent to insert into.
871 * @param[in] node Node to insert.
872 */
873static void
Michal Vaskof03ed032020-03-04 13:31:44 +0100874lyd_insert_last_node(struct lyd_node *parent, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +0100875{
876 struct lyd_node_inner *par;
877
878 assert(!node->next && (node->prev == node));
879 assert(parent->schema->nodetype & LYD_NODE_INNER);
880
881 par = (struct lyd_node_inner *)parent;
882
883 if (!par->child) {
884 par->child = node;
885 } else {
886 node->prev = par->child->prev;
887 par->child->prev->next = node;
888 par->child->prev = node;
889 }
890 node->parent = par;
891}
892
893void
Michal Vasko9b368d32020-02-14 13:53:31 +0100894lyd_insert_node(struct lyd_node *parent, struct lyd_node **first_sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +0100895{
Michal Vasko9b368d32020-02-14 13:53:31 +0100896 struct lyd_node *anchor;
Michal Vasko90932a92020-02-12 14:33:03 +0100897
Michal Vasko9b368d32020-02-14 13:53:31 +0100898 assert((parent || first_sibling) && node && node->hash);
899
900 if (!parent && first_sibling && (*first_sibling) && (*first_sibling)->parent) {
901 parent = (struct lyd_node *)(*first_sibling)->parent;
902 }
Michal Vasko90932a92020-02-12 14:33:03 +0100903
904 if (parent) {
905 if (node->schema->flags & LYS_KEY) {
906 /* it is key and we need to insert it at the correct place */
Michal Vasko9b368d32020-02-14 13:53:31 +0100907 anchor = lyd_get_prev_key_anchor(lyd_node_children(parent), node->schema);
908 if (anchor) {
Michal Vaskof03ed032020-03-04 13:31:44 +0100909 lyd_insert_after_node(anchor, node);
Michal Vasko90932a92020-02-12 14:33:03 +0100910 } else if (lyd_node_children(parent)) {
Michal Vaskof03ed032020-03-04 13:31:44 +0100911 lyd_insert_before_node((struct lyd_node *)lyd_node_children(parent), node);
Michal Vasko90932a92020-02-12 14:33:03 +0100912 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +0100913 lyd_insert_last_node(parent, node);
Michal Vasko90932a92020-02-12 14:33:03 +0100914 }
915 } else {
916 /* last child */
Michal Vaskof03ed032020-03-04 13:31:44 +0100917 lyd_insert_last_node(parent, node);
Michal Vasko90932a92020-02-12 14:33:03 +0100918 }
Michal Vasko9b368d32020-02-14 13:53:31 +0100919 } else if (*first_sibling) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100920 /* top-level siblings */
Michal Vasko9b368d32020-02-14 13:53:31 +0100921 anchor = (*first_sibling)->prev;
922 while (anchor->prev->next && (lyd_top_node_module(anchor) != lyd_top_node_module(node))) {
923 anchor = anchor->prev;
924 }
925
Michal Vaskob1b5c262020-03-05 14:29:47 +0100926 if (lyd_top_node_module(anchor) == lyd_top_node_module(node)) {
927 /* insert after last sibling from this module */
928 lyd_insert_after_node(anchor, node);
929 } else {
930 /* no data from this module, insert at the last position */
931 lyd_insert_after_node((*first_sibling)->prev, node);
932 }
Michal Vasko90932a92020-02-12 14:33:03 +0100933 } else {
Michal Vasko9b368d32020-02-14 13:53:31 +0100934 /* the only sibling */
935 *first_sibling = node;
Michal Vasko90932a92020-02-12 14:33:03 +0100936 }
937
Michal Vasko9b368d32020-02-14 13:53:31 +0100938 if (!(node->flags & LYD_DEFAULT)) {
939 /* remove default flags from NP containers */
940 while (parent && (parent->flags & LYD_DEFAULT)) {
941 parent->flags &= ~LYD_DEFAULT;
942 parent = (struct lyd_node *)parent->parent;
943 }
Michal Vasko90932a92020-02-12 14:33:03 +0100944 }
945
946 /* insert into hash table */
947 lyd_insert_hash(node);
948}
949
Michal Vaskof03ed032020-03-04 13:31:44 +0100950static LY_ERR
951lyd_insert_check_schema(const struct lysc_node *parent, const struct lysc_node *schema)
952{
953 const struct lysc_node *par2;
954
955 assert(schema);
956
957 /* adjust parent first */
958 while (parent && (parent->nodetype & (LYS_CASE | LYS_CHOICE))) {
959 parent = parent->parent;
960 }
961
962 /* find schema parent */
963 for (par2 = schema->parent; par2 && (par2->nodetype & (LYS_CASE | LYS_CHOICE)); par2 = par2->parent);
964
965 if (parent) {
966 /* inner node */
967 if (par2 != parent) {
968 LOGERR(parent->module->ctx, LY_EINVAL, "Cannot insert, parent of \"%s\" is not \"%s\".", schema->name, parent->name);
969 return LY_EINVAL;
970 }
971 } else {
972 /* top-level node */
973 if (par2) {
974 LOGERR(parent->module->ctx, LY_EINVAL, "Cannot insert, node \"%s\" is not top-level.", schema->name);
975 return LY_EINVAL;
976 }
977 }
978
979 return LY_SUCCESS;
980}
981
982API LY_ERR
983lyd_insert(struct lyd_node *parent, struct lyd_node *node)
984{
985 struct lyd_node *iter;
986
987 LY_CHECK_ARG_RET(NULL, parent, node, !(parent->schema->nodetype & LYD_NODE_INNER), LY_EINVAL);
988
989 LY_CHECK_RET(lyd_insert_check_schema(parent->schema, node->schema));
990
991 if (node->schema->flags & LYS_KEY) {
992 LOGERR(parent->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
993 return LY_EINVAL;
994 }
995
996 if (node->parent || node->prev->next) {
997 lyd_unlink_tree(node);
998 }
999
1000 while (node) {
1001 iter = node->next;
1002 lyd_unlink_tree(node);
1003 lyd_insert_node(parent, NULL, node);
1004 node = iter;
1005 }
1006 return LY_SUCCESS;
1007}
1008
1009API LY_ERR
Michal Vaskob1b5c262020-03-05 14:29:47 +01001010lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node)
1011{
1012 struct lyd_node *iter;
1013
1014 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1015
1016 LY_CHECK_RET(lyd_insert_check_schema(sibling->schema->parent, node->schema));
1017
1018 if (node->schema->flags & LYS_KEY) {
1019 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1020 return LY_EINVAL;
1021 }
1022
1023 if (node->parent || node->prev->next) {
1024 lyd_unlink_tree(node);
1025 }
1026
1027 while (node) {
1028 iter = node->next;
1029 lyd_unlink_tree(node);
1030 lyd_insert_node(NULL, &sibling, node);
1031 node = iter;
1032 }
1033 return LY_SUCCESS;
1034}
1035
1036API LY_ERR
Michal Vaskof03ed032020-03-04 13:31:44 +01001037lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
1038{
1039 struct lyd_node *iter;
1040
1041 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1042
1043 LY_CHECK_RET(lyd_insert_check_schema(sibling->schema->parent, node->schema));
1044
1045 if (node->schema->flags & LYS_KEY) {
1046 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1047 return LY_EINVAL;
1048 } else if (sibling->schema->flags & LYS_KEY) {
1049 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert into keys.");
1050 return LY_EINVAL;
1051 }
1052
1053 if (node->parent || node->prev->next) {
1054 lyd_unlink_tree(node);
1055 }
1056
1057 /* insert in reverse order to get the original order */
1058 node = node->prev;
1059 while (node) {
1060 iter = node->prev;
1061 lyd_unlink_tree(node);
1062
1063 lyd_insert_before_node(sibling, node);
1064 /* move the anchor accordingly */
1065 sibling = node;
1066
1067 node = (iter == node) ? NULL : iter;
1068 }
1069 return LY_SUCCESS;
1070}
1071
1072API LY_ERR
1073lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
1074{
1075 struct lyd_node *iter;
1076
1077 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1078
1079 LY_CHECK_RET(lyd_insert_check_schema(sibling->schema->parent, node->schema));
1080
1081 if (node->schema->flags & LYS_KEY) {
1082 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1083 return LY_EINVAL;
1084 } else if (sibling->next && (sibling->next->schema->flags & LYS_KEY)) {
1085 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert into keys.");
1086 return LY_EINVAL;
1087 }
1088
1089 if (node->parent || node->prev->next) {
1090 lyd_unlink_tree(node);
1091 }
1092
1093 while (node) {
1094 iter = node->next;
1095 lyd_unlink_tree(node);
1096
1097 lyd_insert_after_node(sibling, node);
1098 /* move the anchor accordingly */
1099 sibling = node;
1100
1101 node = iter;
1102 }
1103 return LY_SUCCESS;
1104}
1105
1106API void
1107lyd_unlink_tree(struct lyd_node *node)
1108{
1109 struct lyd_node *iter;
1110
1111 if (!node) {
1112 return;
1113 }
1114
1115 /* unlink from siblings */
1116 if (node->prev->next) {
1117 node->prev->next = node->next;
1118 }
1119 if (node->next) {
1120 node->next->prev = node->prev;
1121 } else {
1122 /* unlinking the last node */
1123 if (node->parent) {
1124 iter = node->parent->child;
1125 } else {
1126 iter = node->prev;
1127 while (iter->prev != node) {
1128 iter = iter->prev;
1129 }
1130 }
1131 /* update the "last" pointer from the first node */
1132 iter->prev = node->prev;
1133 }
1134
1135 /* unlink from parent */
1136 if (node->parent) {
1137 if (node->parent->child == node) {
1138 /* the node is the first child */
1139 node->parent->child = node->next;
1140 }
1141
1142 lyd_unlink_hash(node);
1143
1144 /* check for keyless list and update its hash */
1145 for (iter = (struct lyd_node *)node->parent; iter; iter = (struct lyd_node *)iter->parent) {
1146 if (iter->schema->flags & LYS_KEYLESS) {
1147 lyd_hash(iter);
1148 }
1149 }
1150
1151 node->parent = NULL;
1152 }
1153
1154 node->next = NULL;
1155 node->prev = node;
1156}
1157
Michal Vasko90932a92020-02-12 14:33:03 +01001158LY_ERR
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001159lyd_create_attr(struct lyd_node *parent, struct lyd_attr **attr, const struct lys_module *mod, const char *name,
1160 size_t name_len, const char *value, size_t value_len, int *dynamic, ly_clb_resolve_prefix get_prefix,
Michal Vasko8d544252020-03-02 10:19:52 +01001161 void *prefix_data, LYD_FORMAT format, const struct lysc_node *ctx_snode)
Michal Vasko90932a92020-02-12 14:33:03 +01001162{
1163 LY_ERR ret;
1164 struct lysc_ext_instance *ant = NULL;
1165 struct lyd_attr *at, *last;
1166 uint32_t v;
1167
Michal Vasko8d544252020-03-02 10:19:52 +01001168 assert((parent || attr) && mod);
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001169
Michal Vasko90932a92020-02-12 14:33:03 +01001170 LY_ARRAY_FOR(mod->compiled->exts, v) {
1171 if (mod->compiled->exts[v].def->plugin == lyext_plugins_internal[LYEXT_PLUGIN_INTERNAL_ANNOTATION].plugin &&
1172 !ly_strncmp(mod->compiled->exts[v].argument, name, name_len)) {
1173 /* we have the annotation definition */
1174 ant = &mod->compiled->exts[v];
1175 break;
1176 }
1177 }
1178 if (!ant) {
1179 /* attribute is not defined as a metadata annotation (RFC 7952) */
1180 LOGERR(mod->ctx, LY_EINVAL, "Annotation definition for attribute \"%s:%.*s\" not found.",
1181 mod->name, name_len, name);
1182 return LY_EINVAL;
1183 }
1184
1185 at = calloc(1, sizeof *at);
1186 LY_CHECK_ERR_RET(!at, LOGMEM(mod->ctx), LY_EMEM);
1187 at->parent = parent;
1188 at->annotation = ant;
Michal Vasko8d544252020-03-02 10:19:52 +01001189 ret = lyd_value_parse_attr(mod->ctx, at, value, value_len, dynamic, 0, get_prefix, prefix_data, format, ctx_snode, NULL);
Michal Vasko90932a92020-02-12 14:33:03 +01001190 if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
1191 free(at);
1192 return ret;
1193 }
1194 at->name = lydict_insert(mod->ctx, name, name_len);
1195
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001196 /* insert as the last attribute */
1197 if (parent) {
1198 if (parent->attr) {
1199 for (last = parent->attr; last->next; last = last->next);
1200 last->next = at;
1201 } else {
1202 parent->attr = at;
1203 }
1204 } else if (*attr) {
1205 for (last = *attr; last->next; last = last->next);
Michal Vasko90932a92020-02-12 14:33:03 +01001206 last->next = at;
Michal Vasko90932a92020-02-12 14:33:03 +01001207 }
1208
1209 /* remove default flags from NP containers */
1210 while (parent && (parent->flags & LYD_DEFAULT)) {
1211 parent->flags &= ~LYD_DEFAULT;
1212 parent = (struct lyd_node *)parent->parent;
1213 }
1214
1215 if (attr) {
1216 *attr = at;
1217 }
1218 return ret;
1219}
1220
Radek Krejci084289f2019-07-09 17:35:30 +02001221API const struct lyd_node_term *
Michal Vaskof03ed032020-03-04 13:31:44 +01001222lyd_target(struct lyd_value_path *path, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +02001223{
Michal Vaskof03ed032020-03-04 13:31:44 +01001224 unsigned int u, x;
Michal Vaskoe444f752020-02-10 12:20:06 +01001225 const struct lyd_node *parent = NULL, *start_search;
1226 struct lyd_node *node = NULL;
Radek Krejci084289f2019-07-09 17:35:30 +02001227 uint64_t pos = 1;
1228
Michal Vaskof03ed032020-03-04 13:31:44 +01001229 LY_CHECK_ARG_RET(NULL, path, tree, NULL);
Radek Krejci084289f2019-07-09 17:35:30 +02001230
1231 LY_ARRAY_FOR(path, u) {
1232 if (parent) {
1233 start_search = lyd_node_children(parent);
1234search_inner:
Michal Vaskoe444f752020-02-10 12:20:06 +01001235 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 +02001236 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +01001237 start_search = tree;
Radek Krejci084289f2019-07-09 17:35:30 +02001238search_toplevel:
Michal Vaskof03ed032020-03-04 13:31:44 +01001239 /* WARNING! to use search_toplevel label correctly, variable v must be preserved and not changed! */
1240 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 +02001241 }
1242 if (!node) {
1243 return NULL;
1244 }
1245
1246 /* check predicate if any */
1247 LY_ARRAY_FOR(path[u].predicates, x) {
1248 if (path[u].predicates[x].type == 0) {
1249 /* position predicate */
1250 if (pos != path[u].predicates[x].position) {
1251 pos++;
1252 goto search_repeat;
1253 }
1254 /* done, no more predicates are allowed here */
1255 break;
1256 } else if (path[u].predicates[x].type == 1) {
1257 /* key-predicate */
1258 struct lysc_type *type = ((struct lysc_node_leaf*)path[u].predicates[x].key)->type;
Michal Vaskoe444f752020-02-10 12:20:06 +01001259 struct lyd_node *key;
1260 lyd_find_sibling_next(lyd_node_children(node), path[u].predicates[x].key->module,
1261 path[u].predicates[x].key->name, 0, NULL, 0, &key);
Radek Krejci084289f2019-07-09 17:35:30 +02001262 if (!key) {
1263 /* probably error and we shouldn't be here due to previous checks when creating path */
1264 goto search_repeat;
1265 }
1266 if (type->plugin->compare(&((struct lyd_node_term*)key)->value, path[u].predicates[x].value)) {
1267 goto search_repeat;
1268 }
1269 } else if (path[u].predicates[x].type == 2) {
1270 /* leaf-list-predicate */
1271 struct lysc_type *type = ((struct lysc_node_leaf*)path[u].node)->type;
1272 if (type->plugin->compare(&((struct lyd_node_term*)node)->value, path[u].predicates[x].value)) {
1273 goto search_repeat;
1274 }
1275 } else {
1276 LOGINT(NULL);
1277 }
1278 }
1279
1280 parent = node;
1281 }
1282
1283 return (const struct lyd_node_term*)node;
1284
1285search_repeat:
1286 start_search = node->next;
1287 if (parent) {
1288 goto search_inner;
1289 } else {
1290 goto search_toplevel;
1291 }
1292}
1293
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001294API LY_ERR
1295lyd_compare(const struct lyd_node *node1, const struct lyd_node *node2, int options)
1296{
1297 const struct lyd_node *iter1, *iter2;
1298 struct lyd_node_term *term1, *term2;
1299 struct lyd_node_any *any1, *any2;
1300 struct lysc_type *type;
1301 size_t len1, len2;
Radek Krejci084289f2019-07-09 17:35:30 +02001302
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001303 if (!node1 || !node2) {
1304 if (node1 == node2) {
1305 return LY_SUCCESS;
1306 } else {
1307 return LY_ENOT;
1308 }
1309 }
1310
Michal Vasko14654712020-02-06 08:35:21 +01001311 if (node1->schema->module->ctx != node2->schema->module->ctx || node1->schema != node2->schema) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001312 return LY_ENOT;
1313 }
1314
1315 if (node1->hash != node2->hash) {
1316 return LY_ENOT;
1317 }
1318
1319 /* equal hashes do not mean equal nodes, they can be just in collision so the nodes must be checked explicitly */
1320
1321 switch (node1->schema->nodetype) {
1322 case LYS_LEAF:
1323 case LYS_LEAFLIST:
1324 if (options & LYD_COMPARE_DEFAULTS) {
1325 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
1326 return LY_ENOT;
1327 }
1328 }
1329
1330 term1 = (struct lyd_node_term*)node1;
1331 term2 = (struct lyd_node_term*)node2;
1332 type = ((struct lysc_node_leaf*)node1->schema)->type;
1333
1334 return type->plugin->compare(&term1->value, &term2->value);
1335 case LYS_CONTAINER:
1336 if (options & LYD_COMPARE_DEFAULTS) {
1337 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
1338 return LY_ENOT;
1339 }
1340 }
1341 if (options & LYD_COMPARE_FULL_RECURSION) {
1342 iter1 = ((struct lyd_node_inner*)node1)->child;
1343 iter2 = ((struct lyd_node_inner*)node2)->child;
1344 goto all_children_compare;
1345 }
1346 return LY_SUCCESS;
1347 case LYS_ACTION:
1348 if (options & LYD_COMPARE_FULL_RECURSION) {
1349 /* TODO action/RPC
1350 goto all_children_compare;
1351 */
1352 }
1353 return LY_SUCCESS;
1354 case LYS_NOTIF:
1355 if (options & LYD_COMPARE_FULL_RECURSION) {
1356 /* TODO Notification
1357 goto all_children_compare;
1358 */
1359 }
1360 return LY_SUCCESS;
1361 case LYS_LIST:
1362 iter1 = ((struct lyd_node_inner*)node1)->child;
1363 iter2 = ((struct lyd_node_inner*)node2)->child;
1364
Radek Krejci0fe9b512019-07-26 17:51:05 +02001365 if (!(node1->schema->flags & LYS_KEYLESS) && !(options & LYD_COMPARE_FULL_RECURSION)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001366 /* lists with keys, their equivalence is based on their keys */
Radek Krejci0fe9b512019-07-26 17:51:05 +02001367 for (struct lysc_node *key = ((struct lysc_node_list*)node1->schema)->child;
1368 key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
1369 key = key->next) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001370 if (lyd_compare(iter1, iter2, options)) {
1371 return LY_ENOT;
1372 }
1373 iter1 = iter1->next;
1374 iter2 = iter2->next;
1375 }
1376 } else {
1377 /* lists without keys, their equivalence is based on equivalence of all the children (both direct and indirect) */
1378
1379all_children_compare:
1380 if (!iter1 && !iter2) {
1381 /* no children, nothing to compare */
1382 return LY_SUCCESS;
1383 }
1384
1385 for (; iter1 && iter2; iter1 = iter1->next, iter2 = iter2->next) {
1386 if (lyd_compare(iter1, iter2, options | LYD_COMPARE_FULL_RECURSION)) {
1387 return LY_ENOT;
1388 }
1389 }
1390 if (iter1 || iter2) {
1391 return LY_ENOT;
1392 }
1393 }
1394 return LY_SUCCESS;
1395 case LYS_ANYXML:
1396 case LYS_ANYDATA:
1397 any1 = (struct lyd_node_any*)node1;
1398 any2 = (struct lyd_node_any*)node2;
1399
1400 if (any1->value_type != any2->value_type) {
1401 return LY_ENOT;
1402 }
1403 switch (any1->value_type) {
1404 case LYD_ANYDATA_DATATREE:
1405 iter1 = any1->value.tree;
1406 iter2 = any2->value.tree;
1407 goto all_children_compare;
1408 case LYD_ANYDATA_STRING:
1409 case LYD_ANYDATA_XML:
1410 case LYD_ANYDATA_JSON:
1411 len1 = strlen(any1->value.str);
1412 len2 = strlen(any2->value.str);
1413 if (len1 != len2 || strcmp(any1->value.str, any2->value.str)) {
1414 return LY_ENOT;
1415 }
1416 return LY_SUCCESS;
1417#if 0 /* TODO LYB format */
1418 case LYD_ANYDATA_LYB:
1419 int len1 = lyd_lyb_data_length(any1->value.mem);
1420 int len2 = lyd_lyb_data_length(any2->value.mem);
1421 if (len1 != len2 || memcmp(any1->value.mem, any2->value.mem, len1)) {
1422 return LY_ENOT;
1423 }
1424 return LY_SUCCESS;
1425#endif
1426 }
1427 }
1428
1429 LOGINT(node1->schema->module->ctx);
1430 return LY_EINT;
1431}
Radek Krejci22ebdba2019-07-25 13:59:43 +02001432
1433/**
1434 * @brief Duplicates just a single node and interconnect it into a @p parent (if present) and after the @p prev
1435 * sibling (if present).
1436 *
1437 * Ignores LYD_DUP_WITH_PARENTS and LYD_DUP_WITH_SIBLINGS which are supposed to be handled by lyd_dup().
1438 */
1439static struct lyd_node *
1440lyd_dup_recursive(const struct lyd_node *node, struct lyd_node_inner *parent, struct lyd_node *prev, int options)
1441{
1442 struct ly_ctx *ctx;
1443 struct lyd_node *dup = NULL;
1444
1445 LY_CHECK_ARG_RET(NULL, node, NULL);
1446 ctx = node->schema->module->ctx;
1447
1448 switch (node->schema->nodetype) {
1449 case LYS_ACTION:
1450 case LYS_NOTIF:
1451 case LYS_CONTAINER:
1452 case LYS_LIST:
1453 dup = calloc(1, sizeof(struct lyd_node_inner));
1454 break;
1455 case LYS_LEAF:
1456 case LYS_LEAFLIST:
1457 dup = calloc(1, sizeof(struct lyd_node_term));
1458 break;
1459 case LYS_ANYDATA:
1460 case LYS_ANYXML:
1461 dup = calloc(1, sizeof(struct lyd_node_any));
1462 break;
1463 default:
1464 LOGINT(ctx);
1465 goto error;
1466 }
1467
1468 /* TODO implement LYD_DUP_WITH_WHEN */
1469 dup->flags = node->flags;
1470 dup->schema = node->schema;
1471
1472 /* interconnect the node at the end */
1473 dup->parent = parent;
1474 if (prev) {
1475 dup->prev = prev;
1476 prev->next = dup;
1477 } else {
1478 dup->prev = dup;
1479 if (parent) {
1480 parent->child = dup;
1481 }
1482 }
1483 if (parent) {
1484 parent->child->prev = dup;
1485 } else if (prev) {
1486 struct lyd_node *first;
1487 for (first = prev; first->prev != prev; first = first->prev);
1488 first->prev = dup;
1489 }
1490
1491 /* TODO duplicate attributes, implement LYD_DUP_NO_ATTR */
1492
1493 /* nodetype-specific work */
1494 if (dup->schema->nodetype & LYD_NODE_TERM) {
1495 struct lyd_node_term *term = (struct lyd_node_term*)dup;
1496 struct lyd_node_term *orig = (struct lyd_node_term*)node;
1497
1498 term->hash = orig->hash;
1499 term->value.realtype = orig->value.realtype;
1500 LY_CHECK_ERR_GOTO(term->value.realtype->plugin->duplicate(ctx, &orig->value, &term->value),
1501 LOGERR(ctx, LY_EINT, "Value duplication failed."), error);
1502 } else if (dup->schema->nodetype & LYD_NODE_INNER) {
1503 struct lyd_node_inner *inner = (struct lyd_node_inner*)dup;
1504 struct lyd_node_inner *orig = (struct lyd_node_inner*)node;
1505 struct lyd_node *child, *last = NULL;
1506
1507 if (options & LYD_DUP_RECURSIVE) {
1508 /* duplicate all the children */
1509 LY_LIST_FOR(orig->child, child) {
1510 last = lyd_dup_recursive(child, inner, last, options);
1511 LY_CHECK_GOTO(!last, error);
1512 }
Radek Krejci0fe9b512019-07-26 17:51:05 +02001513 } else if (dup->schema->nodetype == LYS_LIST && !(dup->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001514 /* always duplicate keys of a list */
Radek Krejci22ebdba2019-07-25 13:59:43 +02001515 child = orig->child;
Radek Krejci0fe9b512019-07-26 17:51:05 +02001516 for (struct lysc_node *key = ((struct lysc_node_list*)dup->schema)->child;
1517 key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
1518 key = key->next) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001519 if (!child) {
1520 /* possibly not keys are present in filtered tree */
1521 break;
Radek Krejci0fe9b512019-07-26 17:51:05 +02001522 } else if (child->schema != key) {
1523 /* possibly not all keys are present in filtered tree,
1524 * but there can be also some non-key nodes */
1525 continue;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001526 }
1527 last = lyd_dup_recursive(child, inner, last, options);
1528 child = child->next;
1529 }
1530 }
1531 lyd_hash(dup);
1532 } else if (dup->schema->nodetype & LYD_NODE_ANY) {
1533 struct lyd_node_any *any = (struct lyd_node_any*)dup;
1534 struct lyd_node_any *orig = (struct lyd_node_any*)node;
1535
1536 any->hash = orig->hash;
1537 any->value_type = orig->value_type;
1538 switch (any->value_type) {
1539 case LYD_ANYDATA_DATATREE:
1540 if (orig->value.tree) {
1541 any->value.tree = lyd_dup(orig->value.tree, NULL, LYD_DUP_RECURSIVE | LYD_DUP_WITH_SIBLINGS);
1542 LY_CHECK_GOTO(!any->value.tree, error);
1543 }
1544 break;
1545 case LYD_ANYDATA_STRING:
1546 case LYD_ANYDATA_XML:
1547 case LYD_ANYDATA_JSON:
1548 if (orig->value.str) {
1549 any->value.str = lydict_insert(ctx, orig->value.str, strlen(orig->value.str));
1550 }
1551 break;
1552 }
1553 }
1554
1555 lyd_insert_hash(dup);
1556 return dup;
1557
1558error:
1559 if (!parent && !prev) {
1560 lyd_free_tree(dup);
1561 }
1562 return NULL;
1563}
1564
1565API struct lyd_node *
1566lyd_dup(const struct lyd_node *node, struct lyd_node_inner *parent, int options)
1567{
1568 struct ly_ctx *ctx;
1569 const struct lyd_node *orig; /* original node to be duplicated */
1570 struct lyd_node *first = NULL; /* the first duplicated node, this is returned */
1571 struct lyd_node *last = NULL; /* the last sibling of the duplicated nodes */
1572 struct lyd_node *top = NULL; /* the most higher created node */
1573 struct lyd_node_inner *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
1574 int keyless_parent_list = 0;
1575
1576 LY_CHECK_ARG_RET(NULL, node, NULL);
1577 ctx = node->schema->module->ctx;
1578
1579 if (options & LYD_DUP_WITH_PARENTS) {
1580 struct lyd_node_inner *orig_parent, *iter;
1581 int repeat = 1;
1582 for (top = NULL, orig_parent = node->parent; repeat && orig_parent; orig_parent = orig_parent->parent) {
1583 if (parent && parent->schema == orig_parent->schema) {
1584 /* stop creating parents, connect what we have into the provided parent */
1585 iter = parent;
1586 repeat = 0;
1587 /* get know if there is a keyless list which we will have to rehash */
1588 for (struct lyd_node_inner *piter = parent; piter; piter = piter->parent) {
Radek Krejci0fe9b512019-07-26 17:51:05 +02001589 if (piter->schema->nodetype == LYS_LIST && (piter->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001590 keyless_parent_list = 1;
1591 break;
1592 }
1593 }
1594 } else {
1595 iter = (struct lyd_node_inner*)lyd_dup_recursive((struct lyd_node*)orig_parent, NULL, NULL, 0);
1596 LY_CHECK_GOTO(!iter, error);
1597 }
1598 if (!local_parent) {
1599 local_parent = iter;
1600 }
1601 if (iter->child) {
1602 /* 1) list - add after keys
1603 * 2) provided parent with some children */
1604 iter->child->prev->next = top;
1605 if (top) {
1606 top->prev = iter->child->prev;
1607 iter->child->prev = top;
1608 }
1609 } else {
1610 iter->child = top;
1611 if (iter->schema->nodetype == LYS_LIST) {
1612 /* keyless list - we will need to rehash it since we are going to add nodes into it */
1613 keyless_parent_list = 1;
1614 }
1615 }
1616 if (top) {
1617 top->parent = iter;
1618 }
1619 top = (struct lyd_node*)iter;
1620 }
1621 if (repeat && parent) {
1622 /* given parent and created parents chain actually do not interconnect */
1623 LOGERR(ctx, LY_EINVAL, "Invalid argument parent (%s()) - does not interconnect with the created node's parents chain.", __func__);
1624 goto error;
1625 }
1626 } else {
1627 local_parent = parent;
1628 }
1629
1630 if (local_parent && local_parent->child) {
1631 last = local_parent->child->prev;
1632 }
1633
1634 LY_LIST_FOR(node, orig) {
1635 last = lyd_dup_recursive(orig, local_parent, last, options);
1636 LY_CHECK_GOTO(!last, error);
1637 if (!first) {
1638 first = last;
1639 }
1640
1641 if (!(options & LYD_DUP_WITH_SIBLINGS)) {
1642 break;
1643 }
1644 }
1645 if (keyless_parent_list) {
1646 /* rehash */
1647 for (; local_parent; local_parent = local_parent->parent) {
Radek Krejci0fe9b512019-07-26 17:51:05 +02001648 if (local_parent->schema->nodetype == LYS_LIST && (local_parent->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001649 lyd_hash((struct lyd_node*)local_parent);
1650 }
1651 }
1652 }
1653 return first;
1654
1655error:
1656 if (top) {
1657 lyd_free_tree(top);
1658 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +01001659 lyd_free_siblings(first);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001660 }
1661 return NULL;
1662}
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001663
1664static LY_ERR
1665lyd_path_str_enlarge(char **buffer, size_t *buflen, size_t reqlen, int is_static)
1666{
Michal Vasko14654712020-02-06 08:35:21 +01001667 /* ending \0 */
1668 ++reqlen;
1669
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001670 if (reqlen > *buflen) {
1671 if (is_static) {
1672 return LY_EINCOMPLETE;
1673 }
1674
1675 *buffer = ly_realloc(*buffer, reqlen * sizeof **buffer);
1676 if (!*buffer) {
1677 return LY_EMEM;
1678 }
1679
1680 *buflen = reqlen;
1681 }
1682
1683 return LY_SUCCESS;
1684}
1685
1686/**
1687 * @brief Append all list key predicates to path.
1688 *
1689 * @param[in] node Node with keys to print.
1690 * @param[in,out] buffer Buffer to print to.
1691 * @param[in,out] buflen Current buffer length.
1692 * @param[in,out] bufused Current number of characters used in @p buffer.
1693 * @param[in] is_static Whether buffer is static or can be reallocated.
1694 * @return LY_ERR
1695 */
1696static LY_ERR
1697lyd_path_list_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
1698{
1699 const struct lyd_node *key;
1700 int dynamic = 0;
1701 size_t len;
1702 const char *val;
1703 char quot;
1704 LY_ERR rc;
1705
Michal Vasko14654712020-02-06 08:35:21 +01001706 for (key = lyd_node_children(node); key && (key->schema->flags & LYS_KEY); key = key->next) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001707 val = lyd_value2str((struct lyd_node_term *)key, &dynamic);
1708 len = 1 + strlen(key->schema->name) + 2 + strlen(val) + 2;
1709 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
1710 if (rc != LY_SUCCESS) {
1711 if (dynamic) {
1712 free((char *)val);
1713 }
1714 return rc;
1715 }
1716
1717 quot = '\'';
1718 if (strchr(val, '\'')) {
1719 quot = '"';
1720 }
1721 *bufused += sprintf(*buffer + *bufused, "[%s=%c%s%c]", key->schema->name, quot, val, quot);
1722
1723 if (dynamic) {
1724 free((char *)val);
1725 }
1726 }
1727
1728 return LY_SUCCESS;
1729}
1730
1731/**
1732 * @brief Append leaf-list value predicate to path.
1733 *
1734 * @param[in] node Node to print.
1735 * @param[in,out] buffer Buffer to print to.
1736 * @param[in,out] buflen Current buffer length.
1737 * @param[in,out] bufused Current number of characters used in @p buffer.
1738 * @param[in] is_static Whether buffer is static or can be reallocated.
1739 * @return LY_ERR
1740 */
1741static LY_ERR
1742lyd_path_leaflist_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
1743{
1744 int dynamic = 0;
1745 size_t len;
1746 const char *val;
1747 char quot;
1748 LY_ERR rc;
1749
1750 val = lyd_value2str((struct lyd_node_term *)node, &dynamic);
1751 len = 4 + strlen(val) + 2;
1752 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
1753 if (rc != LY_SUCCESS) {
1754 goto cleanup;
1755 }
1756
1757 quot = '\'';
1758 if (strchr(val, '\'')) {
1759 quot = '"';
1760 }
1761 *bufused += sprintf(*buffer + *bufused, "[.=%c%s%c]", quot, val, quot);
1762
1763cleanup:
1764 if (dynamic) {
1765 free((char *)val);
1766 }
1767 return rc;
1768}
1769
1770/**
1771 * @brief Append node position (relative to its other instances) predicate to path.
1772 *
1773 * @param[in] node Node to print.
1774 * @param[in,out] buffer Buffer to print to.
1775 * @param[in,out] buflen Current buffer length.
1776 * @param[in,out] bufused Current number of characters used in @p buffer.
1777 * @param[in] is_static Whether buffer is static or can be reallocated.
1778 * @return LY_ERR
1779 */
1780static LY_ERR
1781lyd_path_position_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
1782{
1783 const struct lyd_node *first, *iter;
1784 size_t len;
1785 int pos;
1786 char *val = NULL;
1787 LY_ERR rc;
1788
1789 if (node->parent) {
1790 first = node->parent->child;
1791 } else {
1792 for (first = node; node->prev->next; node = node->prev);
1793 }
1794 pos = 1;
1795 for (iter = first; iter != node; iter = iter->next) {
1796 if (iter->schema == node->schema) {
1797 ++pos;
1798 }
1799 }
1800 if (asprintf(&val, "%d", pos) == -1) {
1801 return LY_EMEM;
1802 }
1803
1804 len = 1 + strlen(val) + 1;
1805 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
1806 if (rc != LY_SUCCESS) {
1807 goto cleanup;
1808 }
1809
1810 *bufused += sprintf(*buffer + *bufused, "[%s]", val);
1811
1812cleanup:
1813 free(val);
1814 return rc;
1815}
1816
1817API char *
1818lyd_path(const struct lyd_node *node, LYD_PATH_TYPE pathtype, char *buffer, size_t buflen)
1819{
Michal Vasko14654712020-02-06 08:35:21 +01001820 int is_static = 0, i, depth;
1821 size_t bufused = 0, len;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001822 const struct lyd_node *iter;
1823 const struct lys_module *mod;
1824 LY_ERR rc;
1825
1826 LY_CHECK_ARG_RET(NULL, node, NULL);
1827 if (buffer) {
1828 LY_CHECK_ARG_RET(node->schema->module->ctx, buflen > 1, NULL);
1829 is_static = 1;
Michal Vasko14654712020-02-06 08:35:21 +01001830 } else {
1831 buflen = 0;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001832 }
1833
1834 switch (pathtype) {
Michal Vasko14654712020-02-06 08:35:21 +01001835 case LYD_PATH_LOG:
1836 depth = 1;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001837 for (iter = node; iter->parent; iter = (const struct lyd_node *)iter->parent) {
1838 ++depth;
1839 }
1840
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001841 goto iter_print;
Michal Vasko14654712020-02-06 08:35:21 +01001842 while (depth) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001843 /* find the right node */
Michal Vasko14654712020-02-06 08:35:21 +01001844 for (iter = node, i = 1; i < depth; iter = (const struct lyd_node *)iter->parent, ++i);
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001845iter_print:
1846 /* print prefix and name */
1847 mod = NULL;
1848 if (!iter->parent || (iter->schema->module != iter->parent->schema->module)) {
1849 mod = iter->schema->module;
1850 }
1851
1852 /* realloc string */
1853 len = 1 + (mod ? strlen(mod->name) + 1 : 0) + strlen(iter->schema->name);
1854 rc = lyd_path_str_enlarge(&buffer, &buflen, bufused + len, is_static);
1855 if (rc != LY_SUCCESS) {
1856 break;
1857 }
1858
1859 /* print next node */
1860 bufused += sprintf(buffer + bufused, "/%s%s%s", mod ? mod->name : "", mod ? ":" : "", iter->schema->name);
1861
1862 switch (iter->schema->nodetype) {
1863 case LYS_LIST:
1864 if (iter->schema->flags & LYS_KEYLESS) {
1865 /* print its position */
1866 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
1867 } else {
1868 /* print all list keys in predicates */
1869 rc = lyd_path_list_predicate(iter, &buffer, &buflen, &bufused, is_static);
1870 }
1871 break;
1872 case LYS_LEAFLIST:
1873 if (iter->schema->flags & LYS_CONFIG_W) {
1874 /* print leaf-list value */
1875 rc = lyd_path_leaflist_predicate(iter, &buffer, &buflen, &bufused, is_static);
1876 } else {
1877 /* print its position */
1878 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
1879 }
1880 break;
1881 default:
1882 /* nothing to print more */
1883 rc = LY_SUCCESS;
1884 break;
1885 }
1886 if (rc != LY_SUCCESS) {
1887 break;
1888 }
1889
Michal Vasko14654712020-02-06 08:35:21 +01001890 --depth;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001891 }
1892 break;
1893 }
1894
1895 return buffer;
1896}
Michal Vaskoe444f752020-02-10 12:20:06 +01001897
Michal Vasko9b368d32020-02-14 13:53:31 +01001898LY_ERR
1899lyd_find_sibling_next2(const struct lyd_node *first, const struct lysc_node *schema, const char *key_or_value,
1900 size_t val_len, struct lyd_node **match)
Michal Vaskoe444f752020-02-10 12:20:06 +01001901{
1902 LY_ERR rc;
1903 const struct lyd_node *node = NULL;
1904 struct lyd_node_term *term;
Michal Vaskoe444f752020-02-10 12:20:06 +01001905 struct ly_keys keys = {0};
Michal Vasko90932a92020-02-12 14:33:03 +01001906 struct lyd_value val = {0};
Michal Vaskoe444f752020-02-10 12:20:06 +01001907 size_t i;
Michal Vaskoe444f752020-02-10 12:20:06 +01001908
Michal Vasko9b368d32020-02-14 13:53:31 +01001909 LY_CHECK_ARG_RET(NULL, schema, LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01001910
1911 if (!first) {
1912 /* no data */
Michal Vasko9b368d32020-02-14 13:53:31 +01001913 if (match) {
1914 *match = NULL;
1915 }
Michal Vaskoe444f752020-02-10 12:20:06 +01001916 return LY_ENOTFOUND;
1917 }
1918
Michal Vaskoe444f752020-02-10 12:20:06 +01001919 if (key_or_value && !val_len) {
1920 val_len = strlen(key_or_value);
1921 }
1922
1923 if (key_or_value && (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko90932a92020-02-12 14:33:03 +01001924 /* store the value */
Michal Vasko9b368d32020-02-14 13:53:31 +01001925 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 +01001926 } else if (key_or_value && (schema->nodetype == LYS_LIST)) {
1927 /* parse keys into canonical values */
1928 LY_CHECK_GOTO(rc = ly_keys_parse(schema, key_or_value, val_len, 1, &keys), cleanup);
1929 }
1930
1931 /* find first matching value */
1932 LY_LIST_FOR(first, node) {
1933 if (node->schema != schema) {
1934 continue;
1935 }
1936
1937 if ((schema->nodetype == LYS_LIST) && keys.str) {
1938 /* compare all set keys */
1939 for (i = 0; i < keys.key_count; ++i) {
1940 /* find key */
1941 rc = lyd_find_sibling_val(lyd_node_children(node), (struct lysc_node *)keys.keys[i].schema, NULL, 0,
1942 (struct lyd_node **)&term);
1943 if (rc == LY_ENOTFOUND) {
1944 /* all keys must always exist */
Michal Vasko9b368d32020-02-14 13:53:31 +01001945 LOGINT_RET(schema->module->ctx);
Michal Vaskoe444f752020-02-10 12:20:06 +01001946 }
1947 LY_CHECK_GOTO(rc, cleanup);
1948
1949 /* compare values */
Michal Vasko90932a92020-02-12 14:33:03 +01001950 if (!term->value.realtype->plugin->compare(&term->value, &keys.keys[i].val)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01001951 break;
1952 }
1953 }
1954
1955 if (i < keys.key_count) {
1956 /* not a match */
1957 continue;
1958 }
Michal Vasko90932a92020-02-12 14:33:03 +01001959 } else if ((schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && val.realtype) {
Michal Vaskoe444f752020-02-10 12:20:06 +01001960 term = (struct lyd_node_term *)node;
1961
1962 /* compare values */
Michal Vasko90932a92020-02-12 14:33:03 +01001963 if (!term->value.realtype->plugin->compare(&term->value, &val)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01001964 /* not a match */
1965 continue;
1966 }
1967 }
1968
1969 /* all criteria passed */
1970 break;
1971 }
1972
1973 if (!node) {
1974 rc = LY_ENOTFOUND;
Michal Vasko9b368d32020-02-14 13:53:31 +01001975 if (match) {
1976 *match = NULL;
1977 }
Michal Vaskoe444f752020-02-10 12:20:06 +01001978 goto cleanup;
1979 }
1980
1981 /* success */
Michal Vasko9b368d32020-02-14 13:53:31 +01001982 if (match) {
1983 *match = (struct lyd_node *)node;
1984 }
Michal Vaskoe444f752020-02-10 12:20:06 +01001985 rc = LY_SUCCESS;
1986
1987cleanup:
1988 ly_keys_clean(&keys);
Michal Vasko90932a92020-02-12 14:33:03 +01001989 if (val.realtype) {
Michal Vasko9b368d32020-02-14 13:53:31 +01001990 val.realtype->plugin->free(schema->module->ctx, &val);
Michal Vasko90932a92020-02-12 14:33:03 +01001991 }
Michal Vaskoe444f752020-02-10 12:20:06 +01001992 return rc;
1993}
1994
1995API LY_ERR
Michal Vasko9b368d32020-02-14 13:53:31 +01001996lyd_find_sibling_next(const struct lyd_node *first, const struct lys_module *module, const char *name, size_t name_len,
1997 const char *key_or_value, size_t val_len, struct lyd_node **match)
1998{
1999 const struct lysc_node *schema;
2000
2001 LY_CHECK_ARG_RET(NULL, module, name, match, LY_EINVAL);
2002
2003 if (!first) {
2004 /* no data */
2005 *match = NULL;
2006 return LY_ENOTFOUND;
2007 }
2008
2009 /* find schema */
2010 schema = lys_find_child(first->parent ? first->parent->schema : NULL, module, name, name_len, 0, 0);
2011 if (!schema) {
2012 LOGERR(module->ctx, LY_EINVAL, "Schema node not found.");
2013 return LY_EINVAL;
2014 }
2015
2016 return lyd_find_sibling_next2(first, schema, key_or_value, val_len, match);
2017}
2018
2019API LY_ERR
Michal Vaskoe444f752020-02-10 12:20:06 +01002020lyd_find_sibling_first(const struct lyd_node *siblings, const struct lyd_node *target, struct lyd_node **match)
2021{
2022 struct lyd_node **match_p;
2023 struct lyd_node_inner *parent;
2024
Michal Vaskof03ed032020-03-04 13:31:44 +01002025 LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01002026
2027 if (!siblings) {
2028 /* no data */
Michal Vasko9b368d32020-02-14 13:53:31 +01002029 if (match) {
2030 *match = NULL;
2031 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002032 return LY_ENOTFOUND;
2033 }
2034
2035 /* find first sibling */
2036 if (siblings->parent) {
2037 siblings = siblings->parent->child;
2038 } else {
2039 while (siblings->prev->next) {
2040 siblings = siblings->prev;
2041 }
2042 }
2043
2044 parent = (struct lyd_node_inner *)siblings->parent;
2045 if (parent && parent->children_ht) {
2046 assert(target->hash);
2047
2048 /* find by hash */
2049 if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
2050 siblings = *match_p;
2051 } else {
2052 /* not found */
2053 siblings = NULL;
2054 }
2055 } else {
2056 /* no children hash table */
2057 for (; siblings; siblings = siblings->next) {
2058 if (!lyd_compare(siblings, target, 0)) {
2059 break;
2060 }
2061 }
2062 }
2063
2064 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002065 if (match) {
2066 *match = NULL;
2067 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002068 return LY_ENOTFOUND;
2069 }
2070
Michal Vasko9b368d32020-02-14 13:53:31 +01002071 if (match) {
2072 *match = (struct lyd_node *)siblings;
2073 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002074 return LY_SUCCESS;
2075}
2076
2077API LY_ERR
2078lyd_find_sibling_set(const struct lyd_node *siblings, const struct lyd_node *target, struct ly_set **set)
2079{
2080 struct lyd_node_inner *parent;
2081 struct lyd_node *match;
2082 struct lyd_node **match_p;
2083 struct ly_set *ret;
2084
2085 LY_CHECK_ARG_RET(NULL, target, set, LY_EINVAL);
2086
2087 if (!siblings) {
2088 /* no data */
2089 return LY_ENOTFOUND;
2090 }
2091
2092 ret = ly_set_new();
2093 LY_CHECK_ERR_RET(!ret, LOGMEM(target->schema->module->ctx), LY_EMEM);
2094
2095 /* find first sibling */
2096 if (siblings->parent) {
2097 siblings = siblings->parent->child;
2098 } else {
2099 while (siblings->prev->next) {
2100 siblings = siblings->prev;
2101 }
2102 }
2103
2104 parent = (struct lyd_node_inner *)siblings->parent;
2105 if (parent && parent->children_ht) {
2106 assert(target->hash);
2107
2108 /* find by hash */
2109 if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
2110 match = *match_p;
2111 } else {
2112 /* not found */
2113 match = NULL;
2114 }
2115 while (match) {
2116 /* add all found nodes into the return set */
2117 if (ly_set_add(ret, match, LY_SET_OPT_USEASLIST) == -1) {
2118 goto error;
2119 }
2120
2121 /* find next instance */
2122 if (lyht_find_next(parent->children_ht, &match, match->hash, (void **)&match_p)) {
2123 match = NULL;
2124 } else {
2125 match = *match_p;
2126 }
2127 }
2128 } else {
2129 /* no children hash table */
2130 for (; siblings; siblings = siblings->next) {
2131 if (!lyd_compare(siblings, target, 0)) {
2132 /* a match */
2133 if (ly_set_add(ret, (struct lyd_node *)siblings, LY_SET_OPT_USEASLIST) == -1) {
2134 goto error;
2135 }
2136 }
2137 }
2138 }
2139
2140 if (!ret->count) {
2141 ly_set_free(ret, NULL);
2142 return LY_ENOTFOUND;
2143 }
2144
2145 *set = ret;
2146 return LY_SUCCESS;
2147
2148error:
2149 ly_set_free(ret, NULL);
2150 return LY_EMEM;
2151}
2152
Michal Vasko90932a92020-02-12 14:33:03 +01002153static int
2154lyd_hash_table_schema_val_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *UNUSED(cb_data))
2155{
2156 struct lysc_node *val1;
2157 struct lyd_node *val2;
2158
2159 val1 = *((struct lysc_node **)val1_p);
2160 val2 = *((struct lyd_node **)val2_p);
2161
2162 assert(val1->nodetype & (LYD_NODE_INNER | LYS_LEAF));
2163
2164 if (val1 == val2->schema) {
2165 /* schema match is enough */
2166 return 1;
2167 } else {
2168 return 0;
2169 }
2170}
2171
2172static LY_ERR
2173lyd_find_sibling_schema(const struct lyd_node *siblings, const struct lysc_node *schema, struct lyd_node **match)
2174{
2175 struct lyd_node **match_p;
2176 struct lyd_node_inner *parent;
2177 uint32_t hash;
2178 values_equal_cb ht_cb;
2179
2180 assert(siblings && schema && (schema->nodetype & (LYD_NODE_INNER | LYS_LEAF)));
2181
2182 /* find first sibling */
2183 if (siblings->parent) {
2184 siblings = siblings->parent->child;
2185 } else {
2186 while (siblings->prev->next) {
2187 siblings = siblings->prev;
2188 }
2189 }
2190
2191 parent = (struct lyd_node_inner *)siblings->parent;
2192 if (parent && parent->children_ht) {
2193 /* calculate our hash */
2194 hash = dict_hash_multi(0, schema->module->name, strlen(schema->module->name));
2195 hash = dict_hash_multi(hash, schema->name, strlen(schema->name));
2196 hash = dict_hash_multi(hash, NULL, 0);
2197
2198 /* use special hash table function */
2199 ht_cb = lyht_set_cb(parent->children_ht, lyd_hash_table_schema_val_equal);
2200
2201 /* find by hash */
2202 if (!lyht_find(parent->children_ht, &schema, hash, (void **)&match_p)) {
2203 siblings = *match_p;
2204 } else {
2205 /* not found */
2206 siblings = NULL;
2207 }
2208
2209 /* set the original hash table compare function back */
2210 lyht_set_cb(parent->children_ht, ht_cb);
2211 } else {
2212 /* no children hash table */
2213 for (; siblings; siblings = siblings->next) {
2214 if (siblings->schema == schema) {
2215 /* schema match is enough */
2216 break;
2217 }
2218 }
2219 }
2220
2221 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002222 if (match) {
2223 *match = NULL;
2224 }
Michal Vasko90932a92020-02-12 14:33:03 +01002225 return LY_ENOTFOUND;
2226 }
2227
Michal Vasko9b368d32020-02-14 13:53:31 +01002228 if (match) {
2229 *match = (struct lyd_node *)siblings;
2230 }
Michal Vasko90932a92020-02-12 14:33:03 +01002231 return LY_SUCCESS;
2232}
2233
Michal Vaskoe444f752020-02-10 12:20:06 +01002234API LY_ERR
2235lyd_find_sibling_val(const struct lyd_node *siblings, const struct lysc_node *schema, const char *key_or_value,
2236 size_t val_len, struct lyd_node **match)
2237{
2238 LY_ERR rc;
2239 struct lyd_node *target = NULL;
2240
2241 LY_CHECK_ARG_RET(NULL, schema, LY_EINVAL);
2242 if ((schema->nodetype == LYS_LIST) && schema->flags & LYS_KEYLESS) {
2243 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - key-less list (%s()).", __func__);
2244 return LY_EINVAL;
2245 } else if ((schema->nodetype & (LYS_LEAFLIST | LYS_LIST)) && !key_or_value) {
2246 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - no value/keys for a (leaf-)list (%s()).", __func__);
2247 return LY_EINVAL;
2248 } else if (schema->nodetype & (LYS_CHOICE | LYS_CASE)) {
2249 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - schema type %s (%s()).",
2250 lys_nodetype2str(schema->nodetype), __func__);
2251 return LY_EINVAL;
2252 }
2253
2254 if (!siblings) {
2255 /* no data */
Michal Vasko9b368d32020-02-14 13:53:31 +01002256 if (match) {
2257 *match = NULL;
2258 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002259 return LY_ENOTFOUND;
2260 }
2261
Michal Vaskof03ed032020-03-04 13:31:44 +01002262 if (key_or_value && !val_len) {
2263 val_len = strlen(key_or_value);
2264 }
2265
Michal Vasko90932a92020-02-12 14:33:03 +01002266 /* create data node if needed and find it */
Michal Vaskoe444f752020-02-10 12:20:06 +01002267 switch (schema->nodetype) {
2268 case LYS_CONTAINER:
2269 case LYS_ANYXML:
2270 case LYS_ANYDATA:
2271 case LYS_NOTIF:
Michal Vasko9b368d32020-02-14 13:53:31 +01002272 case LYS_ACTION:
Michal Vaskoe444f752020-02-10 12:20:06 +01002273 case LYS_LEAF:
Michal Vasko90932a92020-02-12 14:33:03 +01002274 /* find it based on schema only */
2275 rc = lyd_find_sibling_schema(siblings, schema, match);
Michal Vaskoe444f752020-02-10 12:20:06 +01002276 break;
2277 case LYS_LEAFLIST:
2278 /* target used attributes: schema, hash, value */
Michal Vasko90932a92020-02-12 14:33:03 +01002279 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 +01002280 /* fallthrough */
Michal Vaskoe444f752020-02-10 12:20:06 +01002281 case LYS_LIST:
Michal Vasko90932a92020-02-12 14:33:03 +01002282 if (schema->nodetype == LYS_LIST) {
2283 /* target used attributes: schema, hash, child (all keys) */
2284 LY_CHECK_RET(lyd_create_list(schema, key_or_value, val_len, &target));
Michal Vasko90932a92020-02-12 14:33:03 +01002285 }
2286
2287 /* find it */
2288 rc = lyd_find_sibling_first(siblings, target, match);
Michal Vaskoe444f752020-02-10 12:20:06 +01002289 break;
2290 default:
2291 /* unreachable */
2292 LOGINT(schema->module->ctx);
2293 return LY_EINT;
2294 }
2295
Michal Vaskoe444f752020-02-10 12:20:06 +01002296 lyd_free_tree(target);
2297 return rc;
2298}