blob: 8ca974dd9ae821f9bc6ac239ea0daefc381be985 [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;
Michal Vaskoc2f11292020-05-22 16:43:47 +0200482 const char *pref;
483 size_t pref_len, key_len;
484 int have_equal = 0;
Michal Vasko90932a92020-02-12 14:33:03 +0100485
486 ptr = *next_key;
487
488 /* "[" */
489 LY_CHECK_GOTO(ptr[0] != '[', error);
490 ++ptr;
491
Michal Vaskoc2f11292020-05-22 16:43:47 +0200492 /* skip WS */
493 while (isspace(ptr[0])) {
494 ++ptr;
495 }
Michal Vasko90932a92020-02-12 14:33:03 +0100496
Michal Vaskoc2f11292020-05-22 16:43:47 +0200497 /* key name without prefix */
498 LY_CHECK_GOTO(ly_parse_nodeid((const char **)&ptr, &pref, &pref_len, (const char **)key_name, &key_len), error);
499 if (pref) {
500 goto error;
501 }
Michal Vasko90932a92020-02-12 14:33:03 +0100502
Michal Vaskoc2f11292020-05-22 16:43:47 +0200503 /* terminate it */
504 LY_CHECK_GOTO((ptr[0] != '=') && !isspace(ptr[0]), error);
505 if (ptr[0] == '=') {
506 have_equal = 1;
507 }
508 ptr[0] = '\0';
509 ++ptr;
510
511 if (!have_equal) {
512 /* skip WS */
513 while (isspace(ptr[0])) {
514 ++ptr;
515 }
516
517 /* '=' */
518 LY_CHECK_GOTO(ptr[0] != '=', error);
519 ++ptr;
520 }
521
522 /* skip WS */
523 while (isspace(ptr[0])) {
524 ++ptr;
525 }
Michal Vasko90932a92020-02-12 14:33:03 +0100526
527 /* quote */
528 LY_CHECK_GOTO((ptr[0] != '\'') && (ptr[0] != '\"'), error);
529 quot = ptr[0];
530 ++ptr;
531
532 /* value, terminate it */
533 val = ptr;
534 ptr2 = strchr(ptr, quot);
535 LY_CHECK_GOTO(!ptr2, error);
536 ptr2[0] = '\0';
537
538 /* \0, was quote */
539 ptr = ptr2 + 1;
540
Michal Vaskoc2f11292020-05-22 16:43:47 +0200541 /* skip WS */
542 while (isspace(ptr[0])) {
543 ++ptr;
544 }
545
Michal Vasko90932a92020-02-12 14:33:03 +0100546 /* "]" */
547 LY_CHECK_GOTO(ptr[0] != ']', error);
548 ++ptr;
549
550 *next_key = ptr;
551 return val;
552
553error:
554 *next_key = ptr;
555 return NULL;
556}
557
Michal Vaskod3678892020-05-21 10:06:58 +0200558/* fill keys structure that is expected to be zeroed and must always be cleaned (even on error);
559 * if store is set, fill also each val */
Michal Vasko90932a92020-02-12 14:33:03 +0100560static LY_ERR
Michal Vaskod3678892020-05-21 10:06:58 +0200561ly_keys_parse(const struct lysc_node *list, const char *keys_str, size_t keys_len, int store, int log,
562 struct ly_keys *keys)
Michal Vasko90932a92020-02-12 14:33:03 +0100563{
564 LY_ERR ret = LY_SUCCESS;
565 char *next_key, *name;
566 const struct lysc_node *key;
567 size_t i;
568
569 assert(list->nodetype == LYS_LIST);
570
Michal Vaskof03ed032020-03-04 13:31:44 +0100571 if (!keys_str) {
572 /* nothing to parse */
573 return LY_SUCCESS;
574 }
575
576 keys->str = strndup(keys_str, keys_len);
Michal Vasko90932a92020-02-12 14:33:03 +0100577 LY_CHECK_ERR_GOTO(!keys->str, LOGMEM(list->module->ctx); ret = LY_EMEM, cleanup);
578
579 next_key = keys->str;
580 while (next_key[0]) {
581 /* new key */
582 keys->keys = ly_realloc(keys->keys, (keys->key_count + 1) * sizeof *keys->keys);
583 LY_CHECK_ERR_GOTO(!keys->keys, LOGMEM(list->module->ctx); ret = LY_EMEM, cleanup);
584
585 /* fill */
586 keys->keys[keys->key_count].value = ly_keys_parse_next(&next_key, &name);
587 if (!keys->keys[keys->key_count].value) {
Michal Vaskod3678892020-05-21 10:06:58 +0200588 if (log) {
589 LOGERR(list->module->ctx, LY_EINVAL, "Invalid keys string (at \"%s\").", next_key);
590 }
Michal Vasko90932a92020-02-12 14:33:03 +0100591 ret = LY_EINVAL;
592 goto cleanup;
593 }
594
595 /* find schema node */
596 key = lys_find_child(list, list->module, name, 0, LYS_LEAF, 0);
597 if (!key) {
Michal Vaskod3678892020-05-21 10:06:58 +0200598 if (log) {
599 LOGERR(list->module->ctx, LY_EINVAL, "List \"%s\" has no key \"%s\".", list->name, name);
600 }
Michal Vasko90932a92020-02-12 14:33:03 +0100601 ret = LY_EINVAL;
602 goto cleanup;
603 }
604 keys->keys[keys->key_count].schema = (const struct lysc_node_leaf *)key;
605
606 /* check that we do not have it already */
607 for (i = 0; i < keys->key_count; ++i) {
608 if (keys->keys[i].schema == keys->keys[keys->key_count].schema) {
Michal Vaskod3678892020-05-21 10:06:58 +0200609 if (log) {
610 LOGERR(list->module->ctx, LY_EINVAL, "Duplicit key \"%s\" value.", name);
611 }
Michal Vasko90932a92020-02-12 14:33:03 +0100612 ret = LY_EINVAL;
613 goto cleanup;
614 }
615 }
616
617 if (store) {
618 /* store the value */
619 ret = lyd_value_store(&keys->keys[keys->key_count].val, key, keys->keys[keys->key_count].value, 0, 0,
620 lydjson_resolve_prefix, NULL, LYD_JSON);
621 LY_CHECK_GOTO(ret, cleanup);
Michal Vaskoae420e92020-05-21 10:00:40 +0200622 } else {
623 memset(&keys->keys[keys->key_count].val, 0, sizeof keys->keys[keys->key_count].val);
Michal Vasko90932a92020-02-12 14:33:03 +0100624 }
625
626 /* another valid key */
627 ++keys->key_count;
628 }
629
630cleanup:
Michal Vasko90932a92020-02-12 14:33:03 +0100631 return ret;
632}
633
634LY_ERR
Michal Vaskod3678892020-05-21 10:06:58 +0200635lyd_create_list(const struct lysc_node *schema, const char *keys_str, size_t keys_len, LYD_FORMAT keys_format, int log,
636 struct lyd_node **node)
Michal Vasko90932a92020-02-12 14:33:03 +0100637{
638 LY_ERR ret = LY_SUCCESS;
639 const struct lysc_node *key_s;
640 struct lyd_node *list = NULL, *key;
641 struct ly_keys keys = {0};
642 size_t i;
643
Michal Vaskod3678892020-05-21 10:06:58 +0200644 assert((schema->nodetype == LYS_LIST) && !(schema->flags & LYS_KEYLESS) && (keys_format != LYD_XML));
Michal Vasko90932a92020-02-12 14:33:03 +0100645
646 /* parse keys */
Michal Vaskod3678892020-05-21 10:06:58 +0200647 LY_CHECK_GOTO(ret = ly_keys_parse(schema, keys_str, keys_len, 0, log, &keys), cleanup);
Michal Vasko90932a92020-02-12 14:33:03 +0100648
649 /* create list */
650 LY_CHECK_GOTO(ret = lyd_create_inner(schema, &list), cleanup);
651
652 /* everything was checked except that all keys are set */
653 i = 0;
654 for (key_s = lysc_node_children(schema, 0); key_s && (key_s->flags & LYS_KEY); key_s = key_s->next) {
655 ++i;
656 }
657 if (i != keys.key_count) {
Michal Vaskod3678892020-05-21 10:06:58 +0200658 if (log) {
659 LOGERR(schema->module->ctx, LY_EINVAL, "List \"%s\" is missing some keys.", schema->name);
660 }
Michal Vasko90932a92020-02-12 14:33:03 +0100661 ret = LY_EINVAL;
662 goto cleanup;
663 }
664
665 /* create and insert all the keys */
666 for (i = 0; i < keys.key_count; ++i) {
Michal Vaskod3678892020-05-21 10:06:58 +0200667 if (keys_format == LYD_JSON) {
668 ret = lyd_create_term((struct lysc_node *)keys.keys[i].schema, keys.keys[i].value, strlen(keys.keys[i].value),
669 NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &key);
670 } else {
671 assert(keys_format == LYD_SCHEMA);
672 ret = lyd_create_term((struct lysc_node *)keys.keys[i].schema, keys.keys[i].value, strlen(keys.keys[i].value),
673 NULL, lys_resolve_prefix, NULL, LYD_SCHEMA, &key);
674 }
675 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko90932a92020-02-12 14:33:03 +0100676 lyd_insert_node(list, NULL, key);
677 }
678
Michal Vasko9b368d32020-02-14 13:53:31 +0100679 /* hash having all the keys */
680 lyd_hash(list);
681
Michal Vasko90932a92020-02-12 14:33:03 +0100682 /* success */
683 *node = list;
684 list = NULL;
685
686cleanup:
687 lyd_free_tree(list);
688 ly_keys_clean(&keys);
689 return ret;
690}
691
692LY_ERR
693lyd_create_any(const struct lysc_node *schema, const void *value, LYD_ANYDATA_VALUETYPE value_type, struct lyd_node **node)
694{
695 struct lyd_node_any *any;
696
Michal Vasko9b368d32020-02-14 13:53:31 +0100697 assert(schema->nodetype & LYD_NODE_ANY);
698
Michal Vasko90932a92020-02-12 14:33:03 +0100699 any = calloc(1, sizeof *any);
700 LY_CHECK_ERR_RET(!any, LOGMEM(schema->module->ctx), LY_EMEM);
701
702 any->schema = schema;
703 any->prev = (struct lyd_node *)any;
Michal Vasko9b368d32020-02-14 13:53:31 +0100704 any->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100705
706 any->value.xml = value;
707 any->value_type = value_type;
Michal Vasko9b368d32020-02-14 13:53:31 +0100708 lyd_hash((struct lyd_node *)any);
Michal Vasko90932a92020-02-12 14:33:03 +0100709
710 *node = (struct lyd_node *)any;
711 return LY_SUCCESS;
712}
713
Michal Vasko52927e22020-03-16 17:26:14 +0100714LY_ERR
715lyd_create_opaq(const struct ly_ctx *ctx, const char *name, size_t name_len, const char *value, size_t value_len,
716 int *dynamic, LYD_FORMAT format, struct ly_prefix *val_prefs, const char *prefix, size_t pref_len,
717 const char *ns, struct lyd_node **node)
718{
719 struct lyd_node_opaq *opaq;
720
721 assert(ctx && name && name_len && ns);
722
723 if (!value_len) {
724 value = "";
725 }
726
727 opaq = calloc(1, sizeof *opaq);
728 LY_CHECK_ERR_RET(!opaq, LOGMEM(ctx), LY_EMEM);
729
730 opaq->prev = (struct lyd_node *)opaq;
731
732 opaq->name = lydict_insert(ctx, name, name_len);
733 opaq->format = format;
734 if (pref_len) {
735 opaq->prefix.pref = lydict_insert(ctx, prefix, pref_len);
736 }
737 opaq->prefix.ns = lydict_insert(ctx, ns, 0);
738 opaq->val_prefs = val_prefs;
739 if (dynamic && *dynamic) {
740 opaq->value = lydict_insert_zc(ctx, (char *)value);
741 *dynamic = 0;
742 } else {
743 opaq->value = lydict_insert(ctx, value, value_len);
744 }
745 opaq->ctx = ctx;
746
747 *node = (struct lyd_node *)opaq;
748 return LY_SUCCESS;
749}
750
Michal Vasko013a8182020-03-03 10:46:53 +0100751API struct lyd_node *
752lyd_new_inner(struct lyd_node *parent, const struct lys_module *module, const char *name)
753{
754 struct lyd_node *ret = NULL;
755 const struct lysc_node *schema;
756 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
757
758 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
759
Michal Vaskof03ed032020-03-04 13:31:44 +0100760 if (!module) {
761 module = parent->schema->module;
762 }
763
Michal Vasko1bf09392020-03-27 12:38:10 +0100764 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 +0100765 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Inner node \"%s\" not found.", name), NULL);
766
767 if (!lyd_create_inner(schema, &ret) && parent) {
768 lyd_insert_node(parent, NULL, ret);
769 }
770 return ret;
771}
772
773API struct lyd_node *
774lyd_new_list(struct lyd_node *parent, const struct lys_module *module, const char *name, ...)
775{
776 struct lyd_node *ret = NULL, *key;
777 const struct lysc_node *schema, *key_s;
778 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
779 va_list ap;
780 const char *key_val;
781 LY_ERR rc = LY_SUCCESS;
782
783 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
784
Michal Vaskof03ed032020-03-04 13:31:44 +0100785 if (!module) {
786 module = parent->schema->module;
787 }
788
Michal Vasko013a8182020-03-03 10:46:53 +0100789 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, 0);
790 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), NULL);
791
792 /* create list inner node */
793 LY_CHECK_RET(lyd_create_inner(schema, &ret), NULL);
794
795 va_start(ap, name);
796
797 /* create and insert all the keys */
798 for (key_s = lysc_node_children(schema, 0); key_s && (key_s->flags & LYS_KEY); key_s = key_s->next) {
799 key_val = va_arg(ap, const char *);
800
Michal Vaskof03ed032020-03-04 13:31:44 +0100801 rc = lyd_create_term(key_s, key_val, key_val ? strlen(key_val) : 0, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &key);
802 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko013a8182020-03-03 10:46:53 +0100803 lyd_insert_node(ret, NULL, key);
804 }
805
806 /* hash having all the keys */
807 lyd_hash(ret);
808
809 if (parent) {
810 lyd_insert_node(parent, NULL, ret);
811 }
812
813cleanup:
814 if (rc) {
815 lyd_free_tree(ret);
816 ret = NULL;
817 }
818 va_end(ap);
819 return ret;
820}
821
822API struct lyd_node *
823lyd_new_list2(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *keys)
824{
825 struct lyd_node *ret = NULL;
826 const struct lysc_node *schema;
827 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
828
829 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
830
Michal Vaskof03ed032020-03-04 13:31:44 +0100831 if (!module) {
832 module = parent->schema->module;
833 }
834
Michal Vasko013a8182020-03-03 10:46:53 +0100835 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, 0);
836 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), NULL);
837
Michal Vaskod3678892020-05-21 10:06:58 +0200838 if (!lyd_create_list(schema, keys, keys ? strlen(keys) : 0, LYD_JSON, 1, &ret) && parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100839 lyd_insert_node(parent, NULL, ret);
840 }
841 return ret;
842}
843
844API struct lyd_node *
845lyd_new_term(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str)
846{
847 struct lyd_node *ret = NULL;
848 const struct lysc_node *schema;
849 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
850
851 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
852
Michal Vaskof03ed032020-03-04 13:31:44 +0100853 if (!module) {
854 module = parent->schema->module;
855 }
856
Michal Vasko013a8182020-03-03 10:46:53 +0100857 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_TERM, 0);
858 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Term node \"%s\" not found.", name), NULL);
859
Michal Vaskof03ed032020-03-04 13:31:44 +0100860 if (!lyd_create_term(schema, val_str, val_str ? strlen(val_str) : 0, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &ret)
861 && parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100862 lyd_insert_node(parent, NULL, ret);
863 }
864 return ret;
865}
866
867API struct lyd_node *
868lyd_new_any(struct lyd_node *parent, const struct lys_module *module, const char *name, const void *value,
869 LYD_ANYDATA_VALUETYPE value_type)
870{
871 struct lyd_node *ret = NULL;
872 const struct lysc_node *schema;
873 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
874
875 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
876
Michal Vaskof03ed032020-03-04 13:31:44 +0100877 if (!module) {
878 module = parent->schema->module;
879 }
880
Michal Vasko013a8182020-03-03 10:46:53 +0100881 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_ANY, 0);
882 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Any node \"%s\" not found.", name), NULL);
883
884 if (!lyd_create_any(schema, value, value_type, &ret) && parent) {
885 lyd_insert_node(parent, NULL, ret);
886 }
887 return ret;
888}
889
Michal Vasko90932a92020-02-12 14:33:03 +0100890struct lyd_node *
891lyd_get_prev_key_anchor(const struct lyd_node *first_sibling, const struct lysc_node *new_key)
892{
893 const struct lysc_node *prev_key;
894 struct lyd_node *match = NULL;
895
896 if (!first_sibling) {
897 return NULL;
898 }
899
900 for (prev_key = new_key->prev; !match && prev_key->next; prev_key = prev_key->prev) {
901 lyd_find_sibling_val(first_sibling, prev_key, NULL, 0, &match);
902 }
903
904 return match;
905}
906
907/**
908 * @brief Insert node after a sibling.
909 *
Michal Vasko9f96a052020-03-10 09:41:45 +0100910 * Handles inserting into NP containers and key-less lists.
911 *
Michal Vasko90932a92020-02-12 14:33:03 +0100912 * @param[in] sibling Sibling to insert after.
913 * @param[in] node Node to insert.
914 */
915static void
Michal Vaskof03ed032020-03-04 13:31:44 +0100916lyd_insert_after_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +0100917{
Michal Vasko0249f7c2020-03-05 16:36:40 +0100918 struct lyd_node_inner *par;
919
Michal Vasko90932a92020-02-12 14:33:03 +0100920 assert(!node->next && (node->prev == node));
921
922 node->next = sibling->next;
923 node->prev = sibling;
924 sibling->next = node;
925 if (node->next) {
926 /* sibling had a succeeding node */
927 node->next->prev = node;
928 } else {
929 /* sibling was last, find first sibling and change its prev */
930 if (sibling->parent) {
931 sibling = sibling->parent->child;
932 } else {
933 for (; sibling->prev->next != node; sibling = sibling->prev);
934 }
935 sibling->prev = node;
936 }
937 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +0100938
Michal Vasko9f96a052020-03-10 09:41:45 +0100939 for (par = node->parent; par; par = par->parent) {
940 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
941 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +0100942 par->flags &= ~LYD_DEFAULT;
943 }
Michal Vasko9f96a052020-03-10 09:41:45 +0100944 if ((par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
945 /* rehash key-less list */
946 lyd_hash((struct lyd_node *)par);
947 }
Michal Vasko0249f7c2020-03-05 16:36:40 +0100948 }
949
950 /* insert into hash table */
951 lyd_insert_hash(node);
Michal Vasko90932a92020-02-12 14:33:03 +0100952}
953
954/**
955 * @brief Insert node before a sibling.
956 *
Michal Vasko9f96a052020-03-10 09:41:45 +0100957 * Handles inserting into NP containers and key-less lists.
958 *
Michal Vasko90932a92020-02-12 14:33:03 +0100959 * @param[in] sibling Sibling to insert before.
960 * @param[in] node Node to insert.
961 */
962static void
Michal Vaskof03ed032020-03-04 13:31:44 +0100963lyd_insert_before_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +0100964{
Michal Vasko0249f7c2020-03-05 16:36:40 +0100965 struct lyd_node_inner *par;
966
Michal Vasko90932a92020-02-12 14:33:03 +0100967 assert(!node->next && (node->prev == node));
968
969 node->next = sibling;
970 /* covers situation of sibling being first */
971 node->prev = sibling->prev;
972 sibling->prev = node;
973 if (node->prev->next) {
974 /* sibling had a preceding node */
975 node->prev->next = node;
976 } else if (sibling->parent) {
977 /* sibling was first and we must also change parent child pointer */
978 sibling->parent->child = node;
979 }
980 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +0100981
Michal Vasko9f96a052020-03-10 09:41:45 +0100982 for (par = node->parent; par; par = par->parent) {
983 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
984 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +0100985 par->flags &= ~LYD_DEFAULT;
986 }
Michal Vasko9f96a052020-03-10 09:41:45 +0100987 if ((par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
988 /* rehash key-less list */
989 lyd_hash((struct lyd_node *)par);
990 }
Michal Vasko0249f7c2020-03-05 16:36:40 +0100991 }
992
993 /* insert into hash table */
994 lyd_insert_hash(node);
Michal Vasko90932a92020-02-12 14:33:03 +0100995}
996
997/**
998 * @brief Insert node as the last child of a parent.
999 *
Michal Vasko9f96a052020-03-10 09:41:45 +01001000 * Handles inserting into NP containers and key-less lists.
1001 *
Michal Vasko90932a92020-02-12 14:33:03 +01001002 * @param[in] parent Parent to insert into.
1003 * @param[in] node Node to insert.
1004 */
1005static void
Michal Vaskof03ed032020-03-04 13:31:44 +01001006lyd_insert_last_node(struct lyd_node *parent, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001007{
1008 struct lyd_node_inner *par;
1009
Michal Vasko0249f7c2020-03-05 16:36:40 +01001010 assert(parent && !node->next && (node->prev == node));
Michal Vasko52927e22020-03-16 17:26:14 +01001011 assert(!parent->schema || (parent->schema->nodetype & LYD_NODE_INNER));
Michal Vasko90932a92020-02-12 14:33:03 +01001012
1013 par = (struct lyd_node_inner *)parent;
1014
1015 if (!par->child) {
1016 par->child = node;
1017 } else {
1018 node->prev = par->child->prev;
1019 par->child->prev->next = node;
1020 par->child->prev = node;
1021 }
1022 node->parent = par;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001023
Michal Vasko9f96a052020-03-10 09:41:45 +01001024 for (; par; par = par->parent) {
1025 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
1026 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +01001027 par->flags &= ~LYD_DEFAULT;
1028 }
Michal Vasko52927e22020-03-16 17:26:14 +01001029 if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001030 /* rehash key-less list */
1031 lyd_hash((struct lyd_node *)par);
1032 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001033 }
1034
1035 /* insert into hash table */
1036 lyd_insert_hash(node);
Michal Vasko90932a92020-02-12 14:33:03 +01001037}
1038
1039void
Michal Vasko9b368d32020-02-14 13:53:31 +01001040lyd_insert_node(struct lyd_node *parent, struct lyd_node **first_sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001041{
Michal Vasko9b368d32020-02-14 13:53:31 +01001042 struct lyd_node *anchor;
Michal Vasko9f96a052020-03-10 09:41:45 +01001043 const struct lysc_node *skey = NULL;
1044 int has_keys;
Michal Vasko90932a92020-02-12 14:33:03 +01001045
Michal Vasko52927e22020-03-16 17:26:14 +01001046 assert((parent || first_sibling) && node && (node->hash || !node->schema));
Michal Vasko9b368d32020-02-14 13:53:31 +01001047
1048 if (!parent && first_sibling && (*first_sibling) && (*first_sibling)->parent) {
1049 parent = (struct lyd_node *)(*first_sibling)->parent;
1050 }
Michal Vasko90932a92020-02-12 14:33:03 +01001051
1052 if (parent) {
Michal Vasko52927e22020-03-16 17:26:14 +01001053 if (node->schema && (node->schema->flags & LYS_KEY)) {
Michal Vasko90932a92020-02-12 14:33:03 +01001054 /* it is key and we need to insert it at the correct place */
Michal Vasko9b368d32020-02-14 13:53:31 +01001055 anchor = lyd_get_prev_key_anchor(lyd_node_children(parent), node->schema);
1056 if (anchor) {
Michal Vaskof03ed032020-03-04 13:31:44 +01001057 lyd_insert_after_node(anchor, node);
Michal Vasko90932a92020-02-12 14:33:03 +01001058 } else if (lyd_node_children(parent)) {
Radek Krejcidae0ee82020-05-06 16:53:24 +02001059 lyd_insert_before_node(lyd_node_children(parent), node);
Michal Vasko90932a92020-02-12 14:33:03 +01001060 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +01001061 lyd_insert_last_node(parent, node);
Michal Vasko90932a92020-02-12 14:33:03 +01001062 }
Michal Vasko9f96a052020-03-10 09:41:45 +01001063
1064 /* hash list if all its keys were added */
1065 assert(parent->schema->nodetype == LYS_LIST);
Radek Krejcidae0ee82020-05-06 16:53:24 +02001066 anchor = lyd_node_children(parent);
Michal Vasko9f96a052020-03-10 09:41:45 +01001067 has_keys = 1;
1068 while ((skey = lys_getnext(skey, parent->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
1069 if (!anchor || (anchor->schema != skey)) {
1070 /* key missing */
1071 has_keys = 0;
1072 break;
1073 }
1074
1075 anchor = anchor->next;
1076 }
1077 if (has_keys) {
1078 lyd_hash(parent);
1079 }
1080
Michal Vasko90932a92020-02-12 14:33:03 +01001081 } else {
1082 /* last child */
Michal Vaskof03ed032020-03-04 13:31:44 +01001083 lyd_insert_last_node(parent, node);
Michal Vasko90932a92020-02-12 14:33:03 +01001084 }
Michal Vasko9b368d32020-02-14 13:53:31 +01001085 } else if (*first_sibling) {
Michal Vaskob1b5c262020-03-05 14:29:47 +01001086 /* top-level siblings */
Michal Vasko9b368d32020-02-14 13:53:31 +01001087 anchor = (*first_sibling)->prev;
Michal Vaskoc193ce92020-03-06 11:04:48 +01001088 while (anchor->prev->next && (lyd_owner_module(anchor) != lyd_owner_module(node))) {
Michal Vasko9b368d32020-02-14 13:53:31 +01001089 anchor = anchor->prev;
1090 }
1091
Michal Vaskoc193ce92020-03-06 11:04:48 +01001092 if (lyd_owner_module(anchor) == lyd_owner_module(node)) {
Michal Vaskob1b5c262020-03-05 14:29:47 +01001093 /* insert after last sibling from this module */
1094 lyd_insert_after_node(anchor, node);
1095 } else {
1096 /* no data from this module, insert at the last position */
1097 lyd_insert_after_node((*first_sibling)->prev, node);
1098 }
Michal Vasko90932a92020-02-12 14:33:03 +01001099 } else {
Michal Vasko9b368d32020-02-14 13:53:31 +01001100 /* the only sibling */
1101 *first_sibling = node;
Michal Vasko90932a92020-02-12 14:33:03 +01001102 }
Michal Vasko90932a92020-02-12 14:33:03 +01001103}
1104
Michal Vaskof03ed032020-03-04 13:31:44 +01001105static LY_ERR
1106lyd_insert_check_schema(const struct lysc_node *parent, const struct lysc_node *schema)
1107{
1108 const struct lysc_node *par2;
1109
1110 assert(schema);
Michal Vasko62ed12d2020-05-21 10:08:25 +02001111 assert(!parent || !(parent->nodetype & (LYS_CASE | LYS_CHOICE)));
Michal Vaskof03ed032020-03-04 13:31:44 +01001112
1113 /* find schema parent */
Michal Vasko62ed12d2020-05-21 10:08:25 +02001114 par2 = lysc_data_parent(schema);
Michal Vaskof03ed032020-03-04 13:31:44 +01001115
1116 if (parent) {
1117 /* inner node */
1118 if (par2 != parent) {
1119 LOGERR(parent->module->ctx, LY_EINVAL, "Cannot insert, parent of \"%s\" is not \"%s\".", schema->name, parent->name);
1120 return LY_EINVAL;
1121 }
1122 } else {
1123 /* top-level node */
1124 if (par2) {
1125 LOGERR(parent->module->ctx, LY_EINVAL, "Cannot insert, node \"%s\" is not top-level.", schema->name);
1126 return LY_EINVAL;
1127 }
1128 }
1129
1130 return LY_SUCCESS;
1131}
1132
1133API LY_ERR
1134lyd_insert(struct lyd_node *parent, struct lyd_node *node)
1135{
1136 struct lyd_node *iter;
1137
1138 LY_CHECK_ARG_RET(NULL, parent, node, !(parent->schema->nodetype & LYD_NODE_INNER), LY_EINVAL);
1139
1140 LY_CHECK_RET(lyd_insert_check_schema(parent->schema, node->schema));
1141
1142 if (node->schema->flags & LYS_KEY) {
1143 LOGERR(parent->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1144 return LY_EINVAL;
1145 }
1146
1147 if (node->parent || node->prev->next) {
1148 lyd_unlink_tree(node);
1149 }
1150
1151 while (node) {
1152 iter = node->next;
1153 lyd_unlink_tree(node);
1154 lyd_insert_node(parent, NULL, node);
1155 node = iter;
1156 }
1157 return LY_SUCCESS;
1158}
1159
1160API LY_ERR
Michal Vaskob1b5c262020-03-05 14:29:47 +01001161lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node)
1162{
1163 struct lyd_node *iter;
1164
1165 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1166
Michal Vasko62ed12d2020-05-21 10:08:25 +02001167 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskob1b5c262020-03-05 14:29:47 +01001168
1169 if (node->schema->flags & LYS_KEY) {
1170 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1171 return LY_EINVAL;
1172 }
1173
1174 if (node->parent || node->prev->next) {
1175 lyd_unlink_tree(node);
1176 }
1177
1178 while (node) {
1179 iter = node->next;
1180 lyd_unlink_tree(node);
1181 lyd_insert_node(NULL, &sibling, node);
1182 node = iter;
1183 }
1184 return LY_SUCCESS;
1185}
1186
Michal Vasko0249f7c2020-03-05 16:36:40 +01001187static LY_ERR
1188lyd_insert_after_check_place(struct lyd_node *anchor, struct lyd_node *sibling, struct lyd_node *node)
1189{
1190 if (sibling->parent) {
1191 /* nested, we do not care for the order */
1192 return LY_SUCCESS;
1193 }
1194
1195 if (anchor) {
Michal Vaskoc193ce92020-03-06 11:04:48 +01001196 if (anchor->next && (lyd_owner_module(anchor) == lyd_owner_module(anchor->next))
1197 && (lyd_owner_module(node) != lyd_owner_module(anchor))) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001198 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 +01001199 lyd_owner_module(node)->name, lyd_owner_module(anchor)->name);
Michal Vasko0249f7c2020-03-05 16:36:40 +01001200 return LY_EINVAL;
1201 }
1202
Michal Vaskoc193ce92020-03-06 11:04:48 +01001203 if ((lyd_owner_module(node) == lyd_owner_module(anchor))
1204 || (anchor->next && (lyd_owner_module(node) == lyd_owner_module(anchor->next)))) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001205 /* inserting before/after its module data */
1206 return LY_SUCCESS;
1207 }
1208 }
1209
1210 /* find first sibling */
1211 while (sibling->prev->next) {
1212 sibling = sibling->prev;
1213 }
1214
1215 if (!anchor) {
Michal Vaskoc193ce92020-03-06 11:04:48 +01001216 if (lyd_owner_module(node) == lyd_owner_module(sibling)) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001217 /* inserting before its module data */
1218 return LY_SUCCESS;
1219 }
1220 }
1221
1222 /* check there are no data of this module */
1223 LY_LIST_FOR(sibling, sibling) {
Michal Vaskoc193ce92020-03-06 11:04:48 +01001224 if (lyd_owner_module(node) == lyd_owner_module(sibling)) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001225 /* some data of this module found */
1226 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Top-level data of module \"%s\" already exist,"
Michal Vaskoc193ce92020-03-06 11:04:48 +01001227 " they must be directly connected.", lyd_owner_module(node)->name);
Michal Vasko0249f7c2020-03-05 16:36:40 +01001228 return LY_EINVAL;
1229 }
1230 }
1231
1232 return LY_SUCCESS;
1233}
1234
Michal Vaskob1b5c262020-03-05 14:29:47 +01001235API LY_ERR
Michal Vaskof03ed032020-03-04 13:31:44 +01001236lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
1237{
1238 struct lyd_node *iter;
1239
1240 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1241
Michal Vasko62ed12d2020-05-21 10:08:25 +02001242 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskof03ed032020-03-04 13:31:44 +01001243
1244 if (node->schema->flags & LYS_KEY) {
1245 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1246 return LY_EINVAL;
1247 } else if (sibling->schema->flags & LYS_KEY) {
1248 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert into keys.");
1249 return LY_EINVAL;
1250 }
1251
Michal Vasko0249f7c2020-03-05 16:36:40 +01001252 LY_CHECK_RET(lyd_insert_after_check_place(sibling->prev->next ? sibling->prev : NULL, sibling, node));
1253
Michal Vaskof03ed032020-03-04 13:31:44 +01001254 if (node->parent || node->prev->next) {
1255 lyd_unlink_tree(node);
1256 }
1257
1258 /* insert in reverse order to get the original order */
1259 node = node->prev;
1260 while (node) {
1261 iter = node->prev;
1262 lyd_unlink_tree(node);
1263
1264 lyd_insert_before_node(sibling, node);
1265 /* move the anchor accordingly */
1266 sibling = node;
1267
1268 node = (iter == node) ? NULL : iter;
1269 }
1270 return LY_SUCCESS;
1271}
1272
1273API LY_ERR
1274lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
1275{
1276 struct lyd_node *iter;
1277
1278 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1279
Michal Vasko62ed12d2020-05-21 10:08:25 +02001280 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskof03ed032020-03-04 13:31:44 +01001281
1282 if (node->schema->flags & LYS_KEY) {
1283 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1284 return LY_EINVAL;
1285 } else if (sibling->next && (sibling->next->schema->flags & LYS_KEY)) {
1286 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert into keys.");
1287 return LY_EINVAL;
1288 }
1289
Michal Vasko0249f7c2020-03-05 16:36:40 +01001290 LY_CHECK_RET(lyd_insert_after_check_place(sibling, sibling, node));
1291
Michal Vaskof03ed032020-03-04 13:31:44 +01001292 if (node->parent || node->prev->next) {
1293 lyd_unlink_tree(node);
1294 }
1295
1296 while (node) {
1297 iter = node->next;
1298 lyd_unlink_tree(node);
1299
1300 lyd_insert_after_node(sibling, node);
1301 /* move the anchor accordingly */
1302 sibling = node;
1303
1304 node = iter;
1305 }
1306 return LY_SUCCESS;
1307}
1308
1309API void
1310lyd_unlink_tree(struct lyd_node *node)
1311{
1312 struct lyd_node *iter;
1313
1314 if (!node) {
1315 return;
1316 }
1317
1318 /* unlink from siblings */
1319 if (node->prev->next) {
1320 node->prev->next = node->next;
1321 }
1322 if (node->next) {
1323 node->next->prev = node->prev;
1324 } else {
1325 /* unlinking the last node */
1326 if (node->parent) {
1327 iter = node->parent->child;
1328 } else {
1329 iter = node->prev;
1330 while (iter->prev != node) {
1331 iter = iter->prev;
1332 }
1333 }
1334 /* update the "last" pointer from the first node */
1335 iter->prev = node->prev;
1336 }
1337
1338 /* unlink from parent */
1339 if (node->parent) {
1340 if (node->parent->child == node) {
1341 /* the node is the first child */
1342 node->parent->child = node->next;
1343 }
1344
1345 lyd_unlink_hash(node);
1346
1347 /* check for keyless list and update its hash */
1348 for (iter = (struct lyd_node *)node->parent; iter; iter = (struct lyd_node *)iter->parent) {
Michal Vasko413c7f22020-05-05 12:34:06 +02001349 if (iter->schema && (iter->schema->flags & LYS_KEYLESS)) {
Michal Vaskof03ed032020-03-04 13:31:44 +01001350 lyd_hash(iter);
1351 }
1352 }
1353
1354 node->parent = NULL;
1355 }
1356
1357 node->next = NULL;
1358 node->prev = node;
1359}
1360
Michal Vasko90932a92020-02-12 14:33:03 +01001361LY_ERR
Michal Vasko9f96a052020-03-10 09:41:45 +01001362lyd_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 +01001363 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 +01001364 void *prefix_data, LYD_FORMAT format, const struct lysc_node *ctx_snode)
Michal Vasko90932a92020-02-12 14:33:03 +01001365{
1366 LY_ERR ret;
1367 struct lysc_ext_instance *ant = NULL;
Michal Vasko9f96a052020-03-10 09:41:45 +01001368 struct lyd_meta *mt, *last;
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001369 LY_ARRAY_SIZE_TYPE u;
Michal Vasko90932a92020-02-12 14:33:03 +01001370
Michal Vasko9f96a052020-03-10 09:41:45 +01001371 assert((parent || meta) && mod);
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001372
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001373 LY_ARRAY_FOR(mod->compiled->exts, u) {
1374 if (mod->compiled->exts[u].def->plugin == lyext_plugins_internal[LYEXT_PLUGIN_INTERNAL_ANNOTATION].plugin &&
1375 !ly_strncmp(mod->compiled->exts[u].argument, name, name_len)) {
Michal Vasko90932a92020-02-12 14:33:03 +01001376 /* we have the annotation definition */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001377 ant = &mod->compiled->exts[u];
Michal Vasko90932a92020-02-12 14:33:03 +01001378 break;
1379 }
1380 }
1381 if (!ant) {
1382 /* attribute is not defined as a metadata annotation (RFC 7952) */
1383 LOGERR(mod->ctx, LY_EINVAL, "Annotation definition for attribute \"%s:%.*s\" not found.",
1384 mod->name, name_len, name);
1385 return LY_EINVAL;
1386 }
1387
Michal Vasko9f96a052020-03-10 09:41:45 +01001388 mt = calloc(1, sizeof *mt);
1389 LY_CHECK_ERR_RET(!mt, LOGMEM(mod->ctx), LY_EMEM);
1390 mt->parent = parent;
1391 mt->annotation = ant;
Michal Vasko52927e22020-03-16 17:26:14 +01001392 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 +01001393 if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001394 free(mt);
Michal Vasko90932a92020-02-12 14:33:03 +01001395 return ret;
1396 }
Michal Vasko9f96a052020-03-10 09:41:45 +01001397 mt->name = lydict_insert(mod->ctx, name, name_len);
Michal Vasko90932a92020-02-12 14:33:03 +01001398
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001399 /* insert as the last attribute */
1400 if (parent) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001401 if (parent->meta) {
1402 for (last = parent->meta; last->next; last = last->next);
1403 last->next = mt;
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001404 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +01001405 parent->meta = mt;
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001406 }
Michal Vasko9f96a052020-03-10 09:41:45 +01001407 } else if (*meta) {
1408 for (last = *meta; last->next; last = last->next);
1409 last->next = mt;
Michal Vasko90932a92020-02-12 14:33:03 +01001410 }
1411
1412 /* remove default flags from NP containers */
1413 while (parent && (parent->flags & LYD_DEFAULT)) {
1414 parent->flags &= ~LYD_DEFAULT;
1415 parent = (struct lyd_node *)parent->parent;
1416 }
1417
Michal Vasko9f96a052020-03-10 09:41:45 +01001418 if (meta) {
1419 *meta = mt;
Michal Vasko90932a92020-02-12 14:33:03 +01001420 }
1421 return ret;
1422}
1423
Michal Vasko52927e22020-03-16 17:26:14 +01001424LY_ERR
1425ly_create_attr(struct lyd_node *parent, struct ly_attr **attr, const struct ly_ctx *ctx, const char *name,
1426 size_t name_len, const char *value, size_t value_len, int *dynamic, LYD_FORMAT format,
1427 struct ly_prefix *val_prefs, const char *prefix, size_t prefix_len, const char *ns)
1428{
1429 struct ly_attr *at, *last;
1430 struct lyd_node_opaq *opaq;
1431
1432 assert(ctx && (parent || attr) && (!parent || !parent->schema));
1433 assert(name && name_len);
1434 assert((prefix_len && ns) || (!prefix_len && !ns));
1435
1436 if (!value_len) {
1437 value = "";
1438 }
1439
1440 at = calloc(1, sizeof *at);
1441 LY_CHECK_ERR_RET(!at, LOGMEM(ctx), LY_EMEM);
1442 at->parent = (struct lyd_node_opaq *)parent;
1443 at->name = lydict_insert(ctx, name, name_len);
1444 if (dynamic && *dynamic) {
1445 at->value = lydict_insert_zc(ctx, (char *)value);
1446 *dynamic = 0;
1447 } else {
1448 at->value = lydict_insert(ctx, value, value_len);
1449 }
1450
1451 at->format = format;
1452 at->val_prefs = val_prefs;
1453 if (ns) {
1454 at->prefix.pref = lydict_insert(ctx, prefix, prefix_len);
1455 at->prefix.ns = lydict_insert(ctx, ns, 0);
1456 }
1457
1458 /* insert as the last attribute */
1459 if (parent) {
1460 opaq = (struct lyd_node_opaq *)parent;
1461 if (opaq->attr) {
1462 for (last = opaq->attr; last->next; last = last->next);
1463 last->next = at;
1464 } else {
1465 opaq->attr = at;
1466 }
1467 } else if (*attr) {
1468 for (last = *attr; last->next; last = last->next);
1469 last->next = at;
1470 }
1471
1472 if (attr) {
1473 *attr = at;
1474 }
1475 return LY_SUCCESS;
1476}
1477
Radek Krejci084289f2019-07-09 17:35:30 +02001478API const struct lyd_node_term *
Michal Vaskof03ed032020-03-04 13:31:44 +01001479lyd_target(struct lyd_value_path *path, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +02001480{
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001481 LY_ARRAY_SIZE_TYPE u, v;
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001482 const struct lyd_node *start_sibling;
Michal Vaskoe444f752020-02-10 12:20:06 +01001483 struct lyd_node *node = NULL;
Radek Krejci084289f2019-07-09 17:35:30 +02001484 uint64_t pos = 1;
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001485 int match;
Radek Krejci084289f2019-07-09 17:35:30 +02001486
Michal Vaskof03ed032020-03-04 13:31:44 +01001487 LY_CHECK_ARG_RET(NULL, path, tree, NULL);
Radek Krejci084289f2019-07-09 17:35:30 +02001488
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001489 /* first iteration */
1490 start_sibling = tree;
1491 u = 0;
1492 while (u < LY_ARRAY_SIZE(path)) {
1493 /* find next node instance */
Michal Vasko84c9f1b2020-05-14 12:08:11 +02001494 if (start_sibling && !start_sibling->prev->next && !(path[u].node->nodetype & (LYS_LEAFLIST | LYS_LIST))) {
1495 /* starting from the beginning using hashes */
1496 lyd_find_sibling_val(start_sibling, path[u].node, NULL, 0, &node);
1497 } else {
1498 /* next matching sibling */
1499 lyd_find_sibling_next2(start_sibling, path[u].node, NULL, 0, &node);
1500 }
Radek Krejci084289f2019-07-09 17:35:30 +02001501 if (!node) {
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001502 break;
Radek Krejci084289f2019-07-09 17:35:30 +02001503 }
1504
1505 /* check predicate if any */
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001506 match = 1;
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001507 LY_ARRAY_FOR(path[u].predicates, v) {
1508 if (path[u].predicates[v].type == 0) {
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001509 assert(LY_ARRAY_SIZE(path[u].predicates) == 1);
Radek Krejci084289f2019-07-09 17:35:30 +02001510 /* position predicate */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001511 if (pos != path[u].predicates[v].position) {
Radek Krejci084289f2019-07-09 17:35:30 +02001512 pos++;
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001513 match = 0;
Radek Krejci084289f2019-07-09 17:35:30 +02001514 }
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001515 } else if (path[u].predicates[v].type == 1) {
Radek Krejci084289f2019-07-09 17:35:30 +02001516 /* key-predicate */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001517 struct lysc_type *type = ((struct lysc_node_leaf *)path[u].predicates[v].key)->type;
Michal Vaskoe444f752020-02-10 12:20:06 +01001518 struct lyd_node *key;
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001519
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001520 lyd_find_sibling_val(lyd_node_children(node), path[u].predicates[v].key, NULL, 0, &key);
Radek Krejci084289f2019-07-09 17:35:30 +02001521 if (!key) {
1522 /* probably error and we shouldn't be here due to previous checks when creating path */
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001523 match = 0;
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001524 } else if (type->plugin->compare(&((struct lyd_node_term *)key)->value, path[u].predicates[v].value)) {
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001525 match = 0;
Radek Krejci084289f2019-07-09 17:35:30 +02001526 }
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001527 } else if (path[u].predicates[v].type == 2) {
Radek Krejci084289f2019-07-09 17:35:30 +02001528 /* leaf-list-predicate */
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001529 struct lysc_type *type = ((struct lysc_node_leaf *)path[u].node)->type;
1530
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001531 if (type->plugin->compare(&((struct lyd_node_term *)node)->value, path[u].predicates[v].value)) {
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001532 match = 0;
Radek Krejci084289f2019-07-09 17:35:30 +02001533 }
1534 } else {
1535 LOGINT(NULL);
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001536 return NULL;
1537 }
1538
1539 if (!match) {
1540 /* useless to check more predicates */
1541 break;
Radek Krejci084289f2019-07-09 17:35:30 +02001542 }
1543 }
1544
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001545 if (!match) {
1546 /* try to match next sibling */
1547 start_sibling = node->next;
1548 } else {
1549 /* matched, move to the next path segment */
1550 ++u;
1551 start_sibling = lyd_node_children(node);
1552 pos = 1;
1553 }
Radek Krejci084289f2019-07-09 17:35:30 +02001554 }
1555
Michal Vasko6a12b4b2020-05-13 14:28:09 +02001556 return (const struct lyd_node_term *)node;
Radek Krejci084289f2019-07-09 17:35:30 +02001557}
1558
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001559API LY_ERR
1560lyd_compare(const struct lyd_node *node1, const struct lyd_node *node2, int options)
1561{
1562 const struct lyd_node *iter1, *iter2;
1563 struct lyd_node_term *term1, *term2;
1564 struct lyd_node_any *any1, *any2;
Michal Vasko52927e22020-03-16 17:26:14 +01001565 struct lyd_node_opaq *opaq1, *opaq2;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001566 struct lysc_type *type;
1567 size_t len1, len2;
Radek Krejci084289f2019-07-09 17:35:30 +02001568
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001569 if (!node1 || !node2) {
1570 if (node1 == node2) {
1571 return LY_SUCCESS;
1572 } else {
1573 return LY_ENOT;
1574 }
1575 }
1576
Michal Vasko52927e22020-03-16 17:26:14 +01001577 if ((LYD_NODE_CTX(node1) != LYD_NODE_CTX(node2)) || (node1->schema != node2->schema)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001578 return LY_ENOT;
1579 }
1580
1581 if (node1->hash != node2->hash) {
1582 return LY_ENOT;
1583 }
Michal Vasko52927e22020-03-16 17:26:14 +01001584 /* 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 +02001585
Michal Vasko52927e22020-03-16 17:26:14 +01001586 if (!node1->schema) {
1587 opaq1 = (struct lyd_node_opaq *)node1;
1588 opaq2 = (struct lyd_node_opaq *)node2;
1589 if ((opaq1->name != opaq2->name) || (opaq1->prefix.ns != opaq2->prefix.ns) || (opaq1->format != opaq2->format)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001590 return LY_ENOT;
1591 }
Michal Vasko52927e22020-03-16 17:26:14 +01001592 switch (opaq1->format) {
1593 case LYD_XML:
1594 if (lyxml_value_compare(opaq1->value, opaq1->val_prefs, opaq2->value, opaq2->val_prefs)) {
1595 return LY_ENOT;
1596 }
1597 break;
1598 case LYD_SCHEMA:
1599 /* not allowed */
1600 LOGINT(LYD_NODE_CTX(node1));
1601 return LY_EINT;
1602 }
1603 if (options & LYD_COMPARE_FULL_RECURSION) {
1604 iter1 = opaq1->child;
1605 iter2 = opaq2->child;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001606 goto all_children_compare;
Michal Vasko52927e22020-03-16 17:26:14 +01001607 }
1608 return LY_SUCCESS;
1609 } else {
1610 switch (node1->schema->nodetype) {
1611 case LYS_LEAF:
1612 case LYS_LEAFLIST:
1613 if (options & LYD_COMPARE_DEFAULTS) {
1614 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
1615 return LY_ENOT;
1616 }
1617 }
1618
1619 term1 = (struct lyd_node_term*)node1;
1620 term2 = (struct lyd_node_term*)node2;
1621 type = ((struct lysc_node_leaf*)node1->schema)->type;
1622
1623 return type->plugin->compare(&term1->value, &term2->value);
1624 case LYS_CONTAINER:
1625 if (options & LYD_COMPARE_DEFAULTS) {
1626 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
1627 return LY_ENOT;
1628 }
1629 }
1630 if (options & LYD_COMPARE_FULL_RECURSION) {
1631 iter1 = ((struct lyd_node_inner*)node1)->child;
1632 iter2 = ((struct lyd_node_inner*)node2)->child;
1633 goto all_children_compare;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001634 }
1635 return LY_SUCCESS;
Michal Vasko1bf09392020-03-27 12:38:10 +01001636 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01001637 case LYS_ACTION:
1638 if (options & LYD_COMPARE_FULL_RECURSION) {
1639 /* TODO action/RPC
1640 goto all_children_compare;
1641 */
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001642 }
1643 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01001644 case LYS_NOTIF:
1645 if (options & LYD_COMPARE_FULL_RECURSION) {
1646 /* TODO Notification
1647 goto all_children_compare;
1648 */
1649 }
1650 return LY_SUCCESS;
1651 case LYS_LIST:
1652 iter1 = ((struct lyd_node_inner*)node1)->child;
1653 iter2 = ((struct lyd_node_inner*)node2)->child;
1654
1655 if (!(node1->schema->flags & LYS_KEYLESS) && !(options & LYD_COMPARE_FULL_RECURSION)) {
1656 /* lists with keys, their equivalence is based on their keys */
1657 for (struct lysc_node *key = ((struct lysc_node_list*)node1->schema)->child;
1658 key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
1659 key = key->next) {
1660 if (lyd_compare(iter1, iter2, options)) {
1661 return LY_ENOT;
1662 }
1663 iter1 = iter1->next;
1664 iter2 = iter2->next;
1665 }
1666 } else {
1667 /* lists without keys, their equivalence is based on equivalence of all the children (both direct and indirect) */
1668
1669 all_children_compare:
1670 if (!iter1 && !iter2) {
1671 /* no children, nothing to compare */
1672 return LY_SUCCESS;
1673 }
1674
1675 for (; iter1 && iter2; iter1 = iter1->next, iter2 = iter2->next) {
1676 if (lyd_compare(iter1, iter2, options | LYD_COMPARE_FULL_RECURSION)) {
1677 return LY_ENOT;
1678 }
1679 }
1680 if (iter1 || iter2) {
1681 return LY_ENOT;
1682 }
1683 }
1684 return LY_SUCCESS;
1685 case LYS_ANYXML:
1686 case LYS_ANYDATA:
1687 any1 = (struct lyd_node_any*)node1;
1688 any2 = (struct lyd_node_any*)node2;
1689
1690 if (any1->value_type != any2->value_type) {
1691 return LY_ENOT;
1692 }
1693 switch (any1->value_type) {
1694 case LYD_ANYDATA_DATATREE:
1695 iter1 = any1->value.tree;
1696 iter2 = any2->value.tree;
1697 goto all_children_compare;
1698 case LYD_ANYDATA_STRING:
1699 case LYD_ANYDATA_XML:
1700 case LYD_ANYDATA_JSON:
1701 len1 = strlen(any1->value.str);
1702 len2 = strlen(any2->value.str);
1703 if (len1 != len2 || strcmp(any1->value.str, any2->value.str)) {
1704 return LY_ENOT;
1705 }
1706 return LY_SUCCESS;
1707 #if 0 /* TODO LYB format */
1708 case LYD_ANYDATA_LYB:
1709 int len1 = lyd_lyb_data_length(any1->value.mem);
1710 int len2 = lyd_lyb_data_length(any2->value.mem);
1711 if (len1 != len2 || memcmp(any1->value.mem, any2->value.mem, len1)) {
1712 return LY_ENOT;
1713 }
1714 return LY_SUCCESS;
1715 #endif
1716 }
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001717 }
1718 }
1719
Michal Vasko52927e22020-03-16 17:26:14 +01001720 LOGINT(LYD_NODE_CTX(node1));
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001721 return LY_EINT;
1722}
Radek Krejci22ebdba2019-07-25 13:59:43 +02001723
1724/**
Michal Vasko52927e22020-03-16 17:26:14 +01001725 * @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 +02001726 *
1727 * 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 +02001728 *
1729 * @param[in] node Original node to duplicate
1730 * @param[in] parent Parent to insert into, NULL for top-level sibling.
1731 * @param[in,out] first First sibling, NULL if no top-level sibling exist yet. Can be also NULL if @p parent is set.
1732 * @param[in] options Bitmask of options flags, see @ref dupoptions.
1733 * @param[out] dup_p Pointer where the created duplicated node is placed (besides connecting it int @p parent / @p first sibling).
1734 * @return LY_ERR value
Radek Krejci22ebdba2019-07-25 13:59:43 +02001735 */
Michal Vasko52927e22020-03-16 17:26:14 +01001736static LY_ERR
1737lyd_dup_recursive(const struct lyd_node *node, struct lyd_node *parent, struct lyd_node **first, int options,
1738 struct lyd_node **dup_p)
Radek Krejci22ebdba2019-07-25 13:59:43 +02001739{
Michal Vasko52927e22020-03-16 17:26:14 +01001740 LY_ERR ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001741 struct lyd_node *dup = NULL;
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001742 LY_ARRAY_SIZE_TYPE u;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001743
Michal Vasko52927e22020-03-16 17:26:14 +01001744 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001745
Michal Vasko52927e22020-03-16 17:26:14 +01001746 if (!node->schema) {
1747 dup = calloc(1, sizeof(struct lyd_node_opaq));
1748 } else {
1749 switch (node->schema->nodetype) {
Michal Vasko1bf09392020-03-27 12:38:10 +01001750 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01001751 case LYS_ACTION:
1752 case LYS_NOTIF:
1753 case LYS_CONTAINER:
1754 case LYS_LIST:
1755 dup = calloc(1, sizeof(struct lyd_node_inner));
1756 break;
1757 case LYS_LEAF:
1758 case LYS_LEAFLIST:
1759 dup = calloc(1, sizeof(struct lyd_node_term));
1760 break;
1761 case LYS_ANYDATA:
1762 case LYS_ANYXML:
1763 dup = calloc(1, sizeof(struct lyd_node_any));
1764 break;
1765 default:
1766 LOGINT(LYD_NODE_CTX(node));
1767 ret = LY_EINT;
1768 goto error;
1769 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02001770 }
Michal Vasko52927e22020-03-16 17:26:14 +01001771 LY_CHECK_ERR_GOTO(!dup, LOGMEM(LYD_NODE_CTX(node)); ret = LY_EMEM, error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001772
1773 /* TODO implement LYD_DUP_WITH_WHEN */
1774 dup->flags = node->flags;
1775 dup->schema = node->schema;
Michal Vasko52927e22020-03-16 17:26:14 +01001776 dup->prev = dup;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001777
1778 /* TODO duplicate attributes, implement LYD_DUP_NO_ATTR */
1779
1780 /* nodetype-specific work */
Michal Vasko52927e22020-03-16 17:26:14 +01001781 if (!dup->schema) {
1782 struct lyd_node_opaq *opaq = (struct lyd_node_opaq *)dup;
1783 struct lyd_node_opaq *orig = (struct lyd_node_opaq *)node;
1784 struct lyd_node *child;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001785
1786 if (options & LYD_DUP_RECURSIVE) {
1787 /* duplicate all the children */
1788 LY_LIST_FOR(orig->child, child) {
Michal Vasko52927e22020-03-16 17:26:14 +01001789 LY_CHECK_GOTO(ret = lyd_dup_recursive(child, dup, NULL, options, NULL), error);
1790 }
1791 }
1792 opaq->name = lydict_insert(LYD_NODE_CTX(node), orig->name, 0);
1793 opaq->format = orig->format;
1794 if (orig->prefix.pref) {
1795 opaq->prefix.pref = lydict_insert(LYD_NODE_CTX(node), orig->prefix.pref, 0);
1796 }
1797 if (orig->prefix.ns) {
1798 opaq->prefix.ns = lydict_insert(LYD_NODE_CTX(node), orig->prefix.ns, 0);
1799 }
1800 if (orig->val_prefs) {
1801 LY_ARRAY_CREATE_GOTO(LYD_NODE_CTX(node), opaq->val_prefs, LY_ARRAY_SIZE(orig->val_prefs), ret, error);
1802 LY_ARRAY_FOR(orig->val_prefs, u) {
1803 opaq->val_prefs[u].pref = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].pref, 0);
1804 opaq->val_prefs[u].ns = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].ns, 0);
1805 LY_ARRAY_INCREMENT(opaq->val_prefs);
1806 }
1807 }
1808 opaq->value = lydict_insert(LYD_NODE_CTX(node), orig->value, 0);
1809 opaq->ctx = orig->ctx;
1810 } else if (dup->schema->nodetype & LYD_NODE_TERM) {
1811 struct lyd_node_term *term = (struct lyd_node_term *)dup;
1812 struct lyd_node_term *orig = (struct lyd_node_term *)node;
1813
1814 term->hash = orig->hash;
1815 term->value.realtype = orig->value.realtype;
1816 LY_CHECK_ERR_GOTO(term->value.realtype->plugin->duplicate(LYD_NODE_CTX(node), &orig->value, &term->value),
1817 LOGERR(LYD_NODE_CTX(node), LY_EINT, "Value duplication failed."); ret = LY_EINT, error);
1818 } else if (dup->schema->nodetype & LYD_NODE_INNER) {
1819 struct lyd_node_inner *orig = (struct lyd_node_inner *)node;
1820 struct lyd_node *child;
1821
1822 if (options & LYD_DUP_RECURSIVE) {
1823 /* duplicate all the children */
1824 LY_LIST_FOR(orig->child, child) {
1825 LY_CHECK_GOTO(ret = lyd_dup_recursive(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001826 }
Radek Krejci0fe9b512019-07-26 17:51:05 +02001827 } else if (dup->schema->nodetype == LYS_LIST && !(dup->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001828 /* always duplicate keys of a list */
Radek Krejci22ebdba2019-07-25 13:59:43 +02001829 child = orig->child;
Michal Vasko52927e22020-03-16 17:26:14 +01001830 for (struct lysc_node *key = ((struct lysc_node_list *)dup->schema)->child;
Radek Krejci0fe9b512019-07-26 17:51:05 +02001831 key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
1832 key = key->next) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001833 if (!child) {
1834 /* possibly not keys are present in filtered tree */
1835 break;
Radek Krejci0fe9b512019-07-26 17:51:05 +02001836 } else if (child->schema != key) {
1837 /* possibly not all keys are present in filtered tree,
1838 * but there can be also some non-key nodes */
1839 continue;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001840 }
Michal Vasko52927e22020-03-16 17:26:14 +01001841 LY_CHECK_GOTO(ret = lyd_dup_recursive(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001842 child = child->next;
1843 }
1844 }
1845 lyd_hash(dup);
1846 } else if (dup->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko52927e22020-03-16 17:26:14 +01001847 struct lyd_node_any *any = (struct lyd_node_any *)dup;
1848 struct lyd_node_any *orig = (struct lyd_node_any *)node;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001849
1850 any->hash = orig->hash;
1851 any->value_type = orig->value_type;
1852 switch (any->value_type) {
1853 case LYD_ANYDATA_DATATREE:
1854 if (orig->value.tree) {
1855 any->value.tree = lyd_dup(orig->value.tree, NULL, LYD_DUP_RECURSIVE | LYD_DUP_WITH_SIBLINGS);
Radek Krejci25dc3432020-05-15 14:42:12 +02001856 if (!any->value.tree) {
1857 /* get the last error's error code recorded by lyd_dup */
1858 struct ly_err_item *ei = ly_err_first(LYD_NODE_CTX(node));
1859 ret = ei ? ei->prev->no : LY_EOTHER;
1860 goto error;
1861 }
1862 LY_CHECK_ERR_GOTO(!any->value.tree, ret = 0 ,error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001863 }
1864 break;
1865 case LYD_ANYDATA_STRING:
1866 case LYD_ANYDATA_XML:
1867 case LYD_ANYDATA_JSON:
1868 if (orig->value.str) {
Michal Vasko52927e22020-03-16 17:26:14 +01001869 any->value.str = lydict_insert(LYD_NODE_CTX(node), orig->value.str, strlen(orig->value.str));
Radek Krejci22ebdba2019-07-25 13:59:43 +02001870 }
1871 break;
1872 }
1873 }
1874
Michal Vasko52927e22020-03-16 17:26:14 +01001875 /* insert */
1876 lyd_insert_node(parent, first, dup);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001877 lyd_insert_hash(dup);
Michal Vasko52927e22020-03-16 17:26:14 +01001878
1879 if (dup_p) {
1880 *dup_p = dup;
1881 }
1882 return LY_SUCCESS;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001883
1884error:
Michal Vasko52927e22020-03-16 17:26:14 +01001885 lyd_free_tree(dup);
1886 return ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001887}
1888
1889API struct lyd_node *
1890lyd_dup(const struct lyd_node *node, struct lyd_node_inner *parent, int options)
1891{
1892 struct ly_ctx *ctx;
1893 const struct lyd_node *orig; /* original node to be duplicated */
1894 struct lyd_node *first = NULL; /* the first duplicated node, this is returned */
Radek Krejci22ebdba2019-07-25 13:59:43 +02001895 struct lyd_node *top = NULL; /* the most higher created node */
1896 struct lyd_node_inner *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
1897 int keyless_parent_list = 0;
1898
1899 LY_CHECK_ARG_RET(NULL, node, NULL);
1900 ctx = node->schema->module->ctx;
1901
1902 if (options & LYD_DUP_WITH_PARENTS) {
1903 struct lyd_node_inner *orig_parent, *iter;
1904 int repeat = 1;
1905 for (top = NULL, orig_parent = node->parent; repeat && orig_parent; orig_parent = orig_parent->parent) {
1906 if (parent && parent->schema == orig_parent->schema) {
1907 /* stop creating parents, connect what we have into the provided parent */
1908 iter = parent;
1909 repeat = 0;
1910 /* get know if there is a keyless list which we will have to rehash */
1911 for (struct lyd_node_inner *piter = parent; piter; piter = piter->parent) {
Radek Krejci0fe9b512019-07-26 17:51:05 +02001912 if (piter->schema->nodetype == LYS_LIST && (piter->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001913 keyless_parent_list = 1;
1914 break;
1915 }
1916 }
1917 } else {
Michal Vasko52927e22020-03-16 17:26:14 +01001918 iter = NULL;
1919 LY_CHECK_GOTO(lyd_dup_recursive((struct lyd_node *)orig_parent, NULL, (struct lyd_node **)&iter, 0,
1920 (struct lyd_node **)&iter), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001921 }
1922 if (!local_parent) {
1923 local_parent = iter;
1924 }
1925 if (iter->child) {
1926 /* 1) list - add after keys
1927 * 2) provided parent with some children */
1928 iter->child->prev->next = top;
1929 if (top) {
1930 top->prev = iter->child->prev;
1931 iter->child->prev = top;
1932 }
1933 } else {
1934 iter->child = top;
1935 if (iter->schema->nodetype == LYS_LIST) {
1936 /* keyless list - we will need to rehash it since we are going to add nodes into it */
1937 keyless_parent_list = 1;
1938 }
1939 }
1940 if (top) {
1941 top->parent = iter;
1942 }
1943 top = (struct lyd_node*)iter;
1944 }
1945 if (repeat && parent) {
1946 /* given parent and created parents chain actually do not interconnect */
1947 LOGERR(ctx, LY_EINVAL, "Invalid argument parent (%s()) - does not interconnect with the created node's parents chain.", __func__);
1948 goto error;
1949 }
1950 } else {
1951 local_parent = parent;
1952 }
1953
Radek Krejci22ebdba2019-07-25 13:59:43 +02001954 LY_LIST_FOR(node, orig) {
Michal Vasko52927e22020-03-16 17:26:14 +01001955 /* if there is no local parent, it will be inserted into first */
1956 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 +02001957 if (!(options & LYD_DUP_WITH_SIBLINGS)) {
1958 break;
1959 }
1960 }
1961 if (keyless_parent_list) {
1962 /* rehash */
1963 for (; local_parent; local_parent = local_parent->parent) {
Radek Krejci0fe9b512019-07-26 17:51:05 +02001964 if (local_parent->schema->nodetype == LYS_LIST && (local_parent->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02001965 lyd_hash((struct lyd_node*)local_parent);
1966 }
1967 }
1968 }
1969 return first;
1970
1971error:
1972 if (top) {
1973 lyd_free_tree(top);
1974 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +01001975 lyd_free_siblings(first);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001976 }
1977 return NULL;
1978}
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001979
1980static LY_ERR
1981lyd_path_str_enlarge(char **buffer, size_t *buflen, size_t reqlen, int is_static)
1982{
Michal Vasko14654712020-02-06 08:35:21 +01001983 /* ending \0 */
1984 ++reqlen;
1985
Michal Vasko5ec7cda2019-09-11 13:43:08 +02001986 if (reqlen > *buflen) {
1987 if (is_static) {
1988 return LY_EINCOMPLETE;
1989 }
1990
1991 *buffer = ly_realloc(*buffer, reqlen * sizeof **buffer);
1992 if (!*buffer) {
1993 return LY_EMEM;
1994 }
1995
1996 *buflen = reqlen;
1997 }
1998
1999 return LY_SUCCESS;
2000}
2001
2002/**
2003 * @brief Append all list key predicates to path.
2004 *
2005 * @param[in] node Node with keys to print.
2006 * @param[in,out] buffer Buffer to print to.
2007 * @param[in,out] buflen Current buffer length.
2008 * @param[in,out] bufused Current number of characters used in @p buffer.
2009 * @param[in] is_static Whether buffer is static or can be reallocated.
2010 * @return LY_ERR
2011 */
2012static LY_ERR
2013lyd_path_list_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2014{
2015 const struct lyd_node *key;
2016 int dynamic = 0;
2017 size_t len;
2018 const char *val;
2019 char quot;
2020 LY_ERR rc;
2021
Michal Vasko14654712020-02-06 08:35:21 +01002022 for (key = lyd_node_children(node); key && (key->schema->flags & LYS_KEY); key = key->next) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002023 val = lyd_value2str((struct lyd_node_term *)key, &dynamic);
2024 len = 1 + strlen(key->schema->name) + 2 + strlen(val) + 2;
2025 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2026 if (rc != LY_SUCCESS) {
2027 if (dynamic) {
2028 free((char *)val);
2029 }
2030 return rc;
2031 }
2032
2033 quot = '\'';
2034 if (strchr(val, '\'')) {
2035 quot = '"';
2036 }
2037 *bufused += sprintf(*buffer + *bufused, "[%s=%c%s%c]", key->schema->name, quot, val, quot);
2038
2039 if (dynamic) {
2040 free((char *)val);
2041 }
2042 }
2043
2044 return LY_SUCCESS;
2045}
2046
2047/**
2048 * @brief Append leaf-list value predicate to path.
2049 *
2050 * @param[in] node Node to print.
2051 * @param[in,out] buffer Buffer to print to.
2052 * @param[in,out] buflen Current buffer length.
2053 * @param[in,out] bufused Current number of characters used in @p buffer.
2054 * @param[in] is_static Whether buffer is static or can be reallocated.
2055 * @return LY_ERR
2056 */
2057static LY_ERR
2058lyd_path_leaflist_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2059{
2060 int dynamic = 0;
2061 size_t len;
2062 const char *val;
2063 char quot;
2064 LY_ERR rc;
2065
2066 val = lyd_value2str((struct lyd_node_term *)node, &dynamic);
2067 len = 4 + strlen(val) + 2;
2068 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2069 if (rc != LY_SUCCESS) {
2070 goto cleanup;
2071 }
2072
2073 quot = '\'';
2074 if (strchr(val, '\'')) {
2075 quot = '"';
2076 }
2077 *bufused += sprintf(*buffer + *bufused, "[.=%c%s%c]", quot, val, quot);
2078
2079cleanup:
2080 if (dynamic) {
2081 free((char *)val);
2082 }
2083 return rc;
2084}
2085
2086/**
2087 * @brief Append node position (relative to its other instances) predicate to path.
2088 *
2089 * @param[in] node Node to print.
2090 * @param[in,out] buffer Buffer to print to.
2091 * @param[in,out] buflen Current buffer length.
2092 * @param[in,out] bufused Current number of characters used in @p buffer.
2093 * @param[in] is_static Whether buffer is static or can be reallocated.
2094 * @return LY_ERR
2095 */
2096static LY_ERR
2097lyd_path_position_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2098{
2099 const struct lyd_node *first, *iter;
2100 size_t len;
2101 int pos;
2102 char *val = NULL;
2103 LY_ERR rc;
2104
2105 if (node->parent) {
2106 first = node->parent->child;
2107 } else {
2108 for (first = node; node->prev->next; node = node->prev);
2109 }
2110 pos = 1;
2111 for (iter = first; iter != node; iter = iter->next) {
2112 if (iter->schema == node->schema) {
2113 ++pos;
2114 }
2115 }
2116 if (asprintf(&val, "%d", pos) == -1) {
2117 return LY_EMEM;
2118 }
2119
2120 len = 1 + strlen(val) + 1;
2121 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2122 if (rc != LY_SUCCESS) {
2123 goto cleanup;
2124 }
2125
2126 *bufused += sprintf(*buffer + *bufused, "[%s]", val);
2127
2128cleanup:
2129 free(val);
2130 return rc;
2131}
2132
2133API char *
2134lyd_path(const struct lyd_node *node, LYD_PATH_TYPE pathtype, char *buffer, size_t buflen)
2135{
Michal Vasko14654712020-02-06 08:35:21 +01002136 int is_static = 0, i, depth;
2137 size_t bufused = 0, len;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002138 const struct lyd_node *iter;
2139 const struct lys_module *mod;
2140 LY_ERR rc;
2141
2142 LY_CHECK_ARG_RET(NULL, node, NULL);
2143 if (buffer) {
2144 LY_CHECK_ARG_RET(node->schema->module->ctx, buflen > 1, NULL);
2145 is_static = 1;
Michal Vasko14654712020-02-06 08:35:21 +01002146 } else {
2147 buflen = 0;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002148 }
2149
2150 switch (pathtype) {
Michal Vasko14654712020-02-06 08:35:21 +01002151 case LYD_PATH_LOG:
2152 depth = 1;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002153 for (iter = node; iter->parent; iter = (const struct lyd_node *)iter->parent) {
2154 ++depth;
2155 }
2156
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002157 goto iter_print;
Michal Vasko14654712020-02-06 08:35:21 +01002158 while (depth) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002159 /* find the right node */
Michal Vasko14654712020-02-06 08:35:21 +01002160 for (iter = node, i = 1; i < depth; iter = (const struct lyd_node *)iter->parent, ++i);
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002161iter_print:
2162 /* print prefix and name */
2163 mod = NULL;
2164 if (!iter->parent || (iter->schema->module != iter->parent->schema->module)) {
2165 mod = iter->schema->module;
2166 }
2167
2168 /* realloc string */
2169 len = 1 + (mod ? strlen(mod->name) + 1 : 0) + strlen(iter->schema->name);
2170 rc = lyd_path_str_enlarge(&buffer, &buflen, bufused + len, is_static);
2171 if (rc != LY_SUCCESS) {
2172 break;
2173 }
2174
2175 /* print next node */
2176 bufused += sprintf(buffer + bufused, "/%s%s%s", mod ? mod->name : "", mod ? ":" : "", iter->schema->name);
2177
2178 switch (iter->schema->nodetype) {
2179 case LYS_LIST:
2180 if (iter->schema->flags & LYS_KEYLESS) {
2181 /* print its position */
2182 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2183 } else {
2184 /* print all list keys in predicates */
2185 rc = lyd_path_list_predicate(iter, &buffer, &buflen, &bufused, is_static);
2186 }
2187 break;
2188 case LYS_LEAFLIST:
2189 if (iter->schema->flags & LYS_CONFIG_W) {
2190 /* print leaf-list value */
2191 rc = lyd_path_leaflist_predicate(iter, &buffer, &buflen, &bufused, is_static);
2192 } else {
2193 /* print its position */
2194 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2195 }
2196 break;
2197 default:
2198 /* nothing to print more */
2199 rc = LY_SUCCESS;
2200 break;
2201 }
2202 if (rc != LY_SUCCESS) {
2203 break;
2204 }
2205
Michal Vasko14654712020-02-06 08:35:21 +01002206 --depth;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002207 }
2208 break;
2209 }
2210
2211 return buffer;
2212}
Michal Vaskoe444f752020-02-10 12:20:06 +01002213
Michal Vasko9b368d32020-02-14 13:53:31 +01002214LY_ERR
2215lyd_find_sibling_next2(const struct lyd_node *first, const struct lysc_node *schema, const char *key_or_value,
2216 size_t val_len, struct lyd_node **match)
Michal Vaskoe444f752020-02-10 12:20:06 +01002217{
2218 LY_ERR rc;
2219 const struct lyd_node *node = NULL;
2220 struct lyd_node_term *term;
Michal Vaskoe444f752020-02-10 12:20:06 +01002221 struct ly_keys keys = {0};
Michal Vasko90932a92020-02-12 14:33:03 +01002222 struct lyd_value val = {0};
Michal Vaskoe444f752020-02-10 12:20:06 +01002223 size_t i;
Michal Vaskoe444f752020-02-10 12:20:06 +01002224
Michal Vasko9b368d32020-02-14 13:53:31 +01002225 LY_CHECK_ARG_RET(NULL, schema, LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01002226
2227 if (!first) {
2228 /* no data */
Michal Vasko9b368d32020-02-14 13:53:31 +01002229 if (match) {
2230 *match = NULL;
2231 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002232 return LY_ENOTFOUND;
2233 }
2234
Michal Vaskoe444f752020-02-10 12:20:06 +01002235 if (key_or_value && !val_len) {
2236 val_len = strlen(key_or_value);
2237 }
2238
2239 if (key_or_value && (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko90932a92020-02-12 14:33:03 +01002240 /* store the value */
Michal Vasko9b368d32020-02-14 13:53:31 +01002241 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 +01002242 } else if (key_or_value && (schema->nodetype == LYS_LIST)) {
2243 /* parse keys into canonical values */
Michal Vaskod3678892020-05-21 10:06:58 +02002244 LY_CHECK_GOTO(rc = ly_keys_parse(schema, key_or_value, val_len, 1, 1, &keys), cleanup);
Michal Vaskoe444f752020-02-10 12:20:06 +01002245 }
2246
2247 /* find first matching value */
2248 LY_LIST_FOR(first, node) {
2249 if (node->schema != schema) {
2250 continue;
2251 }
2252
2253 if ((schema->nodetype == LYS_LIST) && keys.str) {
2254 /* compare all set keys */
2255 for (i = 0; i < keys.key_count; ++i) {
2256 /* find key */
2257 rc = lyd_find_sibling_val(lyd_node_children(node), (struct lysc_node *)keys.keys[i].schema, NULL, 0,
2258 (struct lyd_node **)&term);
2259 if (rc == LY_ENOTFOUND) {
2260 /* all keys must always exist */
Michal Vasko9b368d32020-02-14 13:53:31 +01002261 LOGINT_RET(schema->module->ctx);
Michal Vaskoe444f752020-02-10 12:20:06 +01002262 }
2263 LY_CHECK_GOTO(rc, cleanup);
2264
2265 /* compare values */
Michal Vasko90932a92020-02-12 14:33:03 +01002266 if (!term->value.realtype->plugin->compare(&term->value, &keys.keys[i].val)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002267 break;
2268 }
2269 }
2270
2271 if (i < keys.key_count) {
2272 /* not a match */
2273 continue;
2274 }
Michal Vasko90932a92020-02-12 14:33:03 +01002275 } else if ((schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && val.realtype) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002276 term = (struct lyd_node_term *)node;
2277
2278 /* compare values */
Michal Vasko90932a92020-02-12 14:33:03 +01002279 if (!term->value.realtype->plugin->compare(&term->value, &val)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002280 /* not a match */
2281 continue;
2282 }
2283 }
2284
2285 /* all criteria passed */
2286 break;
2287 }
2288
2289 if (!node) {
2290 rc = LY_ENOTFOUND;
Michal Vasko9b368d32020-02-14 13:53:31 +01002291 if (match) {
2292 *match = NULL;
2293 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002294 goto cleanup;
2295 }
2296
2297 /* success */
Michal Vasko9b368d32020-02-14 13:53:31 +01002298 if (match) {
2299 *match = (struct lyd_node *)node;
2300 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002301 rc = LY_SUCCESS;
2302
2303cleanup:
2304 ly_keys_clean(&keys);
Michal Vasko90932a92020-02-12 14:33:03 +01002305 if (val.realtype) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002306 val.realtype->plugin->free(schema->module->ctx, &val);
Michal Vasko90932a92020-02-12 14:33:03 +01002307 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002308 return rc;
2309}
2310
2311API LY_ERR
Michal Vasko9b368d32020-02-14 13:53:31 +01002312lyd_find_sibling_next(const struct lyd_node *first, const struct lys_module *module, const char *name, size_t name_len,
2313 const char *key_or_value, size_t val_len, struct lyd_node **match)
2314{
2315 const struct lysc_node *schema;
2316
2317 LY_CHECK_ARG_RET(NULL, module, name, match, LY_EINVAL);
2318
2319 if (!first) {
2320 /* no data */
2321 *match = NULL;
2322 return LY_ENOTFOUND;
2323 }
2324
2325 /* find schema */
2326 schema = lys_find_child(first->parent ? first->parent->schema : NULL, module, name, name_len, 0, 0);
2327 if (!schema) {
2328 LOGERR(module->ctx, LY_EINVAL, "Schema node not found.");
2329 return LY_EINVAL;
2330 }
2331
2332 return lyd_find_sibling_next2(first, schema, key_or_value, val_len, match);
2333}
2334
2335API LY_ERR
Michal Vaskoe444f752020-02-10 12:20:06 +01002336lyd_find_sibling_first(const struct lyd_node *siblings, const struct lyd_node *target, struct lyd_node **match)
2337{
2338 struct lyd_node **match_p;
2339 struct lyd_node_inner *parent;
2340
Michal Vaskof03ed032020-03-04 13:31:44 +01002341 LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01002342
Michal Vasko62ed12d2020-05-21 10:08:25 +02002343 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(target->schema))) {
2344 /* no data or schema mismatch */
Michal Vasko9b368d32020-02-14 13:53:31 +01002345 if (match) {
2346 *match = NULL;
2347 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002348 return LY_ENOTFOUND;
2349 }
2350
2351 /* find first sibling */
2352 if (siblings->parent) {
2353 siblings = siblings->parent->child;
2354 } else {
2355 while (siblings->prev->next) {
2356 siblings = siblings->prev;
2357 }
2358 }
2359
2360 parent = (struct lyd_node_inner *)siblings->parent;
2361 if (parent && parent->children_ht) {
2362 assert(target->hash);
2363
2364 /* find by hash */
2365 if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
2366 siblings = *match_p;
2367 } else {
2368 /* not found */
2369 siblings = NULL;
2370 }
2371 } else {
2372 /* no children hash table */
2373 for (; siblings; siblings = siblings->next) {
2374 if (!lyd_compare(siblings, target, 0)) {
2375 break;
2376 }
2377 }
2378 }
2379
2380 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002381 if (match) {
2382 *match = NULL;
2383 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002384 return LY_ENOTFOUND;
2385 }
2386
Michal Vasko9b368d32020-02-14 13:53:31 +01002387 if (match) {
2388 *match = (struct lyd_node *)siblings;
2389 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002390 return LY_SUCCESS;
2391}
2392
2393API LY_ERR
2394lyd_find_sibling_set(const struct lyd_node *siblings, const struct lyd_node *target, struct ly_set **set)
2395{
2396 struct lyd_node_inner *parent;
2397 struct lyd_node *match;
2398 struct lyd_node **match_p;
2399 struct ly_set *ret;
2400
2401 LY_CHECK_ARG_RET(NULL, target, set, LY_EINVAL);
2402
Michal Vasko62ed12d2020-05-21 10:08:25 +02002403 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(target->schema))) {
2404 /* no data or schema mismatch */
Michal Vaskoe444f752020-02-10 12:20:06 +01002405 return LY_ENOTFOUND;
2406 }
2407
2408 ret = ly_set_new();
2409 LY_CHECK_ERR_RET(!ret, LOGMEM(target->schema->module->ctx), LY_EMEM);
2410
2411 /* find first sibling */
2412 if (siblings->parent) {
2413 siblings = siblings->parent->child;
2414 } else {
2415 while (siblings->prev->next) {
2416 siblings = siblings->prev;
2417 }
2418 }
2419
2420 parent = (struct lyd_node_inner *)siblings->parent;
2421 if (parent && parent->children_ht) {
2422 assert(target->hash);
2423
2424 /* find by hash */
2425 if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
2426 match = *match_p;
2427 } else {
2428 /* not found */
2429 match = NULL;
2430 }
2431 while (match) {
2432 /* add all found nodes into the return set */
2433 if (ly_set_add(ret, match, LY_SET_OPT_USEASLIST) == -1) {
2434 goto error;
2435 }
2436
2437 /* find next instance */
2438 if (lyht_find_next(parent->children_ht, &match, match->hash, (void **)&match_p)) {
2439 match = NULL;
2440 } else {
2441 match = *match_p;
2442 }
2443 }
2444 } else {
2445 /* no children hash table */
2446 for (; siblings; siblings = siblings->next) {
2447 if (!lyd_compare(siblings, target, 0)) {
2448 /* a match */
2449 if (ly_set_add(ret, (struct lyd_node *)siblings, LY_SET_OPT_USEASLIST) == -1) {
2450 goto error;
2451 }
2452 }
2453 }
2454 }
2455
2456 if (!ret->count) {
2457 ly_set_free(ret, NULL);
2458 return LY_ENOTFOUND;
2459 }
2460
2461 *set = ret;
2462 return LY_SUCCESS;
2463
2464error:
2465 ly_set_free(ret, NULL);
2466 return LY_EMEM;
2467}
2468
Michal Vasko90932a92020-02-12 14:33:03 +01002469static int
2470lyd_hash_table_schema_val_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *UNUSED(cb_data))
2471{
2472 struct lysc_node *val1;
2473 struct lyd_node *val2;
2474
2475 val1 = *((struct lysc_node **)val1_p);
2476 val2 = *((struct lyd_node **)val2_p);
2477
2478 assert(val1->nodetype & (LYD_NODE_INNER | LYS_LEAF));
2479
2480 if (val1 == val2->schema) {
2481 /* schema match is enough */
2482 return 1;
2483 } else {
2484 return 0;
2485 }
2486}
2487
2488static LY_ERR
2489lyd_find_sibling_schema(const struct lyd_node *siblings, const struct lysc_node *schema, struct lyd_node **match)
2490{
2491 struct lyd_node **match_p;
2492 struct lyd_node_inner *parent;
2493 uint32_t hash;
2494 values_equal_cb ht_cb;
2495
2496 assert(siblings && schema && (schema->nodetype & (LYD_NODE_INNER | LYS_LEAF)));
2497
2498 /* find first sibling */
2499 if (siblings->parent) {
2500 siblings = siblings->parent->child;
2501 } else {
2502 while (siblings->prev->next) {
2503 siblings = siblings->prev;
2504 }
2505 }
2506
2507 parent = (struct lyd_node_inner *)siblings->parent;
2508 if (parent && parent->children_ht) {
2509 /* calculate our hash */
2510 hash = dict_hash_multi(0, schema->module->name, strlen(schema->module->name));
2511 hash = dict_hash_multi(hash, schema->name, strlen(schema->name));
2512 hash = dict_hash_multi(hash, NULL, 0);
2513
2514 /* use special hash table function */
2515 ht_cb = lyht_set_cb(parent->children_ht, lyd_hash_table_schema_val_equal);
2516
2517 /* find by hash */
2518 if (!lyht_find(parent->children_ht, &schema, hash, (void **)&match_p)) {
2519 siblings = *match_p;
2520 } else {
2521 /* not found */
2522 siblings = NULL;
2523 }
2524
2525 /* set the original hash table compare function back */
2526 lyht_set_cb(parent->children_ht, ht_cb);
2527 } else {
2528 /* no children hash table */
2529 for (; siblings; siblings = siblings->next) {
2530 if (siblings->schema == schema) {
2531 /* schema match is enough */
2532 break;
2533 }
2534 }
2535 }
2536
2537 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002538 if (match) {
2539 *match = NULL;
2540 }
Michal Vasko90932a92020-02-12 14:33:03 +01002541 return LY_ENOTFOUND;
2542 }
2543
Michal Vasko9b368d32020-02-14 13:53:31 +01002544 if (match) {
2545 *match = (struct lyd_node *)siblings;
2546 }
Michal Vasko90932a92020-02-12 14:33:03 +01002547 return LY_SUCCESS;
2548}
2549
Michal Vaskoe444f752020-02-10 12:20:06 +01002550API LY_ERR
2551lyd_find_sibling_val(const struct lyd_node *siblings, const struct lysc_node *schema, const char *key_or_value,
2552 size_t val_len, struct lyd_node **match)
2553{
2554 LY_ERR rc;
2555 struct lyd_node *target = NULL;
2556
2557 LY_CHECK_ARG_RET(NULL, schema, LY_EINVAL);
Michal Vasko62ed12d2020-05-21 10:08:25 +02002558 if ((schema->nodetype == LYS_LIST) && (schema->flags & LYS_KEYLESS)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002559 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - key-less list (%s()).", __func__);
2560 return LY_EINVAL;
2561 } else if ((schema->nodetype & (LYS_LEAFLIST | LYS_LIST)) && !key_or_value) {
2562 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - no value/keys for a (leaf-)list (%s()).", __func__);
2563 return LY_EINVAL;
2564 } else if (schema->nodetype & (LYS_CHOICE | LYS_CASE)) {
2565 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - schema type %s (%s()).",
2566 lys_nodetype2str(schema->nodetype), __func__);
2567 return LY_EINVAL;
2568 }
2569
Michal Vasko62ed12d2020-05-21 10:08:25 +02002570 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(schema))) {
2571 /* no data or schema mismatch */
Michal Vasko9b368d32020-02-14 13:53:31 +01002572 if (match) {
2573 *match = NULL;
2574 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002575 return LY_ENOTFOUND;
2576 }
2577
Michal Vaskof03ed032020-03-04 13:31:44 +01002578 if (key_or_value && !val_len) {
2579 val_len = strlen(key_or_value);
2580 }
2581
Michal Vasko90932a92020-02-12 14:33:03 +01002582 /* create data node if needed and find it */
Michal Vaskoe444f752020-02-10 12:20:06 +01002583 switch (schema->nodetype) {
2584 case LYS_CONTAINER:
2585 case LYS_ANYXML:
2586 case LYS_ANYDATA:
2587 case LYS_NOTIF:
Michal Vasko1bf09392020-03-27 12:38:10 +01002588 case LYS_RPC:
Michal Vasko9b368d32020-02-14 13:53:31 +01002589 case LYS_ACTION:
Michal Vaskoe444f752020-02-10 12:20:06 +01002590 case LYS_LEAF:
Michal Vasko90932a92020-02-12 14:33:03 +01002591 /* find it based on schema only */
2592 rc = lyd_find_sibling_schema(siblings, schema, match);
Michal Vaskoe444f752020-02-10 12:20:06 +01002593 break;
2594 case LYS_LEAFLIST:
2595 /* target used attributes: schema, hash, value */
Michal Vasko90932a92020-02-12 14:33:03 +01002596 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 +01002597 /* fallthrough */
Michal Vaskoe444f752020-02-10 12:20:06 +01002598 case LYS_LIST:
Michal Vasko90932a92020-02-12 14:33:03 +01002599 if (schema->nodetype == LYS_LIST) {
2600 /* target used attributes: schema, hash, child (all keys) */
Michal Vaskod3678892020-05-21 10:06:58 +02002601 LY_CHECK_RET(lyd_create_list(schema, key_or_value, val_len, LYD_JSON, 1, &target));
Michal Vasko90932a92020-02-12 14:33:03 +01002602 }
2603
2604 /* find it */
2605 rc = lyd_find_sibling_first(siblings, target, match);
Michal Vaskoe444f752020-02-10 12:20:06 +01002606 break;
2607 default:
2608 /* unreachable */
2609 LOGINT(schema->module->ctx);
2610 return LY_EINT;
2611 }
2612
Michal Vaskoe444f752020-02-10 12:20:06 +01002613 lyd_free_tree(target);
2614 return rc;
2615}
Michal Vaskoccc02342020-05-21 10:09:21 +02002616
2617API LY_ERR
2618lyd_find_xpath(const struct lyd_node *ctx_node, const char *xpath, struct ly_set **set)
2619{
2620 LY_ERR ret = LY_SUCCESS;
2621 struct lyxp_set xp_set;
2622 struct lyxp_expr *exp;
2623 uint32_t i;
2624
2625 LY_CHECK_ARG_RET(NULL, ctx_node, xpath, set, LY_EINVAL);
2626
2627 memset(&xp_set, 0, sizeof xp_set);
2628
2629 /* compile expression */
2630 exp = lyxp_expr_parse((struct ly_ctx *)LYD_NODE_CTX(ctx_node), xpath);
2631 LY_CHECK_ERR_GOTO(!exp, ret = LY_EINVAL, cleanup);
2632
2633 /* evaluate expression */
2634 ret = lyxp_eval(exp, LYD_JSON, ctx_node->schema->module, ctx_node, LYXP_NODE_ELEM, ctx_node, &xp_set, 0);
2635 LY_CHECK_GOTO(ret, cleanup);
2636
2637 /* allocate return set */
2638 *set = ly_set_new();
2639 LY_CHECK_ERR_GOTO(!*set, LOGMEM(LYD_NODE_CTX(ctx_node)); ret = LY_EMEM, cleanup);
2640
2641 /* transform into ly_set */
2642 if (xp_set.type == LYXP_SET_NODE_SET) {
2643 /* allocate memory for all the elements once (even though not all items must be elements but most likely will be) */
2644 (*set)->objs = malloc(xp_set.used * sizeof *(*set)->objs);
2645 LY_CHECK_ERR_GOTO(!(*set)->objs, LOGMEM(LYD_NODE_CTX(ctx_node)); ret = LY_EMEM, cleanup);
2646 (*set)->size = xp_set.used;
2647
2648 for (i = 0; i < xp_set.used; ++i) {
2649 if (xp_set.val.nodes[i].type == LYXP_NODE_ELEM) {
2650 ly_set_add(*set, xp_set.val.nodes[i].node, LY_SET_OPT_USEASLIST);
2651 }
2652 }
2653 }
2654
2655cleanup:
Michal Vasko0691d522020-05-21 13:21:47 +02002656 lyxp_set_free_content(&xp_set);
Michal Vaskoccc02342020-05-21 10:09:21 +02002657 lyxp_expr_free((struct ly_ctx *)LYD_NODE_CTX(ctx_node), exp);
2658 return ret;
2659}