blob: 9b4abd784c9353cf928d6e1ffe6c84e82c32aed3 [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>
Michal Vasko6cd9b6b2020-06-22 10:05:22 +02004 * @brief Data tree functions
Radek Krejcie7b95092019-05-15 11:03:07 +02005 *
Michal Vasko6cd9b6b2020-06-22 10:05:22 +02006 * Copyright (c) 2015 - 2020 CESNET, z.s.p.o.
Radek Krejcie7b95092019-05-15 11:03:07 +02007 *
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
Radek Krejci535ea9f2020-05-29 16:01:05 +020015#define _GNU_SOURCE
16
17#include "tree_data.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020018
Radek Krejci084289f2019-07-09 17:35:30 +020019#include <assert.h>
Radek Krejcie7b95092019-05-15 11:03:07 +020020#include <ctype.h>
21#include <errno.h>
22#include <fcntl.h>
23#include <stdarg.h>
24#include <stdint.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020025#include <stdio.h>
26#include <stdlib.h>
Radek Krejcie7b95092019-05-15 11:03:07 +020027#include <string.h>
28#include <unistd.h>
29
Radek Krejci535ea9f2020-05-29 16:01:05 +020030#include "common.h"
Michal Vasko5aa44c02020-06-29 11:47:02 +020031#include "compat.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020032#include "config.h"
33#include "context.h"
34#include "dict.h"
Michal Vasko90932a92020-02-12 14:33:03 +010035#include "hash_table.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020036#include "log.h"
Radek Krejci7931b192020-06-25 17:05:03 +020037#include "parser_data.h"
38#include "parser_internal.h"
Michal Vasko004d3152020-06-11 19:59:22 +020039#include "path.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020040#include "plugins_exts.h"
Radek Krejci38d85362019-09-05 16:26:38 +020041#include "plugins_exts_metadata.h"
Michal Vasko90932a92020-02-12 14:33:03 +010042#include "plugins_exts_internal.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020043#include "plugins_types.h"
44#include "set.h"
45#include "tree.h"
46#include "tree_data_internal.h"
47#include "tree_schema.h"
48#include "tree_schema_internal.h"
49#include "xml.h"
50#include "xpath.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020051
Michal Vaskob104f112020-07-17 09:54:54 +020052static LY_ERR lyd_find_sibling_schema(const struct lyd_node *siblings, const struct lysc_node *schema,
53 struct lyd_node **match);
54
Radek Krejci084289f2019-07-09 17:35:30 +020055LY_ERR
Michal Vasko90932a92020-02-12 14:33:03 +010056lyd_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 +010057 ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +020058{
Michal Vasko90932a92020-02-12 14:33:03 +010059 LY_ERR ret = LY_SUCCESS;
Radek Krejci084289f2019-07-09 17:35:30 +020060 struct ly_err_item *err = NULL;
61 struct ly_ctx *ctx;
62 struct lysc_type *type;
Radek Krejci3c9758d2019-07-11 16:49:10 +020063 int options = LY_TYPE_OPTS_STORE | (second ? LY_TYPE_OPTS_SECOND_CALL : 0) |
Michal Vaskof03ed032020-03-04 13:31:44 +010064 (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci084289f2019-07-09 17:35:30 +020065 assert(node);
66
67 ctx = node->schema->module->ctx;
Radek Krejci084289f2019-07-09 17:35:30 +020068
Radek Krejci73dead22019-07-11 16:46:16 +020069 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci62903c32019-07-15 14:42:05 +020070 if (!second) {
71 node->value.realtype = type;
72 }
Michal Vasko90932a92020-02-12 14:33:03 +010073 ret = type->plugin->store(ctx, type, value, value_len, options, get_prefix, parser, format,
Michal Vasko004d3152020-06-11 19:59:22 +020074 tree ? (void *)node : (void *)node->schema, tree, &node->value, NULL, &err);
Michal Vasko90932a92020-02-12 14:33:03 +010075 if (ret && (ret != LY_EINCOMPLETE)) {
Radek Krejci73dead22019-07-11 16:46:16 +020076 if (err) {
Michal Vasko3544d1e2020-05-27 11:17:51 +020077 /* node may not be connected yet so use the schema node */
Michal Vaskof872e202020-05-27 11:49:06 +020078 if (!node->parent && lysc_data_parent(node->schema)) {
79 LOGVAL(ctx, LY_VLOG_LYSC, node->schema, err->vecode, err->msg);
80 } else {
81 LOGVAL(ctx, LY_VLOG_LYD, node, err->vecode, err->msg);
82 }
Radek Krejci73dead22019-07-11 16:46:16 +020083 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +020084 }
Radek Krejci73dead22019-07-11 16:46:16 +020085 goto error;
Michal Vasko90932a92020-02-12 14:33:03 +010086 } else if (dynamic) {
87 *dynamic = 0;
Radek Krejci084289f2019-07-09 17:35:30 +020088 }
89
90error:
91 return ret;
92}
93
Michal Vasko00cbf532020-06-15 13:58:47 +020094/* similar to lyd_value_parse except can be used just to store the value, hence also does not support a second call */
Michal Vasko004d3152020-06-11 19:59:22 +020095LY_ERR
Michal Vasko90932a92020-02-12 14:33:03 +010096lyd_value_store(struct lyd_value *val, const struct lysc_node *schema, const char *value, size_t value_len, int *dynamic,
97 ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format)
98{
99 LY_ERR ret = LY_SUCCESS;
100 struct ly_err_item *err = NULL;
101 struct ly_ctx *ctx;
102 struct lysc_type *type;
103 int options = LY_TYPE_OPTS_STORE | LY_TYPE_OPTS_INCOMPLETE_DATA | (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0);
104
105 assert(val && schema && (schema->nodetype & LYD_NODE_TERM));
106
107 ctx = schema->module->ctx;
108 type = ((struct lysc_node_leaf *)schema)->type;
109 val->realtype = type;
110 ret = type->plugin->store(ctx, type, value, value_len, options, get_prefix, parser, format, (void *)schema, NULL,
111 val, NULL, &err);
112 if (ret == LY_EINCOMPLETE) {
113 /* this is fine, we do not need it resolved */
114 ret = LY_SUCCESS;
115 } else if (ret && err) {
116 ly_err_print(err);
117 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
118 ly_err_free(err);
119 }
120 if (!ret && dynamic) {
121 *dynamic = 0;
122 }
123
124 return ret;
125}
126
Radek Krejci38d85362019-09-05 16:26:38 +0200127LY_ERR
Michal Vasko41586352020-07-13 13:54:25 +0200128lyd_value_parse_meta(const struct ly_ctx *ctx, struct lyd_meta *meta, const char *value, size_t value_len, int *dynamic,
Michal Vasko8d544252020-03-02 10:19:52 +0100129 int second, ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format,
Michal Vaskof03ed032020-03-04 13:31:44 +0100130 const struct lysc_node *ctx_snode, const struct lyd_node *tree)
Radek Krejci38d85362019-09-05 16:26:38 +0200131{
Michal Vasko90932a92020-02-12 14:33:03 +0100132 LY_ERR ret = LY_SUCCESS;
Radek Krejci38d85362019-09-05 16:26:38 +0200133 struct ly_err_item *err = NULL;
Radek Krejci38d85362019-09-05 16:26:38 +0200134 struct lyext_metadata *ant;
135 int options = LY_TYPE_OPTS_STORE | (second ? LY_TYPE_OPTS_SECOND_CALL : 0) |
Michal Vaskof03ed032020-03-04 13:31:44 +0100136 (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci38d85362019-09-05 16:26:38 +0200137
Michal Vasko9f96a052020-03-10 09:41:45 +0100138 assert(ctx && meta && ((tree && meta->parent) || ctx_snode));
Michal Vasko8d544252020-03-02 10:19:52 +0100139
Michal Vasko9f96a052020-03-10 09:41:45 +0100140 ant = meta->annotation->data;
Radek Krejci38d85362019-09-05 16:26:38 +0200141
142 if (!second) {
Michal Vasko9f96a052020-03-10 09:41:45 +0100143 meta->value.realtype = ant->type;
Radek Krejci38d85362019-09-05 16:26:38 +0200144 }
Michal Vasko90932a92020-02-12 14:33:03 +0100145 ret = ant->type->plugin->store(ctx, ant->type, value, value_len, options, get_prefix, parser, format,
Michal Vasko9f96a052020-03-10 09:41:45 +0100146 tree ? (void *)meta->parent : (void *)ctx_snode, tree, &meta->value, NULL, &err);
Michal Vasko90932a92020-02-12 14:33:03 +0100147 if (ret && (ret != LY_EINCOMPLETE)) {
Radek Krejci38d85362019-09-05 16:26:38 +0200148 if (err) {
149 ly_err_print(err);
150 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
151 ly_err_free(err);
152 }
153 goto error;
Michal Vasko90932a92020-02-12 14:33:03 +0100154 } else if (dynamic) {
155 *dynamic = 0;
Radek Krejci38d85362019-09-05 16:26:38 +0200156 }
157
158error:
159 return ret;
160}
161
Radek Krejci084289f2019-07-09 17:35:30 +0200162API LY_ERR
Michal Vasko44685da2020-03-17 15:38:06 +0100163lys_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 +0200164 ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format)
165{
166 LY_ERR rc = LY_SUCCESS;
167 struct ly_err_item *err = NULL;
168 struct lysc_type *type;
Radek Krejci084289f2019-07-09 17:35:30 +0200169
170 LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
171
172 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
173 LOGARG(ctx, node);
174 return LY_EINVAL;
175 }
176
177 type = ((struct lysc_node_leaf*)node)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200178 /* just validate, no storing of enything */
179 rc = type->plugin->store(ctx ? ctx : node->module->ctx, type, value, value_len, LY_TYPE_OPTS_INCOMPLETE_DATA,
180 get_prefix, get_prefix_data, format, node, NULL, NULL, NULL, &err);
181 if (rc == LY_EINCOMPLETE) {
182 /* actually success since we do not provide the context tree and call validation with
183 * LY_TYPE_OPTS_INCOMPLETE_DATA */
184 rc = LY_SUCCESS;
185 } else if (rc && err) {
186 if (ctx) {
187 /* log only in case the ctx was provided as input parameter */
188 ly_err_print(err);
189 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
Radek Krejci084289f2019-07-09 17:35:30 +0200190 }
Radek Krejci73dead22019-07-11 16:46:16 +0200191 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200192 }
193
194 return rc;
195}
196
197API LY_ERR
Michal Vasko44685da2020-03-17 15:38:06 +0100198lyd_value_validate(const struct ly_ctx *ctx, const struct lyd_node_term *node, const char *value, size_t value_len,
Michal Vasko3701af52020-08-03 14:29:38 +0200199 ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format,
200 const struct lyd_node *tree, struct lysc_type **realtype)
Radek Krejci084289f2019-07-09 17:35:30 +0200201{
202 LY_ERR rc;
203 struct ly_err_item *err = NULL;
204 struct lysc_type *type;
Michal Vasko3701af52020-08-03 14:29:38 +0200205 struct lyd_value val = {0};
206 int options = (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA) | (realtype ? LY_TYPE_OPTS_STORE : 0);
Radek Krejci084289f2019-07-09 17:35:30 +0200207
208 LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
209
210 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200211 rc = type->plugin->store(ctx ? ctx : node->schema->module->ctx, type, value, value_len, options,
Michal Vaskof03ed032020-03-04 13:31:44 +0100212 get_prefix, get_prefix_data, format, tree ? (void*)node : (void*)node->schema, tree,
Michal Vasko3701af52020-08-03 14:29:38 +0200213 &val, NULL, &err);
Radek Krejci73dead22019-07-11 16:46:16 +0200214 if (rc == LY_EINCOMPLETE) {
215 return rc;
216 } else if (rc) {
217 if (err) {
218 if (ctx) {
219 ly_err_print(err);
220 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
Radek Krejci084289f2019-07-09 17:35:30 +0200221 }
Radek Krejci73dead22019-07-11 16:46:16 +0200222 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200223 }
Radek Krejci73dead22019-07-11 16:46:16 +0200224 return rc;
Radek Krejci084289f2019-07-09 17:35:30 +0200225 }
226
Michal Vasko3701af52020-08-03 14:29:38 +0200227 if (realtype) {
228 *realtype = val.realtype;
229 }
230
231 type->plugin->free(ctx ? ctx : node->schema->module->ctx, &val);
Radek Krejci084289f2019-07-09 17:35:30 +0200232 return LY_SUCCESS;
233}
234
235API LY_ERR
236lyd_value_compare(const struct lyd_node_term *node, const char *value, size_t value_len,
Michal Vaskof03ed032020-03-04 13:31:44 +0100237 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 +0200238{
239 LY_ERR ret = LY_SUCCESS, rc;
240 struct ly_err_item *err = NULL;
241 struct ly_ctx *ctx;
242 struct lysc_type *type;
Radek Krejci084289f2019-07-09 17:35:30 +0200243 struct lyd_value data = {0};
Michal Vaskof03ed032020-03-04 13:31:44 +0100244 int options = LY_TYPE_OPTS_STORE | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci084289f2019-07-09 17:35:30 +0200245
246 LY_CHECK_ARG_RET(node ? node->schema->module->ctx : NULL, node, value, LY_EINVAL);
247
248 ctx = node->schema->module->ctx;
249 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200250 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 +0100251 tree, &data, NULL, &err);
Radek Krejci73dead22019-07-11 16:46:16 +0200252 if (rc == LY_EINCOMPLETE) {
253 ret = rc;
254 /* continue with comparing, just remember what to return if storing is ok */
255 } else if (rc) {
256 /* value to compare is invalid */
257 ret = LY_EINVAL;
258 if (err) {
259 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200260 }
Radek Krejci73dead22019-07-11 16:46:16 +0200261 goto cleanup;
Radek Krejci084289f2019-07-09 17:35:30 +0200262 }
263
264 /* compare data */
Radek Krejci5af04842019-07-12 11:32:07 +0200265 if (type->plugin->compare(&node->value, &data)) {
266 /* do not assign it directly from the compare callback to keep possible LY_EINCOMPLETE from validation */
Michal Vaskob3ddccb2020-07-09 15:43:05 +0200267 ret = LY_ENOT;
Radek Krejci5af04842019-07-12 11:32:07 +0200268 }
Radek Krejci084289f2019-07-09 17:35:30 +0200269
270cleanup:
Radek Krejci62903c32019-07-15 14:42:05 +0200271 type->plugin->free(ctx, &data);
Radek Krejci084289f2019-07-09 17:35:30 +0200272
273 return ret;
274}
275
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200276API const char *
277lyd_value2str(const struct lyd_node_term *node, int *dynamic)
278{
279 LY_CHECK_ARG_RET(node ? node->schema->module->ctx : NULL, node, dynamic, NULL);
280
281 return node->value.realtype->plugin->print(&node->value, LYD_JSON, json_print_get_prefix, NULL, dynamic);
282}
283
284API const char *
Michal Vasko9f96a052020-03-10 09:41:45 +0100285lyd_meta2str(const struct lyd_meta *meta, int *dynamic)
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200286{
Michal Vasko9f96a052020-03-10 09:41:45 +0100287 LY_CHECK_ARG_RET(meta ? meta->parent->schema->module->ctx : NULL, meta, dynamic, NULL);
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200288
Michal Vasko9f96a052020-03-10 09:41:45 +0100289 return meta->value.realtype->plugin->print(&meta->value, LYD_JSON, json_print_get_prefix, NULL, dynamic);
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200290}
291
Radek Krejci7931b192020-06-25 17:05:03 +0200292static LYD_FORMAT
Michal Vasko63f3d842020-07-08 10:10:14 +0200293lyd_parse_get_format(const struct ly_in *in, LYD_FORMAT format)
Radek Krejcie7b95092019-05-15 11:03:07 +0200294{
Radek Krejcie7b95092019-05-15 11:03:07 +0200295
Radek Krejci7931b192020-06-25 17:05:03 +0200296 if (!format && in->type == LY_IN_FILEPATH) {
Radek Krejcie7b95092019-05-15 11:03:07 +0200297 /* unknown format - try to detect it from filename's suffix */
Radek Krejci7931b192020-06-25 17:05:03 +0200298 const char *path = in->method.fpath.filepath;
299 size_t len = strlen(path);
Radek Krejcie7b95092019-05-15 11:03:07 +0200300
301 /* ignore trailing whitespaces */
302 for (; len > 0 && isspace(path[len - 1]); len--);
303
304 if (len >= 5 && !strncmp(&path[len - 4], ".xml", 4)) {
305 format = LYD_XML;
306#if 0
307 } else if (len >= 6 && !strncmp(&path[len - 5], ".json", 5)) {
308 format = LYD_JSON;
Radek Krejci7931b192020-06-25 17:05:03 +0200309#endif
Radek Krejcie7b95092019-05-15 11:03:07 +0200310 } else if (len >= 5 && !strncmp(&path[len - 4], ".lyb", 4)) {
311 format = LYD_LYB;
Radek Krejci7931b192020-06-25 17:05:03 +0200312 } /* else still unknown */
Radek Krejcie7b95092019-05-15 11:03:07 +0200313 }
314
Radek Krejci7931b192020-06-25 17:05:03 +0200315 return format;
316}
Radek Krejcie7b95092019-05-15 11:03:07 +0200317
Radek Krejci7931b192020-06-25 17:05:03 +0200318API LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +0200319lyd_parse_data(const struct ly_ctx *ctx, struct ly_in *in, LYD_FORMAT format, int parse_options, int validate_options,
320 struct lyd_node **tree)
Radek Krejci7931b192020-06-25 17:05:03 +0200321{
322 LY_CHECK_ARG_RET(ctx, ctx, in, tree, LY_EINVAL);
323 LY_CHECK_ARG_RET(ctx, !(parse_options & ~LYD_PARSE_OPTS_MASK), LY_EINVAL);
324 LY_CHECK_ARG_RET(ctx, !(validate_options & ~LYD_VALIDATE_OPTS_MASK), LY_EINVAL);
325
326 format = lyd_parse_get_format(in, format);
327 LY_CHECK_ARG_RET(ctx, format, LY_EINVAL);
328
Michal Vasko63f3d842020-07-08 10:10:14 +0200329 /* remember input position */
330 in->func_start = in->current;
Radek Krejci7931b192020-06-25 17:05:03 +0200331
332 switch (format) {
333 case LYD_XML:
Michal Vasko63f3d842020-07-08 10:10:14 +0200334 return lyd_parse_xml_data(ctx, in, parse_options, validate_options, tree);
Radek Krejci7931b192020-06-25 17:05:03 +0200335#if 0
336 case LYD_JSON:
Michal Vasko63f3d842020-07-08 10:10:14 +0200337 return lyd_parse_json_data(ctx, in, parse_options, validate_options, tree);
Radek Krejci7931b192020-06-25 17:05:03 +0200338#endif
339 case LYD_LYB:
Michal Vasko63f3d842020-07-08 10:10:14 +0200340 return lyd_parse_lyb_data(ctx, in, parse_options, validate_options, tree);
Radek Krejci7931b192020-06-25 17:05:03 +0200341 case LYD_SCHEMA:
342 LOGINT_RET(ctx);
343 }
344
345 /* TODO move here the top-level validation from parser_xml.c's lyd_parse_xml_data() and make
346 * it common for all the lyd_parse_*_data() functions */
347
348 LOGINT_RET(ctx);
349}
350
351API LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +0200352lyd_parse_data_mem(const struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int parse_options, int validate_options,
353 struct lyd_node **tree)
Radek Krejci7931b192020-06-25 17:05:03 +0200354{
355 LY_ERR ret;
356 struct ly_in *in;
357
358 LY_CHECK_RET(ly_in_new_memory(data, &in));
359 ret = lyd_parse_data(ctx, in, format, parse_options, validate_options, tree);
360
361 ly_in_free(in, 0);
362 return ret;
363}
364
365API LY_ERR
Michal Vaskob104f112020-07-17 09:54:54 +0200366lyd_parse_data_fd(const struct ly_ctx *ctx, int fd, LYD_FORMAT format, int parse_options, int validate_options,
367 struct lyd_node **tree)
Radek Krejci7931b192020-06-25 17:05:03 +0200368{
369 LY_ERR ret;
370 struct ly_in *in;
371
372 LY_CHECK_RET(ly_in_new_fd(fd, &in));
373 ret = lyd_parse_data(ctx, in, format, parse_options, validate_options, tree);
374
375 ly_in_free(in, 0);
376 return ret;
377}
378
379API LY_ERR
Michal Vaskob104f112020-07-17 09:54:54 +0200380lyd_parse_data_path(const struct ly_ctx *ctx, const char *path, LYD_FORMAT format, int parse_options,
381 int validate_options, struct lyd_node **tree)
Radek Krejci7931b192020-06-25 17:05:03 +0200382{
383 LY_ERR ret;
384 struct ly_in *in;
385
386 LY_CHECK_RET(ly_in_new_filepath(path, 0, &in));
387 ret = lyd_parse_data(ctx, in, format, parse_options, validate_options, tree);
388
389 ly_in_free(in, 0);
390 return ret;
391}
392
Radek Krejci7931b192020-06-25 17:05:03 +0200393API LY_ERR
394lyd_parse_rpc(const struct ly_ctx *ctx, struct ly_in *in, LYD_FORMAT format, struct lyd_node **tree, struct lyd_node **op)
395{
396 LY_CHECK_ARG_RET(ctx, ctx, in, tree, LY_EINVAL);
397
398 format = lyd_parse_get_format(in, format);
399 LY_CHECK_ARG_RET(ctx, format, LY_EINVAL);
400
Michal Vasko63f3d842020-07-08 10:10:14 +0200401 /* remember input position */
402 in->func_start = in->current;
403
Radek Krejci7931b192020-06-25 17:05:03 +0200404 switch (format) {
405 case LYD_XML:
Michal Vasko63f3d842020-07-08 10:10:14 +0200406 return lyd_parse_xml_rpc(ctx, in, tree, op);
Radek Krejci7931b192020-06-25 17:05:03 +0200407#if 0
408 case LYD_JSON:
Michal Vasko63f3d842020-07-08 10:10:14 +0200409 return lyd_parse_json_rpc(ctx, in, tree, op);
Radek Krejci7931b192020-06-25 17:05:03 +0200410#endif
411 case LYD_LYB:
Michal Vasko63f3d842020-07-08 10:10:14 +0200412 return lyd_parse_lyb_rpc(ctx, in, tree, op);
Radek Krejci7931b192020-06-25 17:05:03 +0200413 case LYD_SCHEMA:
414 LOGINT_RET(ctx);
415 }
416
417 LOGINT_RET(ctx);
418}
419
420API LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +0200421lyd_parse_reply(const struct lyd_node *request, struct ly_in *in, LYD_FORMAT format, struct lyd_node **tree,
422 struct lyd_node **op)
Radek Krejci7931b192020-06-25 17:05:03 +0200423{
424 LY_CHECK_ARG_RET(NULL, request, LY_EINVAL);
425 LY_CHECK_ARG_RET(LYD_NODE_CTX(request), in, tree, LY_EINVAL);
426
427 format = lyd_parse_get_format(in, format);
428 LY_CHECK_ARG_RET(LYD_NODE_CTX(request), format, LY_EINVAL);
429
Michal Vasko63f3d842020-07-08 10:10:14 +0200430 /* remember input position */
431 in->func_start = in->current;
432
Radek Krejci7931b192020-06-25 17:05:03 +0200433 switch (format) {
434 case LYD_XML:
Michal Vasko63f3d842020-07-08 10:10:14 +0200435 return lyd_parse_xml_reply(request, in, tree, op);
Radek Krejci7931b192020-06-25 17:05:03 +0200436#if 0
437 case LYD_JSON:
Michal Vasko63f3d842020-07-08 10:10:14 +0200438 return lyd_parse_json_reply(request, in, tree, op);
Radek Krejci7931b192020-06-25 17:05:03 +0200439#endif
440 case LYD_LYB:
Michal Vasko63f3d842020-07-08 10:10:14 +0200441 return lyd_parse_lyb_reply(request, in, tree, op);
Radek Krejci7931b192020-06-25 17:05:03 +0200442 case LYD_SCHEMA:
443 LOGINT_RET(LYD_NODE_CTX(request));
444 }
445
446 LOGINT_RET(LYD_NODE_CTX(request));
447}
448
449API LY_ERR
450lyd_parse_notif(const struct ly_ctx *ctx, struct ly_in *in, LYD_FORMAT format, struct lyd_node **tree, struct lyd_node **ntf)
451{
452 LY_CHECK_ARG_RET(ctx, ctx, in, tree, LY_EINVAL);
453
454 format = lyd_parse_get_format(in, format);
455 LY_CHECK_ARG_RET(ctx, format, LY_EINVAL);
456
Michal Vasko63f3d842020-07-08 10:10:14 +0200457 /* remember input position */
458 in->func_start = in->current;
459
Radek Krejci7931b192020-06-25 17:05:03 +0200460 switch (format) {
461 case LYD_XML:
Michal Vasko63f3d842020-07-08 10:10:14 +0200462 return lyd_parse_xml_notif(ctx, in, tree, ntf);
Radek Krejci7931b192020-06-25 17:05:03 +0200463#if 0
464 case LYD_JSON:
Michal Vasko63f3d842020-07-08 10:10:14 +0200465 return lyd_parse_json_notif(ctx, in, tree, ntf);
Radek Krejci7931b192020-06-25 17:05:03 +0200466#endif
467 case LYD_LYB:
Michal Vasko63f3d842020-07-08 10:10:14 +0200468 return lyd_parse_lyb_notif(ctx, in, tree, ntf);
Radek Krejci7931b192020-06-25 17:05:03 +0200469 case LYD_SCHEMA:
470 LOGINT_RET(ctx);
471 }
472
473 LOGINT_RET(ctx);
Radek Krejcie7b95092019-05-15 11:03:07 +0200474}
Radek Krejci084289f2019-07-09 17:35:30 +0200475
Michal Vasko90932a92020-02-12 14:33:03 +0100476LY_ERR
477lyd_create_term(const struct lysc_node *schema, const char *value, size_t value_len, int *dynamic,
478 ly_clb_resolve_prefix get_prefix, void *prefix_data, LYD_FORMAT format, struct lyd_node **node)
479{
480 LY_ERR ret;
481 struct lyd_node_term *term;
482
Michal Vasko9b368d32020-02-14 13:53:31 +0100483 assert(schema->nodetype & LYD_NODE_TERM);
484
Michal Vasko90932a92020-02-12 14:33:03 +0100485 term = calloc(1, sizeof *term);
486 LY_CHECK_ERR_RET(!term, LOGMEM(schema->module->ctx), LY_EMEM);
487
488 term->schema = schema;
489 term->prev = (struct lyd_node *)term;
Michal Vasko9b368d32020-02-14 13:53:31 +0100490 term->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100491
492 ret = lyd_value_parse(term, value, value_len, dynamic, 0, get_prefix, prefix_data, format, NULL);
493 if (ret && (ret != LY_EINCOMPLETE)) {
494 free(term);
495 return ret;
496 }
Michal Vasko9b368d32020-02-14 13:53:31 +0100497 lyd_hash((struct lyd_node *)term);
498
499 *node = (struct lyd_node *)term;
500 return ret;
501}
502
503LY_ERR
504lyd_create_term2(const struct lysc_node *schema, const struct lyd_value *val, struct lyd_node **node)
505{
506 LY_ERR ret;
507 struct lyd_node_term *term;
508 struct lysc_type *type;
509
510 assert(schema->nodetype & LYD_NODE_TERM);
Michal Vasko00cbf532020-06-15 13:58:47 +0200511 assert(val && val->realtype);
Michal Vasko9b368d32020-02-14 13:53:31 +0100512
513 term = calloc(1, sizeof *term);
514 LY_CHECK_ERR_RET(!term, LOGMEM(schema->module->ctx), LY_EMEM);
515
516 term->schema = schema;
517 term->prev = (struct lyd_node *)term;
518 term->flags = LYD_NEW;
519
520 type = ((struct lysc_node_leaf *)schema)->type;
521 ret = type->plugin->duplicate(schema->module->ctx, val, &term->value);
522 if (ret) {
523 LOGERR(schema->module->ctx, ret, "Value duplication failed.");
524 free(term);
525 return ret;
526 }
Michal Vasko00cbf532020-06-15 13:58:47 +0200527 term->value.realtype = val->realtype;
Michal Vasko9b368d32020-02-14 13:53:31 +0100528 lyd_hash((struct lyd_node *)term);
Michal Vasko90932a92020-02-12 14:33:03 +0100529
530 *node = (struct lyd_node *)term;
531 return ret;
532}
533
534LY_ERR
535lyd_create_inner(const struct lysc_node *schema, struct lyd_node **node)
536{
537 struct lyd_node_inner *in;
538
Michal Vasko9b368d32020-02-14 13:53:31 +0100539 assert(schema->nodetype & LYD_NODE_INNER);
540
Michal Vasko90932a92020-02-12 14:33:03 +0100541 in = calloc(1, sizeof *in);
542 LY_CHECK_ERR_RET(!in, LOGMEM(schema->module->ctx), LY_EMEM);
543
544 in->schema = schema;
545 in->prev = (struct lyd_node *)in;
Michal Vasko9b368d32020-02-14 13:53:31 +0100546 in->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100547
Michal Vasko9b368d32020-02-14 13:53:31 +0100548 /* do not hash list with keys, we need them for the hash */
549 if ((schema->nodetype != LYS_LIST) || (schema->flags & LYS_KEYLESS)) {
550 lyd_hash((struct lyd_node *)in);
551 }
Michal Vasko90932a92020-02-12 14:33:03 +0100552
553 *node = (struct lyd_node *)in;
554 return LY_SUCCESS;
555}
556
Michal Vasko90932a92020-02-12 14:33:03 +0100557LY_ERR
Michal Vasko004d3152020-06-11 19:59:22 +0200558lyd_create_list(const struct lysc_node *schema, const struct ly_path_predicate *predicates, struct lyd_node **node)
Michal Vasko90932a92020-02-12 14:33:03 +0100559{
560 LY_ERR ret = LY_SUCCESS;
Michal Vasko90932a92020-02-12 14:33:03 +0100561 struct lyd_node *list = NULL, *key;
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200562 LY_ARRAY_COUNT_TYPE u;
Michal Vasko90932a92020-02-12 14:33:03 +0100563
Michal Vasko004d3152020-06-11 19:59:22 +0200564 assert((schema->nodetype == LYS_LIST) && !(schema->flags & LYS_KEYLESS));
Michal Vasko90932a92020-02-12 14:33:03 +0100565
566 /* create list */
567 LY_CHECK_GOTO(ret = lyd_create_inner(schema, &list), cleanup);
568
Michal Vasko90932a92020-02-12 14:33:03 +0100569 /* create and insert all the keys */
Michal Vasko004d3152020-06-11 19:59:22 +0200570 LY_ARRAY_FOR(predicates, u) {
571 LY_CHECK_GOTO(ret = lyd_create_term2(predicates[u].key, &predicates[u].value, &key), cleanup);
Michal Vasko90932a92020-02-12 14:33:03 +0100572 lyd_insert_node(list, NULL, key);
573 }
574
Michal Vasko9b368d32020-02-14 13:53:31 +0100575 /* hash having all the keys */
576 lyd_hash(list);
577
Michal Vasko90932a92020-02-12 14:33:03 +0100578 /* success */
579 *node = list;
580 list = NULL;
581
582cleanup:
583 lyd_free_tree(list);
Michal Vasko004d3152020-06-11 19:59:22 +0200584 return ret;
585}
586
587static LY_ERR
588lyd_create_list2(const struct lysc_node *schema, const char *keys, size_t keys_len, struct lyd_node **node)
589{
590 LY_ERR ret = LY_SUCCESS;
591 struct lyxp_expr *expr = NULL;
592 uint16_t exp_idx = 0;
593 enum ly_path_pred_type pred_type = 0;
594 struct ly_path_predicate *predicates = NULL;
595
596 /* parse keys */
Michal Vasko6b26e742020-07-17 15:02:10 +0200597 LY_CHECK_GOTO(ret = ly_path_parse_predicate(schema->module->ctx, NULL, keys, keys_len, LY_PATH_PREFIX_OPTIONAL,
Michal Vasko004d3152020-06-11 19:59:22 +0200598 LY_PATH_PRED_KEYS, &expr), cleanup);
599
600 /* compile them */
Michal Vasko6b26e742020-07-17 15:02:10 +0200601 LY_CHECK_GOTO(ret = ly_path_compile_predicate(schema->module->ctx, NULL, NULL, schema, expr, &exp_idx,
602 lydjson_resolve_prefix, NULL, LYD_JSON, &predicates, &pred_type), cleanup);
Michal Vasko004d3152020-06-11 19:59:22 +0200603
604 /* create the list node */
605 LY_CHECK_GOTO(ret = lyd_create_list(schema, predicates, node), cleanup);
606
607cleanup:
608 lyxp_expr_free(schema->module->ctx, expr);
609 ly_path_predicates_free(schema->module->ctx, pred_type, NULL, predicates);
Michal Vasko90932a92020-02-12 14:33:03 +0100610 return ret;
611}
612
613LY_ERR
614lyd_create_any(const struct lysc_node *schema, const void *value, LYD_ANYDATA_VALUETYPE value_type, struct lyd_node **node)
615{
616 struct lyd_node_any *any;
617
Michal Vasko9b368d32020-02-14 13:53:31 +0100618 assert(schema->nodetype & LYD_NODE_ANY);
619
Michal Vasko90932a92020-02-12 14:33:03 +0100620 any = calloc(1, sizeof *any);
621 LY_CHECK_ERR_RET(!any, LOGMEM(schema->module->ctx), LY_EMEM);
622
623 any->schema = schema;
624 any->prev = (struct lyd_node *)any;
Michal Vasko9b368d32020-02-14 13:53:31 +0100625 any->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100626
627 any->value.xml = value;
628 any->value_type = value_type;
Michal Vasko9b368d32020-02-14 13:53:31 +0100629 lyd_hash((struct lyd_node *)any);
Michal Vasko90932a92020-02-12 14:33:03 +0100630
631 *node = (struct lyd_node *)any;
632 return LY_SUCCESS;
633}
634
Michal Vasko52927e22020-03-16 17:26:14 +0100635LY_ERR
636lyd_create_opaq(const struct ly_ctx *ctx, const char *name, size_t name_len, const char *value, size_t value_len,
637 int *dynamic, LYD_FORMAT format, struct ly_prefix *val_prefs, const char *prefix, size_t pref_len,
638 const char *ns, struct lyd_node **node)
639{
640 struct lyd_node_opaq *opaq;
641
642 assert(ctx && name && name_len && ns);
643
644 if (!value_len) {
645 value = "";
646 }
647
648 opaq = calloc(1, sizeof *opaq);
649 LY_CHECK_ERR_RET(!opaq, LOGMEM(ctx), LY_EMEM);
650
651 opaq->prev = (struct lyd_node *)opaq;
652
653 opaq->name = lydict_insert(ctx, name, name_len);
654 opaq->format = format;
655 if (pref_len) {
656 opaq->prefix.pref = lydict_insert(ctx, prefix, pref_len);
657 }
658 opaq->prefix.ns = lydict_insert(ctx, ns, 0);
659 opaq->val_prefs = val_prefs;
660 if (dynamic && *dynamic) {
661 opaq->value = lydict_insert_zc(ctx, (char *)value);
662 *dynamic = 0;
663 } else {
664 opaq->value = lydict_insert(ctx, value, value_len);
665 }
666 opaq->ctx = ctx;
667
668 *node = (struct lyd_node *)opaq;
669 return LY_SUCCESS;
670}
671
Michal Vasko3a41dff2020-07-15 14:30:28 +0200672API LY_ERR
673lyd_new_inner(struct lyd_node *parent, const struct lys_module *module, const char *name, struct lyd_node **node)
Michal Vasko013a8182020-03-03 10:46:53 +0100674{
675 struct lyd_node *ret = NULL;
676 const struct lysc_node *schema;
677 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
678
Michal Vasko6027eb92020-07-15 16:37:30 +0200679 LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
Michal Vasko013a8182020-03-03 10:46:53 +0100680
Michal Vaskof03ed032020-03-04 13:31:44 +0100681 if (!module) {
682 module = parent->schema->module;
683 }
684
Michal Vasko3a41dff2020-07-15 14:30:28 +0200685 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0,
686 LYS_CONTAINER | LYS_NOTIF | LYS_RPC | LYS_ACTION, 0);
687 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Inner node (and not a list) \"%s\" not found.", name), LY_ENOTFOUND);
Michal Vasko013a8182020-03-03 10:46:53 +0100688
Michal Vasko3a41dff2020-07-15 14:30:28 +0200689 LY_CHECK_RET(lyd_create_inner(schema, &ret));
690 if (parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100691 lyd_insert_node(parent, NULL, ret);
692 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200693
694 if (node) {
695 *node = ret;
696 }
697 return LY_SUCCESS;
Michal Vasko013a8182020-03-03 10:46:53 +0100698}
699
Michal Vasko3a41dff2020-07-15 14:30:28 +0200700API LY_ERR
701lyd_new_list(struct lyd_node *parent, const struct lys_module *module, const char *name, struct lyd_node **node, ...)
Michal Vasko013a8182020-03-03 10:46:53 +0100702{
703 struct lyd_node *ret = NULL, *key;
704 const struct lysc_node *schema, *key_s;
705 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
706 va_list ap;
707 const char *key_val;
708 LY_ERR rc = LY_SUCCESS;
709
Michal Vasko6027eb92020-07-15 16:37:30 +0200710 LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
Michal Vasko013a8182020-03-03 10:46:53 +0100711
Michal Vaskof03ed032020-03-04 13:31:44 +0100712 if (!module) {
713 module = parent->schema->module;
714 }
715
Michal Vasko013a8182020-03-03 10:46:53 +0100716 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, 0);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200717 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), LY_ENOTFOUND);
Michal Vasko013a8182020-03-03 10:46:53 +0100718
719 /* create list inner node */
Michal Vasko3a41dff2020-07-15 14:30:28 +0200720 LY_CHECK_RET(lyd_create_inner(schema, &ret));
Michal Vasko013a8182020-03-03 10:46:53 +0100721
Michal Vasko3a41dff2020-07-15 14:30:28 +0200722 va_start(ap, node);
Michal Vasko013a8182020-03-03 10:46:53 +0100723
724 /* create and insert all the keys */
725 for (key_s = lysc_node_children(schema, 0); key_s && (key_s->flags & LYS_KEY); key_s = key_s->next) {
726 key_val = va_arg(ap, const char *);
727
Michal Vaskof03ed032020-03-04 13:31:44 +0100728 rc = lyd_create_term(key_s, key_val, key_val ? strlen(key_val) : 0, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &key);
Michal Vaskocbff3e92020-05-27 12:56:41 +0200729 LY_CHECK_GOTO(rc && (rc != LY_EINCOMPLETE), cleanup);
730 rc = LY_SUCCESS;
Michal Vasko013a8182020-03-03 10:46:53 +0100731 lyd_insert_node(ret, NULL, key);
732 }
733
Michal Vasko013a8182020-03-03 10:46:53 +0100734 if (parent) {
735 lyd_insert_node(parent, NULL, ret);
736 }
737
738cleanup:
Michal Vasko3a41dff2020-07-15 14:30:28 +0200739 va_end(ap);
Michal Vasko013a8182020-03-03 10:46:53 +0100740 if (rc) {
741 lyd_free_tree(ret);
742 ret = NULL;
Michal Vasko3a41dff2020-07-15 14:30:28 +0200743 } else if (node) {
744 *node = ret;
Michal Vasko013a8182020-03-03 10:46:53 +0100745 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200746 return rc;
Michal Vasko013a8182020-03-03 10:46:53 +0100747}
748
Michal Vasko3a41dff2020-07-15 14:30:28 +0200749API LY_ERR
750lyd_new_list2(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *keys,
751 struct lyd_node **node)
Michal Vasko013a8182020-03-03 10:46:53 +0100752{
753 struct lyd_node *ret = NULL;
754 const struct lysc_node *schema;
755 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
756
Michal Vasko6027eb92020-07-15 16:37:30 +0200757 LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
Michal Vasko013a8182020-03-03 10:46:53 +0100758
Michal Vaskof03ed032020-03-04 13:31:44 +0100759 if (!module) {
760 module = parent->schema->module;
761 }
Michal Vasko004d3152020-06-11 19:59:22 +0200762 if (!keys) {
763 keys = "";
764 }
Michal Vaskof03ed032020-03-04 13:31:44 +0100765
Michal Vasko004d3152020-06-11 19:59:22 +0200766 /* find schema node */
Michal Vasko013a8182020-03-03 10:46:53 +0100767 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, 0);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200768 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), LY_ENOTFOUND);
Michal Vasko013a8182020-03-03 10:46:53 +0100769
Michal Vasko004d3152020-06-11 19:59:22 +0200770 if ((schema->flags & LYS_KEYLESS) && !keys[0]) {
771 /* key-less list */
Michal Vasko3a41dff2020-07-15 14:30:28 +0200772 LY_CHECK_RET(lyd_create_inner(schema, &ret));
Michal Vasko004d3152020-06-11 19:59:22 +0200773 } else {
774 /* create the list node */
Michal Vasko3a41dff2020-07-15 14:30:28 +0200775 LY_CHECK_RET(lyd_create_list2(schema, keys, strlen(keys), &ret));
Michal Vasko004d3152020-06-11 19:59:22 +0200776 }
Michal Vasko004d3152020-06-11 19:59:22 +0200777 if (parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100778 lyd_insert_node(parent, NULL, ret);
779 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200780
781 if (node) {
782 *node = ret;
783 }
784 return LY_SUCCESS;
Michal Vasko013a8182020-03-03 10:46:53 +0100785}
786
Michal Vasko3a41dff2020-07-15 14:30:28 +0200787API LY_ERR
788lyd_new_term(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str,
789 struct lyd_node **node)
Michal Vasko013a8182020-03-03 10:46:53 +0100790{
Michal Vaskocbff3e92020-05-27 12:56:41 +0200791 LY_ERR rc;
Michal Vasko013a8182020-03-03 10:46:53 +0100792 struct lyd_node *ret = NULL;
793 const struct lysc_node *schema;
794 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
795
Michal Vasko6027eb92020-07-15 16:37:30 +0200796 LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
Michal Vasko013a8182020-03-03 10:46:53 +0100797
Michal Vaskof03ed032020-03-04 13:31:44 +0100798 if (!module) {
799 module = parent->schema->module;
800 }
801
Michal Vasko013a8182020-03-03 10:46:53 +0100802 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_TERM, 0);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200803 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Term node \"%s\" not found.", name), LY_ENOTFOUND);
Michal Vasko013a8182020-03-03 10:46:53 +0100804
Michal Vaskocbff3e92020-05-27 12:56:41 +0200805 rc = lyd_create_term(schema, val_str, val_str ? strlen(val_str) : 0, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &ret);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200806 LY_CHECK_RET(rc && (rc != LY_EINCOMPLETE), rc);
Michal Vaskocbff3e92020-05-27 12:56:41 +0200807 if (parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100808 lyd_insert_node(parent, NULL, ret);
809 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200810
811 if (node) {
812 *node = ret;
813 }
814 return LY_SUCCESS;
Michal Vasko013a8182020-03-03 10:46:53 +0100815}
816
Michal Vasko3a41dff2020-07-15 14:30:28 +0200817API LY_ERR
Michal Vasko013a8182020-03-03 10:46:53 +0100818lyd_new_any(struct lyd_node *parent, const struct lys_module *module, const char *name, const void *value,
Michal Vasko3a41dff2020-07-15 14:30:28 +0200819 LYD_ANYDATA_VALUETYPE value_type, struct lyd_node **node)
Michal Vasko013a8182020-03-03 10:46:53 +0100820{
821 struct lyd_node *ret = NULL;
822 const struct lysc_node *schema;
823 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
824
Michal Vasko6027eb92020-07-15 16:37:30 +0200825 LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
Michal Vasko013a8182020-03-03 10:46:53 +0100826
Michal Vaskof03ed032020-03-04 13:31:44 +0100827 if (!module) {
828 module = parent->schema->module;
829 }
830
Michal Vasko013a8182020-03-03 10:46:53 +0100831 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_ANY, 0);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200832 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Any node \"%s\" not found.", name), LY_ENOTFOUND);
Michal Vasko013a8182020-03-03 10:46:53 +0100833
Michal Vasko3a41dff2020-07-15 14:30:28 +0200834 LY_CHECK_RET(lyd_create_any(schema, value, value_type, &ret));
835 if (parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100836 lyd_insert_node(parent, NULL, ret);
837 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200838
839 if (node) {
840 *node = ret;
841 }
842 return LY_SUCCESS;
Michal Vasko013a8182020-03-03 10:46:53 +0100843}
844
Michal Vasko4490d312020-06-16 13:08:55 +0200845/**
846 * @brief Update node value.
847 *
848 * @param[in] node Node to update.
849 * @param[in] value New value to set.
850 * @param[in] value_type Type of @p value for any node.
851 * @param[out] new_parent Set to @p node if the value was updated, otherwise set to NULL.
852 * @param[out] new_node Set to @p node if the value was updated, otherwise set to NULL.
853 * @return LY_ERR value.
854 */
Michal Vasko00cbf532020-06-15 13:58:47 +0200855static LY_ERR
856lyd_new_path_update(struct lyd_node *node, const void *value, LYD_ANYDATA_VALUETYPE value_type,
857 struct lyd_node **new_parent, struct lyd_node **new_node)
858{
859 LY_ERR ret = LY_SUCCESS;
860 struct lyd_node *new_any;
861
862 switch (node->schema->nodetype) {
863 case LYS_CONTAINER:
864 case LYS_NOTIF:
865 case LYS_RPC:
866 case LYS_ACTION:
867 case LYS_LIST:
868 case LYS_LEAFLIST:
869 /* if it exists, there is nothing to update */
870 *new_parent = NULL;
871 *new_node = NULL;
872 break;
873 case LYS_LEAF:
874 ret = lyd_change_term(node, value);
875 if ((ret == LY_SUCCESS) || (ret == LY_EEXIST)) {
876 /* there was an actual change (at least of the default flag) */
877 *new_parent = node;
878 *new_node = node;
879 ret = LY_SUCCESS;
880 } else if (ret == LY_ENOT) {
881 /* no change */
882 *new_parent = NULL;
883 *new_node = NULL;
884 ret = LY_SUCCESS;
885 } /* else error */
886 break;
887 case LYS_ANYDATA:
888 case LYS_ANYXML:
889 /* create a new any node */
890 LY_CHECK_RET(lyd_create_any(node->schema, value, value_type, &new_any));
891
892 /* compare with the existing one */
Michal Vasko8f359bf2020-07-28 10:41:15 +0200893 if (lyd_compare_single(node, new_any, 0)) {
Michal Vasko00cbf532020-06-15 13:58:47 +0200894 /* not equal, switch values (so that we can use generic node free) */
895 ((struct lyd_node_any *)new_any)->value = ((struct lyd_node_any *)node)->value;
896 ((struct lyd_node_any *)new_any)->value_type = ((struct lyd_node_any *)node)->value_type;
897 ((struct lyd_node_any *)node)->value.str = value;
898 ((struct lyd_node_any *)node)->value_type = value_type;
899
900 *new_parent = node;
901 *new_node = node;
902 } else {
903 /* they are equal */
904 *new_parent = NULL;
905 *new_node = NULL;
906 }
907 lyd_free_tree(new_any);
908 break;
909 default:
910 LOGINT(LYD_NODE_CTX(node));
911 ret = LY_EINT;
912 break;
913 }
914
915 return ret;
916}
917
Michal Vasko3a41dff2020-07-15 14:30:28 +0200918API LY_ERR
919lyd_new_meta(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str,
920 struct lyd_meta **meta)
Michal Vaskod86997b2020-05-26 15:19:54 +0200921{
922 struct lyd_meta *ret = NULL;
Michal Vasko00cbf532020-06-15 13:58:47 +0200923 const struct ly_ctx *ctx;
Michal Vaskod86997b2020-05-26 15:19:54 +0200924 const char *prefix, *tmp;
925 char *str;
926 size_t pref_len, name_len;
927
Michal Vasko3a41dff2020-07-15 14:30:28 +0200928 LY_CHECK_ARG_RET(NULL, parent, name, module || strchr(name, ':'), LY_EINVAL);
Michal Vasko00cbf532020-06-15 13:58:47 +0200929
930 ctx = LYD_NODE_CTX(parent);
Michal Vaskod86997b2020-05-26 15:19:54 +0200931
932 /* parse the name */
933 tmp = name;
934 if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
935 LOGERR(ctx, LY_EINVAL, "Metadata name \"%s\" is not valid.", name);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200936 return LY_EVALID;
Michal Vaskod86997b2020-05-26 15:19:54 +0200937 }
938
939 /* find the module */
940 if (prefix) {
Michal Vasko0b245382020-07-09 15:43:52 +0200941 str = strndup(prefix, pref_len);
Michal Vaskod86997b2020-05-26 15:19:54 +0200942 module = ly_ctx_get_module_implemented(ctx, str);
943 free(str);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200944 LY_CHECK_ERR_RET(!module, LOGERR(ctx, LY_EINVAL, "Module \"%.*s\" not found.", pref_len, prefix), LY_ENOTFOUND);
Michal Vaskod86997b2020-05-26 15:19:54 +0200945 }
946
947 /* set value if none */
948 if (!val_str) {
949 val_str = "";
950 }
951
Michal Vasko3a41dff2020-07-15 14:30:28 +0200952 LY_CHECK_RET(lyd_create_meta(parent, &ret, module, name, name_len, val_str, strlen(val_str), NULL,
953 lydjson_resolve_prefix, NULL, LYD_JSON, parent->schema));
954
955 if (meta) {
956 *meta = ret;
957 }
958 return LY_SUCCESS;
Michal Vaskod86997b2020-05-26 15:19:54 +0200959}
960
Michal Vasko3a41dff2020-07-15 14:30:28 +0200961API LY_ERR
Michal Vasko00cbf532020-06-15 13:58:47 +0200962lyd_new_opaq(struct lyd_node *parent, const struct ly_ctx *ctx, const char *name, const char *value,
Michal Vasko3a41dff2020-07-15 14:30:28 +0200963 const char *module_name, struct lyd_node **node)
Michal Vasko00cbf532020-06-15 13:58:47 +0200964{
965 struct lyd_node *ret = NULL;
966
Michal Vasko6027eb92020-07-15 16:37:30 +0200967 LY_CHECK_ARG_RET(ctx, parent || ctx, parent || node, name, module_name, LY_EINVAL);
Michal Vasko00cbf532020-06-15 13:58:47 +0200968
969 if (!ctx) {
970 ctx = LYD_NODE_CTX(parent);
971 }
972 if (!value) {
973 value = "";
974 }
975
Michal Vasko3a41dff2020-07-15 14:30:28 +0200976 LY_CHECK_RET(lyd_create_opaq(ctx, name, strlen(name), value, strlen(value), NULL, LYD_JSON, NULL, NULL, 0,
977 module_name, &ret));
978 if (parent) {
Michal Vasko00cbf532020-06-15 13:58:47 +0200979 lyd_insert_node(parent, NULL, ret);
980 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200981
982 if (node) {
983 *node = ret;
984 }
985 return LY_SUCCESS;
Michal Vasko00cbf532020-06-15 13:58:47 +0200986}
987
Michal Vasko3a41dff2020-07-15 14:30:28 +0200988API LY_ERR
989lyd_new_attr(struct lyd_node *parent, const char *module_name, const char *name, const char *val_str,
990 struct ly_attr **attr)
Michal Vasko00cbf532020-06-15 13:58:47 +0200991{
992 struct ly_attr *ret = NULL;
993 const struct ly_ctx *ctx;
994 const char *prefix, *tmp;
995 size_t pref_len, name_len;
996
Michal Vasko3a41dff2020-07-15 14:30:28 +0200997 LY_CHECK_ARG_RET(NULL, parent, !parent->schema, name, LY_EINVAL);
Michal Vasko00cbf532020-06-15 13:58:47 +0200998
999 ctx = LYD_NODE_CTX(parent);
1000
1001 /* parse the name */
1002 tmp = name;
1003 if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
1004 LOGERR(ctx, LY_EINVAL, "Metadata name \"%s\" is not valid.", name);
Michal Vasko3a41dff2020-07-15 14:30:28 +02001005 return LY_EVALID;
Michal Vasko00cbf532020-06-15 13:58:47 +02001006 }
1007
1008 /* set value if none */
1009 if (!val_str) {
1010 val_str = "";
1011 }
1012
Michal Vasko3a41dff2020-07-15 14:30:28 +02001013 LY_CHECK_RET(ly_create_attr(parent, &ret, ctx, name, name_len, val_str, strlen(val_str), NULL, LYD_JSON, NULL,
1014 prefix, pref_len, module_name));
1015
1016 if (attr) {
1017 *attr = ret;
1018 }
1019 return LY_SUCCESS;
Michal Vasko00cbf532020-06-15 13:58:47 +02001020}
1021
1022API LY_ERR
1023lyd_change_term(struct lyd_node *term, const char *val_str)
1024{
1025 LY_ERR ret = LY_SUCCESS;
1026 struct lysc_type *type;
1027 struct lyd_node_term *t;
1028 struct lyd_node *parent;
1029 struct lyd_value val = {0};
1030 int dflt_change, val_change;
1031
1032 LY_CHECK_ARG_RET(NULL, term, term->schema, term->schema->nodetype & LYD_NODE_TERM, LY_EINVAL);
1033
1034 if (!val_str) {
1035 val_str = "";
1036 }
1037 t = (struct lyd_node_term *)term;
1038 type = ((struct lysc_node_leaf *)term->schema)->type;
1039
1040 /* parse the new value */
1041 LY_CHECK_GOTO(ret = lyd_value_store(&val, term->schema, val_str, strlen(val_str), NULL, lydjson_resolve_prefix, NULL,
1042 LYD_JSON), cleanup);
1043
1044 /* compare original and new value */
1045 if (type->plugin->compare(&t->value, &val)) {
1046 /* values differ, switch them */
1047 type->plugin->free(LYD_NODE_CTX(term), &t->value);
1048 t->value = val;
1049 memset(&val, 0, sizeof val);
1050 val_change = 1;
1051 } else {
1052 val_change = 0;
1053 }
1054
1055 /* always clear the default flag */
1056 if (term->flags & LYD_DEFAULT) {
1057 for (parent = term; parent; parent = (struct lyd_node *)parent->parent) {
1058 parent->flags &= ~LYD_DEFAULT;
1059 }
1060 dflt_change = 1;
1061 } else {
1062 dflt_change = 0;
1063 }
1064
1065 if (val_change || dflt_change) {
1066 /* make the node non-validated */
1067 term->flags &= LYD_NEW;
1068 }
1069
1070 if (val_change) {
1071 if (term->schema->nodetype == LYS_LEAFLIST) {
1072 /* leaf-list needs to be hashed again and re-inserted into parent */
1073 lyd_unlink_hash(term);
1074 lyd_hash(term);
1075 LY_CHECK_GOTO(ret = lyd_insert_hash(term), cleanup);
1076 } else if ((term->schema->flags & LYS_KEY) && term->parent) {
1077 /* list needs to be updated if its key was changed */
1078 assert(term->parent->schema->nodetype == LYS_LIST);
1079 lyd_unlink_hash((struct lyd_node *)term->parent);
1080 lyd_hash((struct lyd_node *)term->parent);
1081 LY_CHECK_GOTO(ret = lyd_insert_hash((struct lyd_node *)term->parent), cleanup);
1082 } /* else leaf that is not a key, its value is not used for its hash so it does not change */
1083 }
1084
1085 /* retrun value */
1086 if (!val_change) {
1087 if (dflt_change) {
1088 /* only default flag change */
1089 ret = LY_EEXIST;
1090 } else {
1091 /* no change */
1092 ret = LY_ENOT;
1093 }
1094 } /* else value changed, LY_SUCCESS */
1095
1096cleanup:
1097 type->plugin->free(LYD_NODE_CTX(term), &val);
1098 return ret;
1099}
1100
Michal Vasko41586352020-07-13 13:54:25 +02001101API LY_ERR
1102lyd_change_meta(struct lyd_meta *meta, const char *val_str)
1103{
1104 LY_ERR ret = LY_SUCCESS;
1105 struct lyd_meta *m2;
1106 struct lyd_value val;
1107 int val_change;
1108
1109 LY_CHECK_ARG_RET(NULL, meta, LY_EINVAL);
1110
1111 if (!val_str) {
1112 val_str = "";
1113 }
1114
1115 /* parse the new value into a new meta structure */
1116 LY_CHECK_GOTO(ret = lyd_create_meta(NULL, &m2, meta->annotation->module, meta->name, strlen(meta->name), val_str,
1117 strlen(val_str), NULL, lydjson_resolve_prefix, NULL, LYD_JSON, NULL), cleanup);
1118
1119 /* compare original and new value */
1120 if (lyd_compare_meta(meta, m2)) {
1121 /* values differ, switch them */
1122 val = meta->value;
1123 meta->value = m2->value;
1124 m2->value = val;
1125 val_change = 1;
1126 } else {
1127 val_change = 0;
1128 }
1129
1130 /* retrun value */
1131 if (!val_change) {
1132 /* no change */
1133 ret = LY_ENOT;
1134 } /* else value changed, LY_SUCCESS */
1135
1136cleanup:
1137 return ret;
1138}
1139
Michal Vasko3a41dff2020-07-15 14:30:28 +02001140API LY_ERR
1141lyd_new_path(struct lyd_node *parent, const struct ly_ctx *ctx, const char *path, const char *value, int options,
1142 struct lyd_node **node)
Michal Vasko00cbf532020-06-15 13:58:47 +02001143{
Michal Vasko3a41dff2020-07-15 14:30:28 +02001144 return lyd_new_path2(parent, ctx, path, value, 0, options, node, NULL);
Michal Vasko00cbf532020-06-15 13:58:47 +02001145}
1146
1147API LY_ERR
1148lyd_new_path2(struct lyd_node *parent, const struct ly_ctx *ctx, const char *path, const void *value,
1149 LYD_ANYDATA_VALUETYPE value_type, int options, struct lyd_node **new_parent, struct lyd_node **new_node)
1150{
1151 LY_ERR ret = LY_SUCCESS, r;
1152 struct lyxp_expr *exp = NULL;
1153 struct ly_path *p = NULL;
1154 struct lyd_node *nparent = NULL, *nnode = NULL, *node = NULL, *cur_parent;
1155 const struct lysc_node *schema;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001156 LY_ARRAY_COUNT_TYPE path_idx = 0;
Michal Vasko00cbf532020-06-15 13:58:47 +02001157 struct ly_path_predicate *pred;
1158
1159 LY_CHECK_ARG_RET(ctx, parent || ctx, path, (path[0] == '/') || parent, LY_EINVAL);
1160
1161 if (!ctx) {
1162 ctx = LYD_NODE_CTX(parent);
1163 }
1164
1165 /* parse path */
Michal Vasko6b26e742020-07-17 15:02:10 +02001166 LY_CHECK_GOTO(ret = ly_path_parse(ctx, NULL, path, strlen(path), LY_PATH_BEGIN_EITHER, LY_PATH_LREF_FALSE,
Michal Vasko00cbf532020-06-15 13:58:47 +02001167 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_SIMPLE, &exp), cleanup);
1168
1169 /* compile path */
1170 LY_CHECK_GOTO(ret = ly_path_compile(ctx, NULL, parent ? parent->schema : NULL, exp, LY_PATH_LREF_FALSE,
1171 options & LYD_NEWOPT_OUTPUT ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT,
1172 LY_PATH_TARGET_MANY, lydjson_resolve_prefix, NULL, LYD_JSON, &p), cleanup);
1173
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001174 schema = p[LY_ARRAY_COUNT(p) - 1].node;
1175 if ((schema->nodetype == LYS_LIST) && (p[LY_ARRAY_COUNT(p) - 1].pred_type == LY_PATH_PREDTYPE_NONE)
Michal Vasko00cbf532020-06-15 13:58:47 +02001176 && !(options & LYD_NEWOPT_OPAQ)) {
1177 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_XPATH, "Predicate missing for %s \"%s\" in path.",
1178 lys_nodetype2str(schema->nodetype), schema->name);
1179 ret = LY_EINVAL;
1180 goto cleanup;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001181 } else if ((schema->nodetype == LYS_LEAFLIST) && (p[LY_ARRAY_COUNT(p) - 1].pred_type == LY_PATH_PREDTYPE_NONE)) {
Michal Vasko00cbf532020-06-15 13:58:47 +02001182 /* parse leafref value into a predicate, if not defined in the path */
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001183 p[LY_ARRAY_COUNT(p) - 1].pred_type = LY_PATH_PREDTYPE_LEAFLIST;
1184 LY_ARRAY_NEW_GOTO(ctx, p[LY_ARRAY_COUNT(p) - 1].predicates, pred, ret, cleanup);
Michal Vasko00cbf532020-06-15 13:58:47 +02001185
1186 if (!value) {
1187 value = "";
1188 }
1189
1190 r = LY_SUCCESS;
1191 if (options & LYD_NEWOPT_OPAQ) {
1192 r = lys_value_validate(NULL, schema, value, strlen(value), lydjson_resolve_prefix, NULL, LYD_JSON);
1193 }
1194 if (!r) {
1195 LY_CHECK_GOTO(ret = lyd_value_store(&pred->value, schema, value, strlen(value), NULL, lydjson_resolve_prefix,
1196 NULL, LYD_JSON), cleanup);
1197 } /* else we have opaq flag and the value is not valid, leavne no predicate and then create an opaque node */
1198 }
1199
1200 /* try to find any existing nodes in the path */
1201 if (parent) {
1202 ret = ly_path_eval_partial(p, parent, &path_idx, &node);
1203 if (ret == LY_SUCCESS) {
1204 /* the node exists, are we supposed to update it or is it just a default? */
1205 if (!(options & LYD_NEWOPT_UPDATE) && !(node->flags & LYD_DEFAULT)) {
1206 LOGERR(ctx, LY_EEXIST, "Path \"%s\" already exists", path);
1207 ret = LY_EEXIST;
1208 goto cleanup;
1209 }
1210
1211 /* update the existing node */
1212 ret = lyd_new_path_update(node, value, value_type, &nparent, &nnode);
1213 goto cleanup;
1214 } else if (ret == LY_EINCOMPLETE) {
1215 /* some nodes were found, adjust the iterator to the next segment */
1216 ++path_idx;
1217 } else if (ret == LY_ENOTFOUND) {
1218 /* we will create the nodes from top-level, default behavior (absolute path), or from the parent (relative path) */
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001219 if (lysc_data_parent(p[LY_ARRAY_COUNT(p) - 1].node)) {
Michal Vasko00cbf532020-06-15 13:58:47 +02001220 node = parent;
1221 }
1222 } else {
1223 /* error */
1224 goto cleanup;
1225 }
1226 }
1227
1228 /* create all the non-existing nodes in a loop */
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001229 for (; path_idx < LY_ARRAY_COUNT(p); ++path_idx) {
Michal Vasko00cbf532020-06-15 13:58:47 +02001230 cur_parent = node;
1231 schema = p[path_idx].node;
1232
1233 switch (schema->nodetype) {
1234 case LYS_LIST:
1235 if (!(schema->flags & LYS_KEYLESS)) {
1236 if ((options & LYD_NEWOPT_OPAQ) && (p[path_idx].pred_type == LY_PATH_PREDTYPE_NONE)) {
1237 /* creating opaque list without keys */
1238 LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, NULL,
1239 LYD_JSON, NULL, NULL, 0, schema->module->name, &node), cleanup);
1240 } else {
1241 assert(p[path_idx].pred_type == LY_PATH_PREDTYPE_LIST);
1242 LY_CHECK_GOTO(ret = lyd_create_list(schema, p[path_idx].predicates, &node), cleanup);
1243 }
1244 break;
1245 }
1246 /* fallthrough */
1247 case LYS_CONTAINER:
1248 case LYS_NOTIF:
1249 case LYS_RPC:
1250 case LYS_ACTION:
1251 LY_CHECK_GOTO(ret = lyd_create_inner(schema, &node), cleanup);
1252 break;
1253 case LYS_LEAFLIST:
1254 if ((options & LYD_NEWOPT_OPAQ) && (p[path_idx].pred_type == LY_PATH_PREDTYPE_NONE)) {
1255 /* creating opaque leaf-list without value */
1256 LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, NULL,
1257 LYD_JSON, NULL, NULL, 0, schema->module->name, &node), cleanup);
1258 } else {
1259 assert(p[path_idx].pred_type == LY_PATH_PREDTYPE_LEAFLIST);
1260 LY_CHECK_GOTO(ret = lyd_create_term2(schema, &p[path_idx].predicates[0].value, &node), cleanup);
1261 }
1262 break;
1263 case LYS_LEAF:
1264 /* make there is some value */
1265 if (!value) {
1266 value = "";
1267 }
1268
1269 r = LY_SUCCESS;
1270 if (options & LYD_NEWOPT_OPAQ) {
1271 r = lys_value_validate(NULL, schema, value, strlen(value), lydjson_resolve_prefix, NULL, LYD_JSON);
1272 }
1273 if (!r) {
1274 LY_CHECK_GOTO(ret = lyd_create_term(schema, value, strlen(value), NULL, lydjson_resolve_prefix, NULL,
1275 LYD_JSON, &node), cleanup);
1276 } else {
1277 /* creating opaque leaf without value */
1278 LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, NULL,
1279 LYD_JSON, NULL, NULL, 0, schema->module->name, &node), cleanup);
1280 }
1281 break;
1282 case LYS_ANYDATA:
1283 case LYS_ANYXML:
1284 LY_CHECK_GOTO(ret = lyd_create_any(schema, value, value_type, &node), cleanup);
1285 break;
1286 default:
1287 LOGINT(ctx);
1288 ret = LY_EINT;
1289 goto cleanup;
1290 }
1291
1292 if (cur_parent) {
1293 /* connect to the parent */
1294 lyd_insert_node(cur_parent, NULL, node);
1295 } else if (parent) {
1296 /* connect to top-level siblings */
1297 lyd_insert_node(NULL, &parent, node);
1298 }
1299
1300 /* update remembered nodes */
1301 if (!nparent) {
1302 nparent = node;
1303 }
1304 nnode = node;
1305 }
1306
1307cleanup:
1308 lyxp_expr_free(ctx, exp);
1309 ly_path_free(ctx, p);
1310 if (!ret) {
1311 /* set out params only on success */
1312 if (new_parent) {
1313 *new_parent = nparent;
1314 }
1315 if (new_node) {
1316 *new_node = nnode;
1317 }
1318 }
1319 return ret;
1320}
1321
Michal Vasko90932a92020-02-12 14:33:03 +01001322struct lyd_node *
Michal Vaskob104f112020-07-17 09:54:54 +02001323lyd_insert_get_next_anchor(const struct lyd_node *first_sibling, const struct lyd_node *new_node)
Michal Vasko90932a92020-02-12 14:33:03 +01001324{
Michal Vaskob104f112020-07-17 09:54:54 +02001325 const struct lysc_node *schema, *sparent;
Michal Vasko90932a92020-02-12 14:33:03 +01001326 struct lyd_node *match = NULL;
Michal Vaskob104f112020-07-17 09:54:54 +02001327 int found;
Michal Vasko90932a92020-02-12 14:33:03 +01001328
Michal Vaskob104f112020-07-17 09:54:54 +02001329 assert(new_node);
1330
1331 if (!first_sibling || !new_node->schema) {
1332 /* insert at the end, no next anchor */
Michal Vasko90932a92020-02-12 14:33:03 +01001333 return NULL;
1334 }
1335
Michal Vaskob104f112020-07-17 09:54:54 +02001336 if (first_sibling->parent && first_sibling->parent->children_ht) {
1337 /* find the anchor using hashes */
1338 sparent = first_sibling->parent->schema;
1339 schema = lys_getnext(new_node->schema, sparent, NULL, 0);
1340 while (schema) {
1341 /* keep trying to find the first existing instance of the closest following schema sibling,
1342 * otherwise return NULL - inserting at the end */
1343 if (!lyd_find_sibling_schema(first_sibling, schema, &match)) {
1344 break;
1345 }
1346
1347 schema = lys_getnext(schema, sparent, NULL, 0);
1348 }
1349 } else {
1350 /* find the anchor without hashes */
1351 match = (struct lyd_node *)first_sibling;
1352 if (!lysc_data_parent(new_node->schema)) {
1353 /* we are in top-level, skip all the data from preceding modules */
1354 LY_LIST_FOR(match, match) {
1355 if (!match->schema || (strcmp(lyd_owner_module(match)->name, lyd_owner_module(new_node)->name) >= 0)) {
1356 break;
1357 }
1358 }
1359 }
1360
1361 /* get the first schema sibling */
1362 sparent = lysc_data_parent(new_node->schema);
1363 schema = lys_getnext(NULL, sparent, new_node->schema->module->compiled, 0);
1364
1365 found = 0;
1366 LY_LIST_FOR(match, match) {
1367 if (!match->schema || (lyd_owner_module(match) != lyd_owner_module(new_node))) {
1368 /* we have found an opaque node, which must be at the end, so use it OR
1369 * modules do not match, so we must have traversed all the data from new_node module (if any),
1370 * we have found the first node of the next module, that is what we want */
1371 break;
1372 }
1373
1374 /* skip schema nodes until we find the instantiated one */
1375 while (!found) {
1376 if (new_node->schema == schema) {
1377 /* we have found the schema of the new node, continue search to find the first
1378 * data node with a different schema (after our schema) */
1379 found = 1;
1380 break;
1381 }
1382 if (match->schema == schema) {
1383 /* current node (match) is a data node still before the new node, continue search in data */
1384 break;
1385 }
1386 schema = lys_getnext(schema, sparent, new_node->schema->module->compiled, 0);
1387 assert(schema);
1388 }
1389
1390 if (found && (match->schema != new_node->schema)) {
1391 /* find the next node after we have found our node schema data instance */
1392 break;
1393 }
1394 }
Michal Vasko90932a92020-02-12 14:33:03 +01001395 }
1396
1397 return match;
1398}
1399
1400/**
1401 * @brief Insert node after a sibling.
1402 *
Michal Vasko9f96a052020-03-10 09:41:45 +01001403 * Handles inserting into NP containers and key-less lists.
1404 *
Michal Vasko90932a92020-02-12 14:33:03 +01001405 * @param[in] sibling Sibling to insert after.
1406 * @param[in] node Node to insert.
1407 */
1408static void
Michal Vaskof03ed032020-03-04 13:31:44 +01001409lyd_insert_after_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001410{
Michal Vasko0249f7c2020-03-05 16:36:40 +01001411 struct lyd_node_inner *par;
1412
Michal Vasko90932a92020-02-12 14:33:03 +01001413 assert(!node->next && (node->prev == node));
1414
1415 node->next = sibling->next;
1416 node->prev = sibling;
1417 sibling->next = node;
1418 if (node->next) {
1419 /* sibling had a succeeding node */
1420 node->next->prev = node;
1421 } else {
1422 /* sibling was last, find first sibling and change its prev */
1423 if (sibling->parent) {
1424 sibling = sibling->parent->child;
1425 } else {
1426 for (; sibling->prev->next != node; sibling = sibling->prev);
1427 }
1428 sibling->prev = node;
1429 }
1430 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001431
Michal Vasko9f96a052020-03-10 09:41:45 +01001432 for (par = node->parent; par; par = par->parent) {
1433 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
1434 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +01001435 par->flags &= ~LYD_DEFAULT;
1436 }
Michal Vaskob104f112020-07-17 09:54:54 +02001437 if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001438 /* rehash key-less list */
1439 lyd_hash((struct lyd_node *)par);
1440 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001441 }
Michal Vasko90932a92020-02-12 14:33:03 +01001442}
1443
1444/**
1445 * @brief Insert node before a sibling.
1446 *
Michal Vasko9f96a052020-03-10 09:41:45 +01001447 * Handles inserting into NP containers and key-less lists.
1448 *
Michal Vasko90932a92020-02-12 14:33:03 +01001449 * @param[in] sibling Sibling to insert before.
1450 * @param[in] node Node to insert.
1451 */
1452static void
Michal Vaskof03ed032020-03-04 13:31:44 +01001453lyd_insert_before_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001454{
Michal Vasko0249f7c2020-03-05 16:36:40 +01001455 struct lyd_node_inner *par;
1456
Michal Vasko90932a92020-02-12 14:33:03 +01001457 assert(!node->next && (node->prev == node));
1458
1459 node->next = sibling;
1460 /* covers situation of sibling being first */
1461 node->prev = sibling->prev;
1462 sibling->prev = node;
1463 if (node->prev->next) {
1464 /* sibling had a preceding node */
1465 node->prev->next = node;
1466 } else if (sibling->parent) {
1467 /* sibling was first and we must also change parent child pointer */
1468 sibling->parent->child = node;
1469 }
1470 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001471
Michal Vasko9f96a052020-03-10 09:41:45 +01001472 for (par = node->parent; par; par = par->parent) {
1473 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
1474 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +01001475 par->flags &= ~LYD_DEFAULT;
1476 }
Michal Vaskob104f112020-07-17 09:54:54 +02001477 if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001478 /* rehash key-less list */
1479 lyd_hash((struct lyd_node *)par);
1480 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001481 }
Michal Vasko90932a92020-02-12 14:33:03 +01001482}
1483
1484/**
Michal Vaskob104f112020-07-17 09:54:54 +02001485 * @brief Insert node as the first and only child of a parent.
Michal Vasko90932a92020-02-12 14:33:03 +01001486 *
Michal Vasko9f96a052020-03-10 09:41:45 +01001487 * Handles inserting into NP containers and key-less lists.
1488 *
Michal Vasko90932a92020-02-12 14:33:03 +01001489 * @param[in] parent Parent to insert into.
1490 * @param[in] node Node to insert.
1491 */
1492static void
Michal Vaskob104f112020-07-17 09:54:54 +02001493lyd_insert_only_child(struct lyd_node *parent, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001494{
1495 struct lyd_node_inner *par;
1496
Michal Vaskob104f112020-07-17 09:54:54 +02001497 assert(parent && !lyd_node_children(parent, 0) && !node->next && (node->prev == node));
Michal Vasko52927e22020-03-16 17:26:14 +01001498 assert(!parent->schema || (parent->schema->nodetype & LYD_NODE_INNER));
Michal Vasko90932a92020-02-12 14:33:03 +01001499
1500 par = (struct lyd_node_inner *)parent;
1501
Michal Vaskob104f112020-07-17 09:54:54 +02001502 par->child = node;
Michal Vasko90932a92020-02-12 14:33:03 +01001503 node->parent = par;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001504
Michal Vasko9f96a052020-03-10 09:41:45 +01001505 for (; par; par = par->parent) {
1506 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
1507 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +01001508 par->flags &= ~LYD_DEFAULT;
1509 }
Michal Vasko52927e22020-03-16 17:26:14 +01001510 if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001511 /* rehash key-less list */
1512 lyd_hash((struct lyd_node *)par);
1513 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001514 }
Michal Vasko751cb4d2020-07-14 12:25:28 +02001515}
Michal Vasko0249f7c2020-03-05 16:36:40 +01001516
Michal Vasko751cb4d2020-07-14 12:25:28 +02001517/**
1518 * @brief Learn whether a list instance has all the keys.
1519 *
1520 * @param[in] list List instance to check.
1521 * @return non-zero if all the keys were found,
1522 * @return 0 otherwise.
1523 */
1524static int
1525lyd_insert_has_keys(const struct lyd_node *list)
1526{
1527 const struct lyd_node *key;
1528 const struct lysc_node *skey = NULL;
1529
1530 assert(list->schema->nodetype == LYS_LIST);
1531 key = lyd_node_children(list, 0);
1532 while ((skey = lys_getnext(skey, list->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
1533 if (!key || (key->schema != skey)) {
1534 /* key missing */
1535 return 0;
1536 }
1537
1538 key = key->next;
1539 }
1540
1541 /* all keys found */
1542 return 1;
Michal Vasko90932a92020-02-12 14:33:03 +01001543}
1544
1545void
Michal Vaskob104f112020-07-17 09:54:54 +02001546lyd_insert_node(struct lyd_node *parent, struct lyd_node **first_sibling_p, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001547{
Michal Vaskob104f112020-07-17 09:54:54 +02001548 struct lyd_node *anchor, *first_sibling;
Michal Vasko90932a92020-02-12 14:33:03 +01001549
Michal Vaskob104f112020-07-17 09:54:54 +02001550 /* inserting list without its keys is not supported */
1551 assert((parent || first_sibling_p) && node && (node->hash || !node->schema));
Michal Vasko9b368d32020-02-14 13:53:31 +01001552
Michal Vaskob104f112020-07-17 09:54:54 +02001553 if (!parent && first_sibling_p && (*first_sibling_p) && (*first_sibling_p)->parent) {
1554 parent = (struct lyd_node *)(*first_sibling_p)->parent;
Michal Vasko9b368d32020-02-14 13:53:31 +01001555 }
Michal Vasko90932a92020-02-12 14:33:03 +01001556
Michal Vaskob104f112020-07-17 09:54:54 +02001557 /* get first sibling */
1558 first_sibling = parent ? ((struct lyd_node_inner *)parent)->child : *first_sibling_p;
Michal Vasko9f96a052020-03-10 09:41:45 +01001559
Michal Vaskob104f112020-07-17 09:54:54 +02001560 /* find the anchor, our next node, so we can insert before it */
1561 anchor = lyd_insert_get_next_anchor(first_sibling, node);
1562 if (anchor) {
1563 lyd_insert_before_node(anchor, node);
1564 } else if (first_sibling) {
1565 lyd_insert_after_node(first_sibling->prev, node);
1566 } else if (parent) {
1567 lyd_insert_only_child(parent, node);
Michal Vasko90932a92020-02-12 14:33:03 +01001568 } else {
Michal Vaskob104f112020-07-17 09:54:54 +02001569 *first_sibling_p = node;
1570 }
1571
1572 /* insert into parent HT */
1573 lyd_insert_hash(node);
1574
1575 /* finish hashes for our parent, if needed and possible */
1576 if (node->schema && (node->schema->flags & LYS_KEY) && lyd_insert_has_keys(parent)) {
1577 lyd_hash(parent);
1578
1579 /* now we can insert even the list into its parent HT */
1580 lyd_insert_hash(parent);
Michal Vasko90932a92020-02-12 14:33:03 +01001581 }
Michal Vasko90932a92020-02-12 14:33:03 +01001582}
1583
Michal Vaskof03ed032020-03-04 13:31:44 +01001584static LY_ERR
1585lyd_insert_check_schema(const struct lysc_node *parent, const struct lysc_node *schema)
1586{
1587 const struct lysc_node *par2;
1588
1589 assert(schema);
Michal Vasko62ed12d2020-05-21 10:08:25 +02001590 assert(!parent || !(parent->nodetype & (LYS_CASE | LYS_CHOICE)));
Michal Vaskof03ed032020-03-04 13:31:44 +01001591
1592 /* find schema parent */
Michal Vasko62ed12d2020-05-21 10:08:25 +02001593 par2 = lysc_data_parent(schema);
Michal Vaskof03ed032020-03-04 13:31:44 +01001594
1595 if (parent) {
1596 /* inner node */
1597 if (par2 != parent) {
Michal Vaskob104f112020-07-17 09:54:54 +02001598 LOGERR(schema->module->ctx, LY_EINVAL, "Cannot insert, parent of \"%s\" is not \"%s\".", schema->name,
1599 parent->name);
Michal Vaskof03ed032020-03-04 13:31:44 +01001600 return LY_EINVAL;
1601 }
1602 } else {
1603 /* top-level node */
1604 if (par2) {
Radek Krejcif6d14cb2020-07-02 16:11:45 +02001605 LOGERR(schema->module->ctx, LY_EINVAL, "Cannot insert, node \"%s\" is not top-level.", schema->name);
Michal Vaskof03ed032020-03-04 13:31:44 +01001606 return LY_EINVAL;
1607 }
1608 }
1609
1610 return LY_SUCCESS;
1611}
1612
1613API LY_ERR
Michal Vaskob104f112020-07-17 09:54:54 +02001614lyd_insert_child(struct lyd_node *parent, struct lyd_node *node)
Michal Vaskof03ed032020-03-04 13:31:44 +01001615{
1616 struct lyd_node *iter;
1617
Michal Vasko654bc852020-06-23 13:28:06 +02001618 LY_CHECK_ARG_RET(NULL, parent, node, parent->schema->nodetype & LYD_NODE_INNER, LY_EINVAL);
Michal Vaskof03ed032020-03-04 13:31:44 +01001619
1620 LY_CHECK_RET(lyd_insert_check_schema(parent->schema, node->schema));
1621
1622 if (node->schema->flags & LYS_KEY) {
1623 LOGERR(parent->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1624 return LY_EINVAL;
1625 }
1626
1627 if (node->parent || node->prev->next) {
1628 lyd_unlink_tree(node);
1629 }
1630
1631 while (node) {
1632 iter = node->next;
1633 lyd_unlink_tree(node);
1634 lyd_insert_node(parent, NULL, node);
1635 node = iter;
1636 }
1637 return LY_SUCCESS;
1638}
1639
1640API LY_ERR
Michal Vaskob104f112020-07-17 09:54:54 +02001641lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, struct lyd_node **first)
Michal Vaskob1b5c262020-03-05 14:29:47 +01001642{
1643 struct lyd_node *iter;
1644
Michal Vaskob104f112020-07-17 09:54:54 +02001645 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Michal Vaskob1b5c262020-03-05 14:29:47 +01001646
Michal Vaskob104f112020-07-17 09:54:54 +02001647 if (sibling) {
1648 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskob1b5c262020-03-05 14:29:47 +01001649 }
1650
1651 if (node->parent || node->prev->next) {
1652 lyd_unlink_tree(node);
1653 }
1654
1655 while (node) {
Michal Vaskob104f112020-07-17 09:54:54 +02001656 if (node->schema->flags & LYS_KEY) {
1657 LOGERR(LYD_NODE_CTX(node), LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1658 return LY_EINVAL;
1659 }
1660
Michal Vaskob1b5c262020-03-05 14:29:47 +01001661 iter = node->next;
1662 lyd_unlink_tree(node);
1663 lyd_insert_node(NULL, &sibling, node);
1664 node = iter;
1665 }
Michal Vaskob1b5c262020-03-05 14:29:47 +01001666
Michal Vaskob104f112020-07-17 09:54:54 +02001667 if (first) {
1668 /* find the first sibling */
1669 *first = sibling;
1670 while ((*first)->prev->next) {
1671 *first = (*first)->prev;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001672 }
1673 }
1674
1675 return LY_SUCCESS;
1676}
1677
Michal Vaskob1b5c262020-03-05 14:29:47 +01001678API LY_ERR
Michal Vaskof03ed032020-03-04 13:31:44 +01001679lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
1680{
1681 struct lyd_node *iter;
1682
1683 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1684
Michal Vasko62ed12d2020-05-21 10:08:25 +02001685 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskof03ed032020-03-04 13:31:44 +01001686
Michal Vaskob104f112020-07-17 09:54:54 +02001687 if (!(node->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(node->schema->flags & LYS_ORDBY_USER)) {
1688 LOGERR(LYD_NODE_CTX(sibling), LY_EINVAL, "Can be used only for user-ordered nodes.");
Michal Vaskof03ed032020-03-04 13:31:44 +01001689 return LY_EINVAL;
1690 }
1691
1692 if (node->parent || node->prev->next) {
1693 lyd_unlink_tree(node);
1694 }
1695
1696 /* insert in reverse order to get the original order */
1697 node = node->prev;
1698 while (node) {
1699 iter = node->prev;
1700 lyd_unlink_tree(node);
1701
1702 lyd_insert_before_node(sibling, node);
Michal Vasko751cb4d2020-07-14 12:25:28 +02001703 lyd_insert_hash(node);
1704
Michal Vaskof03ed032020-03-04 13:31:44 +01001705 /* move the anchor accordingly */
1706 sibling = node;
1707
1708 node = (iter == node) ? NULL : iter;
1709 }
1710 return LY_SUCCESS;
1711}
1712
1713API LY_ERR
1714lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
1715{
1716 struct lyd_node *iter;
1717
1718 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1719
Michal Vasko62ed12d2020-05-21 10:08:25 +02001720 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskof03ed032020-03-04 13:31:44 +01001721
Michal Vaskob104f112020-07-17 09:54:54 +02001722 if (!(node->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(node->schema->flags & LYS_ORDBY_USER)) {
1723 LOGERR(LYD_NODE_CTX(sibling), LY_EINVAL, "Can be used only for user-ordered nodes.");
Michal Vaskof03ed032020-03-04 13:31:44 +01001724 return LY_EINVAL;
1725 }
1726
1727 if (node->parent || node->prev->next) {
1728 lyd_unlink_tree(node);
1729 }
1730
1731 while (node) {
1732 iter = node->next;
1733 lyd_unlink_tree(node);
1734
1735 lyd_insert_after_node(sibling, node);
Michal Vasko751cb4d2020-07-14 12:25:28 +02001736 lyd_insert_hash(node);
1737
Michal Vaskof03ed032020-03-04 13:31:44 +01001738 /* move the anchor accordingly */
1739 sibling = node;
1740
1741 node = iter;
1742 }
1743 return LY_SUCCESS;
1744}
1745
1746API void
1747lyd_unlink_tree(struct lyd_node *node)
1748{
1749 struct lyd_node *iter;
1750
1751 if (!node) {
1752 return;
1753 }
1754
Michal Vaskob104f112020-07-17 09:54:54 +02001755 /* update hashes while still linked into the tree */
1756 lyd_unlink_hash(node);
1757
Michal Vaskof03ed032020-03-04 13:31:44 +01001758 /* unlink from siblings */
1759 if (node->prev->next) {
1760 node->prev->next = node->next;
1761 }
1762 if (node->next) {
1763 node->next->prev = node->prev;
1764 } else {
1765 /* unlinking the last node */
1766 if (node->parent) {
1767 iter = node->parent->child;
1768 } else {
1769 iter = node->prev;
1770 while (iter->prev != node) {
1771 iter = iter->prev;
1772 }
1773 }
1774 /* update the "last" pointer from the first node */
1775 iter->prev = node->prev;
1776 }
1777
1778 /* unlink from parent */
1779 if (node->parent) {
1780 if (node->parent->child == node) {
1781 /* the node is the first child */
1782 node->parent->child = node->next;
1783 }
1784
Michal Vaskoab49dbe2020-07-17 12:32:47 +02001785 /* check for NP container whether its last non-default node is not being unlinked */
1786 if (node->parent->schema && (node->parent->schema->nodetype == LYS_CONTAINER)
1787 && !(node->parent->flags & LYD_DEFAULT) && !(node->parent->schema->flags & LYS_PRESENCE)) {
1788 LY_LIST_FOR(node->parent->child, iter) {
1789 if ((iter != node) && !(iter->flags & LYD_DEFAULT)) {
1790 break;
1791 }
1792 }
1793 if (!iter) {
1794 node->parent->flags |= LYD_DEFAULT;
1795 }
1796 }
1797
Michal Vaskof03ed032020-03-04 13:31:44 +01001798 /* check for keyless list and update its hash */
1799 for (iter = (struct lyd_node *)node->parent; iter; iter = (struct lyd_node *)iter->parent) {
Michal Vasko413c7f22020-05-05 12:34:06 +02001800 if (iter->schema && (iter->schema->flags & LYS_KEYLESS)) {
Michal Vaskof03ed032020-03-04 13:31:44 +01001801 lyd_hash(iter);
1802 }
1803 }
1804
1805 node->parent = NULL;
1806 }
1807
1808 node->next = NULL;
1809 node->prev = node;
1810}
1811
Michal Vasko90932a92020-02-12 14:33:03 +01001812LY_ERR
Michal Vasko9f96a052020-03-10 09:41:45 +01001813lyd_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 +01001814 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 +01001815 void *prefix_data, LYD_FORMAT format, const struct lysc_node *ctx_snode)
Michal Vasko90932a92020-02-12 14:33:03 +01001816{
1817 LY_ERR ret;
1818 struct lysc_ext_instance *ant = NULL;
Michal Vasko9f96a052020-03-10 09:41:45 +01001819 struct lyd_meta *mt, *last;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001820 LY_ARRAY_COUNT_TYPE u;
Michal Vasko90932a92020-02-12 14:33:03 +01001821
Michal Vasko9f96a052020-03-10 09:41:45 +01001822 assert((parent || meta) && mod);
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001823
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001824 LY_ARRAY_FOR(mod->compiled->exts, u) {
1825 if (mod->compiled->exts[u].def->plugin == lyext_plugins_internal[LYEXT_PLUGIN_INTERNAL_ANNOTATION].plugin &&
1826 !ly_strncmp(mod->compiled->exts[u].argument, name, name_len)) {
Michal Vasko90932a92020-02-12 14:33:03 +01001827 /* we have the annotation definition */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001828 ant = &mod->compiled->exts[u];
Michal Vasko90932a92020-02-12 14:33:03 +01001829 break;
1830 }
1831 }
1832 if (!ant) {
1833 /* attribute is not defined as a metadata annotation (RFC 7952) */
1834 LOGERR(mod->ctx, LY_EINVAL, "Annotation definition for attribute \"%s:%.*s\" not found.",
1835 mod->name, name_len, name);
1836 return LY_EINVAL;
1837 }
1838
Michal Vasko9f96a052020-03-10 09:41:45 +01001839 mt = calloc(1, sizeof *mt);
1840 LY_CHECK_ERR_RET(!mt, LOGMEM(mod->ctx), LY_EMEM);
1841 mt->parent = parent;
1842 mt->annotation = ant;
Michal Vasko52927e22020-03-16 17:26:14 +01001843 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 +01001844 if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001845 free(mt);
Michal Vasko90932a92020-02-12 14:33:03 +01001846 return ret;
1847 }
Michal Vasko9f96a052020-03-10 09:41:45 +01001848 mt->name = lydict_insert(mod->ctx, name, name_len);
Michal Vasko90932a92020-02-12 14:33:03 +01001849
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001850 /* insert as the last attribute */
1851 if (parent) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001852 if (parent->meta) {
1853 for (last = parent->meta; last->next; last = last->next);
1854 last->next = mt;
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001855 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +01001856 parent->meta = mt;
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001857 }
Michal Vasko9f96a052020-03-10 09:41:45 +01001858 } else if (*meta) {
1859 for (last = *meta; last->next; last = last->next);
1860 last->next = mt;
Michal Vasko90932a92020-02-12 14:33:03 +01001861 }
1862
1863 /* remove default flags from NP containers */
Michal Vasko4ba6aef2020-07-09 15:44:23 +02001864 while (parent && (parent->schema->nodetype == LYS_CONTAINER) && (parent->flags & LYD_DEFAULT)) {
Michal Vasko90932a92020-02-12 14:33:03 +01001865 parent->flags &= ~LYD_DEFAULT;
1866 parent = (struct lyd_node *)parent->parent;
1867 }
1868
Michal Vasko9f96a052020-03-10 09:41:45 +01001869 if (meta) {
1870 *meta = mt;
Michal Vasko90932a92020-02-12 14:33:03 +01001871 }
1872 return ret;
1873}
1874
Michal Vasko52927e22020-03-16 17:26:14 +01001875LY_ERR
1876ly_create_attr(struct lyd_node *parent, struct ly_attr **attr, const struct ly_ctx *ctx, const char *name,
1877 size_t name_len, const char *value, size_t value_len, int *dynamic, LYD_FORMAT format,
1878 struct ly_prefix *val_prefs, const char *prefix, size_t prefix_len, const char *ns)
1879{
1880 struct ly_attr *at, *last;
1881 struct lyd_node_opaq *opaq;
1882
1883 assert(ctx && (parent || attr) && (!parent || !parent->schema));
1884 assert(name && name_len);
1885 assert((prefix_len && ns) || (!prefix_len && !ns));
1886
1887 if (!value_len) {
1888 value = "";
1889 }
1890
1891 at = calloc(1, sizeof *at);
1892 LY_CHECK_ERR_RET(!at, LOGMEM(ctx), LY_EMEM);
1893 at->parent = (struct lyd_node_opaq *)parent;
1894 at->name = lydict_insert(ctx, name, name_len);
1895 if (dynamic && *dynamic) {
1896 at->value = lydict_insert_zc(ctx, (char *)value);
1897 *dynamic = 0;
1898 } else {
1899 at->value = lydict_insert(ctx, value, value_len);
1900 }
1901
1902 at->format = format;
1903 at->val_prefs = val_prefs;
1904 if (ns) {
1905 at->prefix.pref = lydict_insert(ctx, prefix, prefix_len);
1906 at->prefix.ns = lydict_insert(ctx, ns, 0);
1907 }
1908
1909 /* insert as the last attribute */
1910 if (parent) {
1911 opaq = (struct lyd_node_opaq *)parent;
1912 if (opaq->attr) {
1913 for (last = opaq->attr; last->next; last = last->next);
1914 last->next = at;
1915 } else {
1916 opaq->attr = at;
1917 }
1918 } else if (*attr) {
1919 for (last = *attr; last->next; last = last->next);
1920 last->next = at;
1921 }
1922
1923 if (attr) {
1924 *attr = at;
1925 }
1926 return LY_SUCCESS;
1927}
1928
Radek Krejci084289f2019-07-09 17:35:30 +02001929API const struct lyd_node_term *
Michal Vasko004d3152020-06-11 19:59:22 +02001930lyd_target(const struct ly_path *path, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +02001931{
Michal Vasko004d3152020-06-11 19:59:22 +02001932 struct lyd_node *target;
Radek Krejci084289f2019-07-09 17:35:30 +02001933
Michal Vasko004d3152020-06-11 19:59:22 +02001934 if (ly_path_eval(path, tree, &target)) {
1935 return NULL;
Radek Krejci084289f2019-07-09 17:35:30 +02001936 }
1937
Michal Vasko004d3152020-06-11 19:59:22 +02001938 return (struct lyd_node_term *)target;
Radek Krejci084289f2019-07-09 17:35:30 +02001939}
1940
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001941API LY_ERR
Michal Vasko8f359bf2020-07-28 10:41:15 +02001942lyd_compare_single(const struct lyd_node *node1, const struct lyd_node *node2, int options)
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001943{
1944 const struct lyd_node *iter1, *iter2;
1945 struct lyd_node_term *term1, *term2;
1946 struct lyd_node_any *any1, *any2;
Michal Vasko52927e22020-03-16 17:26:14 +01001947 struct lyd_node_opaq *opaq1, *opaq2;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001948 size_t len1, len2;
Radek Krejci084289f2019-07-09 17:35:30 +02001949
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001950 if (!node1 || !node2) {
1951 if (node1 == node2) {
1952 return LY_SUCCESS;
1953 } else {
1954 return LY_ENOT;
1955 }
1956 }
1957
Michal Vasko52927e22020-03-16 17:26:14 +01001958 if ((LYD_NODE_CTX(node1) != LYD_NODE_CTX(node2)) || (node1->schema != node2->schema)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001959 return LY_ENOT;
1960 }
1961
1962 if (node1->hash != node2->hash) {
1963 return LY_ENOT;
1964 }
Michal Vasko52927e22020-03-16 17:26:14 +01001965 /* 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 +02001966
Michal Vasko52927e22020-03-16 17:26:14 +01001967 if (!node1->schema) {
1968 opaq1 = (struct lyd_node_opaq *)node1;
1969 opaq2 = (struct lyd_node_opaq *)node2;
1970 if ((opaq1->name != opaq2->name) || (opaq1->prefix.ns != opaq2->prefix.ns) || (opaq1->format != opaq2->format)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001971 return LY_ENOT;
1972 }
Michal Vasko52927e22020-03-16 17:26:14 +01001973 switch (opaq1->format) {
1974 case LYD_XML:
1975 if (lyxml_value_compare(opaq1->value, opaq1->val_prefs, opaq2->value, opaq2->val_prefs)) {
1976 return LY_ENOT;
1977 }
1978 break;
1979 case LYD_SCHEMA:
Michal Vasko60ea6352020-06-29 13:39:39 +02001980 case LYD_LYB:
Michal Vasko52927e22020-03-16 17:26:14 +01001981 /* not allowed */
1982 LOGINT(LYD_NODE_CTX(node1));
1983 return LY_EINT;
1984 }
1985 if (options & LYD_COMPARE_FULL_RECURSION) {
1986 iter1 = opaq1->child;
1987 iter2 = opaq2->child;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001988 goto all_children_compare;
Michal Vasko52927e22020-03-16 17:26:14 +01001989 }
1990 return LY_SUCCESS;
1991 } else {
1992 switch (node1->schema->nodetype) {
1993 case LYS_LEAF:
1994 case LYS_LEAFLIST:
1995 if (options & LYD_COMPARE_DEFAULTS) {
1996 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
1997 return LY_ENOT;
1998 }
1999 }
2000
Michal Vasko1a2bf2e2020-06-16 13:07:48 +02002001 term1 = (struct lyd_node_term *)node1;
2002 term2 = (struct lyd_node_term *)node2;
2003 if (term1->value.realtype != term2->value.realtype) {
2004 return LY_ENOT;
2005 }
Michal Vasko52927e22020-03-16 17:26:14 +01002006
Michal Vasko1a2bf2e2020-06-16 13:07:48 +02002007 return term1->value.realtype->plugin->compare(&term1->value, &term2->value);
Michal Vasko52927e22020-03-16 17:26:14 +01002008 case LYS_CONTAINER:
2009 if (options & LYD_COMPARE_DEFAULTS) {
2010 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
2011 return LY_ENOT;
2012 }
2013 }
2014 if (options & LYD_COMPARE_FULL_RECURSION) {
2015 iter1 = ((struct lyd_node_inner*)node1)->child;
2016 iter2 = ((struct lyd_node_inner*)node2)->child;
2017 goto all_children_compare;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002018 }
2019 return LY_SUCCESS;
Michal Vasko1bf09392020-03-27 12:38:10 +01002020 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01002021 case LYS_ACTION:
2022 if (options & LYD_COMPARE_FULL_RECURSION) {
2023 /* TODO action/RPC
2024 goto all_children_compare;
2025 */
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002026 }
2027 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01002028 case LYS_NOTIF:
2029 if (options & LYD_COMPARE_FULL_RECURSION) {
2030 /* TODO Notification
2031 goto all_children_compare;
2032 */
2033 }
2034 return LY_SUCCESS;
2035 case LYS_LIST:
2036 iter1 = ((struct lyd_node_inner*)node1)->child;
2037 iter2 = ((struct lyd_node_inner*)node2)->child;
2038
2039 if (!(node1->schema->flags & LYS_KEYLESS) && !(options & LYD_COMPARE_FULL_RECURSION)) {
2040 /* lists with keys, their equivalence is based on their keys */
2041 for (struct lysc_node *key = ((struct lysc_node_list*)node1->schema)->child;
Michal Vaskoc57d9a92020-06-23 13:28:27 +02002042 key && (key->flags & LYS_KEY);
Michal Vasko52927e22020-03-16 17:26:14 +01002043 key = key->next) {
Michal Vasko8f359bf2020-07-28 10:41:15 +02002044 if (lyd_compare_single(iter1, iter2, options)) {
Michal Vasko52927e22020-03-16 17:26:14 +01002045 return LY_ENOT;
2046 }
2047 iter1 = iter1->next;
2048 iter2 = iter2->next;
2049 }
2050 } else {
2051 /* lists without keys, their equivalence is based on equivalence of all the children (both direct and indirect) */
2052
2053 all_children_compare:
2054 if (!iter1 && !iter2) {
2055 /* no children, nothing to compare */
2056 return LY_SUCCESS;
2057 }
2058
2059 for (; iter1 && iter2; iter1 = iter1->next, iter2 = iter2->next) {
Michal Vasko8f359bf2020-07-28 10:41:15 +02002060 if (lyd_compare_single(iter1, iter2, options | LYD_COMPARE_FULL_RECURSION)) {
Michal Vasko52927e22020-03-16 17:26:14 +01002061 return LY_ENOT;
2062 }
2063 }
2064 if (iter1 || iter2) {
2065 return LY_ENOT;
2066 }
2067 }
2068 return LY_SUCCESS;
2069 case LYS_ANYXML:
2070 case LYS_ANYDATA:
2071 any1 = (struct lyd_node_any*)node1;
2072 any2 = (struct lyd_node_any*)node2;
2073
2074 if (any1->value_type != any2->value_type) {
2075 return LY_ENOT;
2076 }
2077 switch (any1->value_type) {
2078 case LYD_ANYDATA_DATATREE:
2079 iter1 = any1->value.tree;
2080 iter2 = any2->value.tree;
2081 goto all_children_compare;
2082 case LYD_ANYDATA_STRING:
2083 case LYD_ANYDATA_XML:
2084 case LYD_ANYDATA_JSON:
2085 len1 = strlen(any1->value.str);
2086 len2 = strlen(any2->value.str);
2087 if (len1 != len2 || strcmp(any1->value.str, any2->value.str)) {
2088 return LY_ENOT;
2089 }
2090 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01002091 case LYD_ANYDATA_LYB:
Michal Vasko60ea6352020-06-29 13:39:39 +02002092 len1 = lyd_lyb_data_length(any1->value.mem);
2093 len2 = lyd_lyb_data_length(any2->value.mem);
Michal Vasko52927e22020-03-16 17:26:14 +01002094 if (len1 != len2 || memcmp(any1->value.mem, any2->value.mem, len1)) {
2095 return LY_ENOT;
2096 }
2097 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01002098 }
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002099 }
2100 }
2101
Michal Vasko52927e22020-03-16 17:26:14 +01002102 LOGINT(LYD_NODE_CTX(node1));
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002103 return LY_EINT;
2104}
Radek Krejci22ebdba2019-07-25 13:59:43 +02002105
Michal Vasko21725742020-06-29 11:49:25 +02002106API LY_ERR
Michal Vasko8f359bf2020-07-28 10:41:15 +02002107lyd_compare_siblings(const struct lyd_node *node1, const struct lyd_node *node2, int options)
2108{
2109 for (; node1 && node2; node1 = node1->next, node2 = node2->next) {
2110 LY_CHECK_RET(lyd_compare_single(node1, node2, options));
2111 }
2112
Michal Vasko11a81432020-07-28 16:31:29 +02002113 if (node1 == node2) {
2114 return LY_SUCCESS;
Michal Vasko8f359bf2020-07-28 10:41:15 +02002115 }
Michal Vasko11a81432020-07-28 16:31:29 +02002116 return LY_ENOT;
Michal Vasko8f359bf2020-07-28 10:41:15 +02002117}
2118
2119API LY_ERR
Michal Vasko21725742020-06-29 11:49:25 +02002120lyd_compare_meta(const struct lyd_meta *meta1, const struct lyd_meta *meta2)
2121{
2122 if (!meta1 || !meta2) {
2123 if (meta1 == meta2) {
2124 return LY_SUCCESS;
2125 } else {
2126 return LY_ENOT;
2127 }
2128 }
2129
2130 if ((LYD_NODE_CTX(meta1->parent) != LYD_NODE_CTX(meta2->parent)) || (meta1->annotation != meta2->annotation)) {
2131 return LY_ENOT;
2132 }
2133
2134 if (meta1->value.realtype != meta2->value.realtype) {
2135 return LY_ENOT;
2136 }
2137
2138 return meta1->value.realtype->plugin->compare(&meta1->value, &meta2->value);
2139}
2140
Radek Krejci22ebdba2019-07-25 13:59:43 +02002141/**
Michal Vasko52927e22020-03-16 17:26:14 +01002142 * @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 +02002143 *
2144 * 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 +02002145 *
2146 * @param[in] node Original node to duplicate
2147 * @param[in] parent Parent to insert into, NULL for top-level sibling.
2148 * @param[in,out] first First sibling, NULL if no top-level sibling exist yet. Can be also NULL if @p parent is set.
2149 * @param[in] options Bitmask of options flags, see @ref dupoptions.
2150 * @param[out] dup_p Pointer where the created duplicated node is placed (besides connecting it int @p parent / @p first sibling).
2151 * @return LY_ERR value
Radek Krejci22ebdba2019-07-25 13:59:43 +02002152 */
Michal Vasko52927e22020-03-16 17:26:14 +01002153static LY_ERR
Michal Vasko3a41dff2020-07-15 14:30:28 +02002154lyd_dup_r(const struct lyd_node *node, struct lyd_node *parent, struct lyd_node **first, int options,
2155 struct lyd_node **dup_p)
Radek Krejci22ebdba2019-07-25 13:59:43 +02002156{
Michal Vasko52927e22020-03-16 17:26:14 +01002157 LY_ERR ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002158 struct lyd_node *dup = NULL;
Michal Vasko61551fa2020-07-09 15:45:45 +02002159 struct lyd_meta *meta;
2160 struct lyd_node_any *any;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002161 LY_ARRAY_COUNT_TYPE u;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002162
Michal Vasko52927e22020-03-16 17:26:14 +01002163 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002164
Michal Vasko52927e22020-03-16 17:26:14 +01002165 if (!node->schema) {
2166 dup = calloc(1, sizeof(struct lyd_node_opaq));
2167 } else {
2168 switch (node->schema->nodetype) {
Michal Vasko1bf09392020-03-27 12:38:10 +01002169 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01002170 case LYS_ACTION:
2171 case LYS_NOTIF:
2172 case LYS_CONTAINER:
2173 case LYS_LIST:
2174 dup = calloc(1, sizeof(struct lyd_node_inner));
2175 break;
2176 case LYS_LEAF:
2177 case LYS_LEAFLIST:
2178 dup = calloc(1, sizeof(struct lyd_node_term));
2179 break;
2180 case LYS_ANYDATA:
2181 case LYS_ANYXML:
2182 dup = calloc(1, sizeof(struct lyd_node_any));
2183 break;
2184 default:
2185 LOGINT(LYD_NODE_CTX(node));
2186 ret = LY_EINT;
2187 goto error;
2188 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02002189 }
Michal Vasko52927e22020-03-16 17:26:14 +01002190 LY_CHECK_ERR_GOTO(!dup, LOGMEM(LYD_NODE_CTX(node)); ret = LY_EMEM, error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002191
Michal Vaskof6df0a02020-06-16 13:08:34 +02002192 if (options & LYD_DUP_WITH_FLAGS) {
2193 dup->flags = node->flags;
2194 } else {
2195 dup->flags = (node->flags & LYD_DEFAULT) | LYD_NEW;
2196 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02002197 dup->schema = node->schema;
Michal Vasko52927e22020-03-16 17:26:14 +01002198 dup->prev = dup;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002199
Michal Vasko25a32822020-07-09 15:48:22 +02002200 /* duplicate metadata */
2201 if (!(options & LYD_DUP_NO_META)) {
2202 LY_LIST_FOR(node->meta, meta) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002203 LY_CHECK_GOTO(ret = lyd_dup_meta_single(meta, dup, NULL), error);
Michal Vasko25a32822020-07-09 15:48:22 +02002204 }
2205 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02002206
2207 /* nodetype-specific work */
Michal Vasko52927e22020-03-16 17:26:14 +01002208 if (!dup->schema) {
2209 struct lyd_node_opaq *opaq = (struct lyd_node_opaq *)dup;
2210 struct lyd_node_opaq *orig = (struct lyd_node_opaq *)node;
2211 struct lyd_node *child;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002212
2213 if (options & LYD_DUP_RECURSIVE) {
2214 /* duplicate all the children */
2215 LY_LIST_FOR(orig->child, child) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002216 LY_CHECK_GOTO(ret = lyd_dup_r(child, dup, NULL, options, NULL), error);
Michal Vasko52927e22020-03-16 17:26:14 +01002217 }
2218 }
2219 opaq->name = lydict_insert(LYD_NODE_CTX(node), orig->name, 0);
2220 opaq->format = orig->format;
2221 if (orig->prefix.pref) {
2222 opaq->prefix.pref = lydict_insert(LYD_NODE_CTX(node), orig->prefix.pref, 0);
2223 }
2224 if (orig->prefix.ns) {
2225 opaq->prefix.ns = lydict_insert(LYD_NODE_CTX(node), orig->prefix.ns, 0);
2226 }
2227 if (orig->val_prefs) {
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002228 LY_ARRAY_CREATE_GOTO(LYD_NODE_CTX(node), opaq->val_prefs, LY_ARRAY_COUNT(orig->val_prefs), ret, error);
Michal Vasko52927e22020-03-16 17:26:14 +01002229 LY_ARRAY_FOR(orig->val_prefs, u) {
2230 opaq->val_prefs[u].pref = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].pref, 0);
2231 opaq->val_prefs[u].ns = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].ns, 0);
2232 LY_ARRAY_INCREMENT(opaq->val_prefs);
2233 }
2234 }
2235 opaq->value = lydict_insert(LYD_NODE_CTX(node), orig->value, 0);
2236 opaq->ctx = orig->ctx;
2237 } else if (dup->schema->nodetype & LYD_NODE_TERM) {
2238 struct lyd_node_term *term = (struct lyd_node_term *)dup;
2239 struct lyd_node_term *orig = (struct lyd_node_term *)node;
2240
2241 term->hash = orig->hash;
2242 term->value.realtype = orig->value.realtype;
2243 LY_CHECK_ERR_GOTO(term->value.realtype->plugin->duplicate(LYD_NODE_CTX(node), &orig->value, &term->value),
2244 LOGERR(LYD_NODE_CTX(node), LY_EINT, "Value duplication failed."); ret = LY_EINT, error);
2245 } else if (dup->schema->nodetype & LYD_NODE_INNER) {
2246 struct lyd_node_inner *orig = (struct lyd_node_inner *)node;
2247 struct lyd_node *child;
2248
2249 if (options & LYD_DUP_RECURSIVE) {
2250 /* duplicate all the children */
2251 LY_LIST_FOR(orig->child, child) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002252 LY_CHECK_GOTO(ret = lyd_dup_r(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002253 }
Radek Krejci0fe9b512019-07-26 17:51:05 +02002254 } else if (dup->schema->nodetype == LYS_LIST && !(dup->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002255 /* always duplicate keys of a list */
Radek Krejci22ebdba2019-07-25 13:59:43 +02002256 child = orig->child;
Michal Vasko52927e22020-03-16 17:26:14 +01002257 for (struct lysc_node *key = ((struct lysc_node_list *)dup->schema)->child;
Michal Vaskoc57d9a92020-06-23 13:28:27 +02002258 key && (key->flags & LYS_KEY);
Radek Krejci0fe9b512019-07-26 17:51:05 +02002259 key = key->next) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002260 if (!child) {
2261 /* possibly not keys are present in filtered tree */
2262 break;
Radek Krejci0fe9b512019-07-26 17:51:05 +02002263 } else if (child->schema != key) {
2264 /* possibly not all keys are present in filtered tree,
2265 * but there can be also some non-key nodes */
2266 continue;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002267 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002268 LY_CHECK_GOTO(ret = lyd_dup_r(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002269 child = child->next;
2270 }
2271 }
2272 lyd_hash(dup);
2273 } else if (dup->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko61551fa2020-07-09 15:45:45 +02002274 dup->hash = node->hash;
2275 any = (struct lyd_node_any *)node;
2276 LY_CHECK_GOTO(ret = lyd_any_copy_value(dup, &any->value, any->value_type), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002277 }
2278
Michal Vasko52927e22020-03-16 17:26:14 +01002279 /* insert */
2280 lyd_insert_node(parent, first, dup);
Michal Vasko52927e22020-03-16 17:26:14 +01002281
2282 if (dup_p) {
2283 *dup_p = dup;
2284 }
2285 return LY_SUCCESS;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002286
2287error:
Michal Vasko52927e22020-03-16 17:26:14 +01002288 lyd_free_tree(dup);
2289 return ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002290}
2291
Michal Vasko3a41dff2020-07-15 14:30:28 +02002292static LY_ERR
2293lyd_dup_get_local_parent(const struct lyd_node *node, const struct lyd_node_inner *parent, struct lyd_node **dup_parent,
2294 struct lyd_node_inner **local_parent)
Radek Krejci22ebdba2019-07-25 13:59:43 +02002295{
Michal Vasko3a41dff2020-07-15 14:30:28 +02002296 const struct lyd_node_inner *orig_parent, *iter;
2297 int repeat = 1;
2298
2299 *dup_parent = NULL;
2300 *local_parent = NULL;
2301
2302 for (orig_parent = node->parent; repeat && orig_parent; orig_parent = orig_parent->parent) {
2303 if (parent && (parent->schema == orig_parent->schema)) {
2304 /* stop creating parents, connect what we have into the provided parent */
2305 iter = parent;
2306 repeat = 0;
2307 } else {
2308 iter = NULL;
2309 LY_CHECK_RET(lyd_dup_r((struct lyd_node *)orig_parent, NULL, (struct lyd_node **)&iter, 0,
2310 (struct lyd_node **)&iter));
2311 }
2312 if (!*local_parent) {
2313 *local_parent = (struct lyd_node_inner *)iter;
2314 }
2315 if (iter->child) {
2316 /* 1) list - add after keys
2317 * 2) provided parent with some children */
2318 iter->child->prev->next = *dup_parent;
2319 if (*dup_parent) {
2320 (*dup_parent)->prev = iter->child->prev;
2321 iter->child->prev = *dup_parent;
2322 }
2323 } else {
2324 ((struct lyd_node_inner *)iter)->child = *dup_parent;
2325 }
2326 if (*dup_parent) {
2327 (*dup_parent)->parent = (struct lyd_node_inner *)iter;
2328 }
2329 *dup_parent = (struct lyd_node *)iter;
2330 }
2331
2332 if (repeat && parent) {
2333 /* given parent and created parents chain actually do not interconnect */
2334 LOGERR(LYD_NODE_CTX(node), LY_EINVAL,
2335 "Invalid argument parent (%s()) - does not interconnect with the created node's parents chain.", __func__);
2336 return LY_EINVAL;
2337 }
2338
2339 return LY_SUCCESS;
2340}
2341
2342static LY_ERR
2343lyd_dup(const struct lyd_node *node, struct lyd_node_inner *parent, int options, int nosiblings, struct lyd_node **dup)
2344{
2345 LY_ERR rc;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002346 const struct lyd_node *orig; /* original node to be duplicated */
2347 struct lyd_node *first = NULL; /* the first duplicated node, this is returned */
Radek Krejci22ebdba2019-07-25 13:59:43 +02002348 struct lyd_node *top = NULL; /* the most higher created node */
2349 struct lyd_node_inner *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
Radek Krejci22ebdba2019-07-25 13:59:43 +02002350
Michal Vasko3a41dff2020-07-15 14:30:28 +02002351 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002352
2353 if (options & LYD_DUP_WITH_PARENTS) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002354 LY_CHECK_GOTO(rc = lyd_dup_get_local_parent(node, parent, &top, &local_parent), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002355 } else {
2356 local_parent = parent;
2357 }
2358
Radek Krejci22ebdba2019-07-25 13:59:43 +02002359 LY_LIST_FOR(node, orig) {
Michal Vasko52927e22020-03-16 17:26:14 +01002360 /* if there is no local parent, it will be inserted into first */
Michal Vasko3a41dff2020-07-15 14:30:28 +02002361 LY_CHECK_GOTO(rc = lyd_dup_r(orig, (struct lyd_node *)local_parent, &first, options, first ? NULL : &first), error);
2362 if (nosiblings) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002363 break;
2364 }
2365 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002366
2367 /* rehash if needed */
2368 for (; local_parent; local_parent = local_parent->parent) {
2369 if (local_parent->schema->nodetype == LYS_LIST && (local_parent->schema->flags & LYS_KEYLESS)) {
2370 lyd_hash((struct lyd_node *)local_parent);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002371 }
2372 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002373
2374 if (dup) {
2375 *dup = first;
2376 }
2377 return LY_SUCCESS;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002378
2379error:
2380 if (top) {
2381 lyd_free_tree(top);
2382 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +01002383 lyd_free_siblings(first);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002384 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002385 return rc;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002386}
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002387
Michal Vasko3a41dff2020-07-15 14:30:28 +02002388API LY_ERR
2389lyd_dup_single(const struct lyd_node *node, struct lyd_node_inner *parent, int options, struct lyd_node **dup)
2390{
2391 return lyd_dup(node, parent, options, 1, dup);
2392}
2393
2394API LY_ERR
2395lyd_dup_siblings(const struct lyd_node *node, struct lyd_node_inner *parent, int options, struct lyd_node **dup)
2396{
2397 return lyd_dup(node, parent, options, 0, dup);
2398}
2399
2400API LY_ERR
2401lyd_dup_meta_single(const struct lyd_meta *meta, struct lyd_node *node, struct lyd_meta **dup)
Michal Vasko25a32822020-07-09 15:48:22 +02002402{
2403 LY_ERR ret;
2404 struct lyd_meta *mt, *last;
2405
Michal Vasko3a41dff2020-07-15 14:30:28 +02002406 LY_CHECK_ARG_RET(NULL, meta, node, LY_EINVAL);
Michal Vasko25a32822020-07-09 15:48:22 +02002407
2408 /* create a copy */
2409 mt = calloc(1, sizeof *mt);
Michal Vasko3a41dff2020-07-15 14:30:28 +02002410 LY_CHECK_ERR_RET(!mt, LOGMEM(LYD_NODE_CTX(node)), LY_EMEM);
Michal Vasko25a32822020-07-09 15:48:22 +02002411 mt->parent = node;
2412 mt->annotation = meta->annotation;
2413 mt->value.realtype = meta->value.realtype;
2414 ret = mt->value.realtype->plugin->duplicate(LYD_NODE_CTX(node), &meta->value, &mt->value);
Michal Vasko3a41dff2020-07-15 14:30:28 +02002415 LY_CHECK_ERR_RET(ret, LOGERR(LYD_NODE_CTX(node), LY_EINT, "Value duplication failed."), ret);
Michal Vasko25a32822020-07-09 15:48:22 +02002416 mt->name = lydict_insert(LYD_NODE_CTX(node), meta->name, 0);
2417
2418 /* insert as the last attribute */
2419 if (node->meta) {
2420 for (last = node->meta; last->next; last = last->next);
2421 last->next = mt;
2422 } else {
2423 node->meta = mt;
2424 }
2425
Michal Vasko3a41dff2020-07-15 14:30:28 +02002426 if (dup) {
2427 *dup = mt;
2428 }
2429 return LY_SUCCESS;
Michal Vasko25a32822020-07-09 15:48:22 +02002430}
2431
Michal Vasko4490d312020-06-16 13:08:55 +02002432/**
2433 * @brief Merge a source sibling into target siblings.
2434 *
2435 * @param[in,out] first_trg First target sibling, is updated if top-level.
2436 * @param[in] parent_trg Target parent.
2437 * @param[in,out] sibling_src Source sibling to merge, set to NULL if spent.
2438 * @param[in] options Merge options.
2439 * @return LY_ERR value.
2440 */
2441static LY_ERR
2442lyd_merge_sibling_r(struct lyd_node **first_trg, struct lyd_node *parent_trg, const struct lyd_node **sibling_src_p,
2443 int options)
2444{
2445 LY_ERR ret;
2446 const struct lyd_node *child_src, *tmp, *sibling_src;
2447 struct lyd_node *match_trg, *dup_src, *next, *elem;
2448 struct lysc_type *type;
Michal Vasko4490d312020-06-16 13:08:55 +02002449
2450 sibling_src = *sibling_src_p;
2451 if (sibling_src->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
2452 /* try to find the exact instance */
2453 ret = lyd_find_sibling_first(*first_trg, sibling_src, &match_trg);
2454 } else {
2455 /* try to simply find the node, there cannot be more instances */
2456 ret = lyd_find_sibling_val(*first_trg, sibling_src->schema, NULL, 0, &match_trg);
2457 }
2458
2459 if (!ret) {
2460 /* node found, make sure even value matches for all node types */
Michal Vasko8f359bf2020-07-28 10:41:15 +02002461 if ((match_trg->schema->nodetype == LYS_LEAF) && lyd_compare_single(sibling_src, match_trg, LYD_COMPARE_DEFAULTS)) {
Michal Vasko4490d312020-06-16 13:08:55 +02002462 /* since they are different, they cannot both be default */
2463 assert(!(sibling_src->flags & LYD_DEFAULT) || !(match_trg->flags & LYD_DEFAULT));
2464
Michal Vasko3a41dff2020-07-15 14:30:28 +02002465 /* update value (or only LYD_DEFAULT flag) only if flag set or the source node is not default */
2466 if ((options & LYD_MERGE_DEFAULTS) || !(sibling_src->flags & LYD_DEFAULT)) {
Michal Vasko4490d312020-06-16 13:08:55 +02002467 type = ((struct lysc_node_leaf *)match_trg->schema)->type;
2468 type->plugin->free(LYD_NODE_CTX(match_trg), &((struct lyd_node_term *)match_trg)->value);
2469 LY_CHECK_RET(type->plugin->duplicate(LYD_NODE_CTX(match_trg), &((struct lyd_node_term *)sibling_src)->value,
2470 &((struct lyd_node_term *)match_trg)->value));
2471
2472 /* copy flags and add LYD_NEW */
2473 match_trg->flags = sibling_src->flags | LYD_NEW;
2474 }
Michal Vasko8f359bf2020-07-28 10:41:15 +02002475 } else if ((match_trg->schema->nodetype & LYS_ANYDATA) && lyd_compare_single(sibling_src, match_trg, 0)) {
Michal Vasko4c583e82020-07-17 12:16:14 +02002476 /* update value */
2477 LY_CHECK_RET(lyd_any_copy_value(match_trg, &((struct lyd_node_any *)sibling_src)->value,
2478 ((struct lyd_node_any *)sibling_src)->value_type));
Michal Vasko4490d312020-06-16 13:08:55 +02002479
2480 /* copy flags and add LYD_NEW */
2481 match_trg->flags = sibling_src->flags | LYD_NEW;
Michal Vasko4490d312020-06-16 13:08:55 +02002482 } else {
2483 /* check descendants, recursively */
Michal Vasko5bfd4be2020-06-23 13:26:19 +02002484 LY_LIST_FOR_SAFE(LYD_CHILD(sibling_src), tmp, child_src) {
Michal Vasko4490d312020-06-16 13:08:55 +02002485 LY_CHECK_RET(lyd_merge_sibling_r(lyd_node_children_p(match_trg), match_trg, &child_src, options));
2486 }
2487 }
2488 } else {
2489 /* node not found, merge it */
2490 if (options & LYD_MERGE_DESTRUCT) {
2491 dup_src = (struct lyd_node *)sibling_src;
2492 lyd_unlink_tree(dup_src);
2493 /* spend it */
2494 *sibling_src_p = NULL;
2495 } else {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002496 LY_CHECK_RET(lyd_dup_single(sibling_src, NULL, LYD_DUP_RECURSIVE | LYD_DUP_WITH_FLAGS, &dup_src));
Michal Vasko4490d312020-06-16 13:08:55 +02002497 }
2498
2499 /* set LYD_NEW for all the new nodes, required for validation */
2500 LYD_TREE_DFS_BEGIN(dup_src, next, elem) {
2501 elem->flags |= LYD_NEW;
2502 LYD_TREE_DFS_END(dup_src, next, elem);
2503 }
2504
2505 lyd_insert_node(parent_trg, first_trg, dup_src);
2506 }
2507
2508 return LY_SUCCESS;
2509}
2510
Michal Vasko3a41dff2020-07-15 14:30:28 +02002511static LY_ERR
2512lyd_merge(struct lyd_node **target, const struct lyd_node *source, int options, int nosiblings)
Michal Vasko4490d312020-06-16 13:08:55 +02002513{
2514 const struct lyd_node *sibling_src, *tmp;
2515 int first;
2516
2517 LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
2518
2519 if (!source) {
2520 /* nothing to merge */
2521 return LY_SUCCESS;
2522 }
2523
2524 if (lysc_data_parent((*target)->schema) || lysc_data_parent(source->schema)) {
2525 LOGERR(LYD_NODE_CTX(source), LY_EINVAL, "Invalid arguments - can merge only 2 top-level subtrees (%s()).", __func__);
2526 return LY_EINVAL;
2527 }
2528
2529 LY_LIST_FOR_SAFE(source, tmp, sibling_src) {
2530 first = sibling_src == source ? 1 : 0;
2531 LY_CHECK_RET(lyd_merge_sibling_r(target, NULL, &sibling_src, options));
2532 if (first && !sibling_src) {
2533 /* source was spent (unlinked), move to the next node */
2534 source = tmp;
2535 }
2536
Michal Vasko3a41dff2020-07-15 14:30:28 +02002537 if (nosiblings) {
Michal Vasko4490d312020-06-16 13:08:55 +02002538 break;
2539 }
2540 }
2541
2542 if (options & LYD_MERGE_DESTRUCT) {
2543 /* free any leftover source data that were not merged */
2544 lyd_free_siblings((struct lyd_node *)source);
2545 }
2546
2547 return LY_SUCCESS;
2548}
2549
Michal Vasko3a41dff2020-07-15 14:30:28 +02002550API LY_ERR
2551lyd_merge_tree(struct lyd_node **target, const struct lyd_node *source, int options)
2552{
2553 return lyd_merge(target, source, options, 1);
2554}
2555
2556API LY_ERR
2557lyd_merge_siblings(struct lyd_node **target, const struct lyd_node *source, int options)
2558{
2559 return lyd_merge(target, source, options, 0);
2560}
2561
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002562static LY_ERR
2563lyd_path_str_enlarge(char **buffer, size_t *buflen, size_t reqlen, int is_static)
2564{
Michal Vasko14654712020-02-06 08:35:21 +01002565 /* ending \0 */
2566 ++reqlen;
2567
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002568 if (reqlen > *buflen) {
2569 if (is_static) {
2570 return LY_EINCOMPLETE;
2571 }
2572
2573 *buffer = ly_realloc(*buffer, reqlen * sizeof **buffer);
2574 if (!*buffer) {
2575 return LY_EMEM;
2576 }
2577
2578 *buflen = reqlen;
2579 }
2580
2581 return LY_SUCCESS;
2582}
2583
Michal Vaskod59035b2020-07-08 12:00:06 +02002584LY_ERR
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002585lyd_path_list_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2586{
2587 const struct lyd_node *key;
2588 int dynamic = 0;
2589 size_t len;
2590 const char *val;
2591 char quot;
2592 LY_ERR rc;
2593
Michal Vasko5bfd4be2020-06-23 13:26:19 +02002594 for (key = lyd_node_children(node, 0); key && (key->schema->flags & LYS_KEY); key = key->next) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002595 val = lyd_value2str((struct lyd_node_term *)key, &dynamic);
2596 len = 1 + strlen(key->schema->name) + 2 + strlen(val) + 2;
2597 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2598 if (rc != LY_SUCCESS) {
2599 if (dynamic) {
2600 free((char *)val);
2601 }
2602 return rc;
2603 }
2604
2605 quot = '\'';
2606 if (strchr(val, '\'')) {
2607 quot = '"';
2608 }
2609 *bufused += sprintf(*buffer + *bufused, "[%s=%c%s%c]", key->schema->name, quot, val, quot);
2610
2611 if (dynamic) {
2612 free((char *)val);
2613 }
2614 }
2615
2616 return LY_SUCCESS;
2617}
2618
2619/**
2620 * @brief Append leaf-list value predicate to path.
2621 *
2622 * @param[in] node Node to print.
2623 * @param[in,out] buffer Buffer to print to.
2624 * @param[in,out] buflen Current buffer length.
2625 * @param[in,out] bufused Current number of characters used in @p buffer.
2626 * @param[in] is_static Whether buffer is static or can be reallocated.
2627 * @return LY_ERR
2628 */
2629static LY_ERR
2630lyd_path_leaflist_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2631{
2632 int dynamic = 0;
2633 size_t len;
2634 const char *val;
2635 char quot;
2636 LY_ERR rc;
2637
2638 val = lyd_value2str((struct lyd_node_term *)node, &dynamic);
2639 len = 4 + strlen(val) + 2;
2640 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2641 if (rc != LY_SUCCESS) {
2642 goto cleanup;
2643 }
2644
2645 quot = '\'';
2646 if (strchr(val, '\'')) {
2647 quot = '"';
2648 }
2649 *bufused += sprintf(*buffer + *bufused, "[.=%c%s%c]", quot, val, quot);
2650
2651cleanup:
2652 if (dynamic) {
2653 free((char *)val);
2654 }
2655 return rc;
2656}
2657
2658/**
2659 * @brief Append node position (relative to its other instances) predicate to path.
2660 *
2661 * @param[in] node Node to print.
2662 * @param[in,out] buffer Buffer to print to.
2663 * @param[in,out] buflen Current buffer length.
2664 * @param[in,out] bufused Current number of characters used in @p buffer.
2665 * @param[in] is_static Whether buffer is static or can be reallocated.
2666 * @return LY_ERR
2667 */
2668static LY_ERR
2669lyd_path_position_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2670{
2671 const struct lyd_node *first, *iter;
2672 size_t len;
2673 int pos;
2674 char *val = NULL;
2675 LY_ERR rc;
2676
2677 if (node->parent) {
2678 first = node->parent->child;
2679 } else {
2680 for (first = node; node->prev->next; node = node->prev);
2681 }
2682 pos = 1;
2683 for (iter = first; iter != node; iter = iter->next) {
2684 if (iter->schema == node->schema) {
2685 ++pos;
2686 }
2687 }
2688 if (asprintf(&val, "%d", pos) == -1) {
2689 return LY_EMEM;
2690 }
2691
2692 len = 1 + strlen(val) + 1;
2693 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2694 if (rc != LY_SUCCESS) {
2695 goto cleanup;
2696 }
2697
2698 *bufused += sprintf(*buffer + *bufused, "[%s]", val);
2699
2700cleanup:
2701 free(val);
2702 return rc;
2703}
2704
2705API char *
2706lyd_path(const struct lyd_node *node, LYD_PATH_TYPE pathtype, char *buffer, size_t buflen)
2707{
Michal Vasko14654712020-02-06 08:35:21 +01002708 int is_static = 0, i, depth;
2709 size_t bufused = 0, len;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002710 const struct lyd_node *iter;
2711 const struct lys_module *mod;
Michal Vasko790b2bc2020-08-03 13:35:06 +02002712 LY_ERR rc = LY_SUCCESS;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002713
2714 LY_CHECK_ARG_RET(NULL, node, NULL);
2715 if (buffer) {
2716 LY_CHECK_ARG_RET(node->schema->module->ctx, buflen > 1, NULL);
2717 is_static = 1;
Michal Vasko14654712020-02-06 08:35:21 +01002718 } else {
2719 buflen = 0;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002720 }
2721
2722 switch (pathtype) {
Michal Vasko14654712020-02-06 08:35:21 +01002723 case LYD_PATH_LOG:
Michal Vasko790b2bc2020-08-03 13:35:06 +02002724 case LYD_PATH_LOG_NO_LAST_PRED:
Michal Vasko14654712020-02-06 08:35:21 +01002725 depth = 1;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002726 for (iter = node; iter->parent; iter = (const struct lyd_node *)iter->parent) {
2727 ++depth;
2728 }
2729
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002730 goto iter_print;
Michal Vasko14654712020-02-06 08:35:21 +01002731 while (depth) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002732 /* find the right node */
Michal Vasko14654712020-02-06 08:35:21 +01002733 for (iter = node, i = 1; i < depth; iter = (const struct lyd_node *)iter->parent, ++i);
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002734iter_print:
2735 /* print prefix and name */
2736 mod = NULL;
2737 if (!iter->parent || (iter->schema->module != iter->parent->schema->module)) {
2738 mod = iter->schema->module;
2739 }
2740
2741 /* realloc string */
2742 len = 1 + (mod ? strlen(mod->name) + 1 : 0) + strlen(iter->schema->name);
2743 rc = lyd_path_str_enlarge(&buffer, &buflen, bufused + len, is_static);
2744 if (rc != LY_SUCCESS) {
2745 break;
2746 }
2747
2748 /* print next node */
2749 bufused += sprintf(buffer + bufused, "/%s%s%s", mod ? mod->name : "", mod ? ":" : "", iter->schema->name);
2750
Michal Vasko790b2bc2020-08-03 13:35:06 +02002751 /* do not always print the last (first) predicate */
2752 if (bufused || (pathtype == LYD_PATH_LOG)) {
2753 switch (iter->schema->nodetype) {
2754 case LYS_LIST:
2755 if (iter->schema->flags & LYS_KEYLESS) {
2756 /* print its position */
2757 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2758 } else {
2759 /* print all list keys in predicates */
2760 rc = lyd_path_list_predicate(iter, &buffer, &buflen, &bufused, is_static);
2761 }
2762 break;
2763 case LYS_LEAFLIST:
2764 if (iter->schema->flags & LYS_CONFIG_W) {
2765 /* print leaf-list value */
2766 rc = lyd_path_leaflist_predicate(iter, &buffer, &buflen, &bufused, is_static);
2767 } else {
2768 /* print its position */
2769 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2770 }
2771 break;
2772 default:
2773 /* nothing to print more */
2774 break;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002775 }
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002776 }
2777 if (rc != LY_SUCCESS) {
2778 break;
2779 }
2780
Michal Vasko14654712020-02-06 08:35:21 +01002781 --depth;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002782 }
2783 break;
2784 }
2785
2786 return buffer;
2787}
Michal Vaskoe444f752020-02-10 12:20:06 +01002788
Michal Vasko25a32822020-07-09 15:48:22 +02002789API struct lyd_meta *
2790lyd_find_meta(const struct lyd_meta *first, const struct lys_module *module, const char *name)
2791{
2792 struct lyd_meta *ret = NULL;
2793 const struct ly_ctx *ctx;
2794 const char *prefix, *tmp;
2795 char *str;
2796 size_t pref_len, name_len;
2797
2798 LY_CHECK_ARG_RET(NULL, module || strchr(name, ':'), name, NULL);
2799
2800 if (!first) {
2801 return NULL;
2802 }
2803
2804 ctx = first->annotation->module->ctx;
2805
2806 /* parse the name */
2807 tmp = name;
2808 if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
2809 LOGERR(ctx, LY_EINVAL, "Metadata name \"%s\" is not valid.", name);
2810 return NULL;
2811 }
2812
2813 /* find the module */
2814 if (prefix) {
2815 str = strndup(prefix, pref_len);
2816 module = ly_ctx_get_module_latest(ctx, str);
2817 free(str);
2818 LY_CHECK_ERR_RET(!module, LOGERR(ctx, LY_EINVAL, "Module \"%.*s\" not found.", pref_len, prefix), NULL);
2819 }
2820
2821 /* find the metadata */
2822 LY_LIST_FOR(first, first) {
2823 if ((first->annotation->module == module) && !strcmp(first->name, name)) {
2824 ret = (struct lyd_meta *)first;
2825 break;
2826 }
2827 }
2828
2829 return ret;
2830}
2831
Michal Vasko9b368d32020-02-14 13:53:31 +01002832API LY_ERR
Michal Vaskoe444f752020-02-10 12:20:06 +01002833lyd_find_sibling_first(const struct lyd_node *siblings, const struct lyd_node *target, struct lyd_node **match)
2834{
2835 struct lyd_node **match_p;
2836 struct lyd_node_inner *parent;
2837
Michal Vaskof03ed032020-03-04 13:31:44 +01002838 LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01002839
Michal Vasko62ed12d2020-05-21 10:08:25 +02002840 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(target->schema))) {
2841 /* no data or schema mismatch */
Michal Vasko9b368d32020-02-14 13:53:31 +01002842 if (match) {
2843 *match = NULL;
2844 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002845 return LY_ENOTFOUND;
2846 }
2847
2848 /* find first sibling */
2849 if (siblings->parent) {
2850 siblings = siblings->parent->child;
2851 } else {
2852 while (siblings->prev->next) {
2853 siblings = siblings->prev;
2854 }
2855 }
2856
2857 parent = (struct lyd_node_inner *)siblings->parent;
2858 if (parent && parent->children_ht) {
2859 assert(target->hash);
2860
2861 /* find by hash */
2862 if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
Michal Vaskoda859032020-07-14 12:20:14 +02002863 /* check even value when needed */
Michal Vasko8f359bf2020-07-28 10:41:15 +02002864 if (!(target->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !lyd_compare_single(target, *match_p, 0)) {
Michal Vaskoda859032020-07-14 12:20:14 +02002865 siblings = *match_p;
2866 } else {
2867 siblings = NULL;
2868 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002869 } else {
2870 /* not found */
2871 siblings = NULL;
2872 }
2873 } else {
2874 /* no children hash table */
2875 for (; siblings; siblings = siblings->next) {
Michal Vasko8f359bf2020-07-28 10:41:15 +02002876 if (!lyd_compare_single(siblings, target, 0)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002877 break;
2878 }
2879 }
2880 }
2881
2882 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002883 if (match) {
2884 *match = NULL;
2885 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002886 return LY_ENOTFOUND;
2887 }
2888
Michal Vasko9b368d32020-02-14 13:53:31 +01002889 if (match) {
2890 *match = (struct lyd_node *)siblings;
2891 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002892 return LY_SUCCESS;
2893}
2894
Michal Vasko90932a92020-02-12 14:33:03 +01002895static int
2896lyd_hash_table_schema_val_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *UNUSED(cb_data))
2897{
2898 struct lysc_node *val1;
2899 struct lyd_node *val2;
2900
2901 val1 = *((struct lysc_node **)val1_p);
2902 val2 = *((struct lyd_node **)val2_p);
2903
Michal Vasko90932a92020-02-12 14:33:03 +01002904 if (val1 == val2->schema) {
2905 /* schema match is enough */
2906 return 1;
2907 } else {
2908 return 0;
2909 }
2910}
2911
2912static LY_ERR
2913lyd_find_sibling_schema(const struct lyd_node *siblings, const struct lysc_node *schema, struct lyd_node **match)
2914{
2915 struct lyd_node **match_p;
2916 struct lyd_node_inner *parent;
2917 uint32_t hash;
2918 values_equal_cb ht_cb;
2919
Michal Vaskob104f112020-07-17 09:54:54 +02002920 assert(siblings && schema);
Michal Vasko90932a92020-02-12 14:33:03 +01002921
2922 parent = (struct lyd_node_inner *)siblings->parent;
2923 if (parent && parent->children_ht) {
2924 /* calculate our hash */
2925 hash = dict_hash_multi(0, schema->module->name, strlen(schema->module->name));
2926 hash = dict_hash_multi(hash, schema->name, strlen(schema->name));
2927 hash = dict_hash_multi(hash, NULL, 0);
2928
2929 /* use special hash table function */
2930 ht_cb = lyht_set_cb(parent->children_ht, lyd_hash_table_schema_val_equal);
2931
2932 /* find by hash */
2933 if (!lyht_find(parent->children_ht, &schema, hash, (void **)&match_p)) {
2934 siblings = *match_p;
2935 } else {
2936 /* not found */
2937 siblings = NULL;
2938 }
2939
2940 /* set the original hash table compare function back */
2941 lyht_set_cb(parent->children_ht, ht_cb);
2942 } else {
Michal Vaskob104f112020-07-17 09:54:54 +02002943 /* find first sibling */
2944 if (siblings->parent) {
2945 siblings = siblings->parent->child;
2946 } else {
2947 while (siblings->prev->next) {
2948 siblings = siblings->prev;
2949 }
2950 }
2951
2952 /* search manually without hashes */
Michal Vasko90932a92020-02-12 14:33:03 +01002953 for (; siblings; siblings = siblings->next) {
2954 if (siblings->schema == schema) {
2955 /* schema match is enough */
2956 break;
2957 }
2958 }
2959 }
2960
2961 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002962 if (match) {
2963 *match = NULL;
2964 }
Michal Vasko90932a92020-02-12 14:33:03 +01002965 return LY_ENOTFOUND;
2966 }
2967
Michal Vasko9b368d32020-02-14 13:53:31 +01002968 if (match) {
2969 *match = (struct lyd_node *)siblings;
2970 }
Michal Vasko90932a92020-02-12 14:33:03 +01002971 return LY_SUCCESS;
2972}
2973
Michal Vaskoe444f752020-02-10 12:20:06 +01002974API LY_ERR
2975lyd_find_sibling_val(const struct lyd_node *siblings, const struct lysc_node *schema, const char *key_or_value,
2976 size_t val_len, struct lyd_node **match)
2977{
2978 LY_ERR rc;
2979 struct lyd_node *target = NULL;
2980
Michal Vasko4c583e82020-07-17 12:16:14 +02002981 LY_CHECK_ARG_RET(NULL, schema, !(schema->nodetype & (LYS_CHOICE | LYS_CASE)), LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01002982
Michal Vasko62ed12d2020-05-21 10:08:25 +02002983 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(schema))) {
2984 /* no data or schema mismatch */
Michal Vasko9b368d32020-02-14 13:53:31 +01002985 if (match) {
2986 *match = NULL;
2987 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002988 return LY_ENOTFOUND;
2989 }
2990
Michal Vaskof03ed032020-03-04 13:31:44 +01002991 if (key_or_value && !val_len) {
2992 val_len = strlen(key_or_value);
2993 }
2994
Michal Vaskob104f112020-07-17 09:54:54 +02002995 if ((schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) && key_or_value) {
2996 /* create a data node and find the instance */
2997 if (schema->nodetype == LYS_LEAFLIST) {
2998 /* target used attributes: schema, hash, value */
2999 rc = lyd_create_term(schema, key_or_value, val_len, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &target);
3000 LY_CHECK_RET(rc && (rc != LY_EINCOMPLETE), rc);
3001 } else {
Michal Vasko90932a92020-02-12 14:33:03 +01003002 /* target used attributes: schema, hash, child (all keys) */
Michal Vasko004d3152020-06-11 19:59:22 +02003003 LY_CHECK_RET(lyd_create_list2(schema, key_or_value, val_len, &target));
Michal Vasko90932a92020-02-12 14:33:03 +01003004 }
3005
3006 /* find it */
3007 rc = lyd_find_sibling_first(siblings, target, match);
Michal Vaskob104f112020-07-17 09:54:54 +02003008 } else {
3009 /* find the first schema node instance */
3010 rc = lyd_find_sibling_schema(siblings, schema, match);
Michal Vaskoe444f752020-02-10 12:20:06 +01003011 }
3012
Michal Vaskoe444f752020-02-10 12:20:06 +01003013 lyd_free_tree(target);
3014 return rc;
3015}
Michal Vaskoccc02342020-05-21 10:09:21 +02003016
3017API LY_ERR
3018lyd_find_xpath(const struct lyd_node *ctx_node, const char *xpath, struct ly_set **set)
3019{
3020 LY_ERR ret = LY_SUCCESS;
3021 struct lyxp_set xp_set;
3022 struct lyxp_expr *exp;
3023 uint32_t i;
3024
3025 LY_CHECK_ARG_RET(NULL, ctx_node, xpath, set, LY_EINVAL);
3026
3027 memset(&xp_set, 0, sizeof xp_set);
3028
3029 /* compile expression */
Michal Vasko004d3152020-06-11 19:59:22 +02003030 exp = lyxp_expr_parse((struct ly_ctx *)LYD_NODE_CTX(ctx_node), xpath, 0, 1);
Michal Vaskoccc02342020-05-21 10:09:21 +02003031 LY_CHECK_ERR_GOTO(!exp, ret = LY_EINVAL, cleanup);
3032
3033 /* evaluate expression */
3034 ret = lyxp_eval(exp, LYD_JSON, ctx_node->schema->module, ctx_node, LYXP_NODE_ELEM, ctx_node, &xp_set, 0);
3035 LY_CHECK_GOTO(ret, cleanup);
3036
3037 /* allocate return set */
3038 *set = ly_set_new();
3039 LY_CHECK_ERR_GOTO(!*set, LOGMEM(LYD_NODE_CTX(ctx_node)); ret = LY_EMEM, cleanup);
3040
3041 /* transform into ly_set */
3042 if (xp_set.type == LYXP_SET_NODE_SET) {
3043 /* allocate memory for all the elements once (even though not all items must be elements but most likely will be) */
3044 (*set)->objs = malloc(xp_set.used * sizeof *(*set)->objs);
3045 LY_CHECK_ERR_GOTO(!(*set)->objs, LOGMEM(LYD_NODE_CTX(ctx_node)); ret = LY_EMEM, cleanup);
3046 (*set)->size = xp_set.used;
3047
3048 for (i = 0; i < xp_set.used; ++i) {
3049 if (xp_set.val.nodes[i].type == LYXP_NODE_ELEM) {
3050 ly_set_add(*set, xp_set.val.nodes[i].node, LY_SET_OPT_USEASLIST);
3051 }
3052 }
3053 }
3054
3055cleanup:
Michal Vasko0691d522020-05-21 13:21:47 +02003056 lyxp_set_free_content(&xp_set);
Michal Vaskoccc02342020-05-21 10:09:21 +02003057 lyxp_expr_free((struct ly_ctx *)LYD_NODE_CTX(ctx_node), exp);
3058 return ret;
3059}