blob: 35d93473a63d3c549bbe90b3c3df275f0141d131 [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 Vaskod3678892020-05-21 10:06:58 +020030#include "tree_schema_internal.h"
Michal Vasko90932a92020-02-12 14:33:03 +010031#include "hash_table.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020032#include "tree_schema.h"
Michal Vaskod3678892020-05-21 10:06:58 +020033#include "xpath.h"
Michal Vasko52927e22020-03-16 17:26:14 +010034#include "xml.h"
Radek Krejci38d85362019-09-05 16:26:38 +020035#include "plugins_exts_metadata.h"
Michal Vasko90932a92020-02-12 14:33:03 +010036#include "plugins_exts_internal.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020037
Michal Vaskoe444f752020-02-10 12:20:06 +010038struct ly_keys {
39 char *str;
40 struct {
41 const struct lysc_node_leaf *schema;
42 char *value;
Michal Vasko90932a92020-02-12 14:33:03 +010043 struct lyd_value val;
Michal Vaskoe444f752020-02-10 12:20:06 +010044 } *keys;
45 size_t key_count;
46};
47
Radek Krejci084289f2019-07-09 17:35:30 +020048LY_ERR
Michal Vasko90932a92020-02-12 14:33:03 +010049lyd_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 +010050 ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +020051{
Michal Vasko90932a92020-02-12 14:33:03 +010052 LY_ERR ret = LY_SUCCESS;
Radek Krejci084289f2019-07-09 17:35:30 +020053 struct ly_err_item *err = NULL;
54 struct ly_ctx *ctx;
55 struct lysc_type *type;
Radek Krejci3c9758d2019-07-11 16:49:10 +020056 int options = LY_TYPE_OPTS_STORE | (second ? LY_TYPE_OPTS_SECOND_CALL : 0) |
Michal Vaskof03ed032020-03-04 13:31:44 +010057 (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci084289f2019-07-09 17:35:30 +020058 assert(node);
59
60 ctx = node->schema->module->ctx;
Radek Krejci084289f2019-07-09 17:35:30 +020061
Radek Krejci73dead22019-07-11 16:46:16 +020062 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci62903c32019-07-15 14:42:05 +020063 if (!second) {
64 node->value.realtype = type;
65 }
Michal Vasko90932a92020-02-12 14:33:03 +010066 ret = type->plugin->store(ctx, type, value, value_len, options, get_prefix, parser, format,
Michal Vaskof03ed032020-03-04 13:31:44 +010067 tree ? (void *)node : (void *)node->schema, tree,
Radek Krejci73dead22019-07-11 16:46:16 +020068 &node->value, NULL, &err);
Michal Vasko90932a92020-02-12 14:33:03 +010069 if (ret && (ret != LY_EINCOMPLETE)) {
Radek Krejci73dead22019-07-11 16:46:16 +020070 if (err) {
Michal Vaskofea12c62020-03-30 11:00:15 +020071 LOGVAL(ctx, LY_VLOG_LYD, node, err->vecode, err->msg);
Radek Krejci73dead22019-07-11 16:46:16 +020072 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +020073 }
Radek Krejci73dead22019-07-11 16:46:16 +020074 goto error;
Michal Vasko90932a92020-02-12 14:33:03 +010075 } else if (dynamic) {
76 *dynamic = 0;
Radek Krejci084289f2019-07-09 17:35:30 +020077 }
78
79error:
80 return ret;
81}
82
Michal Vasko90932a92020-02-12 14:33:03 +010083/* similar to lyd_value_parse except can be used just to store the value, hence does also not support a second call */
84static LY_ERR
85lyd_value_store(struct lyd_value *val, const struct lysc_node *schema, const char *value, size_t value_len, int *dynamic,
86 ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format)
87{
88 LY_ERR ret = LY_SUCCESS;
89 struct ly_err_item *err = NULL;
90 struct ly_ctx *ctx;
91 struct lysc_type *type;
92 int options = LY_TYPE_OPTS_STORE | LY_TYPE_OPTS_INCOMPLETE_DATA | (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0);
93
94 assert(val && schema && (schema->nodetype & LYD_NODE_TERM));
95
96 ctx = schema->module->ctx;
97 type = ((struct lysc_node_leaf *)schema)->type;
98 val->realtype = type;
99 ret = type->plugin->store(ctx, type, value, value_len, options, get_prefix, parser, format, (void *)schema, NULL,
100 val, NULL, &err);
101 if (ret == LY_EINCOMPLETE) {
102 /* this is fine, we do not need it resolved */
103 ret = LY_SUCCESS;
104 } else if (ret && err) {
105 ly_err_print(err);
106 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
107 ly_err_free(err);
108 }
109 if (!ret && dynamic) {
110 *dynamic = 0;
111 }
112
113 return ret;
114}
115
Radek Krejci38d85362019-09-05 16:26:38 +0200116LY_ERR
Michal Vasko9f96a052020-03-10 09:41:45 +0100117lyd_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 +0100118 int second, ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format,
Michal Vaskof03ed032020-03-04 13:31:44 +0100119 const struct lysc_node *ctx_snode, const struct lyd_node *tree)
Radek Krejci38d85362019-09-05 16:26:38 +0200120{
Michal Vasko90932a92020-02-12 14:33:03 +0100121 LY_ERR ret = LY_SUCCESS;
Radek Krejci38d85362019-09-05 16:26:38 +0200122 struct ly_err_item *err = NULL;
Radek Krejci38d85362019-09-05 16:26:38 +0200123 struct lyext_metadata *ant;
124 int options = LY_TYPE_OPTS_STORE | (second ? LY_TYPE_OPTS_SECOND_CALL : 0) |
Michal Vaskof03ed032020-03-04 13:31:44 +0100125 (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci38d85362019-09-05 16:26:38 +0200126
Michal Vasko9f96a052020-03-10 09:41:45 +0100127 assert(ctx && meta && ((tree && meta->parent) || ctx_snode));
Michal Vasko8d544252020-03-02 10:19:52 +0100128
Michal Vasko9f96a052020-03-10 09:41:45 +0100129 ant = meta->annotation->data;
Radek Krejci38d85362019-09-05 16:26:38 +0200130
131 if (!second) {
Michal Vasko9f96a052020-03-10 09:41:45 +0100132 meta->value.realtype = ant->type;
Radek Krejci38d85362019-09-05 16:26:38 +0200133 }
Michal Vasko90932a92020-02-12 14:33:03 +0100134 ret = ant->type->plugin->store(ctx, ant->type, value, value_len, options, get_prefix, parser, format,
Michal Vasko9f96a052020-03-10 09:41:45 +0100135 tree ? (void *)meta->parent : (void *)ctx_snode, tree, &meta->value, NULL, &err);
Michal Vasko90932a92020-02-12 14:33:03 +0100136 if (ret && (ret != LY_EINCOMPLETE)) {
Radek Krejci38d85362019-09-05 16:26:38 +0200137 if (err) {
138 ly_err_print(err);
139 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
140 ly_err_free(err);
141 }
142 goto error;
Michal Vasko90932a92020-02-12 14:33:03 +0100143 } else if (dynamic) {
144 *dynamic = 0;
Radek Krejci38d85362019-09-05 16:26:38 +0200145 }
146
147error:
148 return ret;
149}
150
Radek Krejci084289f2019-07-09 17:35:30 +0200151API LY_ERR
Michal Vasko44685da2020-03-17 15:38:06 +0100152lys_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 +0200153 ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format)
154{
155 LY_ERR rc = LY_SUCCESS;
156 struct ly_err_item *err = NULL;
157 struct lysc_type *type;
Radek Krejci084289f2019-07-09 17:35:30 +0200158
159 LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
160
161 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
162 LOGARG(ctx, node);
163 return LY_EINVAL;
164 }
165
166 type = ((struct lysc_node_leaf*)node)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200167 /* just validate, no storing of enything */
168 rc = type->plugin->store(ctx ? ctx : node->module->ctx, type, value, value_len, LY_TYPE_OPTS_INCOMPLETE_DATA,
169 get_prefix, get_prefix_data, format, node, NULL, NULL, NULL, &err);
170 if (rc == LY_EINCOMPLETE) {
171 /* actually success since we do not provide the context tree and call validation with
172 * LY_TYPE_OPTS_INCOMPLETE_DATA */
173 rc = LY_SUCCESS;
174 } else if (rc && err) {
175 if (ctx) {
176 /* log only in case the ctx was provided as input parameter */
177 ly_err_print(err);
178 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
Radek Krejci084289f2019-07-09 17:35:30 +0200179 }
Radek Krejci73dead22019-07-11 16:46:16 +0200180 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200181 }
182
183 return rc;
184}
185
186API LY_ERR
Michal Vasko44685da2020-03-17 15:38:06 +0100187lyd_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 +0100188 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 +0200189{
190 LY_ERR rc;
191 struct ly_err_item *err = NULL;
192 struct lysc_type *type;
Michal Vaskof03ed032020-03-04 13:31:44 +0100193 int options = (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci084289f2019-07-09 17:35:30 +0200194
195 LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
196
197 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200198 rc = type->plugin->store(ctx ? ctx : node->schema->module->ctx, type, value, value_len, options,
Michal Vaskof03ed032020-03-04 13:31:44 +0100199 get_prefix, get_prefix_data, format, tree ? (void*)node : (void*)node->schema, tree,
Radek Krejci73dead22019-07-11 16:46:16 +0200200 NULL, NULL, &err);
201 if (rc == LY_EINCOMPLETE) {
202 return rc;
203 } else if (rc) {
204 if (err) {
205 if (ctx) {
206 ly_err_print(err);
207 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
Radek Krejci084289f2019-07-09 17:35:30 +0200208 }
Radek Krejci73dead22019-07-11 16:46:16 +0200209 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200210 }
Radek Krejci73dead22019-07-11 16:46:16 +0200211 return rc;
Radek Krejci084289f2019-07-09 17:35:30 +0200212 }
213
214 return LY_SUCCESS;
215}
216
217API LY_ERR
218lyd_value_compare(const struct lyd_node_term *node, const char *value, size_t value_len,
Michal Vaskof03ed032020-03-04 13:31:44 +0100219 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 +0200220{
221 LY_ERR ret = LY_SUCCESS, rc;
222 struct ly_err_item *err = NULL;
223 struct ly_ctx *ctx;
224 struct lysc_type *type;
Radek Krejci084289f2019-07-09 17:35:30 +0200225 struct lyd_value data = {0};
Michal Vaskof03ed032020-03-04 13:31:44 +0100226 int options = LY_TYPE_OPTS_STORE | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci084289f2019-07-09 17:35:30 +0200227
228 LY_CHECK_ARG_RET(node ? node->schema->module->ctx : NULL, node, value, LY_EINVAL);
229
230 ctx = node->schema->module->ctx;
231 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200232 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 +0100233 tree, &data, NULL, &err);
Radek Krejci73dead22019-07-11 16:46:16 +0200234 if (rc == LY_EINCOMPLETE) {
235 ret = rc;
236 /* continue with comparing, just remember what to return if storing is ok */
237 } else if (rc) {
238 /* value to compare is invalid */
239 ret = LY_EINVAL;
240 if (err) {
241 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200242 }
Radek Krejci73dead22019-07-11 16:46:16 +0200243 goto cleanup;
Radek Krejci084289f2019-07-09 17:35:30 +0200244 }
245
246 /* compare data */
Radek Krejci5af04842019-07-12 11:32:07 +0200247 if (type->plugin->compare(&node->value, &data)) {
248 /* do not assign it directly from the compare callback to keep possible LY_EINCOMPLETE from validation */
249 ret = LY_EVALID;
250 }
Radek Krejci084289f2019-07-09 17:35:30 +0200251
252cleanup:
Radek Krejci62903c32019-07-15 14:42:05 +0200253 type->plugin->free(ctx, &data);
Radek Krejci084289f2019-07-09 17:35:30 +0200254
255 return ret;
256}
257
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200258API const char *
259lyd_value2str(const struct lyd_node_term *node, int *dynamic)
260{
261 LY_CHECK_ARG_RET(node ? node->schema->module->ctx : NULL, node, dynamic, NULL);
262
263 return node->value.realtype->plugin->print(&node->value, LYD_JSON, json_print_get_prefix, NULL, dynamic);
264}
265
266API const char *
Michal Vasko9f96a052020-03-10 09:41:45 +0100267lyd_meta2str(const struct lyd_meta *meta, int *dynamic)
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200268{
Michal Vasko9f96a052020-03-10 09:41:45 +0100269 LY_CHECK_ARG_RET(meta ? meta->parent->schema->module->ctx : NULL, meta, dynamic, NULL);
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200270
Michal Vasko9f96a052020-03-10 09:41:45 +0100271 return meta->value.realtype->plugin->print(&meta->value, LYD_JSON, json_print_get_prefix, NULL, dynamic);
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200272}
273
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200274API struct lyd_node *
Michal Vaskoa3881362020-01-21 15:57:35 +0100275lyd_parse_mem(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
Radek Krejcie7b95092019-05-15 11:03:07 +0200276{
Radek Krejcie7b95092019-05-15 11:03:07 +0200277 struct lyd_node *result = NULL;
Radek Krejcie92210c2019-05-17 15:53:35 +0200278#if 0
Radek Krejcie7b95092019-05-15 11:03:07 +0200279 const char *yang_data_name = NULL;
Radek Krejcie92210c2019-05-17 15:53:35 +0200280#endif
Radek Krejcie7b95092019-05-15 11:03:07 +0200281
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200282 LY_CHECK_ARG_RET(ctx, ctx, NULL);
283
Michal Vasko5b37a352020-03-06 13:38:33 +0100284 if ((options & LYD_OPT_PARSE_ONLY) && (options & LYD_VALOPT_MASK)) {
285 LOGERR(ctx, LY_EINVAL, "Passing validation flags with LYD_OPT_PARSE_ONLY is not allowed.");
286 return NULL;
287 }
288
Michal Vaskoa3881362020-01-21 15:57:35 +0100289#if 0
Radek Krejcie7b95092019-05-15 11:03:07 +0200290 if (options & LYD_OPT_RPCREPLY) {
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200291 /* first item in trees is mandatory - the RPC/action request */
292 LY_CHECK_ARG_RET(ctx, trees, LY_ARRAY_SIZE(trees) >= 1, NULL);
293 if (!trees[0] || trees[0]->parent || !(trees[0]->schema->nodetype & (LYS_ACTION | LYS_LIST | LYS_CONTAINER))) {
294 LOGERR(ctx, LY_EINVAL, "Data parser invalid argument trees - the first item in the array must be the RPC/action request when parsing %s.",
295 lyd_parse_options_type2str(options));
Radek Krejcie7b95092019-05-15 11:03:07 +0200296 return NULL;
297 }
298 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200299
Radek Krejcie7b95092019-05-15 11:03:07 +0200300 if (options & LYD_OPT_DATA_TEMPLATE) {
301 yang_data_name = va_arg(ap, const char *);
302 }
Radek Krejcie92210c2019-05-17 15:53:35 +0200303#endif
Radek Krejcie7b95092019-05-15 11:03:07 +0200304
305 if (!format) {
306 /* TODO try to detect format from the content */
307 }
308
309 switch (format) {
310 case LYD_XML:
Michal Vasko9f96a052020-03-10 09:41:45 +0100311 lyd_parse_xml_data(ctx, data, options, &result);
Radek Krejcie7b95092019-05-15 11:03:07 +0200312 break;
313#if 0
314 case LYD_JSON:
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200315 lyd_parse_json(ctx, data, options, trees, &result);
Radek Krejcie7b95092019-05-15 11:03:07 +0200316 break;
317 case LYD_LYB:
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200318 lyd_parse_lyb(ctx, data, options, trees, &result);
Radek Krejcie7b95092019-05-15 11:03:07 +0200319 break;
320#endif
Michal Vasko52927e22020-03-16 17:26:14 +0100321 case LYD_SCHEMA:
Radek Krejcie7b95092019-05-15 11:03:07 +0200322 LOGINT(ctx);
323 break;
324 }
325
Radek Krejcie7b95092019-05-15 11:03:07 +0200326 return result;
327}
328
329API struct lyd_node *
Michal Vaskoa3881362020-01-21 15:57:35 +0100330lyd_parse_fd(struct ly_ctx *ctx, int fd, LYD_FORMAT format, int options)
Radek Krejcie7b95092019-05-15 11:03:07 +0200331{
332 struct lyd_node *result;
333 size_t length;
334 char *addr;
335
336 LY_CHECK_ARG_RET(ctx, ctx, NULL);
337 if (fd < 0) {
338 LOGARG(ctx, fd);
339 return NULL;
340 }
341
342 LY_CHECK_RET(ly_mmap(ctx, fd, &length, (void **)&addr), NULL);
Michal Vaskoa3881362020-01-21 15:57:35 +0100343 result = lyd_parse_mem(ctx, addr ? addr : "", format, options);
Radek Krejcidf3da792019-05-17 10:32:24 +0200344 if (addr) {
345 ly_munmap(addr, length);
346 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200347
348 return result;
349}
350
351API struct lyd_node *
Michal Vaskoa3881362020-01-21 15:57:35 +0100352lyd_parse_path(struct ly_ctx *ctx, const char *path, LYD_FORMAT format, int options)
Radek Krejcie7b95092019-05-15 11:03:07 +0200353{
354 int fd;
355 struct lyd_node *result;
356 size_t len;
Radek Krejcie7b95092019-05-15 11:03:07 +0200357
358 LY_CHECK_ARG_RET(ctx, ctx, path, NULL);
359
360 fd = open(path, O_RDONLY);
361 LY_CHECK_ERR_RET(fd == -1, LOGERR(ctx, LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno)), NULL);
362
363 if (!format) {
364 /* unknown format - try to detect it from filename's suffix */
365 len = strlen(path);
366
367 /* ignore trailing whitespaces */
368 for (; len > 0 && isspace(path[len - 1]); len--);
369
370 if (len >= 5 && !strncmp(&path[len - 4], ".xml", 4)) {
371 format = LYD_XML;
372#if 0
373 } else if (len >= 6 && !strncmp(&path[len - 5], ".json", 5)) {
374 format = LYD_JSON;
375 } else if (len >= 5 && !strncmp(&path[len - 4], ".lyb", 4)) {
376 format = LYD_LYB;
377#endif
378 } /* else still unknown, try later to detect it from the content */
379 }
380
Michal Vaskoa3881362020-01-21 15:57:35 +0100381 result = lyd_parse_fd(ctx, fd, format, options);
Radek Krejcie7b95092019-05-15 11:03:07 +0200382 close(fd);
383
384 return result;
385}
Radek Krejci084289f2019-07-09 17:35:30 +0200386
Michal Vasko90932a92020-02-12 14:33:03 +0100387LY_ERR
388lyd_create_term(const struct lysc_node *schema, const char *value, size_t value_len, int *dynamic,
389 ly_clb_resolve_prefix get_prefix, void *prefix_data, LYD_FORMAT format, struct lyd_node **node)
390{
391 LY_ERR ret;
392 struct lyd_node_term *term;
393
Michal Vasko9b368d32020-02-14 13:53:31 +0100394 assert(schema->nodetype & LYD_NODE_TERM);
395
Michal Vasko90932a92020-02-12 14:33:03 +0100396 term = calloc(1, sizeof *term);
397 LY_CHECK_ERR_RET(!term, LOGMEM(schema->module->ctx), LY_EMEM);
398
399 term->schema = schema;
400 term->prev = (struct lyd_node *)term;
Michal Vasko9b368d32020-02-14 13:53:31 +0100401 term->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100402
403 ret = lyd_value_parse(term, value, value_len, dynamic, 0, get_prefix, prefix_data, format, NULL);
404 if (ret && (ret != LY_EINCOMPLETE)) {
405 free(term);
406 return ret;
407 }
Michal Vasko9b368d32020-02-14 13:53:31 +0100408 lyd_hash((struct lyd_node *)term);
409
410 *node = (struct lyd_node *)term;
411 return ret;
412}
413
414LY_ERR
415lyd_create_term2(const struct lysc_node *schema, const struct lyd_value *val, struct lyd_node **node)
416{
417 LY_ERR ret;
418 struct lyd_node_term *term;
419 struct lysc_type *type;
420
421 assert(schema->nodetype & LYD_NODE_TERM);
422
423 term = calloc(1, sizeof *term);
424 LY_CHECK_ERR_RET(!term, LOGMEM(schema->module->ctx), LY_EMEM);
425
426 term->schema = schema;
427 term->prev = (struct lyd_node *)term;
428 term->flags = LYD_NEW;
429
430 type = ((struct lysc_node_leaf *)schema)->type;
431 ret = type->plugin->duplicate(schema->module->ctx, val, &term->value);
432 if (ret) {
433 LOGERR(schema->module->ctx, ret, "Value duplication failed.");
434 free(term);
435 return ret;
436 }
437 lyd_hash((struct lyd_node *)term);
Michal Vasko90932a92020-02-12 14:33:03 +0100438
439 *node = (struct lyd_node *)term;
440 return ret;
441}
442
443LY_ERR
444lyd_create_inner(const struct lysc_node *schema, struct lyd_node **node)
445{
446 struct lyd_node_inner *in;
447
Michal Vasko9b368d32020-02-14 13:53:31 +0100448 assert(schema->nodetype & LYD_NODE_INNER);
449
Michal Vasko90932a92020-02-12 14:33:03 +0100450 in = calloc(1, sizeof *in);
451 LY_CHECK_ERR_RET(!in, LOGMEM(schema->module->ctx), LY_EMEM);
452
453 in->schema = schema;
454 in->prev = (struct lyd_node *)in;
Michal Vasko9b368d32020-02-14 13:53:31 +0100455 in->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100456
Michal Vasko9b368d32020-02-14 13:53:31 +0100457 /* do not hash list with keys, we need them for the hash */
458 if ((schema->nodetype != LYS_LIST) || (schema->flags & LYS_KEYLESS)) {
459 lyd_hash((struct lyd_node *)in);
460 }
Michal Vasko90932a92020-02-12 14:33:03 +0100461
462 *node = (struct lyd_node *)in;
463 return LY_SUCCESS;
464}
465
466static void
467ly_keys_clean(struct ly_keys *keys)
468{
469 size_t i;
470
471 for (i = 0; i < keys->key_count; ++i) {
472 keys->keys[i].schema->type->plugin->free(keys->keys[i].schema->module->ctx, &keys->keys[i].val);
473 }
474 free(keys->str);
475 free(keys->keys);
476}
477
478static char *
479ly_keys_parse_next(char **next_key, char **key_name)
480{
481 char *ptr, *ptr2, *val, quot;
482
483 ptr = *next_key;
484
485 /* "[" */
486 LY_CHECK_GOTO(ptr[0] != '[', error);
487 ++ptr;
488
489 /* key name */
490 ptr2 = strchr(ptr, '=');
491 LY_CHECK_GOTO(!ptr2, error);
492
493 *key_name = ptr;
494 ptr2[0] = '\0';
495
496 /* \0, was '=' */
497 ptr = ptr2 + 1;
498
499 /* quote */
500 LY_CHECK_GOTO((ptr[0] != '\'') && (ptr[0] != '\"'), error);
501 quot = ptr[0];
502 ++ptr;
503
504 /* value, terminate it */
505 val = ptr;
506 ptr2 = strchr(ptr, quot);
507 LY_CHECK_GOTO(!ptr2, error);
508 ptr2[0] = '\0';
509
510 /* \0, was quote */
511 ptr = ptr2 + 1;
512
513 /* "]" */
514 LY_CHECK_GOTO(ptr[0] != ']', error);
515 ++ptr;
516
517 *next_key = ptr;
518 return val;
519
520error:
521 *next_key = ptr;
522 return NULL;
523}
524
Michal Vaskod3678892020-05-21 10:06:58 +0200525/* fill keys structure that is expected to be zeroed and must always be cleaned (even on error);
526 * if store is set, fill also each val */
Michal Vasko90932a92020-02-12 14:33:03 +0100527static LY_ERR
Michal Vaskod3678892020-05-21 10:06:58 +0200528ly_keys_parse(const struct lysc_node *list, const char *keys_str, size_t keys_len, int store, int log,
529 struct ly_keys *keys)
Michal Vasko90932a92020-02-12 14:33:03 +0100530{
531 LY_ERR ret = LY_SUCCESS;
532 char *next_key, *name;
533 const struct lysc_node *key;
534 size_t i;
535
536 assert(list->nodetype == LYS_LIST);
537
Michal Vaskof03ed032020-03-04 13:31:44 +0100538 if (!keys_str) {
539 /* nothing to parse */
540 return LY_SUCCESS;
541 }
542
543 keys->str = strndup(keys_str, keys_len);
Michal Vasko90932a92020-02-12 14:33:03 +0100544 LY_CHECK_ERR_GOTO(!keys->str, LOGMEM(list->module->ctx); ret = LY_EMEM, cleanup);
545
546 next_key = keys->str;
547 while (next_key[0]) {
548 /* new key */
549 keys->keys = ly_realloc(keys->keys, (keys->key_count + 1) * sizeof *keys->keys);
550 LY_CHECK_ERR_GOTO(!keys->keys, LOGMEM(list->module->ctx); ret = LY_EMEM, cleanup);
551
552 /* fill */
553 keys->keys[keys->key_count].value = ly_keys_parse_next(&next_key, &name);
554 if (!keys->keys[keys->key_count].value) {
Michal Vaskod3678892020-05-21 10:06:58 +0200555 if (log) {
556 LOGERR(list->module->ctx, LY_EINVAL, "Invalid keys string (at \"%s\").", next_key);
557 }
Michal Vasko90932a92020-02-12 14:33:03 +0100558 ret = LY_EINVAL;
559 goto cleanup;
560 }
561
562 /* find schema node */
563 key = lys_find_child(list, list->module, name, 0, LYS_LEAF, 0);
564 if (!key) {
Michal Vaskod3678892020-05-21 10:06:58 +0200565 if (log) {
566 LOGERR(list->module->ctx, LY_EINVAL, "List \"%s\" has no key \"%s\".", list->name, name);
567 }
Michal Vasko90932a92020-02-12 14:33:03 +0100568 ret = LY_EINVAL;
569 goto cleanup;
570 }
571 keys->keys[keys->key_count].schema = (const struct lysc_node_leaf *)key;
572
573 /* check that we do not have it already */
574 for (i = 0; i < keys->key_count; ++i) {
575 if (keys->keys[i].schema == keys->keys[keys->key_count].schema) {
Michal Vaskod3678892020-05-21 10:06:58 +0200576 if (log) {
577 LOGERR(list->module->ctx, LY_EINVAL, "Duplicit key \"%s\" value.", name);
578 }
Michal Vasko90932a92020-02-12 14:33:03 +0100579 ret = LY_EINVAL;
580 goto cleanup;
581 }
582 }
583
584 if (store) {
585 /* store the value */
586 ret = lyd_value_store(&keys->keys[keys->key_count].val, key, keys->keys[keys->key_count].value, 0, 0,
587 lydjson_resolve_prefix, NULL, LYD_JSON);
588 LY_CHECK_GOTO(ret, cleanup);
Michal Vaskoae420e92020-05-21 10:00:40 +0200589 } else {
590 memset(&keys->keys[keys->key_count].val, 0, sizeof keys->keys[keys->key_count].val);
Michal Vasko90932a92020-02-12 14:33:03 +0100591 }
592
593 /* another valid key */
594 ++keys->key_count;
595 }
596
597cleanup:
Michal Vasko90932a92020-02-12 14:33:03 +0100598 return ret;
599}
600
601LY_ERR
Michal Vaskod3678892020-05-21 10:06:58 +0200602lyd_create_list(const struct lysc_node *schema, const char *keys_str, size_t keys_len, LYD_FORMAT keys_format, int log,
603 struct lyd_node **node)
Michal Vasko90932a92020-02-12 14:33:03 +0100604{
605 LY_ERR ret = LY_SUCCESS;
606 const struct lysc_node *key_s;
607 struct lyd_node *list = NULL, *key;
608 struct ly_keys keys = {0};
609 size_t i;
610
Michal Vaskod3678892020-05-21 10:06:58 +0200611 assert((schema->nodetype == LYS_LIST) && !(schema->flags & LYS_KEYLESS) && (keys_format != LYD_XML));
Michal Vasko90932a92020-02-12 14:33:03 +0100612
613 /* parse keys */
Michal Vaskod3678892020-05-21 10:06:58 +0200614 LY_CHECK_GOTO(ret = ly_keys_parse(schema, keys_str, keys_len, 0, log, &keys), cleanup);
Michal Vasko90932a92020-02-12 14:33:03 +0100615
616 /* create list */
617 LY_CHECK_GOTO(ret = lyd_create_inner(schema, &list), cleanup);
618
619 /* everything was checked except that all keys are set */
620 i = 0;
621 for (key_s = lysc_node_children(schema, 0); key_s && (key_s->flags & LYS_KEY); key_s = key_s->next) {
622 ++i;
623 }
624 if (i != keys.key_count) {
Michal Vaskod3678892020-05-21 10:06:58 +0200625 if (log) {
626 LOGERR(schema->module->ctx, LY_EINVAL, "List \"%s\" is missing some keys.", schema->name);
627 }
Michal Vasko90932a92020-02-12 14:33:03 +0100628 ret = LY_EINVAL;
629 goto cleanup;
630 }
631
632 /* create and insert all the keys */
633 for (i = 0; i < keys.key_count; ++i) {
Michal Vaskod3678892020-05-21 10:06:58 +0200634 if (keys_format == LYD_JSON) {
635 ret = lyd_create_term((struct lysc_node *)keys.keys[i].schema, keys.keys[i].value, strlen(keys.keys[i].value),
636 NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &key);
637 } else {
638 assert(keys_format == LYD_SCHEMA);
639 ret = lyd_create_term((struct lysc_node *)keys.keys[i].schema, keys.keys[i].value, strlen(keys.keys[i].value),
640 NULL, lys_resolve_prefix, NULL, LYD_SCHEMA, &key);
641 }
642 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko90932a92020-02-12 14:33:03 +0100643 lyd_insert_node(list, NULL, key);
644 }
645
Michal Vasko9b368d32020-02-14 13:53:31 +0100646 /* hash having all the keys */
647 lyd_hash(list);
648
Michal Vasko90932a92020-02-12 14:33:03 +0100649 /* success */
650 *node = list;
651 list = NULL;
652
653cleanup:
654 lyd_free_tree(list);
655 ly_keys_clean(&keys);
656 return ret;
657}
658
659LY_ERR
660lyd_create_any(const struct lysc_node *schema, const void *value, LYD_ANYDATA_VALUETYPE value_type, struct lyd_node **node)
661{
662 struct lyd_node_any *any;
663
Michal Vasko9b368d32020-02-14 13:53:31 +0100664 assert(schema->nodetype & LYD_NODE_ANY);
665
Michal Vasko90932a92020-02-12 14:33:03 +0100666 any = calloc(1, sizeof *any);
667 LY_CHECK_ERR_RET(!any, LOGMEM(schema->module->ctx), LY_EMEM);
668
669 any->schema = schema;
670 any->prev = (struct lyd_node *)any;
Michal Vasko9b368d32020-02-14 13:53:31 +0100671 any->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100672
673 any->value.xml = value;
674 any->value_type = value_type;
Michal Vasko9b368d32020-02-14 13:53:31 +0100675 lyd_hash((struct lyd_node *)any);
Michal Vasko90932a92020-02-12 14:33:03 +0100676
677 *node = (struct lyd_node *)any;
678 return LY_SUCCESS;
679}
680
Michal Vasko52927e22020-03-16 17:26:14 +0100681LY_ERR
682lyd_create_opaq(const struct ly_ctx *ctx, const char *name, size_t name_len, const char *value, size_t value_len,
683 int *dynamic, LYD_FORMAT format, struct ly_prefix *val_prefs, const char *prefix, size_t pref_len,
684 const char *ns, struct lyd_node **node)
685{
686 struct lyd_node_opaq *opaq;
687
688 assert(ctx && name && name_len && ns);
689
690 if (!value_len) {
691 value = "";
692 }
693
694 opaq = calloc(1, sizeof *opaq);
695 LY_CHECK_ERR_RET(!opaq, LOGMEM(ctx), LY_EMEM);
696
697 opaq->prev = (struct lyd_node *)opaq;
698
699 opaq->name = lydict_insert(ctx, name, name_len);
700 opaq->format = format;
701 if (pref_len) {
702 opaq->prefix.pref = lydict_insert(ctx, prefix, pref_len);
703 }
704 opaq->prefix.ns = lydict_insert(ctx, ns, 0);
705 opaq->val_prefs = val_prefs;
706 if (dynamic && *dynamic) {
707 opaq->value = lydict_insert_zc(ctx, (char *)value);
708 *dynamic = 0;
709 } else {
710 opaq->value = lydict_insert(ctx, value, value_len);
711 }
712 opaq->ctx = ctx;
713
714 *node = (struct lyd_node *)opaq;
715 return LY_SUCCESS;
716}
717
Michal Vasko013a8182020-03-03 10:46:53 +0100718API struct lyd_node *
719lyd_new_inner(struct lyd_node *parent, const struct lys_module *module, const char *name)
720{
721 struct lyd_node *ret = NULL;
722 const struct lysc_node *schema;
723 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
724
725 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
726
Michal Vaskof03ed032020-03-04 13:31:44 +0100727 if (!module) {
728 module = parent->schema->module;
729 }
730
Michal Vasko1bf09392020-03-27 12:38:10 +0100731 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 +0100732 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Inner node \"%s\" not found.", name), NULL);
733
734 if (!lyd_create_inner(schema, &ret) && parent) {
735 lyd_insert_node(parent, NULL, ret);
736 }
737 return ret;
738}
739
740API struct lyd_node *
741lyd_new_list(struct lyd_node *parent, const struct lys_module *module, const char *name, ...)
742{
743 struct lyd_node *ret = NULL, *key;
744 const struct lysc_node *schema, *key_s;
745 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
746 va_list ap;
747 const char *key_val;
748 LY_ERR rc = LY_SUCCESS;
749
750 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
751
Michal Vaskof03ed032020-03-04 13:31:44 +0100752 if (!module) {
753 module = parent->schema->module;
754 }
755
Michal Vasko013a8182020-03-03 10:46:53 +0100756 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, 0);
757 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), NULL);
758
759 /* create list inner node */
760 LY_CHECK_RET(lyd_create_inner(schema, &ret), NULL);
761
762 va_start(ap, name);
763
764 /* create and insert all the keys */
765 for (key_s = lysc_node_children(schema, 0); key_s && (key_s->flags & LYS_KEY); key_s = key_s->next) {
766 key_val = va_arg(ap, const char *);
767
Michal Vaskof03ed032020-03-04 13:31:44 +0100768 rc = lyd_create_term(key_s, key_val, key_val ? strlen(key_val) : 0, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &key);
769 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko013a8182020-03-03 10:46:53 +0100770 lyd_insert_node(ret, NULL, key);
771 }
772
773 /* hash having all the keys */
774 lyd_hash(ret);
775
776 if (parent) {
777 lyd_insert_node(parent, NULL, ret);
778 }
779
780cleanup:
781 if (rc) {
782 lyd_free_tree(ret);
783 ret = NULL;
784 }
785 va_end(ap);
786 return ret;
787}
788
789API struct lyd_node *
790lyd_new_list2(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *keys)
791{
792 struct lyd_node *ret = NULL;
793 const struct lysc_node *schema;
794 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
795
796 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
797
Michal Vaskof03ed032020-03-04 13:31:44 +0100798 if (!module) {
799 module = parent->schema->module;
800 }
801
Michal Vasko013a8182020-03-03 10:46:53 +0100802 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, 0);
803 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), NULL);
804
Michal Vaskod3678892020-05-21 10:06:58 +0200805 if (!lyd_create_list(schema, keys, keys ? strlen(keys) : 0, LYD_JSON, 1, &ret) && parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100806 lyd_insert_node(parent, NULL, ret);
807 }
808 return ret;
809}
810
811API struct lyd_node *
812lyd_new_term(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str)
813{
814 struct lyd_node *ret = NULL;
815 const struct lysc_node *schema;
816 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
817
818 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
819
Michal Vaskof03ed032020-03-04 13:31:44 +0100820 if (!module) {
821 module = parent->schema->module;
822 }
823
Michal Vasko013a8182020-03-03 10:46:53 +0100824 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_TERM, 0);
825 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Term node \"%s\" not found.", name), NULL);
826
Michal Vaskof03ed032020-03-04 13:31:44 +0100827 if (!lyd_create_term(schema, val_str, val_str ? strlen(val_str) : 0, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &ret)
828 && parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100829 lyd_insert_node(parent, NULL, ret);
830 }
831 return ret;
832}
833
834API struct lyd_node *
835lyd_new_any(struct lyd_node *parent, const struct lys_module *module, const char *name, const void *value,
836 LYD_ANYDATA_VALUETYPE value_type)
837{
838 struct lyd_node *ret = NULL;
839 const struct lysc_node *schema;
840 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
841
842 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
843
Michal Vaskof03ed032020-03-04 13:31:44 +0100844 if (!module) {
845 module = parent->schema->module;
846 }
847
Michal Vasko013a8182020-03-03 10:46:53 +0100848 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_ANY, 0);
849 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Any node \"%s\" not found.", name), NULL);
850
851 if (!lyd_create_any(schema, value, value_type, &ret) && parent) {
852 lyd_insert_node(parent, NULL, ret);
853 }
854 return ret;
855}
856
Michal Vasko90932a92020-02-12 14:33:03 +0100857struct lyd_node *
858lyd_get_prev_key_anchor(const struct lyd_node *first_sibling, const struct lysc_node *new_key)
859{
860 const struct lysc_node *prev_key;
861 struct lyd_node *match = NULL;
862
863 if (!first_sibling) {
864 return NULL;
865 }
866
867 for (prev_key = new_key->prev; !match && prev_key->next; prev_key = prev_key->prev) {
868 lyd_find_sibling_val(first_sibling, prev_key, NULL, 0, &match);
869 }
870
871 return match;
872}
873
874/**
875 * @brief Insert node after a sibling.
876 *
Michal Vasko9f96a052020-03-10 09:41:45 +0100877 * Handles inserting into NP containers and key-less lists.
878 *
Michal Vasko90932a92020-02-12 14:33:03 +0100879 * @param[in] sibling Sibling to insert after.
880 * @param[in] node Node to insert.
881 */
882static void
Michal Vaskof03ed032020-03-04 13:31:44 +0100883lyd_insert_after_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +0100884{
Michal Vasko0249f7c2020-03-05 16:36:40 +0100885 struct lyd_node_inner *par;
886
Michal Vasko90932a92020-02-12 14:33:03 +0100887 assert(!node->next && (node->prev == node));
888
889 node->next = sibling->next;
890 node->prev = sibling;
891 sibling->next = node;
892 if (node->next) {
893 /* sibling had a succeeding node */
894 node->next->prev = node;
895 } else {
896 /* sibling was last, find first sibling and change its prev */
897 if (sibling->parent) {
898 sibling = sibling->parent->child;
899 } else {
900 for (; sibling->prev->next != node; sibling = sibling->prev);
901 }
902 sibling->prev = node;
903 }
904 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +0100905
Michal Vasko9f96a052020-03-10 09:41:45 +0100906 for (par = node->parent; par; par = par->parent) {
907 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
908 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +0100909 par->flags &= ~LYD_DEFAULT;
910 }
Michal Vasko9f96a052020-03-10 09:41:45 +0100911 if ((par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
912 /* rehash key-less list */
913 lyd_hash((struct lyd_node *)par);
914 }
Michal Vasko0249f7c2020-03-05 16:36:40 +0100915 }
916
917 /* insert into hash table */
918 lyd_insert_hash(node);
Michal Vasko90932a92020-02-12 14:33:03 +0100919}
920
921/**
922 * @brief Insert node before a sibling.
923 *
Michal Vasko9f96a052020-03-10 09:41:45 +0100924 * Handles inserting into NP containers and key-less lists.
925 *
Michal Vasko90932a92020-02-12 14:33:03 +0100926 * @param[in] sibling Sibling to insert before.
927 * @param[in] node Node to insert.
928 */
929static void
Michal Vaskof03ed032020-03-04 13:31:44 +0100930lyd_insert_before_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +0100931{
Michal Vasko0249f7c2020-03-05 16:36:40 +0100932 struct lyd_node_inner *par;
933
Michal Vasko90932a92020-02-12 14:33:03 +0100934 assert(!node->next && (node->prev == node));
935
936 node->next = sibling;
937 /* covers situation of sibling being first */
938 node->prev = sibling->prev;
939 sibling->prev = node;
940 if (node->prev->next) {
941 /* sibling had a preceding node */
942 node->prev->next = node;
943 } else if (sibling->parent) {
944 /* sibling was first and we must also change parent child pointer */
945 sibling->parent->child = node;
946 }
947 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +0100948
Michal Vasko9f96a052020-03-10 09:41:45 +0100949 for (par = node->parent; par; par = par->parent) {
950 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
951 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +0100952 par->flags &= ~LYD_DEFAULT;
953 }
Michal Vasko9f96a052020-03-10 09:41:45 +0100954 if ((par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
955 /* rehash key-less list */
956 lyd_hash((struct lyd_node *)par);
957 }
Michal Vasko0249f7c2020-03-05 16:36:40 +0100958 }
959
960 /* insert into hash table */
961 lyd_insert_hash(node);
Michal Vasko90932a92020-02-12 14:33:03 +0100962}
963
964/**
965 * @brief Insert node as the last child of a parent.
966 *
Michal Vasko9f96a052020-03-10 09:41:45 +0100967 * Handles inserting into NP containers and key-less lists.
968 *
Michal Vasko90932a92020-02-12 14:33:03 +0100969 * @param[in] parent Parent to insert into.
970 * @param[in] node Node to insert.
971 */
972static void
Michal Vaskof03ed032020-03-04 13:31:44 +0100973lyd_insert_last_node(struct lyd_node *parent, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +0100974{
975 struct lyd_node_inner *par;
976
Michal Vasko0249f7c2020-03-05 16:36:40 +0100977 assert(parent && !node->next && (node->prev == node));
Michal Vasko52927e22020-03-16 17:26:14 +0100978 assert(!parent->schema || (parent->schema->nodetype & LYD_NODE_INNER));
Michal Vasko90932a92020-02-12 14:33:03 +0100979
980 par = (struct lyd_node_inner *)parent;
981
982 if (!par->child) {
983 par->child = node;
984 } else {
985 node->prev = par->child->prev;
986 par->child->prev->next = node;
987 par->child->prev = node;
988 }
989 node->parent = par;
Michal Vasko0249f7c2020-03-05 16:36:40 +0100990
Michal Vasko9f96a052020-03-10 09:41:45 +0100991 for (; par; par = par->parent) {
992 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
993 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +0100994 par->flags &= ~LYD_DEFAULT;
995 }
Michal Vasko52927e22020-03-16 17:26:14 +0100996 if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
Michal Vasko9f96a052020-03-10 09:41:45 +0100997 /* rehash key-less list */
998 lyd_hash((struct lyd_node *)par);
999 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001000 }
1001
1002 /* insert into hash table */
1003 lyd_insert_hash(node);
Michal Vasko90932a92020-02-12 14:33:03 +01001004}
1005
1006void
Michal Vasko9b368d32020-02-14 13:53:31 +01001007lyd_insert_node(struct lyd_node *parent, struct lyd_node **first_sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001008{
Michal Vasko9b368d32020-02-14 13:53:31 +01001009 struct lyd_node *anchor;
Michal Vasko9f96a052020-03-10 09:41:45 +01001010 const struct lysc_node *skey = NULL;
1011 int has_keys;
Michal Vasko90932a92020-02-12 14:33:03 +01001012
Michal Vasko52927e22020-03-16 17:26:14 +01001013 assert((parent || first_sibling) && node && (node->hash || !node->schema));
Michal Vasko9b368d32020-02-14 13:53:31 +01001014
1015 if (!parent && first_sibling && (*first_sibling) && (*first_sibling)->parent) {
1016 parent = (struct lyd_node *)(*first_sibling)->parent;
1017 }
Michal Vasko90932a92020-02-12 14:33:03 +01001018
1019 if (parent) {
Michal Vasko52927e22020-03-16 17:26:14 +01001020 if (node->schema && (node->schema->flags & LYS_KEY)) {
Michal Vasko90932a92020-02-12 14:33:03 +01001021 /* it is key and we need to insert it at the correct place */
Michal Vasko9b368d32020-02-14 13:53:31 +01001022 anchor = lyd_get_prev_key_anchor(lyd_node_children(parent), node->schema);
1023 if (anchor) {
Michal Vaskof03ed032020-03-04 13:31:44 +01001024 lyd_insert_after_node(anchor, node);
Michal Vasko90932a92020-02-12 14:33:03 +01001025 } else if (lyd_node_children(parent)) {
Radek Krejcidae0ee82020-05-06 16:53:24 +02001026 lyd_insert_before_node(lyd_node_children(parent), node);
Michal Vasko90932a92020-02-12 14:33:03 +01001027 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +01001028 lyd_insert_last_node(parent, node);
Michal Vasko90932a92020-02-12 14:33:03 +01001029 }
Michal Vasko9f96a052020-03-10 09:41:45 +01001030
1031 /* hash list if all its keys were added */
1032 assert(parent->schema->nodetype == LYS_LIST);
Radek Krejcidae0ee82020-05-06 16:53:24 +02001033 anchor = lyd_node_children(parent);
Michal Vasko9f96a052020-03-10 09:41:45 +01001034 has_keys = 1;
1035 while ((skey = lys_getnext(skey, parent->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
1036 if (!anchor || (anchor->schema != skey)) {
1037 /* key missing */
1038 has_keys = 0;
1039 break;
1040 }
1041
1042 anchor = anchor->next;
1043 }
1044 if (has_keys) {
1045 lyd_hash(parent);
1046 }
1047
Michal Vasko90932a92020-02-12 14:33:03 +01001048 } else {
1049 /* last child */
Michal Vaskof03ed032020-03-04 13:31:44 +01001050 lyd_insert_last_node(parent, node);
Michal Vasko90932a92020-02-12 14:33:03 +01001051 }
Michal Vasko9b368d32020-02-14 13:53:31 +01001052 } else if (*first_sibling) {
Michal Vaskob1b5c262020-03-05 14:29:47 +01001053 /* top-level siblings */
Michal Vasko9b368d32020-02-14 13:53:31 +01001054 anchor = (*first_sibling)->prev;
Michal Vaskoc193ce92020-03-06 11:04:48 +01001055 while (anchor->prev->next && (lyd_owner_module(anchor) != lyd_owner_module(node))) {
Michal Vasko9b368d32020-02-14 13:53:31 +01001056 anchor = anchor->prev;
1057 }
1058
Michal Vaskoc193ce92020-03-06 11:04:48 +01001059 if (lyd_owner_module(anchor) == lyd_owner_module(node)) {
Michal Vaskob1b5c262020-03-05 14:29:47 +01001060 /* insert after last sibling from this module */
1061 lyd_insert_after_node(anchor, node);
1062 } else {
1063 /* no data from this module, insert at the last position */
1064 lyd_insert_after_node((*first_sibling)->prev, node);
1065 }
Michal Vasko90932a92020-02-12 14:33:03 +01001066 } else {
Michal Vasko9b368d32020-02-14 13:53:31 +01001067 /* the only sibling */
1068 *first_sibling = node;
Michal Vasko90932a92020-02-12 14:33:03 +01001069 }
Michal Vasko90932a92020-02-12 14:33:03 +01001070}
1071
Michal Vaskof03ed032020-03-04 13:31:44 +01001072static LY_ERR
1073lyd_insert_check_schema(const struct lysc_node *parent, const struct lysc_node *schema)
1074{
1075 const struct lysc_node *par2;
1076
1077 assert(schema);
Michal Vasko62ed12d2020-05-21 10:08:25 +02001078 assert(!parent || !(parent->nodetype & (LYS_CASE | LYS_CHOICE)));
Michal Vaskof03ed032020-03-04 13:31:44 +01001079
1080 /* find schema parent */
Michal Vasko62ed12d2020-05-21 10:08:25 +02001081 par2 = lysc_data_parent(schema);
Michal Vaskof03ed032020-03-04 13:31:44 +01001082
1083 if (parent) {
1084 /* inner node */
1085 if (par2 != parent) {
1086 LOGERR(parent->module->ctx, LY_EINVAL, "Cannot insert, parent of \"%s\" is not \"%s\".", schema->name, parent->name);
1087 return LY_EINVAL;
1088 }
1089 } else {
1090 /* top-level node */
1091 if (par2) {
1092 LOGERR(parent->module->ctx, LY_EINVAL, "Cannot insert, node \"%s\" is not top-level.", schema->name);
1093 return LY_EINVAL;
1094 }
1095 }
1096
1097 return LY_SUCCESS;
1098}
1099
1100API LY_ERR
1101lyd_insert(struct lyd_node *parent, struct lyd_node *node)
1102{
1103 struct lyd_node *iter;
1104
1105 LY_CHECK_ARG_RET(NULL, parent, node, !(parent->schema->nodetype & LYD_NODE_INNER), LY_EINVAL);
1106
1107 LY_CHECK_RET(lyd_insert_check_schema(parent->schema, node->schema));
1108
1109 if (node->schema->flags & LYS_KEY) {
1110 LOGERR(parent->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1111 return LY_EINVAL;
1112 }
1113
1114 if (node->parent || node->prev->next) {
1115 lyd_unlink_tree(node);
1116 }
1117
1118 while (node) {
1119 iter = node->next;
1120 lyd_unlink_tree(node);
1121 lyd_insert_node(parent, NULL, node);
1122 node = iter;
1123 }
1124 return LY_SUCCESS;
1125}
1126
1127API LY_ERR
Michal Vaskob1b5c262020-03-05 14:29:47 +01001128lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node)
1129{
1130 struct lyd_node *iter;
1131
1132 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1133
Michal Vasko62ed12d2020-05-21 10:08:25 +02001134 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskob1b5c262020-03-05 14:29:47 +01001135
1136 if (node->schema->flags & LYS_KEY) {
1137 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1138 return LY_EINVAL;
1139 }
1140
1141 if (node->parent || node->prev->next) {
1142 lyd_unlink_tree(node);
1143 }
1144
1145 while (node) {
1146 iter = node->next;
1147 lyd_unlink_tree(node);
1148 lyd_insert_node(NULL, &sibling, node);
1149 node = iter;
1150 }
1151 return LY_SUCCESS;
1152}
1153
Michal Vasko0249f7c2020-03-05 16:36:40 +01001154static LY_ERR
1155lyd_insert_after_check_place(struct lyd_node *anchor, struct lyd_node *sibling, struct lyd_node *node)
1156{
1157 if (sibling->parent) {
1158 /* nested, we do not care for the order */
1159 return LY_SUCCESS;
1160 }
1161
1162 if (anchor) {
Michal Vaskoc193ce92020-03-06 11:04:48 +01001163 if (anchor->next && (lyd_owner_module(anchor) == lyd_owner_module(anchor->next))
1164 && (lyd_owner_module(node) != lyd_owner_module(anchor))) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001165 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 +01001166 lyd_owner_module(node)->name, lyd_owner_module(anchor)->name);
Michal Vasko0249f7c2020-03-05 16:36:40 +01001167 return LY_EINVAL;
1168 }
1169
Michal Vaskoc193ce92020-03-06 11:04:48 +01001170 if ((lyd_owner_module(node) == lyd_owner_module(anchor))
1171 || (anchor->next && (lyd_owner_module(node) == lyd_owner_module(anchor->next)))) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001172 /* inserting before/after its module data */
1173 return LY_SUCCESS;
1174 }
1175 }
1176
1177 /* find first sibling */
1178 while (sibling->prev->next) {
1179 sibling = sibling->prev;
1180 }
1181
1182 if (!anchor) {
Michal Vaskoc193ce92020-03-06 11:04:48 +01001183 if (lyd_owner_module(node) == lyd_owner_module(sibling)) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001184 /* inserting before its module data */
1185 return LY_SUCCESS;
1186 }
1187 }
1188
1189 /* check there are no data of this module */
1190 LY_LIST_FOR(sibling, sibling) {
Michal Vaskoc193ce92020-03-06 11:04:48 +01001191 if (lyd_owner_module(node) == lyd_owner_module(sibling)) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001192 /* some data of this module found */
1193 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Top-level data of module \"%s\" already exist,"
Michal Vaskoc193ce92020-03-06 11:04:48 +01001194 " they must be directly connected.", lyd_owner_module(node)->name);
Michal Vasko0249f7c2020-03-05 16:36:40 +01001195 return LY_EINVAL;
1196 }
1197 }
1198
1199 return LY_SUCCESS;
1200}
1201
Michal Vaskob1b5c262020-03-05 14:29:47 +01001202API LY_ERR
Michal Vaskof03ed032020-03-04 13:31:44 +01001203lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
1204{
1205 struct lyd_node *iter;
1206
1207 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1208
Michal Vasko62ed12d2020-05-21 10:08:25 +02001209 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskof03ed032020-03-04 13:31:44 +01001210
1211 if (node->schema->flags & LYS_KEY) {
1212 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1213 return LY_EINVAL;
1214 } else if (sibling->schema->flags & LYS_KEY) {
1215 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert into keys.");
1216 return LY_EINVAL;
1217 }
1218
Michal Vasko0249f7c2020-03-05 16:36:40 +01001219 LY_CHECK_RET(lyd_insert_after_check_place(sibling->prev->next ? sibling->prev : NULL, sibling, node));
1220
Michal Vaskof03ed032020-03-04 13:31:44 +01001221 if (node->parent || node->prev->next) {
1222 lyd_unlink_tree(node);
1223 }
1224
1225 /* insert in reverse order to get the original order */
1226 node = node->prev;
1227 while (node) {
1228 iter = node->prev;
1229 lyd_unlink_tree(node);
1230
1231 lyd_insert_before_node(sibling, node);
1232 /* move the anchor accordingly */
1233 sibling = node;
1234
1235 node = (iter == node) ? NULL : iter;
1236 }
1237 return LY_SUCCESS;
1238}
1239
1240API LY_ERR
1241lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
1242{
1243 struct lyd_node *iter;
1244
1245 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1246
Michal Vasko62ed12d2020-05-21 10:08:25 +02001247 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskof03ed032020-03-04 13:31:44 +01001248
1249 if (node->schema->flags & LYS_KEY) {
1250 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1251 return LY_EINVAL;
1252 } else if (sibling->next && (sibling->next->schema->flags & LYS_KEY)) {
1253 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert into keys.");
1254 return LY_EINVAL;
1255 }
1256
Michal Vasko0249f7c2020-03-05 16:36:40 +01001257 LY_CHECK_RET(lyd_insert_after_check_place(sibling, sibling, node));
1258
Michal Vaskof03ed032020-03-04 13:31:44 +01001259 if (node->parent || node->prev->next) {
1260 lyd_unlink_tree(node);
1261 }
1262
1263 while (node) {
1264 iter = node->next;
1265 lyd_unlink_tree(node);
1266
1267 lyd_insert_after_node(sibling, node);
1268 /* move the anchor accordingly */
1269 sibling = node;
1270
1271 node = iter;
1272 }
1273 return LY_SUCCESS;
1274}
1275
1276API void
1277lyd_unlink_tree(struct lyd_node *node)
1278{
1279 struct lyd_node *iter;
1280
1281 if (!node) {
1282 return;
1283 }
1284
1285 /* unlink from siblings */
1286 if (node->prev->next) {
1287 node->prev->next = node->next;
1288 }
1289 if (node->next) {
1290 node->next->prev = node->prev;
1291 } else {
1292 /* unlinking the last node */
1293 if (node->parent) {
1294 iter = node->parent->child;
1295 } else {
1296 iter = node->prev;
1297 while (iter->prev != node) {
1298 iter = iter->prev;
1299 }
1300 }
1301 /* update the "last" pointer from the first node */
1302 iter->prev = node->prev;
1303 }
1304
1305 /* unlink from parent */
1306 if (node->parent) {
1307 if (node->parent->child == node) {
1308 /* the node is the first child */
1309 node->parent->child = node->next;
1310 }
1311
1312 lyd_unlink_hash(node);
1313
1314 /* check for keyless list and update its hash */
1315 for (iter = (struct lyd_node *)node->parent; iter; iter = (struct lyd_node *)iter->parent) {
Michal Vasko413c7f22020-05-05 12:34:06 +02001316 if (iter->schema && (iter->schema->flags & LYS_KEYLESS)) {
Michal Vaskof03ed032020-03-04 13:31:44 +01001317 lyd_hash(iter);
1318 }
1319 }
1320
1321 node->parent = NULL;
1322 }
1323
1324 node->next = NULL;
1325 node->prev = node;
1326}
1327
Michal Vasko90932a92020-02-12 14:33:03 +01001328LY_ERR
Michal Vasko9f96a052020-03-10 09:41:45 +01001329lyd_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 +01001330 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 +01001331 void *prefix_data, LYD_FORMAT format, const struct lysc_node *ctx_snode)
Michal Vasko90932a92020-02-12 14:33:03 +01001332{
1333 LY_ERR ret;
1334 struct lysc_ext_instance *ant = NULL;
Michal Vasko9f96a052020-03-10 09:41:45 +01001335 struct lyd_meta *mt, *last;
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001336 LY_ARRAY_SIZE_TYPE u;
Michal Vasko90932a92020-02-12 14:33:03 +01001337
Michal Vasko9f96a052020-03-10 09:41:45 +01001338 assert((parent || meta) && mod);
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001339
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001340 LY_ARRAY_FOR(mod->compiled->exts, u) {
1341 if (mod->compiled->exts[u].def->plugin == lyext_plugins_internal[LYEXT_PLUGIN_INTERNAL_ANNOTATION].plugin &&
1342 !ly_strncmp(mod->compiled->exts[u].argument, name, name_len)) {
Michal Vasko90932a92020-02-12 14:33:03 +01001343 /* we have the annotation definition */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001344 ant = &mod->compiled->exts[u];
Michal Vasko90932a92020-02-12 14:33:03 +01001345 break;
1346 }
1347 }
1348 if (!ant) {
1349 /* attribute is not defined as a metadata annotation (RFC 7952) */
1350 LOGERR(mod->ctx, LY_EINVAL, "Annotation definition for attribute \"%s:%.*s\" not found.",
1351 mod->name, name_len, name);
1352 return LY_EINVAL;
1353 }
1354
Michal Vasko9f96a052020-03-10 09:41:45 +01001355 mt = calloc(1, sizeof *mt);
1356 LY_CHECK_ERR_RET(!mt, LOGMEM(mod->ctx), LY_EMEM);
1357 mt->parent = parent;
1358 mt->annotation = ant;
Michal Vasko52927e22020-03-16 17:26:14 +01001359 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 +01001360 if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001361 free(mt);
Michal Vasko90932a92020-02-12 14:33:03 +01001362 return ret;
1363 }
Michal Vasko9f96a052020-03-10 09:41:45 +01001364 mt->name = lydict_insert(mod->ctx, name, name_len);
Michal Vasko90932a92020-02-12 14:33:03 +01001365
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001366 /* insert as the last attribute */
1367 if (parent) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001368 if (parent->meta) {
1369 for (last = parent->meta; last->next; last = last->next);
1370 last->next = mt;
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001371 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +01001372 parent->meta = mt;
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001373 }
Michal Vasko9f96a052020-03-10 09:41:45 +01001374 } else if (*meta) {
1375 for (last = *meta; last->next; last = last->next);
1376 last->next = mt;
Michal Vasko90932a92020-02-12 14:33:03 +01001377 }
1378
1379 /* remove default flags from NP containers */
1380 while (parent && (parent->flags & LYD_DEFAULT)) {
1381 parent->flags &= ~LYD_DEFAULT;
1382 parent = (struct lyd_node *)parent->parent;
1383 }
1384
Michal Vasko9f96a052020-03-10 09:41:45 +01001385 if (meta) {
1386 *meta = mt;
Michal Vasko90932a92020-02-12 14:33:03 +01001387 }
1388 return ret;
1389}
1390
Michal Vasko52927e22020-03-16 17:26:14 +01001391LY_ERR
1392ly_create_attr(struct lyd_node *parent, struct ly_attr **attr, const struct ly_ctx *ctx, const char *name,
1393 size_t name_len, const char *value, size_t value_len, int *dynamic, LYD_FORMAT format,
1394 struct ly_prefix *val_prefs, const char *prefix, size_t prefix_len, const char *ns)
1395{
1396 struct ly_attr *at, *last;
1397 struct lyd_node_opaq *opaq;
1398
1399 assert(ctx && (parent || attr) && (!parent || !parent->schema));
1400 assert(name && name_len);
1401 assert((prefix_len && ns) || (!prefix_len && !ns));
1402
1403 if (!value_len) {
1404 value = "";
1405 }
1406
1407 at = calloc(1, sizeof *at);
1408 LY_CHECK_ERR_RET(!at, LOGMEM(ctx), LY_EMEM);
1409 at->parent = (struct lyd_node_opaq *)parent;
1410 at->name = lydict_insert(ctx, name, name_len);
1411 if (dynamic && *dynamic) {
1412 at->value = lydict_insert_zc(ctx, (char *)value);
1413 *dynamic = 0;
1414 } else {
1415 at->value = lydict_insert(ctx, value, value_len);
1416 }
1417
1418 at->format = format;
1419 at->val_prefs = val_prefs;
1420 if (ns) {
1421 at->prefix.pref = lydict_insert(ctx, prefix, prefix_len);
1422 at->prefix.ns = lydict_insert(ctx, ns, 0);
1423 }
1424
1425 /* insert as the last attribute */
1426 if (parent) {
1427 opaq = (struct lyd_node_opaq *)parent;
1428 if (opaq->attr) {
1429 for (last = opaq->attr; last->next; last = last->next);
1430 last->next = at;
1431 } else {
1432 opaq->attr = at;
1433 }
1434 } else if (*attr) {
1435 for (last = *attr; last->next; last = last->next);
1436 last->next = at;
1437 }
1438
1439 if (attr) {
1440 *attr = at;
1441 }
1442 return LY_SUCCESS;
1443}
1444
Radek Krejci084289f2019-07-09 17:35:30 +02001445API const struct lyd_node_term *
Michal Vaskof03ed032020-03-04 13:31:44 +01001446lyd_target(struct lyd_value_path *path, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +02001447{
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001448 LY_ARRAY_SIZE_TYPE u, v;
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001449 const struct lyd_node *start_sibling;
Michal Vaskoe444f752020-02-10 12:20:06 +01001450 struct lyd_node *node = NULL;
Radek Krejci084289f2019-07-09 17:35:30 +02001451 uint64_t pos = 1;
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001452 int match;
Radek Krejci084289f2019-07-09 17:35:30 +02001453
Michal Vaskof03ed032020-03-04 13:31:44 +01001454 LY_CHECK_ARG_RET(NULL, path, tree, NULL);
Radek Krejci084289f2019-07-09 17:35:30 +02001455
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001456 /* first iteration */
1457 start_sibling = tree;
1458 u = 0;
1459 while (u < LY_ARRAY_SIZE(path)) {
1460 /* find next node instance */
Michal Vasko84c9f1b2020-05-14 12:08:11 +02001461 if (start_sibling && !start_sibling->prev->next && !(path[u].node->nodetype & (LYS_LEAFLIST | LYS_LIST))) {
1462 /* starting from the beginning using hashes */
1463 lyd_find_sibling_val(start_sibling, path[u].node, NULL, 0, &node);
1464 } else {
1465 /* next matching sibling */
1466 lyd_find_sibling_next2(start_sibling, path[u].node, NULL, 0, &node);
1467 }
Radek Krejci084289f2019-07-09 17:35:30 +02001468 if (!node) {
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001469 break;
Radek Krejci084289f2019-07-09 17:35:30 +02001470 }
1471
1472 /* check predicate if any */
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001473 match = 1;
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001474 LY_ARRAY_FOR(path[u].predicates, v) {
1475 if (path[u].predicates[v].type == 0) {
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001476 assert(LY_ARRAY_SIZE(path[u].predicates) == 1);
Radek Krejci084289f2019-07-09 17:35:30 +02001477 /* position predicate */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001478 if (pos != path[u].predicates[v].position) {
Radek Krejci084289f2019-07-09 17:35:30 +02001479 pos++;
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001480 match = 0;
Radek Krejci084289f2019-07-09 17:35:30 +02001481 }
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001482 } else if (path[u].predicates[v].type == 1) {
Radek Krejci084289f2019-07-09 17:35:30 +02001483 /* key-predicate */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001484 struct lysc_type *type = ((struct lysc_node_leaf *)path[u].predicates[v].key)->type;
Michal Vaskoe444f752020-02-10 12:20:06 +01001485 struct lyd_node *key;
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001486
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001487 lyd_find_sibling_val(lyd_node_children(node), path[u].predicates[v].key, NULL, 0, &key);
Radek Krejci084289f2019-07-09 17:35:30 +02001488 if (!key) {
1489 /* probably error and we shouldn't be here due to previous checks when creating path */
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001490 match = 0;
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001491 } else if (type->plugin->compare(&((struct lyd_node_term *)key)->value, path[u].predicates[v].value)) {
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001492 match = 0;
Radek Krejci084289f2019-07-09 17:35:30 +02001493 }
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001494 } else if (path[u].predicates[v].type == 2) {
Radek Krejci084289f2019-07-09 17:35:30 +02001495 /* leaf-list-predicate */
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001496 struct lysc_type *type = ((struct lysc_node_leaf *)path[u].node)->type;
1497
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001498 if (type->plugin->compare(&((struct lyd_node_term *)node)->value, path[u].predicates[v].value)) {
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001499 match = 0;
Radek Krejci084289f2019-07-09 17:35:30 +02001500 }
1501 } else {
1502 LOGINT(NULL);
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001503 return NULL;
1504 }
1505
1506 if (!match) {
1507 /* useless to check more predicates */
1508 break;
Radek Krejci084289f2019-07-09 17:35:30 +02001509 }
1510 }
1511
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001512 if (!match) {
1513 /* try to match next sibling */
1514 start_sibling = node->next;
1515 } else {
1516 /* matched, move to the next path segment */
1517 ++u;
1518 start_sibling = lyd_node_children(node);
1519 pos = 1;
1520 }
Radek Krejci084289f2019-07-09 17:35:30 +02001521 }
1522
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001523 return (const struct lyd_node_term *)node;
Radek Krejci084289f2019-07-09 17:35:30 +02001524}
1525
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001526API LY_ERR
1527lyd_compare(const struct lyd_node *node1, const struct lyd_node *node2, int options)
1528{
1529 const struct lyd_node *iter1, *iter2;
1530 struct lyd_node_term *term1, *term2;
1531 struct lyd_node_any *any1, *any2;
Michal Vasko52927e22020-03-16 17:26:14 +01001532 struct lyd_node_opaq *opaq1, *opaq2;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001533 struct lysc_type *type;
1534 size_t len1, len2;
Radek Krejci084289f2019-07-09 17:35:30 +02001535
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001536 if (!node1 || !node2) {
1537 if (node1 == node2) {
1538 return LY_SUCCESS;
1539 } else {
1540 return LY_ENOT;
1541 }
1542 }
1543
Michal Vasko52927e22020-03-16 17:26:14 +01001544 if ((LYD_NODE_CTX(node1) != LYD_NODE_CTX(node2)) || (node1->schema != node2->schema)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001545 return LY_ENOT;
1546 }
1547
1548 if (node1->hash != node2->hash) {
1549 return LY_ENOT;
1550 }
Michal Vasko52927e22020-03-16 17:26:14 +01001551 /* 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 +02001552
Michal Vasko52927e22020-03-16 17:26:14 +01001553 if (!node1->schema) {
1554 opaq1 = (struct lyd_node_opaq *)node1;
1555 opaq2 = (struct lyd_node_opaq *)node2;
1556 if ((opaq1->name != opaq2->name) || (opaq1->prefix.ns != opaq2->prefix.ns) || (opaq1->format != opaq2->format)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001557 return LY_ENOT;
1558 }
Michal Vasko52927e22020-03-16 17:26:14 +01001559 switch (opaq1->format) {
1560 case LYD_XML:
1561 if (lyxml_value_compare(opaq1->value, opaq1->val_prefs, opaq2->value, opaq2->val_prefs)) {
1562 return LY_ENOT;
1563 }
1564 break;
1565 case LYD_SCHEMA:
1566 /* not allowed */
1567 LOGINT(LYD_NODE_CTX(node1));
1568 return LY_EINT;
1569 }
1570 if (options & LYD_COMPARE_FULL_RECURSION) {
1571 iter1 = opaq1->child;
1572 iter2 = opaq2->child;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001573 goto all_children_compare;
Michal Vasko52927e22020-03-16 17:26:14 +01001574 }
1575 return LY_SUCCESS;
1576 } else {
1577 switch (node1->schema->nodetype) {
1578 case LYS_LEAF:
1579 case LYS_LEAFLIST:
1580 if (options & LYD_COMPARE_DEFAULTS) {
1581 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
1582 return LY_ENOT;
1583 }
1584 }
1585
1586 term1 = (struct lyd_node_term*)node1;
1587 term2 = (struct lyd_node_term*)node2;
1588 type = ((struct lysc_node_leaf*)node1->schema)->type;
1589
1590 return type->plugin->compare(&term1->value, &term2->value);
1591 case LYS_CONTAINER:
1592 if (options & LYD_COMPARE_DEFAULTS) {
1593 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
1594 return LY_ENOT;
1595 }
1596 }
1597 if (options & LYD_COMPARE_FULL_RECURSION) {
1598 iter1 = ((struct lyd_node_inner*)node1)->child;
1599 iter2 = ((struct lyd_node_inner*)node2)->child;
1600 goto all_children_compare;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001601 }
1602 return LY_SUCCESS;
Michal Vasko1bf09392020-03-27 12:38:10 +01001603 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01001604 case LYS_ACTION:
1605 if (options & LYD_COMPARE_FULL_RECURSION) {
1606 /* TODO action/RPC
1607 goto all_children_compare;
1608 */
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001609 }
1610 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01001611 case LYS_NOTIF:
1612 if (options & LYD_COMPARE_FULL_RECURSION) {
1613 /* TODO Notification
1614 goto all_children_compare;
1615 */
1616 }
1617 return LY_SUCCESS;
1618 case LYS_LIST:
1619 iter1 = ((struct lyd_node_inner*)node1)->child;
1620 iter2 = ((struct lyd_node_inner*)node2)->child;
1621
1622 if (!(node1->schema->flags & LYS_KEYLESS) && !(options & LYD_COMPARE_FULL_RECURSION)) {
1623 /* lists with keys, their equivalence is based on their keys */
1624 for (struct lysc_node *key = ((struct lysc_node_list*)node1->schema)->child;
1625 key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
1626 key = key->next) {
1627 if (lyd_compare(iter1, iter2, options)) {
1628 return LY_ENOT;
1629 }
1630 iter1 = iter1->next;
1631 iter2 = iter2->next;
1632 }
1633 } else {
1634 /* lists without keys, their equivalence is based on equivalence of all the children (both direct and indirect) */
1635
1636 all_children_compare:
1637 if (!iter1 && !iter2) {
1638 /* no children, nothing to compare */
1639 return LY_SUCCESS;
1640 }
1641
1642 for (; iter1 && iter2; iter1 = iter1->next, iter2 = iter2->next) {
1643 if (lyd_compare(iter1, iter2, options | LYD_COMPARE_FULL_RECURSION)) {
1644 return LY_ENOT;
1645 }
1646 }
1647 if (iter1 || iter2) {
1648 return LY_ENOT;
1649 }
1650 }
1651 return LY_SUCCESS;
1652 case LYS_ANYXML:
1653 case LYS_ANYDATA:
1654 any1 = (struct lyd_node_any*)node1;
1655 any2 = (struct lyd_node_any*)node2;
1656
1657 if (any1->value_type != any2->value_type) {
1658 return LY_ENOT;
1659 }
1660 switch (any1->value_type) {
1661 case LYD_ANYDATA_DATATREE:
1662 iter1 = any1->value.tree;
1663 iter2 = any2->value.tree;
1664 goto all_children_compare;
1665 case LYD_ANYDATA_STRING:
1666 case LYD_ANYDATA_XML:
1667 case LYD_ANYDATA_JSON:
1668 len1 = strlen(any1->value.str);
1669 len2 = strlen(any2->value.str);
1670 if (len1 != len2 || strcmp(any1->value.str, any2->value.str)) {
1671 return LY_ENOT;
1672 }
1673 return LY_SUCCESS;
1674 #if 0 /* TODO LYB format */
1675 case LYD_ANYDATA_LYB:
1676 int len1 = lyd_lyb_data_length(any1->value.mem);
1677 int len2 = lyd_lyb_data_length(any2->value.mem);
1678 if (len1 != len2 || memcmp(any1->value.mem, any2->value.mem, len1)) {
1679 return LY_ENOT;
1680 }
1681 return LY_SUCCESS;
1682 #endif
1683 }
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001684 }
1685 }
1686
Michal Vasko52927e22020-03-16 17:26:14 +01001687 LOGINT(LYD_NODE_CTX(node1));
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001688 return LY_EINT;
1689}
Radek Krejci22ebdba2019-07-25 13:59:43 +02001690
1691/**
Michal Vasko52927e22020-03-16 17:26:14 +01001692 * @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 +02001693 *
1694 * Ignores LYD_DUP_WITH_PARENTS and LYD_DUP_WITH_SIBLINGS which are supposed to be handled by lyd_dup().
Radek Krejcif8b95172020-05-15 14:51:06 +02001695 *
1696 * @param[in] node Original node to duplicate
1697 * @param[in] parent Parent to insert into, NULL for top-level sibling.
1698 * @param[in,out] first First sibling, NULL if no top-level sibling exist yet. Can be also NULL if @p parent is set.
1699 * @param[in] options Bitmask of options flags, see @ref dupoptions.
1700 * @param[out] dup_p Pointer where the created duplicated node is placed (besides connecting it int @p parent / @p first sibling).
1701 * @return LY_ERR value
Radek Krejci22ebdba2019-07-25 13:59:43 +02001702 */
Michal Vasko52927e22020-03-16 17:26:14 +01001703static LY_ERR
1704lyd_dup_recursive(const struct lyd_node *node, struct lyd_node *parent, struct lyd_node **first, int options,
1705 struct lyd_node **dup_p)
Radek Krejci22ebdba2019-07-25 13:59:43 +02001706{
Michal Vasko52927e22020-03-16 17:26:14 +01001707 LY_ERR ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001708 struct lyd_node *dup = NULL;
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001709 LY_ARRAY_SIZE_TYPE u;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001710
Michal Vasko52927e22020-03-16 17:26:14 +01001711 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001712
Michal Vasko52927e22020-03-16 17:26:14 +01001713 if (!node->schema) {
1714 dup = calloc(1, sizeof(struct lyd_node_opaq));
1715 } else {
1716 switch (node->schema->nodetype) {
Michal Vasko1bf09392020-03-27 12:38:10 +01001717 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01001718 case LYS_ACTION:
1719 case LYS_NOTIF:
1720 case LYS_CONTAINER:
1721 case LYS_LIST:
1722 dup = calloc(1, sizeof(struct lyd_node_inner));
1723 break;
1724 case LYS_LEAF:
1725 case LYS_LEAFLIST:
1726 dup = calloc(1, sizeof(struct lyd_node_term));
1727 break;
1728 case LYS_ANYDATA:
1729 case LYS_ANYXML:
1730 dup = calloc(1, sizeof(struct lyd_node_any));
1731 break;
1732 default:
1733 LOGINT(LYD_NODE_CTX(node));
1734 ret = LY_EINT;
1735 goto error;
1736 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02001737 }
Michal Vasko52927e22020-03-16 17:26:14 +01001738 LY_CHECK_ERR_GOTO(!dup, LOGMEM(LYD_NODE_CTX(node)); ret = LY_EMEM, error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001739
1740 /* TODO implement LYD_DUP_WITH_WHEN */
1741 dup->flags = node->flags;
1742 dup->schema = node->schema;
Michal Vasko52927e22020-03-16 17:26:14 +01001743 dup->prev = dup;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001744
1745 /* TODO duplicate attributes, implement LYD_DUP_NO_ATTR */
1746
1747 /* nodetype-specific work */
Michal Vasko52927e22020-03-16 17:26:14 +01001748 if (!dup->schema) {
1749 struct lyd_node_opaq *opaq = (struct lyd_node_opaq *)dup;
1750 struct lyd_node_opaq *orig = (struct lyd_node_opaq *)node;
1751 struct lyd_node *child;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001752
1753 if (options & LYD_DUP_RECURSIVE) {
1754 /* duplicate all the children */
1755 LY_LIST_FOR(orig->child, child) {
Michal Vasko52927e22020-03-16 17:26:14 +01001756 LY_CHECK_GOTO(ret = lyd_dup_recursive(child, dup, NULL, options, NULL), error);
1757 }
1758 }
1759 opaq->name = lydict_insert(LYD_NODE_CTX(node), orig->name, 0);
1760 opaq->format = orig->format;
1761 if (orig->prefix.pref) {
1762 opaq->prefix.pref = lydict_insert(LYD_NODE_CTX(node), orig->prefix.pref, 0);
1763 }
1764 if (orig->prefix.ns) {
1765 opaq->prefix.ns = lydict_insert(LYD_NODE_CTX(node), orig->prefix.ns, 0);
1766 }
1767 if (orig->val_prefs) {
1768 LY_ARRAY_CREATE_GOTO(LYD_NODE_CTX(node), opaq->val_prefs, LY_ARRAY_SIZE(orig->val_prefs), ret, error);
1769 LY_ARRAY_FOR(orig->val_prefs, u) {
1770 opaq->val_prefs[u].pref = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].pref, 0);
1771 opaq->val_prefs[u].ns = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].ns, 0);
1772 LY_ARRAY_INCREMENT(opaq->val_prefs);
1773 }
1774 }
1775 opaq->value = lydict_insert(LYD_NODE_CTX(node), orig->value, 0);
1776 opaq->ctx = orig->ctx;
1777 } else if (dup->schema->nodetype & LYD_NODE_TERM) {
1778 struct lyd_node_term *term = (struct lyd_node_term *)dup;
1779 struct lyd_node_term *orig = (struct lyd_node_term *)node;
1780
1781 term->hash = orig->hash;
1782 term->value.realtype = orig->value.realtype;
1783 LY_CHECK_ERR_GOTO(term->value.realtype->plugin->duplicate(LYD_NODE_CTX(node), &orig->value, &term->value),
1784 LOGERR(LYD_NODE_CTX(node), LY_EINT, "Value duplication failed."); ret = LY_EINT, error);
1785 } else if (dup->schema->nodetype & LYD_NODE_INNER) {
1786 struct lyd_node_inner *orig = (struct lyd_node_inner *)node;
1787 struct lyd_node *child;
1788
1789 if (options & LYD_DUP_RECURSIVE) {
1790 /* duplicate all the children */
1791 LY_LIST_FOR(orig->child, child) {
1792 LY_CHECK_GOTO(ret = lyd_dup_recursive(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001793 }
Radek Krejci0fe9b512019-07-26 17:51:05 +02001794 } else if (dup->schema->nodetype == LYS_LIST && !(dup->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001795 /* always duplicate keys of a list */
Radek Krejci22ebdba2019-07-25 13:59:43 +02001796 child = orig->child;
Michal Vasko52927e22020-03-16 17:26:14 +01001797 for (struct lysc_node *key = ((struct lysc_node_list *)dup->schema)->child;
Radek Krejci0fe9b512019-07-26 17:51:05 +02001798 key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
1799 key = key->next) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001800 if (!child) {
1801 /* possibly not keys are present in filtered tree */
1802 break;
Radek Krejci0fe9b512019-07-26 17:51:05 +02001803 } else if (child->schema != key) {
1804 /* possibly not all keys are present in filtered tree,
1805 * but there can be also some non-key nodes */
1806 continue;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001807 }
Michal Vasko52927e22020-03-16 17:26:14 +01001808 LY_CHECK_GOTO(ret = lyd_dup_recursive(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001809 child = child->next;
1810 }
1811 }
1812 lyd_hash(dup);
1813 } else if (dup->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko52927e22020-03-16 17:26:14 +01001814 struct lyd_node_any *any = (struct lyd_node_any *)dup;
1815 struct lyd_node_any *orig = (struct lyd_node_any *)node;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001816
1817 any->hash = orig->hash;
1818 any->value_type = orig->value_type;
1819 switch (any->value_type) {
1820 case LYD_ANYDATA_DATATREE:
1821 if (orig->value.tree) {
1822 any->value.tree = lyd_dup(orig->value.tree, NULL, LYD_DUP_RECURSIVE | LYD_DUP_WITH_SIBLINGS);
Radek Krejci25dc3432020-05-15 14:42:12 +02001823 if (!any->value.tree) {
1824 /* get the last error's error code recorded by lyd_dup */
1825 struct ly_err_item *ei = ly_err_first(LYD_NODE_CTX(node));
1826 ret = ei ? ei->prev->no : LY_EOTHER;
1827 goto error;
1828 }
1829 LY_CHECK_ERR_GOTO(!any->value.tree, ret = 0 ,error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001830 }
1831 break;
1832 case LYD_ANYDATA_STRING:
1833 case LYD_ANYDATA_XML:
1834 case LYD_ANYDATA_JSON:
1835 if (orig->value.str) {
Michal Vasko52927e22020-03-16 17:26:14 +01001836 any->value.str = lydict_insert(LYD_NODE_CTX(node), orig->value.str, strlen(orig->value.str));
Radek Krejci22ebdba2019-07-25 13:59:43 +02001837 }
1838 break;
1839 }
1840 }
1841
Michal Vasko52927e22020-03-16 17:26:14 +01001842 /* insert */
1843 lyd_insert_node(parent, first, dup);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001844 lyd_insert_hash(dup);
Michal Vasko52927e22020-03-16 17:26:14 +01001845
1846 if (dup_p) {
1847 *dup_p = dup;
1848 }
1849 return LY_SUCCESS;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001850
1851error:
Michal Vasko52927e22020-03-16 17:26:14 +01001852 lyd_free_tree(dup);
1853 return ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001854}
1855
1856API struct lyd_node *
1857lyd_dup(const struct lyd_node *node, struct lyd_node_inner *parent, int options)
1858{
1859 struct ly_ctx *ctx;
1860 const struct lyd_node *orig; /* original node to be duplicated */
1861 struct lyd_node *first = NULL; /* the first duplicated node, this is returned */
Radek Krejci22ebdba2019-07-25 13:59:43 +02001862 struct lyd_node *top = NULL; /* the most higher created node */
1863 struct lyd_node_inner *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
1864 int keyless_parent_list = 0;
1865
1866 LY_CHECK_ARG_RET(NULL, node, NULL);
1867 ctx = node->schema->module->ctx;
1868
1869 if (options & LYD_DUP_WITH_PARENTS) {
1870 struct lyd_node_inner *orig_parent, *iter;
1871 int repeat = 1;
1872 for (top = NULL, orig_parent = node->parent; repeat && orig_parent; orig_parent = orig_parent->parent) {
1873 if (parent && parent->schema == orig_parent->schema) {
1874 /* stop creating parents, connect what we have into the provided parent */
1875 iter = parent;
1876 repeat = 0;
1877 /* get know if there is a keyless list which we will have to rehash */
1878 for (struct lyd_node_inner *piter = parent; piter; piter = piter->parent) {
Radek Krejci0fe9b512019-07-26 17:51:05 +02001879 if (piter->schema->nodetype == LYS_LIST && (piter->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001880 keyless_parent_list = 1;
1881 break;
1882 }
1883 }
1884 } else {
Michal Vasko52927e22020-03-16 17:26:14 +01001885 iter = NULL;
1886 LY_CHECK_GOTO(lyd_dup_recursive((struct lyd_node *)orig_parent, NULL, (struct lyd_node **)&iter, 0,
1887 (struct lyd_node **)&iter), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001888 }
1889 if (!local_parent) {
1890 local_parent = iter;
1891 }
1892 if (iter->child) {
1893 /* 1) list - add after keys
1894 * 2) provided parent with some children */
1895 iter->child->prev->next = top;
1896 if (top) {
1897 top->prev = iter->child->prev;
1898 iter->child->prev = top;
1899 }
1900 } else {
1901 iter->child = top;
1902 if (iter->schema->nodetype == LYS_LIST) {
1903 /* keyless list - we will need to rehash it since we are going to add nodes into it */
1904 keyless_parent_list = 1;
1905 }
1906 }
1907 if (top) {
1908 top->parent = iter;
1909 }
1910 top = (struct lyd_node*)iter;
1911 }
1912 if (repeat && parent) {
1913 /* given parent and created parents chain actually do not interconnect */
1914 LOGERR(ctx, LY_EINVAL, "Invalid argument parent (%s()) - does not interconnect with the created node's parents chain.", __func__);
1915 goto error;
1916 }
1917 } else {
1918 local_parent = parent;
1919 }
1920
Radek Krejci22ebdba2019-07-25 13:59:43 +02001921 LY_LIST_FOR(node, orig) {
Michal Vasko52927e22020-03-16 17:26:14 +01001922 /* if there is no local parent, it will be inserted into first */
1923 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 +02001924 if (!(options & LYD_DUP_WITH_SIBLINGS)) {
1925 break;
1926 }
1927 }
1928 if (keyless_parent_list) {
1929 /* rehash */
1930 for (; local_parent; local_parent = local_parent->parent) {
Radek Krejci0fe9b512019-07-26 17:51:05 +02001931 if (local_parent->schema->nodetype == LYS_LIST && (local_parent->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001932 lyd_hash((struct lyd_node*)local_parent);
1933 }
1934 }
1935 }
1936 return first;
1937
1938error:
1939 if (top) {
1940 lyd_free_tree(top);
1941 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +01001942 lyd_free_siblings(first);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001943 }
1944 return NULL;
1945}
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001946
1947static LY_ERR
1948lyd_path_str_enlarge(char **buffer, size_t *buflen, size_t reqlen, int is_static)
1949{
Michal Vasko14654712020-02-06 08:35:21 +01001950 /* ending \0 */
1951 ++reqlen;
1952
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001953 if (reqlen > *buflen) {
1954 if (is_static) {
1955 return LY_EINCOMPLETE;
1956 }
1957
1958 *buffer = ly_realloc(*buffer, reqlen * sizeof **buffer);
1959 if (!*buffer) {
1960 return LY_EMEM;
1961 }
1962
1963 *buflen = reqlen;
1964 }
1965
1966 return LY_SUCCESS;
1967}
1968
1969/**
1970 * @brief Append all list key predicates to path.
1971 *
1972 * @param[in] node Node with keys to print.
1973 * @param[in,out] buffer Buffer to print to.
1974 * @param[in,out] buflen Current buffer length.
1975 * @param[in,out] bufused Current number of characters used in @p buffer.
1976 * @param[in] is_static Whether buffer is static or can be reallocated.
1977 * @return LY_ERR
1978 */
1979static LY_ERR
1980lyd_path_list_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
1981{
1982 const struct lyd_node *key;
1983 int dynamic = 0;
1984 size_t len;
1985 const char *val;
1986 char quot;
1987 LY_ERR rc;
1988
Michal Vasko14654712020-02-06 08:35:21 +01001989 for (key = lyd_node_children(node); key && (key->schema->flags & LYS_KEY); key = key->next) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001990 val = lyd_value2str((struct lyd_node_term *)key, &dynamic);
1991 len = 1 + strlen(key->schema->name) + 2 + strlen(val) + 2;
1992 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
1993 if (rc != LY_SUCCESS) {
1994 if (dynamic) {
1995 free((char *)val);
1996 }
1997 return rc;
1998 }
1999
2000 quot = '\'';
2001 if (strchr(val, '\'')) {
2002 quot = '"';
2003 }
2004 *bufused += sprintf(*buffer + *bufused, "[%s=%c%s%c]", key->schema->name, quot, val, quot);
2005
2006 if (dynamic) {
2007 free((char *)val);
2008 }
2009 }
2010
2011 return LY_SUCCESS;
2012}
2013
2014/**
2015 * @brief Append leaf-list value predicate to path.
2016 *
2017 * @param[in] node Node to print.
2018 * @param[in,out] buffer Buffer to print to.
2019 * @param[in,out] buflen Current buffer length.
2020 * @param[in,out] bufused Current number of characters used in @p buffer.
2021 * @param[in] is_static Whether buffer is static or can be reallocated.
2022 * @return LY_ERR
2023 */
2024static LY_ERR
2025lyd_path_leaflist_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2026{
2027 int dynamic = 0;
2028 size_t len;
2029 const char *val;
2030 char quot;
2031 LY_ERR rc;
2032
2033 val = lyd_value2str((struct lyd_node_term *)node, &dynamic);
2034 len = 4 + strlen(val) + 2;
2035 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2036 if (rc != LY_SUCCESS) {
2037 goto cleanup;
2038 }
2039
2040 quot = '\'';
2041 if (strchr(val, '\'')) {
2042 quot = '"';
2043 }
2044 *bufused += sprintf(*buffer + *bufused, "[.=%c%s%c]", quot, val, quot);
2045
2046cleanup:
2047 if (dynamic) {
2048 free((char *)val);
2049 }
2050 return rc;
2051}
2052
2053/**
2054 * @brief Append node position (relative to its other instances) predicate to path.
2055 *
2056 * @param[in] node Node to print.
2057 * @param[in,out] buffer Buffer to print to.
2058 * @param[in,out] buflen Current buffer length.
2059 * @param[in,out] bufused Current number of characters used in @p buffer.
2060 * @param[in] is_static Whether buffer is static or can be reallocated.
2061 * @return LY_ERR
2062 */
2063static LY_ERR
2064lyd_path_position_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2065{
2066 const struct lyd_node *first, *iter;
2067 size_t len;
2068 int pos;
2069 char *val = NULL;
2070 LY_ERR rc;
2071
2072 if (node->parent) {
2073 first = node->parent->child;
2074 } else {
2075 for (first = node; node->prev->next; node = node->prev);
2076 }
2077 pos = 1;
2078 for (iter = first; iter != node; iter = iter->next) {
2079 if (iter->schema == node->schema) {
2080 ++pos;
2081 }
2082 }
2083 if (asprintf(&val, "%d", pos) == -1) {
2084 return LY_EMEM;
2085 }
2086
2087 len = 1 + strlen(val) + 1;
2088 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2089 if (rc != LY_SUCCESS) {
2090 goto cleanup;
2091 }
2092
2093 *bufused += sprintf(*buffer + *bufused, "[%s]", val);
2094
2095cleanup:
2096 free(val);
2097 return rc;
2098}
2099
2100API char *
2101lyd_path(const struct lyd_node *node, LYD_PATH_TYPE pathtype, char *buffer, size_t buflen)
2102{
Michal Vasko14654712020-02-06 08:35:21 +01002103 int is_static = 0, i, depth;
2104 size_t bufused = 0, len;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002105 const struct lyd_node *iter;
2106 const struct lys_module *mod;
2107 LY_ERR rc;
2108
2109 LY_CHECK_ARG_RET(NULL, node, NULL);
2110 if (buffer) {
2111 LY_CHECK_ARG_RET(node->schema->module->ctx, buflen > 1, NULL);
2112 is_static = 1;
Michal Vasko14654712020-02-06 08:35:21 +01002113 } else {
2114 buflen = 0;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002115 }
2116
2117 switch (pathtype) {
Michal Vasko14654712020-02-06 08:35:21 +01002118 case LYD_PATH_LOG:
2119 depth = 1;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002120 for (iter = node; iter->parent; iter = (const struct lyd_node *)iter->parent) {
2121 ++depth;
2122 }
2123
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002124 goto iter_print;
Michal Vasko14654712020-02-06 08:35:21 +01002125 while (depth) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002126 /* find the right node */
Michal Vasko14654712020-02-06 08:35:21 +01002127 for (iter = node, i = 1; i < depth; iter = (const struct lyd_node *)iter->parent, ++i);
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002128iter_print:
2129 /* print prefix and name */
2130 mod = NULL;
2131 if (!iter->parent || (iter->schema->module != iter->parent->schema->module)) {
2132 mod = iter->schema->module;
2133 }
2134
2135 /* realloc string */
2136 len = 1 + (mod ? strlen(mod->name) + 1 : 0) + strlen(iter->schema->name);
2137 rc = lyd_path_str_enlarge(&buffer, &buflen, bufused + len, is_static);
2138 if (rc != LY_SUCCESS) {
2139 break;
2140 }
2141
2142 /* print next node */
2143 bufused += sprintf(buffer + bufused, "/%s%s%s", mod ? mod->name : "", mod ? ":" : "", iter->schema->name);
2144
2145 switch (iter->schema->nodetype) {
2146 case LYS_LIST:
2147 if (iter->schema->flags & LYS_KEYLESS) {
2148 /* print its position */
2149 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2150 } else {
2151 /* print all list keys in predicates */
2152 rc = lyd_path_list_predicate(iter, &buffer, &buflen, &bufused, is_static);
2153 }
2154 break;
2155 case LYS_LEAFLIST:
2156 if (iter->schema->flags & LYS_CONFIG_W) {
2157 /* print leaf-list value */
2158 rc = lyd_path_leaflist_predicate(iter, &buffer, &buflen, &bufused, is_static);
2159 } else {
2160 /* print its position */
2161 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2162 }
2163 break;
2164 default:
2165 /* nothing to print more */
2166 rc = LY_SUCCESS;
2167 break;
2168 }
2169 if (rc != LY_SUCCESS) {
2170 break;
2171 }
2172
Michal Vasko14654712020-02-06 08:35:21 +01002173 --depth;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002174 }
2175 break;
2176 }
2177
2178 return buffer;
2179}
Michal Vaskoe444f752020-02-10 12:20:06 +01002180
Michal Vasko9b368d32020-02-14 13:53:31 +01002181LY_ERR
2182lyd_find_sibling_next2(const struct lyd_node *first, const struct lysc_node *schema, const char *key_or_value,
2183 size_t val_len, struct lyd_node **match)
Michal Vaskoe444f752020-02-10 12:20:06 +01002184{
2185 LY_ERR rc;
2186 const struct lyd_node *node = NULL;
2187 struct lyd_node_term *term;
Michal Vaskoe444f752020-02-10 12:20:06 +01002188 struct ly_keys keys = {0};
Michal Vasko90932a92020-02-12 14:33:03 +01002189 struct lyd_value val = {0};
Michal Vaskoe444f752020-02-10 12:20:06 +01002190 size_t i;
Michal Vaskoe444f752020-02-10 12:20:06 +01002191
Michal Vasko9b368d32020-02-14 13:53:31 +01002192 LY_CHECK_ARG_RET(NULL, schema, LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01002193
2194 if (!first) {
2195 /* no data */
Michal Vasko9b368d32020-02-14 13:53:31 +01002196 if (match) {
2197 *match = NULL;
2198 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002199 return LY_ENOTFOUND;
2200 }
2201
Michal Vaskoe444f752020-02-10 12:20:06 +01002202 if (key_or_value && !val_len) {
2203 val_len = strlen(key_or_value);
2204 }
2205
2206 if (key_or_value && (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko90932a92020-02-12 14:33:03 +01002207 /* store the value */
Michal Vasko9b368d32020-02-14 13:53:31 +01002208 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 +01002209 } else if (key_or_value && (schema->nodetype == LYS_LIST)) {
2210 /* parse keys into canonical values */
Michal Vaskod3678892020-05-21 10:06:58 +02002211 LY_CHECK_GOTO(rc = ly_keys_parse(schema, key_or_value, val_len, 1, 1, &keys), cleanup);
Michal Vaskoe444f752020-02-10 12:20:06 +01002212 }
2213
2214 /* find first matching value */
2215 LY_LIST_FOR(first, node) {
2216 if (node->schema != schema) {
2217 continue;
2218 }
2219
2220 if ((schema->nodetype == LYS_LIST) && keys.str) {
2221 /* compare all set keys */
2222 for (i = 0; i < keys.key_count; ++i) {
2223 /* find key */
2224 rc = lyd_find_sibling_val(lyd_node_children(node), (struct lysc_node *)keys.keys[i].schema, NULL, 0,
2225 (struct lyd_node **)&term);
2226 if (rc == LY_ENOTFOUND) {
2227 /* all keys must always exist */
Michal Vasko9b368d32020-02-14 13:53:31 +01002228 LOGINT_RET(schema->module->ctx);
Michal Vaskoe444f752020-02-10 12:20:06 +01002229 }
2230 LY_CHECK_GOTO(rc, cleanup);
2231
2232 /* compare values */
Michal Vasko90932a92020-02-12 14:33:03 +01002233 if (!term->value.realtype->plugin->compare(&term->value, &keys.keys[i].val)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002234 break;
2235 }
2236 }
2237
2238 if (i < keys.key_count) {
2239 /* not a match */
2240 continue;
2241 }
Michal Vasko90932a92020-02-12 14:33:03 +01002242 } else if ((schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && val.realtype) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002243 term = (struct lyd_node_term *)node;
2244
2245 /* compare values */
Michal Vasko90932a92020-02-12 14:33:03 +01002246 if (!term->value.realtype->plugin->compare(&term->value, &val)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002247 /* not a match */
2248 continue;
2249 }
2250 }
2251
2252 /* all criteria passed */
2253 break;
2254 }
2255
2256 if (!node) {
2257 rc = LY_ENOTFOUND;
Michal Vasko9b368d32020-02-14 13:53:31 +01002258 if (match) {
2259 *match = NULL;
2260 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002261 goto cleanup;
2262 }
2263
2264 /* success */
Michal Vasko9b368d32020-02-14 13:53:31 +01002265 if (match) {
2266 *match = (struct lyd_node *)node;
2267 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002268 rc = LY_SUCCESS;
2269
2270cleanup:
2271 ly_keys_clean(&keys);
Michal Vasko90932a92020-02-12 14:33:03 +01002272 if (val.realtype) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002273 val.realtype->plugin->free(schema->module->ctx, &val);
Michal Vasko90932a92020-02-12 14:33:03 +01002274 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002275 return rc;
2276}
2277
2278API LY_ERR
Michal Vasko9b368d32020-02-14 13:53:31 +01002279lyd_find_sibling_next(const struct lyd_node *first, const struct lys_module *module, const char *name, size_t name_len,
2280 const char *key_or_value, size_t val_len, struct lyd_node **match)
2281{
2282 const struct lysc_node *schema;
2283
2284 LY_CHECK_ARG_RET(NULL, module, name, match, LY_EINVAL);
2285
2286 if (!first) {
2287 /* no data */
2288 *match = NULL;
2289 return LY_ENOTFOUND;
2290 }
2291
2292 /* find schema */
2293 schema = lys_find_child(first->parent ? first->parent->schema : NULL, module, name, name_len, 0, 0);
2294 if (!schema) {
2295 LOGERR(module->ctx, LY_EINVAL, "Schema node not found.");
2296 return LY_EINVAL;
2297 }
2298
2299 return lyd_find_sibling_next2(first, schema, key_or_value, val_len, match);
2300}
2301
2302API LY_ERR
Michal Vaskoe444f752020-02-10 12:20:06 +01002303lyd_find_sibling_first(const struct lyd_node *siblings, const struct lyd_node *target, struct lyd_node **match)
2304{
2305 struct lyd_node **match_p;
2306 struct lyd_node_inner *parent;
2307
Michal Vaskof03ed032020-03-04 13:31:44 +01002308 LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01002309
Michal Vasko62ed12d2020-05-21 10:08:25 +02002310 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(target->schema))) {
2311 /* no data or schema mismatch */
Michal Vasko9b368d32020-02-14 13:53:31 +01002312 if (match) {
2313 *match = NULL;
2314 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002315 return LY_ENOTFOUND;
2316 }
2317
2318 /* find first sibling */
2319 if (siblings->parent) {
2320 siblings = siblings->parent->child;
2321 } else {
2322 while (siblings->prev->next) {
2323 siblings = siblings->prev;
2324 }
2325 }
2326
2327 parent = (struct lyd_node_inner *)siblings->parent;
2328 if (parent && parent->children_ht) {
2329 assert(target->hash);
2330
2331 /* find by hash */
2332 if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
2333 siblings = *match_p;
2334 } else {
2335 /* not found */
2336 siblings = NULL;
2337 }
2338 } else {
2339 /* no children hash table */
2340 for (; siblings; siblings = siblings->next) {
2341 if (!lyd_compare(siblings, target, 0)) {
2342 break;
2343 }
2344 }
2345 }
2346
2347 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002348 if (match) {
2349 *match = NULL;
2350 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002351 return LY_ENOTFOUND;
2352 }
2353
Michal Vasko9b368d32020-02-14 13:53:31 +01002354 if (match) {
2355 *match = (struct lyd_node *)siblings;
2356 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002357 return LY_SUCCESS;
2358}
2359
2360API LY_ERR
2361lyd_find_sibling_set(const struct lyd_node *siblings, const struct lyd_node *target, struct ly_set **set)
2362{
2363 struct lyd_node_inner *parent;
2364 struct lyd_node *match;
2365 struct lyd_node **match_p;
2366 struct ly_set *ret;
2367
2368 LY_CHECK_ARG_RET(NULL, target, set, LY_EINVAL);
2369
Michal Vasko62ed12d2020-05-21 10:08:25 +02002370 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(target->schema))) {
2371 /* no data or schema mismatch */
Michal Vaskoe444f752020-02-10 12:20:06 +01002372 return LY_ENOTFOUND;
2373 }
2374
2375 ret = ly_set_new();
2376 LY_CHECK_ERR_RET(!ret, LOGMEM(target->schema->module->ctx), LY_EMEM);
2377
2378 /* find first sibling */
2379 if (siblings->parent) {
2380 siblings = siblings->parent->child;
2381 } else {
2382 while (siblings->prev->next) {
2383 siblings = siblings->prev;
2384 }
2385 }
2386
2387 parent = (struct lyd_node_inner *)siblings->parent;
2388 if (parent && parent->children_ht) {
2389 assert(target->hash);
2390
2391 /* find by hash */
2392 if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
2393 match = *match_p;
2394 } else {
2395 /* not found */
2396 match = NULL;
2397 }
2398 while (match) {
2399 /* add all found nodes into the return set */
2400 if (ly_set_add(ret, match, LY_SET_OPT_USEASLIST) == -1) {
2401 goto error;
2402 }
2403
2404 /* find next instance */
2405 if (lyht_find_next(parent->children_ht, &match, match->hash, (void **)&match_p)) {
2406 match = NULL;
2407 } else {
2408 match = *match_p;
2409 }
2410 }
2411 } else {
2412 /* no children hash table */
2413 for (; siblings; siblings = siblings->next) {
2414 if (!lyd_compare(siblings, target, 0)) {
2415 /* a match */
2416 if (ly_set_add(ret, (struct lyd_node *)siblings, LY_SET_OPT_USEASLIST) == -1) {
2417 goto error;
2418 }
2419 }
2420 }
2421 }
2422
2423 if (!ret->count) {
2424 ly_set_free(ret, NULL);
2425 return LY_ENOTFOUND;
2426 }
2427
2428 *set = ret;
2429 return LY_SUCCESS;
2430
2431error:
2432 ly_set_free(ret, NULL);
2433 return LY_EMEM;
2434}
2435
Michal Vasko90932a92020-02-12 14:33:03 +01002436static int
2437lyd_hash_table_schema_val_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *UNUSED(cb_data))
2438{
2439 struct lysc_node *val1;
2440 struct lyd_node *val2;
2441
2442 val1 = *((struct lysc_node **)val1_p);
2443 val2 = *((struct lyd_node **)val2_p);
2444
2445 assert(val1->nodetype & (LYD_NODE_INNER | LYS_LEAF));
2446
2447 if (val1 == val2->schema) {
2448 /* schema match is enough */
2449 return 1;
2450 } else {
2451 return 0;
2452 }
2453}
2454
2455static LY_ERR
2456lyd_find_sibling_schema(const struct lyd_node *siblings, const struct lysc_node *schema, struct lyd_node **match)
2457{
2458 struct lyd_node **match_p;
2459 struct lyd_node_inner *parent;
2460 uint32_t hash;
2461 values_equal_cb ht_cb;
2462
2463 assert(siblings && schema && (schema->nodetype & (LYD_NODE_INNER | LYS_LEAF)));
2464
2465 /* find first sibling */
2466 if (siblings->parent) {
2467 siblings = siblings->parent->child;
2468 } else {
2469 while (siblings->prev->next) {
2470 siblings = siblings->prev;
2471 }
2472 }
2473
2474 parent = (struct lyd_node_inner *)siblings->parent;
2475 if (parent && parent->children_ht) {
2476 /* calculate our hash */
2477 hash = dict_hash_multi(0, schema->module->name, strlen(schema->module->name));
2478 hash = dict_hash_multi(hash, schema->name, strlen(schema->name));
2479 hash = dict_hash_multi(hash, NULL, 0);
2480
2481 /* use special hash table function */
2482 ht_cb = lyht_set_cb(parent->children_ht, lyd_hash_table_schema_val_equal);
2483
2484 /* find by hash */
2485 if (!lyht_find(parent->children_ht, &schema, hash, (void **)&match_p)) {
2486 siblings = *match_p;
2487 } else {
2488 /* not found */
2489 siblings = NULL;
2490 }
2491
2492 /* set the original hash table compare function back */
2493 lyht_set_cb(parent->children_ht, ht_cb);
2494 } else {
2495 /* no children hash table */
2496 for (; siblings; siblings = siblings->next) {
2497 if (siblings->schema == schema) {
2498 /* schema match is enough */
2499 break;
2500 }
2501 }
2502 }
2503
2504 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002505 if (match) {
2506 *match = NULL;
2507 }
Michal Vasko90932a92020-02-12 14:33:03 +01002508 return LY_ENOTFOUND;
2509 }
2510
Michal Vasko9b368d32020-02-14 13:53:31 +01002511 if (match) {
2512 *match = (struct lyd_node *)siblings;
2513 }
Michal Vasko90932a92020-02-12 14:33:03 +01002514 return LY_SUCCESS;
2515}
2516
Michal Vaskoe444f752020-02-10 12:20:06 +01002517API LY_ERR
2518lyd_find_sibling_val(const struct lyd_node *siblings, const struct lysc_node *schema, const char *key_or_value,
2519 size_t val_len, struct lyd_node **match)
2520{
2521 LY_ERR rc;
2522 struct lyd_node *target = NULL;
2523
2524 LY_CHECK_ARG_RET(NULL, schema, LY_EINVAL);
Michal Vasko62ed12d2020-05-21 10:08:25 +02002525 if ((schema->nodetype == LYS_LIST) && (schema->flags & LYS_KEYLESS)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002526 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - key-less list (%s()).", __func__);
2527 return LY_EINVAL;
2528 } else if ((schema->nodetype & (LYS_LEAFLIST | LYS_LIST)) && !key_or_value) {
2529 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - no value/keys for a (leaf-)list (%s()).", __func__);
2530 return LY_EINVAL;
2531 } else if (schema->nodetype & (LYS_CHOICE | LYS_CASE)) {
2532 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - schema type %s (%s()).",
2533 lys_nodetype2str(schema->nodetype), __func__);
2534 return LY_EINVAL;
2535 }
2536
Michal Vasko62ed12d2020-05-21 10:08:25 +02002537 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(schema))) {
2538 /* no data or schema mismatch */
Michal Vasko9b368d32020-02-14 13:53:31 +01002539 if (match) {
2540 *match = NULL;
2541 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002542 return LY_ENOTFOUND;
2543 }
2544
Michal Vaskof03ed032020-03-04 13:31:44 +01002545 if (key_or_value && !val_len) {
2546 val_len = strlen(key_or_value);
2547 }
2548
Michal Vasko90932a92020-02-12 14:33:03 +01002549 /* create data node if needed and find it */
Michal Vaskoe444f752020-02-10 12:20:06 +01002550 switch (schema->nodetype) {
2551 case LYS_CONTAINER:
2552 case LYS_ANYXML:
2553 case LYS_ANYDATA:
2554 case LYS_NOTIF:
Michal Vasko1bf09392020-03-27 12:38:10 +01002555 case LYS_RPC:
Michal Vasko9b368d32020-02-14 13:53:31 +01002556 case LYS_ACTION:
Michal Vaskoe444f752020-02-10 12:20:06 +01002557 case LYS_LEAF:
Michal Vasko90932a92020-02-12 14:33:03 +01002558 /* find it based on schema only */
2559 rc = lyd_find_sibling_schema(siblings, schema, match);
Michal Vaskoe444f752020-02-10 12:20:06 +01002560 break;
2561 case LYS_LEAFLIST:
2562 /* target used attributes: schema, hash, value */
Michal Vasko90932a92020-02-12 14:33:03 +01002563 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 +01002564 /* fallthrough */
Michal Vaskoe444f752020-02-10 12:20:06 +01002565 case LYS_LIST:
Michal Vasko90932a92020-02-12 14:33:03 +01002566 if (schema->nodetype == LYS_LIST) {
2567 /* target used attributes: schema, hash, child (all keys) */
Michal Vaskod3678892020-05-21 10:06:58 +02002568 LY_CHECK_RET(lyd_create_list(schema, key_or_value, val_len, LYD_JSON, 1, &target));
Michal Vasko90932a92020-02-12 14:33:03 +01002569 }
2570
2571 /* find it */
2572 rc = lyd_find_sibling_first(siblings, target, match);
Michal Vaskoe444f752020-02-10 12:20:06 +01002573 break;
2574 default:
2575 /* unreachable */
2576 LOGINT(schema->module->ctx);
2577 return LY_EINT;
2578 }
2579
Michal Vaskoe444f752020-02-10 12:20:06 +01002580 lyd_free_tree(target);
2581 return rc;
2582}
Michal Vaskoccc02342020-05-21 10:09:21 +02002583
2584API LY_ERR
2585lyd_find_xpath(const struct lyd_node *ctx_node, const char *xpath, struct ly_set **set)
2586{
2587 LY_ERR ret = LY_SUCCESS;
2588 struct lyxp_set xp_set;
2589 struct lyxp_expr *exp;
2590 uint32_t i;
2591
2592 LY_CHECK_ARG_RET(NULL, ctx_node, xpath, set, LY_EINVAL);
2593
2594 memset(&xp_set, 0, sizeof xp_set);
2595
2596 /* compile expression */
2597 exp = lyxp_expr_parse((struct ly_ctx *)LYD_NODE_CTX(ctx_node), xpath);
2598 LY_CHECK_ERR_GOTO(!exp, ret = LY_EINVAL, cleanup);
2599
2600 /* evaluate expression */
2601 ret = lyxp_eval(exp, LYD_JSON, ctx_node->schema->module, ctx_node, LYXP_NODE_ELEM, ctx_node, &xp_set, 0);
2602 LY_CHECK_GOTO(ret, cleanup);
2603
2604 /* allocate return set */
2605 *set = ly_set_new();
2606 LY_CHECK_ERR_GOTO(!*set, LOGMEM(LYD_NODE_CTX(ctx_node)); ret = LY_EMEM, cleanup);
2607
2608 /* transform into ly_set */
2609 if (xp_set.type == LYXP_SET_NODE_SET) {
2610 /* allocate memory for all the elements once (even though not all items must be elements but most likely will be) */
2611 (*set)->objs = malloc(xp_set.used * sizeof *(*set)->objs);
2612 LY_CHECK_ERR_GOTO(!(*set)->objs, LOGMEM(LYD_NODE_CTX(ctx_node)); ret = LY_EMEM, cleanup);
2613 (*set)->size = xp_set.used;
2614
2615 for (i = 0; i < xp_set.used; ++i) {
2616 if (xp_set.val.nodes[i].type == LYXP_NODE_ELEM) {
2617 ly_set_add(*set, xp_set.val.nodes[i].node, LY_SET_OPT_USEASLIST);
2618 }
2619 }
2620 }
2621
2622cleanup:
Michal Vasko0691d522020-05-21 13:21:47 +02002623 lyxp_set_free_content(&xp_set);
Michal Vaskoccc02342020-05-21 10:09:21 +02002624 lyxp_expr_free((struct ly_ctx *)LYD_NODE_CTX(ctx_node), exp);
2625 return ret;
2626}