blob: 01a4a33feb31f251a4d561be003056ec1ae2cc56 [file] [log] [blame]
Radek Krejcie7b95092019-05-15 11:03:07 +02001/**
Michal Vaskob1b5c262020-03-05 14:29:47 +01002 * @file tree_data.c
Radek Krejcie7b95092019-05-15 11:03:07 +02003 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Schema tree implementation
5 *
6 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
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"
31#include "config.h"
32#include "context.h"
33#include "dict.h"
Michal Vasko90932a92020-02-12 14:33:03 +010034#include "hash_table.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020035#include "log.h"
Michal Vasko004d3152020-06-11 19:59:22 +020036#include "path.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020037#include "plugins_exts.h"
Radek Krejci38d85362019-09-05 16:26:38 +020038#include "plugins_exts_metadata.h"
Michal Vasko90932a92020-02-12 14:33:03 +010039#include "plugins_exts_internal.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020040#include "plugins_types.h"
41#include "set.h"
42#include "tree.h"
43#include "tree_data_internal.h"
44#include "tree_schema.h"
45#include "tree_schema_internal.h"
46#include "xml.h"
47#include "xpath.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020048
Radek Krejci084289f2019-07-09 17:35:30 +020049LY_ERR
Michal Vasko90932a92020-02-12 14:33:03 +010050lyd_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 +010051 ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +020052{
Michal Vasko90932a92020-02-12 14:33:03 +010053 LY_ERR ret = LY_SUCCESS;
Radek Krejci084289f2019-07-09 17:35:30 +020054 struct ly_err_item *err = NULL;
55 struct ly_ctx *ctx;
56 struct lysc_type *type;
Radek Krejci3c9758d2019-07-11 16:49:10 +020057 int options = LY_TYPE_OPTS_STORE | (second ? LY_TYPE_OPTS_SECOND_CALL : 0) |
Michal Vaskof03ed032020-03-04 13:31:44 +010058 (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci084289f2019-07-09 17:35:30 +020059 assert(node);
60
61 ctx = node->schema->module->ctx;
Radek Krejci084289f2019-07-09 17:35:30 +020062
Radek Krejci73dead22019-07-11 16:46:16 +020063 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci62903c32019-07-15 14:42:05 +020064 if (!second) {
65 node->value.realtype = type;
66 }
Michal Vasko90932a92020-02-12 14:33:03 +010067 ret = type->plugin->store(ctx, type, value, value_len, options, get_prefix, parser, format,
Michal Vasko004d3152020-06-11 19:59:22 +020068 tree ? (void *)node : (void *)node->schema, tree, &node->value, NULL, &err);
Michal Vasko90932a92020-02-12 14:33:03 +010069 if (ret && (ret != LY_EINCOMPLETE)) {
Radek Krejci73dead22019-07-11 16:46:16 +020070 if (err) {
Michal Vasko3544d1e2020-05-27 11:17:51 +020071 /* node may not be connected yet so use the schema node */
Michal Vaskof872e202020-05-27 11:49:06 +020072 if (!node->parent && lysc_data_parent(node->schema)) {
73 LOGVAL(ctx, LY_VLOG_LYSC, node->schema, err->vecode, err->msg);
74 } else {
75 LOGVAL(ctx, LY_VLOG_LYD, node, err->vecode, err->msg);
76 }
Radek Krejci73dead22019-07-11 16:46:16 +020077 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +020078 }
Radek Krejci73dead22019-07-11 16:46:16 +020079 goto error;
Michal Vasko90932a92020-02-12 14:33:03 +010080 } else if (dynamic) {
81 *dynamic = 0;
Radek Krejci084289f2019-07-09 17:35:30 +020082 }
83
84error:
85 return ret;
86}
87
Michal Vasko00cbf532020-06-15 13:58:47 +020088/* 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 +020089LY_ERR
Michal Vasko90932a92020-02-12 14:33:03 +010090lyd_value_store(struct lyd_value *val, const struct lysc_node *schema, const char *value, size_t value_len, int *dynamic,
91 ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format)
92{
93 LY_ERR ret = LY_SUCCESS;
94 struct ly_err_item *err = NULL;
95 struct ly_ctx *ctx;
96 struct lysc_type *type;
97 int options = LY_TYPE_OPTS_STORE | LY_TYPE_OPTS_INCOMPLETE_DATA | (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0);
98
99 assert(val && schema && (schema->nodetype & LYD_NODE_TERM));
100
101 ctx = schema->module->ctx;
102 type = ((struct lysc_node_leaf *)schema)->type;
103 val->realtype = type;
104 ret = type->plugin->store(ctx, type, value, value_len, options, get_prefix, parser, format, (void *)schema, NULL,
105 val, NULL, &err);
106 if (ret == LY_EINCOMPLETE) {
107 /* this is fine, we do not need it resolved */
108 ret = LY_SUCCESS;
109 } else if (ret && err) {
110 ly_err_print(err);
111 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
112 ly_err_free(err);
113 }
114 if (!ret && dynamic) {
115 *dynamic = 0;
116 }
117
118 return ret;
119}
120
Radek Krejci38d85362019-09-05 16:26:38 +0200121LY_ERR
Michal Vasko9f96a052020-03-10 09:41:45 +0100122lyd_value_parse_meta(struct ly_ctx *ctx, struct lyd_meta *meta, const char *value, size_t value_len, int *dynamic,
Michal Vasko8d544252020-03-02 10:19:52 +0100123 int second, ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format,
Michal Vaskof03ed032020-03-04 13:31:44 +0100124 const struct lysc_node *ctx_snode, const struct lyd_node *tree)
Radek Krejci38d85362019-09-05 16:26:38 +0200125{
Michal Vasko90932a92020-02-12 14:33:03 +0100126 LY_ERR ret = LY_SUCCESS;
Radek Krejci38d85362019-09-05 16:26:38 +0200127 struct ly_err_item *err = NULL;
Radek Krejci38d85362019-09-05 16:26:38 +0200128 struct lyext_metadata *ant;
129 int options = LY_TYPE_OPTS_STORE | (second ? LY_TYPE_OPTS_SECOND_CALL : 0) |
Michal Vaskof03ed032020-03-04 13:31:44 +0100130 (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci38d85362019-09-05 16:26:38 +0200131
Michal Vasko9f96a052020-03-10 09:41:45 +0100132 assert(ctx && meta && ((tree && meta->parent) || ctx_snode));
Michal Vasko8d544252020-03-02 10:19:52 +0100133
Michal Vasko9f96a052020-03-10 09:41:45 +0100134 ant = meta->annotation->data;
Radek Krejci38d85362019-09-05 16:26:38 +0200135
136 if (!second) {
Michal Vasko9f96a052020-03-10 09:41:45 +0100137 meta->value.realtype = ant->type;
Radek Krejci38d85362019-09-05 16:26:38 +0200138 }
Michal Vasko90932a92020-02-12 14:33:03 +0100139 ret = ant->type->plugin->store(ctx, ant->type, value, value_len, options, get_prefix, parser, format,
Michal Vasko9f96a052020-03-10 09:41:45 +0100140 tree ? (void *)meta->parent : (void *)ctx_snode, tree, &meta->value, NULL, &err);
Michal Vasko90932a92020-02-12 14:33:03 +0100141 if (ret && (ret != LY_EINCOMPLETE)) {
Radek Krejci38d85362019-09-05 16:26:38 +0200142 if (err) {
143 ly_err_print(err);
144 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
145 ly_err_free(err);
146 }
147 goto error;
Michal Vasko90932a92020-02-12 14:33:03 +0100148 } else if (dynamic) {
149 *dynamic = 0;
Radek Krejci38d85362019-09-05 16:26:38 +0200150 }
151
152error:
153 return ret;
154}
155
Radek Krejci084289f2019-07-09 17:35:30 +0200156API LY_ERR
Michal Vasko44685da2020-03-17 15:38:06 +0100157lys_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 +0200158 ly_clb_resolve_prefix get_prefix, void *get_prefix_data, LYD_FORMAT format)
159{
160 LY_ERR rc = LY_SUCCESS;
161 struct ly_err_item *err = NULL;
162 struct lysc_type *type;
Radek Krejci084289f2019-07-09 17:35:30 +0200163
164 LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
165
166 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
167 LOGARG(ctx, node);
168 return LY_EINVAL;
169 }
170
171 type = ((struct lysc_node_leaf*)node)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200172 /* just validate, no storing of enything */
173 rc = type->plugin->store(ctx ? ctx : node->module->ctx, type, value, value_len, LY_TYPE_OPTS_INCOMPLETE_DATA,
174 get_prefix, get_prefix_data, format, node, NULL, NULL, NULL, &err);
175 if (rc == LY_EINCOMPLETE) {
176 /* actually success since we do not provide the context tree and call validation with
177 * LY_TYPE_OPTS_INCOMPLETE_DATA */
178 rc = LY_SUCCESS;
179 } else if (rc && err) {
180 if (ctx) {
181 /* log only in case the ctx was provided as input parameter */
182 ly_err_print(err);
183 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
Radek Krejci084289f2019-07-09 17:35:30 +0200184 }
Radek Krejci73dead22019-07-11 16:46:16 +0200185 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200186 }
187
188 return rc;
189}
190
191API LY_ERR
Michal Vasko44685da2020-03-17 15:38:06 +0100192lyd_value_validate(const struct ly_ctx *ctx, const struct lyd_node_term *node, const char *value, size_t value_len,
Michal Vaskof03ed032020-03-04 13:31:44 +0100193 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 +0200194{
195 LY_ERR rc;
196 struct ly_err_item *err = NULL;
197 struct lysc_type *type;
Michal Vaskof03ed032020-03-04 13:31:44 +0100198 int options = (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci084289f2019-07-09 17:35:30 +0200199
200 LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
201
202 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200203 rc = type->plugin->store(ctx ? ctx : node->schema->module->ctx, type, value, value_len, options,
Michal Vaskof03ed032020-03-04 13:31:44 +0100204 get_prefix, get_prefix_data, format, tree ? (void*)node : (void*)node->schema, tree,
Radek Krejci73dead22019-07-11 16:46:16 +0200205 NULL, NULL, &err);
206 if (rc == LY_EINCOMPLETE) {
207 return rc;
208 } else if (rc) {
209 if (err) {
210 if (ctx) {
211 ly_err_print(err);
212 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
Radek Krejci084289f2019-07-09 17:35:30 +0200213 }
Radek Krejci73dead22019-07-11 16:46:16 +0200214 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200215 }
Radek Krejci73dead22019-07-11 16:46:16 +0200216 return rc;
Radek Krejci084289f2019-07-09 17:35:30 +0200217 }
218
219 return LY_SUCCESS;
220}
221
222API LY_ERR
223lyd_value_compare(const struct lyd_node_term *node, const char *value, size_t value_len,
Michal Vaskof03ed032020-03-04 13:31:44 +0100224 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 +0200225{
226 LY_ERR ret = LY_SUCCESS, rc;
227 struct ly_err_item *err = NULL;
228 struct ly_ctx *ctx;
229 struct lysc_type *type;
Radek Krejci084289f2019-07-09 17:35:30 +0200230 struct lyd_value data = {0};
Michal Vaskof03ed032020-03-04 13:31:44 +0100231 int options = LY_TYPE_OPTS_STORE | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci084289f2019-07-09 17:35:30 +0200232
233 LY_CHECK_ARG_RET(node ? node->schema->module->ctx : NULL, node, value, LY_EINVAL);
234
235 ctx = node->schema->module->ctx;
236 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200237 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 +0100238 tree, &data, NULL, &err);
Radek Krejci73dead22019-07-11 16:46:16 +0200239 if (rc == LY_EINCOMPLETE) {
240 ret = rc;
241 /* continue with comparing, just remember what to return if storing is ok */
242 } else if (rc) {
243 /* value to compare is invalid */
244 ret = LY_EINVAL;
245 if (err) {
246 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200247 }
Radek Krejci73dead22019-07-11 16:46:16 +0200248 goto cleanup;
Radek Krejci084289f2019-07-09 17:35:30 +0200249 }
250
251 /* compare data */
Radek Krejci5af04842019-07-12 11:32:07 +0200252 if (type->plugin->compare(&node->value, &data)) {
253 /* do not assign it directly from the compare callback to keep possible LY_EINCOMPLETE from validation */
254 ret = LY_EVALID;
255 }
Radek Krejci084289f2019-07-09 17:35:30 +0200256
257cleanup:
Radek Krejci62903c32019-07-15 14:42:05 +0200258 type->plugin->free(ctx, &data);
Radek Krejci084289f2019-07-09 17:35:30 +0200259
260 return ret;
261}
262
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200263API const char *
264lyd_value2str(const struct lyd_node_term *node, int *dynamic)
265{
266 LY_CHECK_ARG_RET(node ? node->schema->module->ctx : NULL, node, dynamic, NULL);
267
268 return node->value.realtype->plugin->print(&node->value, LYD_JSON, json_print_get_prefix, NULL, dynamic);
269}
270
271API const char *
Michal Vasko9f96a052020-03-10 09:41:45 +0100272lyd_meta2str(const struct lyd_meta *meta, int *dynamic)
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200273{
Michal Vasko9f96a052020-03-10 09:41:45 +0100274 LY_CHECK_ARG_RET(meta ? meta->parent->schema->module->ctx : NULL, meta, dynamic, NULL);
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200275
Michal Vasko9f96a052020-03-10 09:41:45 +0100276 return meta->value.realtype->plugin->print(&meta->value, LYD_JSON, json_print_get_prefix, NULL, dynamic);
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200277}
278
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200279API struct lyd_node *
Michal Vaskoa3881362020-01-21 15:57:35 +0100280lyd_parse_mem(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options)
Radek Krejcie7b95092019-05-15 11:03:07 +0200281{
Radek Krejcie7b95092019-05-15 11:03:07 +0200282 struct lyd_node *result = NULL;
Radek Krejcie92210c2019-05-17 15:53:35 +0200283#if 0
Radek Krejcie7b95092019-05-15 11:03:07 +0200284 const char *yang_data_name = NULL;
Radek Krejcie92210c2019-05-17 15:53:35 +0200285#endif
Radek Krejcie7b95092019-05-15 11:03:07 +0200286
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200287 LY_CHECK_ARG_RET(ctx, ctx, NULL);
288
Michal Vasko5b37a352020-03-06 13:38:33 +0100289 if ((options & LYD_OPT_PARSE_ONLY) && (options & LYD_VALOPT_MASK)) {
290 LOGERR(ctx, LY_EINVAL, "Passing validation flags with LYD_OPT_PARSE_ONLY is not allowed.");
291 return NULL;
292 }
293
Michal Vaskoa3881362020-01-21 15:57:35 +0100294#if 0
Radek Krejcie7b95092019-05-15 11:03:07 +0200295 if (options & LYD_OPT_RPCREPLY) {
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200296 /* first item in trees is mandatory - the RPC/action request */
297 LY_CHECK_ARG_RET(ctx, trees, LY_ARRAY_SIZE(trees) >= 1, NULL);
298 if (!trees[0] || trees[0]->parent || !(trees[0]->schema->nodetype & (LYS_ACTION | LYS_LIST | LYS_CONTAINER))) {
299 LOGERR(ctx, LY_EINVAL, "Data parser invalid argument trees - the first item in the array must be the RPC/action request when parsing %s.",
300 lyd_parse_options_type2str(options));
Radek Krejcie7b95092019-05-15 11:03:07 +0200301 return NULL;
302 }
303 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200304
Radek Krejcie7b95092019-05-15 11:03:07 +0200305 if (options & LYD_OPT_DATA_TEMPLATE) {
306 yang_data_name = va_arg(ap, const char *);
307 }
Radek Krejcie92210c2019-05-17 15:53:35 +0200308#endif
Radek Krejcie7b95092019-05-15 11:03:07 +0200309
310 if (!format) {
311 /* TODO try to detect format from the content */
312 }
313
314 switch (format) {
315 case LYD_XML:
Michal Vasko9f96a052020-03-10 09:41:45 +0100316 lyd_parse_xml_data(ctx, data, options, &result);
Radek Krejcie7b95092019-05-15 11:03:07 +0200317 break;
318#if 0
319 case LYD_JSON:
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200320 lyd_parse_json(ctx, data, options, trees, &result);
Radek Krejcie7b95092019-05-15 11:03:07 +0200321 break;
322 case LYD_LYB:
Radek Krejcif3b6fec2019-07-24 15:53:11 +0200323 lyd_parse_lyb(ctx, data, options, trees, &result);
Radek Krejcie7b95092019-05-15 11:03:07 +0200324 break;
325#endif
Michal Vasko52927e22020-03-16 17:26:14 +0100326 case LYD_SCHEMA:
Radek Krejcie7b95092019-05-15 11:03:07 +0200327 LOGINT(ctx);
328 break;
329 }
330
Radek Krejcie7b95092019-05-15 11:03:07 +0200331 return result;
332}
333
334API struct lyd_node *
Michal Vaskoa3881362020-01-21 15:57:35 +0100335lyd_parse_fd(struct ly_ctx *ctx, int fd, LYD_FORMAT format, int options)
Radek Krejcie7b95092019-05-15 11:03:07 +0200336{
337 struct lyd_node *result;
338 size_t length;
339 char *addr;
340
341 LY_CHECK_ARG_RET(ctx, ctx, NULL);
342 if (fd < 0) {
343 LOGARG(ctx, fd);
344 return NULL;
345 }
346
347 LY_CHECK_RET(ly_mmap(ctx, fd, &length, (void **)&addr), NULL);
Michal Vaskoa3881362020-01-21 15:57:35 +0100348 result = lyd_parse_mem(ctx, addr ? addr : "", format, options);
Radek Krejcidf3da792019-05-17 10:32:24 +0200349 if (addr) {
350 ly_munmap(addr, length);
351 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200352
353 return result;
354}
355
356API struct lyd_node *
Michal Vaskoa3881362020-01-21 15:57:35 +0100357lyd_parse_path(struct ly_ctx *ctx, const char *path, LYD_FORMAT format, int options)
Radek Krejcie7b95092019-05-15 11:03:07 +0200358{
359 int fd;
360 struct lyd_node *result;
361 size_t len;
Radek Krejcie7b95092019-05-15 11:03:07 +0200362
363 LY_CHECK_ARG_RET(ctx, ctx, path, NULL);
364
365 fd = open(path, O_RDONLY);
366 LY_CHECK_ERR_RET(fd == -1, LOGERR(ctx, LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno)), NULL);
367
368 if (!format) {
369 /* unknown format - try to detect it from filename's suffix */
370 len = strlen(path);
371
372 /* ignore trailing whitespaces */
373 for (; len > 0 && isspace(path[len - 1]); len--);
374
375 if (len >= 5 && !strncmp(&path[len - 4], ".xml", 4)) {
376 format = LYD_XML;
377#if 0
378 } else if (len >= 6 && !strncmp(&path[len - 5], ".json", 5)) {
379 format = LYD_JSON;
380 } else if (len >= 5 && !strncmp(&path[len - 4], ".lyb", 4)) {
381 format = LYD_LYB;
382#endif
383 } /* else still unknown, try later to detect it from the content */
384 }
385
Michal Vaskoa3881362020-01-21 15:57:35 +0100386 result = lyd_parse_fd(ctx, fd, format, options);
Radek Krejcie7b95092019-05-15 11:03:07 +0200387 close(fd);
388
389 return result;
390}
Radek Krejci084289f2019-07-09 17:35:30 +0200391
Michal Vasko90932a92020-02-12 14:33:03 +0100392LY_ERR
393lyd_create_term(const struct lysc_node *schema, const char *value, size_t value_len, int *dynamic,
394 ly_clb_resolve_prefix get_prefix, void *prefix_data, LYD_FORMAT format, struct lyd_node **node)
395{
396 LY_ERR ret;
397 struct lyd_node_term *term;
398
Michal Vasko9b368d32020-02-14 13:53:31 +0100399 assert(schema->nodetype & LYD_NODE_TERM);
400
Michal Vasko90932a92020-02-12 14:33:03 +0100401 term = calloc(1, sizeof *term);
402 LY_CHECK_ERR_RET(!term, LOGMEM(schema->module->ctx), LY_EMEM);
403
404 term->schema = schema;
405 term->prev = (struct lyd_node *)term;
Michal Vasko9b368d32020-02-14 13:53:31 +0100406 term->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100407
408 ret = lyd_value_parse(term, value, value_len, dynamic, 0, get_prefix, prefix_data, format, NULL);
409 if (ret && (ret != LY_EINCOMPLETE)) {
410 free(term);
411 return ret;
412 }
Michal Vasko9b368d32020-02-14 13:53:31 +0100413 lyd_hash((struct lyd_node *)term);
414
415 *node = (struct lyd_node *)term;
416 return ret;
417}
418
419LY_ERR
420lyd_create_term2(const struct lysc_node *schema, const struct lyd_value *val, struct lyd_node **node)
421{
422 LY_ERR ret;
423 struct lyd_node_term *term;
424 struct lysc_type *type;
425
426 assert(schema->nodetype & LYD_NODE_TERM);
Michal Vasko00cbf532020-06-15 13:58:47 +0200427 assert(val && val->realtype);
Michal Vasko9b368d32020-02-14 13:53:31 +0100428
429 term = calloc(1, sizeof *term);
430 LY_CHECK_ERR_RET(!term, LOGMEM(schema->module->ctx), LY_EMEM);
431
432 term->schema = schema;
433 term->prev = (struct lyd_node *)term;
434 term->flags = LYD_NEW;
435
436 type = ((struct lysc_node_leaf *)schema)->type;
437 ret = type->plugin->duplicate(schema->module->ctx, val, &term->value);
438 if (ret) {
439 LOGERR(schema->module->ctx, ret, "Value duplication failed.");
440 free(term);
441 return ret;
442 }
Michal Vasko00cbf532020-06-15 13:58:47 +0200443 term->value.realtype = val->realtype;
Michal Vasko9b368d32020-02-14 13:53:31 +0100444 lyd_hash((struct lyd_node *)term);
Michal Vasko90932a92020-02-12 14:33:03 +0100445
446 *node = (struct lyd_node *)term;
447 return ret;
448}
449
450LY_ERR
451lyd_create_inner(const struct lysc_node *schema, struct lyd_node **node)
452{
453 struct lyd_node_inner *in;
454
Michal Vasko9b368d32020-02-14 13:53:31 +0100455 assert(schema->nodetype & LYD_NODE_INNER);
456
Michal Vasko90932a92020-02-12 14:33:03 +0100457 in = calloc(1, sizeof *in);
458 LY_CHECK_ERR_RET(!in, LOGMEM(schema->module->ctx), LY_EMEM);
459
460 in->schema = schema;
461 in->prev = (struct lyd_node *)in;
Michal Vasko9b368d32020-02-14 13:53:31 +0100462 in->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100463
Michal Vasko9b368d32020-02-14 13:53:31 +0100464 /* do not hash list with keys, we need them for the hash */
465 if ((schema->nodetype != LYS_LIST) || (schema->flags & LYS_KEYLESS)) {
466 lyd_hash((struct lyd_node *)in);
467 }
Michal Vasko90932a92020-02-12 14:33:03 +0100468
469 *node = (struct lyd_node *)in;
470 return LY_SUCCESS;
471}
472
Michal Vasko90932a92020-02-12 14:33:03 +0100473LY_ERR
Michal Vasko004d3152020-06-11 19:59:22 +0200474lyd_create_list(const struct lysc_node *schema, const struct ly_path_predicate *predicates, struct lyd_node **node)
Michal Vasko90932a92020-02-12 14:33:03 +0100475{
476 LY_ERR ret = LY_SUCCESS;
Michal Vasko90932a92020-02-12 14:33:03 +0100477 struct lyd_node *list = NULL, *key;
Michal Vasko004d3152020-06-11 19:59:22 +0200478 LY_ARRAY_SIZE_TYPE u;
Michal Vasko90932a92020-02-12 14:33:03 +0100479
Michal Vasko004d3152020-06-11 19:59:22 +0200480 assert((schema->nodetype == LYS_LIST) && !(schema->flags & LYS_KEYLESS));
Michal Vasko90932a92020-02-12 14:33:03 +0100481
482 /* create list */
483 LY_CHECK_GOTO(ret = lyd_create_inner(schema, &list), cleanup);
484
Michal Vasko90932a92020-02-12 14:33:03 +0100485 /* create and insert all the keys */
Michal Vasko004d3152020-06-11 19:59:22 +0200486 LY_ARRAY_FOR(predicates, u) {
487 LY_CHECK_GOTO(ret = lyd_create_term2(predicates[u].key, &predicates[u].value, &key), cleanup);
Michal Vasko90932a92020-02-12 14:33:03 +0100488 lyd_insert_node(list, NULL, key);
489 }
490
Michal Vasko9b368d32020-02-14 13:53:31 +0100491 /* hash having all the keys */
492 lyd_hash(list);
493
Michal Vasko90932a92020-02-12 14:33:03 +0100494 /* success */
495 *node = list;
496 list = NULL;
497
498cleanup:
499 lyd_free_tree(list);
Michal Vasko004d3152020-06-11 19:59:22 +0200500 return ret;
501}
502
503static LY_ERR
504lyd_create_list2(const struct lysc_node *schema, const char *keys, size_t keys_len, struct lyd_node **node)
505{
506 LY_ERR ret = LY_SUCCESS;
507 struct lyxp_expr *expr = NULL;
508 uint16_t exp_idx = 0;
509 enum ly_path_pred_type pred_type = 0;
510 struct ly_path_predicate *predicates = NULL;
511
512 /* parse keys */
513 LY_CHECK_GOTO(ret = ly_path_parse_predicate(schema->module->ctx, keys, keys_len, LY_PATH_PREFIX_OPTIONAL,
514 LY_PATH_PRED_KEYS, &expr), cleanup);
515
516 /* compile them */
Michal Vasko00cbf532020-06-15 13:58:47 +0200517 LY_CHECK_GOTO(ret = ly_path_compile_predicate(schema->module->ctx, NULL, schema, expr, &exp_idx, lydjson_resolve_prefix,
518 NULL, LYD_JSON, &predicates, &pred_type), cleanup);
Michal Vasko004d3152020-06-11 19:59:22 +0200519
520 /* create the list node */
521 LY_CHECK_GOTO(ret = lyd_create_list(schema, predicates, node), cleanup);
522
523cleanup:
524 lyxp_expr_free(schema->module->ctx, expr);
525 ly_path_predicates_free(schema->module->ctx, pred_type, NULL, predicates);
Michal Vasko90932a92020-02-12 14:33:03 +0100526 return ret;
527}
528
529LY_ERR
530lyd_create_any(const struct lysc_node *schema, const void *value, LYD_ANYDATA_VALUETYPE value_type, struct lyd_node **node)
531{
532 struct lyd_node_any *any;
533
Michal Vasko9b368d32020-02-14 13:53:31 +0100534 assert(schema->nodetype & LYD_NODE_ANY);
535
Michal Vasko90932a92020-02-12 14:33:03 +0100536 any = calloc(1, sizeof *any);
537 LY_CHECK_ERR_RET(!any, LOGMEM(schema->module->ctx), LY_EMEM);
538
539 any->schema = schema;
540 any->prev = (struct lyd_node *)any;
Michal Vasko9b368d32020-02-14 13:53:31 +0100541 any->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100542
543 any->value.xml = value;
544 any->value_type = value_type;
Michal Vasko9b368d32020-02-14 13:53:31 +0100545 lyd_hash((struct lyd_node *)any);
Michal Vasko90932a92020-02-12 14:33:03 +0100546
547 *node = (struct lyd_node *)any;
548 return LY_SUCCESS;
549}
550
Michal Vasko52927e22020-03-16 17:26:14 +0100551LY_ERR
552lyd_create_opaq(const struct ly_ctx *ctx, const char *name, size_t name_len, const char *value, size_t value_len,
553 int *dynamic, LYD_FORMAT format, struct ly_prefix *val_prefs, const char *prefix, size_t pref_len,
554 const char *ns, struct lyd_node **node)
555{
556 struct lyd_node_opaq *opaq;
557
558 assert(ctx && name && name_len && ns);
559
560 if (!value_len) {
561 value = "";
562 }
563
564 opaq = calloc(1, sizeof *opaq);
565 LY_CHECK_ERR_RET(!opaq, LOGMEM(ctx), LY_EMEM);
566
567 opaq->prev = (struct lyd_node *)opaq;
568
569 opaq->name = lydict_insert(ctx, name, name_len);
570 opaq->format = format;
571 if (pref_len) {
572 opaq->prefix.pref = lydict_insert(ctx, prefix, pref_len);
573 }
574 opaq->prefix.ns = lydict_insert(ctx, ns, 0);
575 opaq->val_prefs = val_prefs;
576 if (dynamic && *dynamic) {
577 opaq->value = lydict_insert_zc(ctx, (char *)value);
578 *dynamic = 0;
579 } else {
580 opaq->value = lydict_insert(ctx, value, value_len);
581 }
582 opaq->ctx = ctx;
583
584 *node = (struct lyd_node *)opaq;
585 return LY_SUCCESS;
586}
587
Michal Vasko013a8182020-03-03 10:46:53 +0100588API struct lyd_node *
589lyd_new_inner(struct lyd_node *parent, const struct lys_module *module, const char *name)
590{
591 struct lyd_node *ret = NULL;
592 const struct lysc_node *schema;
593 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
594
595 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
596
Michal Vaskof03ed032020-03-04 13:31:44 +0100597 if (!module) {
598 module = parent->schema->module;
599 }
600
Michal Vasko1bf09392020-03-27 12:38:10 +0100601 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_CONTAINER | LYS_NOTIF | LYS_RPC | LYS_ACTION, 0);
Michal Vaskob00f3cf2020-05-27 11:20:13 +0200602 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Inner node (and not a list) \"%s\" not found.", name), NULL);
Michal Vasko013a8182020-03-03 10:46:53 +0100603
604 if (!lyd_create_inner(schema, &ret) && parent) {
605 lyd_insert_node(parent, NULL, ret);
606 }
607 return ret;
608}
609
610API struct lyd_node *
611lyd_new_list(struct lyd_node *parent, const struct lys_module *module, const char *name, ...)
612{
613 struct lyd_node *ret = NULL, *key;
614 const struct lysc_node *schema, *key_s;
615 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
616 va_list ap;
617 const char *key_val;
618 LY_ERR rc = LY_SUCCESS;
619
620 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
621
Michal Vaskof03ed032020-03-04 13:31:44 +0100622 if (!module) {
623 module = parent->schema->module;
624 }
625
Michal Vasko013a8182020-03-03 10:46:53 +0100626 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, 0);
627 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), NULL);
628
629 /* create list inner node */
630 LY_CHECK_RET(lyd_create_inner(schema, &ret), NULL);
631
632 va_start(ap, name);
633
634 /* create and insert all the keys */
635 for (key_s = lysc_node_children(schema, 0); key_s && (key_s->flags & LYS_KEY); key_s = key_s->next) {
636 key_val = va_arg(ap, const char *);
637
Michal Vaskof03ed032020-03-04 13:31:44 +0100638 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 +0200639 LY_CHECK_GOTO(rc && (rc != LY_EINCOMPLETE), cleanup);
640 rc = LY_SUCCESS;
Michal Vasko013a8182020-03-03 10:46:53 +0100641 lyd_insert_node(ret, NULL, key);
642 }
643
644 /* hash having all the keys */
645 lyd_hash(ret);
646
647 if (parent) {
648 lyd_insert_node(parent, NULL, ret);
649 }
650
651cleanup:
652 if (rc) {
653 lyd_free_tree(ret);
654 ret = NULL;
655 }
656 va_end(ap);
657 return ret;
658}
659
660API struct lyd_node *
661lyd_new_list2(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *keys)
662{
663 struct lyd_node *ret = NULL;
664 const struct lysc_node *schema;
665 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
666
667 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
668
Michal Vaskof03ed032020-03-04 13:31:44 +0100669 if (!module) {
670 module = parent->schema->module;
671 }
Michal Vasko004d3152020-06-11 19:59:22 +0200672 if (!keys) {
673 keys = "";
674 }
Michal Vaskof03ed032020-03-04 13:31:44 +0100675
Michal Vasko004d3152020-06-11 19:59:22 +0200676 /* find schema node */
Michal Vasko013a8182020-03-03 10:46:53 +0100677 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, 0);
678 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), NULL);
679
Michal Vasko004d3152020-06-11 19:59:22 +0200680 if ((schema->flags & LYS_KEYLESS) && !keys[0]) {
681 /* key-less list */
682 LY_CHECK_RET(lyd_create_inner(schema, &ret), NULL);
683 } else {
684 /* create the list node */
685 LY_CHECK_RET(lyd_create_list2(schema, keys, strlen(keys), &ret), NULL);
686 }
687
688 if (parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100689 lyd_insert_node(parent, NULL, ret);
690 }
691 return ret;
692}
693
694API struct lyd_node *
695lyd_new_term(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str)
696{
Michal Vaskocbff3e92020-05-27 12:56:41 +0200697 LY_ERR rc;
Michal Vasko013a8182020-03-03 10:46:53 +0100698 struct lyd_node *ret = NULL;
699 const struct lysc_node *schema;
700 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
701
702 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
703
Michal Vaskof03ed032020-03-04 13:31:44 +0100704 if (!module) {
705 module = parent->schema->module;
706 }
707
Michal Vasko013a8182020-03-03 10:46:53 +0100708 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_TERM, 0);
709 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Term node \"%s\" not found.", name), NULL);
710
Michal Vaskocbff3e92020-05-27 12:56:41 +0200711 rc = lyd_create_term(schema, val_str, val_str ? strlen(val_str) : 0, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &ret);
712 LY_CHECK_RET(rc && (rc != LY_EINCOMPLETE), NULL);
713
714 if (parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100715 lyd_insert_node(parent, NULL, ret);
716 }
717 return ret;
718}
719
720API struct lyd_node *
721lyd_new_any(struct lyd_node *parent, const struct lys_module *module, const char *name, const void *value,
722 LYD_ANYDATA_VALUETYPE value_type)
723{
724 struct lyd_node *ret = NULL;
725 const struct lysc_node *schema;
726 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
727
728 LY_CHECK_ARG_RET(ctx, parent || module, name, NULL);
729
Michal Vaskof03ed032020-03-04 13:31:44 +0100730 if (!module) {
731 module = parent->schema->module;
732 }
733
Michal Vasko013a8182020-03-03 10:46:53 +0100734 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_ANY, 0);
735 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Any node \"%s\" not found.", name), NULL);
736
737 if (!lyd_create_any(schema, value, value_type, &ret) && parent) {
738 lyd_insert_node(parent, NULL, ret);
739 }
740 return ret;
741}
742
Michal Vasko00cbf532020-06-15 13:58:47 +0200743static LY_ERR
744lyd_new_path_update(struct lyd_node *node, const void *value, LYD_ANYDATA_VALUETYPE value_type,
745 struct lyd_node **new_parent, struct lyd_node **new_node)
746{
747 LY_ERR ret = LY_SUCCESS;
748 struct lyd_node *new_any;
749
750 switch (node->schema->nodetype) {
751 case LYS_CONTAINER:
752 case LYS_NOTIF:
753 case LYS_RPC:
754 case LYS_ACTION:
755 case LYS_LIST:
756 case LYS_LEAFLIST:
757 /* if it exists, there is nothing to update */
758 *new_parent = NULL;
759 *new_node = NULL;
760 break;
761 case LYS_LEAF:
762 ret = lyd_change_term(node, value);
763 if ((ret == LY_SUCCESS) || (ret == LY_EEXIST)) {
764 /* there was an actual change (at least of the default flag) */
765 *new_parent = node;
766 *new_node = node;
767 ret = LY_SUCCESS;
768 } else if (ret == LY_ENOT) {
769 /* no change */
770 *new_parent = NULL;
771 *new_node = NULL;
772 ret = LY_SUCCESS;
773 } /* else error */
774 break;
775 case LYS_ANYDATA:
776 case LYS_ANYXML:
777 /* create a new any node */
778 LY_CHECK_RET(lyd_create_any(node->schema, value, value_type, &new_any));
779
780 /* compare with the existing one */
781 if (lyd_compare(node, new_any, 0)) {
782 /* not equal, switch values (so that we can use generic node free) */
783 ((struct lyd_node_any *)new_any)->value = ((struct lyd_node_any *)node)->value;
784 ((struct lyd_node_any *)new_any)->value_type = ((struct lyd_node_any *)node)->value_type;
785 ((struct lyd_node_any *)node)->value.str = value;
786 ((struct lyd_node_any *)node)->value_type = value_type;
787
788 *new_parent = node;
789 *new_node = node;
790 } else {
791 /* they are equal */
792 *new_parent = NULL;
793 *new_node = NULL;
794 }
795 lyd_free_tree(new_any);
796 break;
797 default:
798 LOGINT(LYD_NODE_CTX(node));
799 ret = LY_EINT;
800 break;
801 }
802
803 return ret;
804}
805
Michal Vaskod86997b2020-05-26 15:19:54 +0200806API struct lyd_meta *
807lyd_new_meta(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str)
808{
809 struct lyd_meta *ret = NULL;
Michal Vasko00cbf532020-06-15 13:58:47 +0200810 const struct ly_ctx *ctx;
Michal Vaskod86997b2020-05-26 15:19:54 +0200811 const char *prefix, *tmp;
812 char *str;
813 size_t pref_len, name_len;
814
Michal Vasko00cbf532020-06-15 13:58:47 +0200815 LY_CHECK_ARG_RET(NULL, parent, name, module || strchr(name, ':'), NULL);
816
817 ctx = LYD_NODE_CTX(parent);
Michal Vaskod86997b2020-05-26 15:19:54 +0200818
819 /* parse the name */
820 tmp = name;
821 if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
822 LOGERR(ctx, LY_EINVAL, "Metadata name \"%s\" is not valid.", name);
823 return NULL;
824 }
825
826 /* find the module */
827 if (prefix) {
828 str = strndup(name, name_len);
829 module = ly_ctx_get_module_implemented(ctx, str);
830 free(str);
Michal Vasko004d3152020-06-11 19:59:22 +0200831 LY_CHECK_ERR_RET(!module, LOGERR(ctx, LY_EINVAL, "Module \"%.*s\" not found.", pref_len, prefix), NULL);
Michal Vaskod86997b2020-05-26 15:19:54 +0200832 }
833
834 /* set value if none */
835 if (!val_str) {
836 val_str = "";
837 }
838
839 lyd_create_meta(parent, &ret, module, name, name_len, val_str, strlen(val_str), NULL, lydjson_resolve_prefix, NULL,
840 LYD_JSON, parent->schema);
841 return ret;
842}
843
Michal Vasko00cbf532020-06-15 13:58:47 +0200844API struct lyd_node *
845lyd_new_opaq(struct lyd_node *parent, const struct ly_ctx *ctx, const char *name, const char *value,
846 const char *module_name)
847{
848 struct lyd_node *ret = NULL;
849
850 LY_CHECK_ARG_RET(ctx, parent || ctx, name, module_name, NULL);
851
852 if (!ctx) {
853 ctx = LYD_NODE_CTX(parent);
854 }
855 if (!value) {
856 value = "";
857 }
858
859 if (!lyd_create_opaq(ctx, name, strlen(name), value, strlen(value), NULL, LYD_JSON, NULL, NULL, 0, module_name, &ret)
860 && parent) {
861 lyd_insert_node(parent, NULL, ret);
862 }
863 return ret;
864}
865
866API struct ly_attr *
867lyd_new_attr(struct lyd_node *parent, const char *module_name, const char *name, const char *val_str)
868{
869 struct ly_attr *ret = NULL;
870 const struct ly_ctx *ctx;
871 const char *prefix, *tmp;
872 size_t pref_len, name_len;
873
874 LY_CHECK_ARG_RET(NULL, parent, !parent->schema, name, NULL);
875
876 ctx = LYD_NODE_CTX(parent);
877
878 /* parse the name */
879 tmp = name;
880 if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
881 LOGERR(ctx, LY_EINVAL, "Metadata name \"%s\" is not valid.", name);
882 return NULL;
883 }
884
885 /* set value if none */
886 if (!val_str) {
887 val_str = "";
888 }
889
890 ly_create_attr(parent, &ret, ctx, name, name_len, val_str, strlen(val_str), NULL, LYD_JSON, NULL, prefix,
891 pref_len, module_name);
892 return ret;
893}
894
895API LY_ERR
896lyd_change_term(struct lyd_node *term, const char *val_str)
897{
898 LY_ERR ret = LY_SUCCESS;
899 struct lysc_type *type;
900 struct lyd_node_term *t;
901 struct lyd_node *parent;
902 struct lyd_value val = {0};
903 int dflt_change, val_change;
904
905 LY_CHECK_ARG_RET(NULL, term, term->schema, term->schema->nodetype & LYD_NODE_TERM, LY_EINVAL);
906
907 if (!val_str) {
908 val_str = "";
909 }
910 t = (struct lyd_node_term *)term;
911 type = ((struct lysc_node_leaf *)term->schema)->type;
912
913 /* parse the new value */
914 LY_CHECK_GOTO(ret = lyd_value_store(&val, term->schema, val_str, strlen(val_str), NULL, lydjson_resolve_prefix, NULL,
915 LYD_JSON), cleanup);
916
917 /* compare original and new value */
918 if (type->plugin->compare(&t->value, &val)) {
919 /* values differ, switch them */
920 type->plugin->free(LYD_NODE_CTX(term), &t->value);
921 t->value = val;
922 memset(&val, 0, sizeof val);
923 val_change = 1;
924 } else {
925 val_change = 0;
926 }
927
928 /* always clear the default flag */
929 if (term->flags & LYD_DEFAULT) {
930 for (parent = term; parent; parent = (struct lyd_node *)parent->parent) {
931 parent->flags &= ~LYD_DEFAULT;
932 }
933 dflt_change = 1;
934 } else {
935 dflt_change = 0;
936 }
937
938 if (val_change || dflt_change) {
939 /* make the node non-validated */
940 term->flags &= LYD_NEW;
941 }
942
943 if (val_change) {
944 if (term->schema->nodetype == LYS_LEAFLIST) {
945 /* leaf-list needs to be hashed again and re-inserted into parent */
946 lyd_unlink_hash(term);
947 lyd_hash(term);
948 LY_CHECK_GOTO(ret = lyd_insert_hash(term), cleanup);
949 } else if ((term->schema->flags & LYS_KEY) && term->parent) {
950 /* list needs to be updated if its key was changed */
951 assert(term->parent->schema->nodetype == LYS_LIST);
952 lyd_unlink_hash((struct lyd_node *)term->parent);
953 lyd_hash((struct lyd_node *)term->parent);
954 LY_CHECK_GOTO(ret = lyd_insert_hash((struct lyd_node *)term->parent), cleanup);
955 } /* else leaf that is not a key, its value is not used for its hash so it does not change */
956 }
957
958 /* retrun value */
959 if (!val_change) {
960 if (dflt_change) {
961 /* only default flag change */
962 ret = LY_EEXIST;
963 } else {
964 /* no change */
965 ret = LY_ENOT;
966 }
967 } /* else value changed, LY_SUCCESS */
968
969cleanup:
970 type->plugin->free(LYD_NODE_CTX(term), &val);
971 return ret;
972}
973
974API struct lyd_node *
975lyd_new_path(struct lyd_node *parent, const struct ly_ctx *ctx, const char *path, const char *value, int options)
976{
Michal Vaskoa8f9eb32020-06-16 13:07:12 +0200977 struct lyd_node *new_parent = NULL;
Michal Vasko00cbf532020-06-15 13:58:47 +0200978
Michal Vaskoa8f9eb32020-06-16 13:07:12 +0200979 lyd_new_path2(parent, ctx, path, value, 0, options, &new_parent, NULL);
980 return new_parent;
Michal Vasko00cbf532020-06-15 13:58:47 +0200981}
982
983API struct lyd_node *
984lyd_new_path_any(struct lyd_node *parent, const struct ly_ctx *ctx, const char *path, const void *value,
985 LYD_ANYDATA_VALUETYPE value_type, int options)
986{
Michal Vaskoa8f9eb32020-06-16 13:07:12 +0200987 struct lyd_node *new_parent = NULL;
Michal Vasko00cbf532020-06-15 13:58:47 +0200988
Michal Vaskoa8f9eb32020-06-16 13:07:12 +0200989 lyd_new_path2(parent, ctx, path, value, value_type, options, &new_parent, NULL);
990 return new_parent;
Michal Vasko00cbf532020-06-15 13:58:47 +0200991}
992
993API LY_ERR
994lyd_new_path2(struct lyd_node *parent, const struct ly_ctx *ctx, const char *path, const void *value,
995 LYD_ANYDATA_VALUETYPE value_type, int options, struct lyd_node **new_parent, struct lyd_node **new_node)
996{
997 LY_ERR ret = LY_SUCCESS, r;
998 struct lyxp_expr *exp = NULL;
999 struct ly_path *p = NULL;
1000 struct lyd_node *nparent = NULL, *nnode = NULL, *node = NULL, *cur_parent;
1001 const struct lysc_node *schema;
1002 LY_ARRAY_SIZE_TYPE path_idx = 0;
1003 struct ly_path_predicate *pred;
1004
1005 LY_CHECK_ARG_RET(ctx, parent || ctx, path, (path[0] == '/') || parent, LY_EINVAL);
1006
1007 if (!ctx) {
1008 ctx = LYD_NODE_CTX(parent);
1009 }
1010
1011 /* parse path */
1012 LY_CHECK_GOTO(ret = ly_path_parse(ctx, path, strlen(path), LY_PATH_BEGIN_EITHER, LY_PATH_LREF_FALSE,
1013 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_SIMPLE, &exp), cleanup);
1014
1015 /* compile path */
1016 LY_CHECK_GOTO(ret = ly_path_compile(ctx, NULL, parent ? parent->schema : NULL, exp, LY_PATH_LREF_FALSE,
1017 options & LYD_NEWOPT_OUTPUT ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT,
1018 LY_PATH_TARGET_MANY, lydjson_resolve_prefix, NULL, LYD_JSON, &p), cleanup);
1019
1020 schema = p[LY_ARRAY_SIZE(p) - 1].node;
1021 if ((schema->nodetype == LYS_LIST) && (p[LY_ARRAY_SIZE(p) - 1].pred_type == LY_PATH_PREDTYPE_NONE)
1022 && !(options & LYD_NEWOPT_OPAQ)) {
1023 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_XPATH, "Predicate missing for %s \"%s\" in path.",
1024 lys_nodetype2str(schema->nodetype), schema->name);
1025 ret = LY_EINVAL;
1026 goto cleanup;
1027 } else if ((schema->nodetype == LYS_LEAFLIST) && (p[LY_ARRAY_SIZE(p) - 1].pred_type == LY_PATH_PREDTYPE_NONE)) {
1028 /* parse leafref value into a predicate, if not defined in the path */
1029 p[LY_ARRAY_SIZE(p) - 1].pred_type = LY_PATH_PREDTYPE_LEAFLIST;
1030 LY_ARRAY_NEW_GOTO(ctx, p[LY_ARRAY_SIZE(p) - 1].predicates, pred, ret, cleanup);
1031
1032 if (!value) {
1033 value = "";
1034 }
1035
1036 r = LY_SUCCESS;
1037 if (options & LYD_NEWOPT_OPAQ) {
1038 r = lys_value_validate(NULL, schema, value, strlen(value), lydjson_resolve_prefix, NULL, LYD_JSON);
1039 }
1040 if (!r) {
1041 LY_CHECK_GOTO(ret = lyd_value_store(&pred->value, schema, value, strlen(value), NULL, lydjson_resolve_prefix,
1042 NULL, LYD_JSON), cleanup);
1043 } /* else we have opaq flag and the value is not valid, leavne no predicate and then create an opaque node */
1044 }
1045
1046 /* try to find any existing nodes in the path */
1047 if (parent) {
1048 ret = ly_path_eval_partial(p, parent, &path_idx, &node);
1049 if (ret == LY_SUCCESS) {
1050 /* the node exists, are we supposed to update it or is it just a default? */
1051 if (!(options & LYD_NEWOPT_UPDATE) && !(node->flags & LYD_DEFAULT)) {
1052 LOGERR(ctx, LY_EEXIST, "Path \"%s\" already exists", path);
1053 ret = LY_EEXIST;
1054 goto cleanup;
1055 }
1056
1057 /* update the existing node */
1058 ret = lyd_new_path_update(node, value, value_type, &nparent, &nnode);
1059 goto cleanup;
1060 } else if (ret == LY_EINCOMPLETE) {
1061 /* some nodes were found, adjust the iterator to the next segment */
1062 ++path_idx;
1063 } else if (ret == LY_ENOTFOUND) {
1064 /* we will create the nodes from top-level, default behavior (absolute path), or from the parent (relative path) */
1065 if (lysc_data_parent(p[LY_ARRAY_SIZE(p) - 1].node)) {
1066 node = parent;
1067 }
1068 } else {
1069 /* error */
1070 goto cleanup;
1071 }
1072 }
1073
1074 /* create all the non-existing nodes in a loop */
1075 for (; path_idx < LY_ARRAY_SIZE(p); ++path_idx) {
1076 cur_parent = node;
1077 schema = p[path_idx].node;
1078
1079 switch (schema->nodetype) {
1080 case LYS_LIST:
1081 if (!(schema->flags & LYS_KEYLESS)) {
1082 if ((options & LYD_NEWOPT_OPAQ) && (p[path_idx].pred_type == LY_PATH_PREDTYPE_NONE)) {
1083 /* creating opaque list without keys */
1084 LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, NULL,
1085 LYD_JSON, NULL, NULL, 0, schema->module->name, &node), cleanup);
1086 } else {
1087 assert(p[path_idx].pred_type == LY_PATH_PREDTYPE_LIST);
1088 LY_CHECK_GOTO(ret = lyd_create_list(schema, p[path_idx].predicates, &node), cleanup);
1089 }
1090 break;
1091 }
1092 /* fallthrough */
1093 case LYS_CONTAINER:
1094 case LYS_NOTIF:
1095 case LYS_RPC:
1096 case LYS_ACTION:
1097 LY_CHECK_GOTO(ret = lyd_create_inner(schema, &node), cleanup);
1098 break;
1099 case LYS_LEAFLIST:
1100 if ((options & LYD_NEWOPT_OPAQ) && (p[path_idx].pred_type == LY_PATH_PREDTYPE_NONE)) {
1101 /* creating opaque leaf-list without value */
1102 LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, NULL,
1103 LYD_JSON, NULL, NULL, 0, schema->module->name, &node), cleanup);
1104 } else {
1105 assert(p[path_idx].pred_type == LY_PATH_PREDTYPE_LEAFLIST);
1106 LY_CHECK_GOTO(ret = lyd_create_term2(schema, &p[path_idx].predicates[0].value, &node), cleanup);
1107 }
1108 break;
1109 case LYS_LEAF:
1110 /* make there is some value */
1111 if (!value) {
1112 value = "";
1113 }
1114
1115 r = LY_SUCCESS;
1116 if (options & LYD_NEWOPT_OPAQ) {
1117 r = lys_value_validate(NULL, schema, value, strlen(value), lydjson_resolve_prefix, NULL, LYD_JSON);
1118 }
1119 if (!r) {
1120 LY_CHECK_GOTO(ret = lyd_create_term(schema, value, strlen(value), NULL, lydjson_resolve_prefix, NULL,
1121 LYD_JSON, &node), cleanup);
1122 } else {
1123 /* creating opaque leaf without value */
1124 LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, NULL,
1125 LYD_JSON, NULL, NULL, 0, schema->module->name, &node), cleanup);
1126 }
1127 break;
1128 case LYS_ANYDATA:
1129 case LYS_ANYXML:
1130 LY_CHECK_GOTO(ret = lyd_create_any(schema, value, value_type, &node), cleanup);
1131 break;
1132 default:
1133 LOGINT(ctx);
1134 ret = LY_EINT;
1135 goto cleanup;
1136 }
1137
1138 if (cur_parent) {
1139 /* connect to the parent */
1140 lyd_insert_node(cur_parent, NULL, node);
1141 } else if (parent) {
1142 /* connect to top-level siblings */
1143 lyd_insert_node(NULL, &parent, node);
1144 }
1145
1146 /* update remembered nodes */
1147 if (!nparent) {
1148 nparent = node;
1149 }
1150 nnode = node;
1151 }
1152
1153cleanup:
1154 lyxp_expr_free(ctx, exp);
1155 ly_path_free(ctx, p);
1156 if (!ret) {
1157 /* set out params only on success */
1158 if (new_parent) {
1159 *new_parent = nparent;
1160 }
1161 if (new_node) {
1162 *new_node = nnode;
1163 }
1164 }
1165 return ret;
1166}
1167
Michal Vasko90932a92020-02-12 14:33:03 +01001168struct lyd_node *
1169lyd_get_prev_key_anchor(const struct lyd_node *first_sibling, const struct lysc_node *new_key)
1170{
1171 const struct lysc_node *prev_key;
1172 struct lyd_node *match = NULL;
1173
1174 if (!first_sibling) {
1175 return NULL;
1176 }
1177
1178 for (prev_key = new_key->prev; !match && prev_key->next; prev_key = prev_key->prev) {
1179 lyd_find_sibling_val(first_sibling, prev_key, NULL, 0, &match);
1180 }
1181
1182 return match;
1183}
1184
1185/**
1186 * @brief Insert node after a sibling.
1187 *
Michal Vasko9f96a052020-03-10 09:41:45 +01001188 * Handles inserting into NP containers and key-less lists.
1189 *
Michal Vasko90932a92020-02-12 14:33:03 +01001190 * @param[in] sibling Sibling to insert after.
1191 * @param[in] node Node to insert.
1192 */
1193static void
Michal Vaskof03ed032020-03-04 13:31:44 +01001194lyd_insert_after_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001195{
Michal Vasko0249f7c2020-03-05 16:36:40 +01001196 struct lyd_node_inner *par;
1197
Michal Vasko90932a92020-02-12 14:33:03 +01001198 assert(!node->next && (node->prev == node));
1199
1200 node->next = sibling->next;
1201 node->prev = sibling;
1202 sibling->next = node;
1203 if (node->next) {
1204 /* sibling had a succeeding node */
1205 node->next->prev = node;
1206 } else {
1207 /* sibling was last, find first sibling and change its prev */
1208 if (sibling->parent) {
1209 sibling = sibling->parent->child;
1210 } else {
1211 for (; sibling->prev->next != node; sibling = sibling->prev);
1212 }
1213 sibling->prev = node;
1214 }
1215 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001216
Michal Vasko9f96a052020-03-10 09:41:45 +01001217 for (par = node->parent; par; par = par->parent) {
1218 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
1219 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +01001220 par->flags &= ~LYD_DEFAULT;
1221 }
Michal Vasko9f96a052020-03-10 09:41:45 +01001222 if ((par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
1223 /* rehash key-less list */
1224 lyd_hash((struct lyd_node *)par);
1225 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001226 }
1227
1228 /* insert into hash table */
1229 lyd_insert_hash(node);
Michal Vasko90932a92020-02-12 14:33:03 +01001230}
1231
1232/**
1233 * @brief Insert node before a sibling.
1234 *
Michal Vasko9f96a052020-03-10 09:41:45 +01001235 * Handles inserting into NP containers and key-less lists.
1236 *
Michal Vasko90932a92020-02-12 14:33:03 +01001237 * @param[in] sibling Sibling to insert before.
1238 * @param[in] node Node to insert.
1239 */
1240static void
Michal Vaskof03ed032020-03-04 13:31:44 +01001241lyd_insert_before_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001242{
Michal Vasko0249f7c2020-03-05 16:36:40 +01001243 struct lyd_node_inner *par;
1244
Michal Vasko90932a92020-02-12 14:33:03 +01001245 assert(!node->next && (node->prev == node));
1246
1247 node->next = sibling;
1248 /* covers situation of sibling being first */
1249 node->prev = sibling->prev;
1250 sibling->prev = node;
1251 if (node->prev->next) {
1252 /* sibling had a preceding node */
1253 node->prev->next = node;
1254 } else if (sibling->parent) {
1255 /* sibling was first and we must also change parent child pointer */
1256 sibling->parent->child = node;
1257 }
1258 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001259
Michal Vasko9f96a052020-03-10 09:41:45 +01001260 for (par = node->parent; par; par = par->parent) {
1261 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
1262 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +01001263 par->flags &= ~LYD_DEFAULT;
1264 }
Michal Vasko9f96a052020-03-10 09:41:45 +01001265 if ((par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
1266 /* rehash key-less list */
1267 lyd_hash((struct lyd_node *)par);
1268 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001269 }
1270
1271 /* insert into hash table */
1272 lyd_insert_hash(node);
Michal Vasko90932a92020-02-12 14:33:03 +01001273}
1274
1275/**
1276 * @brief Insert node as the last child of a parent.
1277 *
Michal Vasko9f96a052020-03-10 09:41:45 +01001278 * Handles inserting into NP containers and key-less lists.
1279 *
Michal Vasko90932a92020-02-12 14:33:03 +01001280 * @param[in] parent Parent to insert into.
1281 * @param[in] node Node to insert.
1282 */
1283static void
Michal Vaskof03ed032020-03-04 13:31:44 +01001284lyd_insert_last_node(struct lyd_node *parent, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001285{
1286 struct lyd_node_inner *par;
1287
Michal Vasko0249f7c2020-03-05 16:36:40 +01001288 assert(parent && !node->next && (node->prev == node));
Michal Vasko52927e22020-03-16 17:26:14 +01001289 assert(!parent->schema || (parent->schema->nodetype & LYD_NODE_INNER));
Michal Vasko90932a92020-02-12 14:33:03 +01001290
1291 par = (struct lyd_node_inner *)parent;
1292
1293 if (!par->child) {
1294 par->child = node;
1295 } else {
1296 node->prev = par->child->prev;
1297 par->child->prev->next = node;
1298 par->child->prev = node;
1299 }
1300 node->parent = par;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001301
Michal Vasko9f96a052020-03-10 09:41:45 +01001302 for (; par; par = par->parent) {
1303 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
1304 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +01001305 par->flags &= ~LYD_DEFAULT;
1306 }
Michal Vasko52927e22020-03-16 17:26:14 +01001307 if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001308 /* rehash key-less list */
1309 lyd_hash((struct lyd_node *)par);
1310 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001311 }
1312
1313 /* insert into hash table */
1314 lyd_insert_hash(node);
Michal Vasko90932a92020-02-12 14:33:03 +01001315}
1316
1317void
Michal Vasko9b368d32020-02-14 13:53:31 +01001318lyd_insert_node(struct lyd_node *parent, struct lyd_node **first_sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001319{
Michal Vasko9b368d32020-02-14 13:53:31 +01001320 struct lyd_node *anchor;
Michal Vasko9f96a052020-03-10 09:41:45 +01001321 const struct lysc_node *skey = NULL;
1322 int has_keys;
Michal Vasko90932a92020-02-12 14:33:03 +01001323
Michal Vasko52927e22020-03-16 17:26:14 +01001324 assert((parent || first_sibling) && node && (node->hash || !node->schema));
Michal Vasko9b368d32020-02-14 13:53:31 +01001325
1326 if (!parent && first_sibling && (*first_sibling) && (*first_sibling)->parent) {
1327 parent = (struct lyd_node *)(*first_sibling)->parent;
1328 }
Michal Vasko90932a92020-02-12 14:33:03 +01001329
1330 if (parent) {
Michal Vasko52927e22020-03-16 17:26:14 +01001331 if (node->schema && (node->schema->flags & LYS_KEY)) {
Michal Vasko90932a92020-02-12 14:33:03 +01001332 /* it is key and we need to insert it at the correct place */
Michal Vasko9b368d32020-02-14 13:53:31 +01001333 anchor = lyd_get_prev_key_anchor(lyd_node_children(parent), node->schema);
1334 if (anchor) {
Michal Vaskof03ed032020-03-04 13:31:44 +01001335 lyd_insert_after_node(anchor, node);
Michal Vasko90932a92020-02-12 14:33:03 +01001336 } else if (lyd_node_children(parent)) {
Radek Krejcidae0ee82020-05-06 16:53:24 +02001337 lyd_insert_before_node(lyd_node_children(parent), node);
Michal Vasko90932a92020-02-12 14:33:03 +01001338 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +01001339 lyd_insert_last_node(parent, node);
Michal Vasko90932a92020-02-12 14:33:03 +01001340 }
Michal Vasko9f96a052020-03-10 09:41:45 +01001341
1342 /* hash list if all its keys were added */
1343 assert(parent->schema->nodetype == LYS_LIST);
Radek Krejcidae0ee82020-05-06 16:53:24 +02001344 anchor = lyd_node_children(parent);
Michal Vasko9f96a052020-03-10 09:41:45 +01001345 has_keys = 1;
1346 while ((skey = lys_getnext(skey, parent->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
1347 if (!anchor || (anchor->schema != skey)) {
1348 /* key missing */
1349 has_keys = 0;
1350 break;
1351 }
1352
1353 anchor = anchor->next;
1354 }
1355 if (has_keys) {
1356 lyd_hash(parent);
1357 }
1358
Michal Vasko90932a92020-02-12 14:33:03 +01001359 } else {
1360 /* last child */
Michal Vaskof03ed032020-03-04 13:31:44 +01001361 lyd_insert_last_node(parent, node);
Michal Vasko90932a92020-02-12 14:33:03 +01001362 }
Michal Vasko9b368d32020-02-14 13:53:31 +01001363 } else if (*first_sibling) {
Michal Vaskob1b5c262020-03-05 14:29:47 +01001364 /* top-level siblings */
Michal Vasko9b368d32020-02-14 13:53:31 +01001365 anchor = (*first_sibling)->prev;
Michal Vaskoc193ce92020-03-06 11:04:48 +01001366 while (anchor->prev->next && (lyd_owner_module(anchor) != lyd_owner_module(node))) {
Michal Vasko9b368d32020-02-14 13:53:31 +01001367 anchor = anchor->prev;
1368 }
1369
Michal Vaskoc193ce92020-03-06 11:04:48 +01001370 if (lyd_owner_module(anchor) == lyd_owner_module(node)) {
Michal Vaskob1b5c262020-03-05 14:29:47 +01001371 /* insert after last sibling from this module */
1372 lyd_insert_after_node(anchor, node);
1373 } else {
1374 /* no data from this module, insert at the last position */
1375 lyd_insert_after_node((*first_sibling)->prev, node);
1376 }
Michal Vasko90932a92020-02-12 14:33:03 +01001377 } else {
Michal Vasko9b368d32020-02-14 13:53:31 +01001378 /* the only sibling */
1379 *first_sibling = node;
Michal Vasko90932a92020-02-12 14:33:03 +01001380 }
Michal Vasko90932a92020-02-12 14:33:03 +01001381}
1382
Michal Vaskof03ed032020-03-04 13:31:44 +01001383static LY_ERR
1384lyd_insert_check_schema(const struct lysc_node *parent, const struct lysc_node *schema)
1385{
1386 const struct lysc_node *par2;
1387
1388 assert(schema);
Michal Vasko62ed12d2020-05-21 10:08:25 +02001389 assert(!parent || !(parent->nodetype & (LYS_CASE | LYS_CHOICE)));
Michal Vaskof03ed032020-03-04 13:31:44 +01001390
1391 /* find schema parent */
Michal Vasko62ed12d2020-05-21 10:08:25 +02001392 par2 = lysc_data_parent(schema);
Michal Vaskof03ed032020-03-04 13:31:44 +01001393
1394 if (parent) {
1395 /* inner node */
1396 if (par2 != parent) {
1397 LOGERR(parent->module->ctx, LY_EINVAL, "Cannot insert, parent of \"%s\" is not \"%s\".", schema->name, parent->name);
1398 return LY_EINVAL;
1399 }
1400 } else {
1401 /* top-level node */
1402 if (par2) {
1403 LOGERR(parent->module->ctx, LY_EINVAL, "Cannot insert, node \"%s\" is not top-level.", schema->name);
1404 return LY_EINVAL;
1405 }
1406 }
1407
1408 return LY_SUCCESS;
1409}
1410
1411API LY_ERR
1412lyd_insert(struct lyd_node *parent, struct lyd_node *node)
1413{
1414 struct lyd_node *iter;
1415
1416 LY_CHECK_ARG_RET(NULL, parent, node, !(parent->schema->nodetype & LYD_NODE_INNER), LY_EINVAL);
1417
1418 LY_CHECK_RET(lyd_insert_check_schema(parent->schema, node->schema));
1419
1420 if (node->schema->flags & LYS_KEY) {
1421 LOGERR(parent->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1422 return LY_EINVAL;
1423 }
1424
1425 if (node->parent || node->prev->next) {
1426 lyd_unlink_tree(node);
1427 }
1428
1429 while (node) {
1430 iter = node->next;
1431 lyd_unlink_tree(node);
1432 lyd_insert_node(parent, NULL, node);
1433 node = iter;
1434 }
1435 return LY_SUCCESS;
1436}
1437
1438API LY_ERR
Michal Vaskob1b5c262020-03-05 14:29:47 +01001439lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node)
1440{
1441 struct lyd_node *iter;
1442
1443 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1444
Michal Vasko62ed12d2020-05-21 10:08:25 +02001445 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskob1b5c262020-03-05 14:29:47 +01001446
1447 if (node->schema->flags & LYS_KEY) {
1448 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1449 return LY_EINVAL;
1450 }
1451
1452 if (node->parent || node->prev->next) {
1453 lyd_unlink_tree(node);
1454 }
1455
1456 while (node) {
1457 iter = node->next;
1458 lyd_unlink_tree(node);
1459 lyd_insert_node(NULL, &sibling, node);
1460 node = iter;
1461 }
1462 return LY_SUCCESS;
1463}
1464
Michal Vasko0249f7c2020-03-05 16:36:40 +01001465static LY_ERR
1466lyd_insert_after_check_place(struct lyd_node *anchor, struct lyd_node *sibling, struct lyd_node *node)
1467{
1468 if (sibling->parent) {
1469 /* nested, we do not care for the order */
1470 return LY_SUCCESS;
1471 }
1472
1473 if (anchor) {
Michal Vaskoc193ce92020-03-06 11:04:48 +01001474 if (anchor->next && (lyd_owner_module(anchor) == lyd_owner_module(anchor->next))
1475 && (lyd_owner_module(node) != lyd_owner_module(anchor))) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001476 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert top-level module \"%s\" data into module \"%s\" data.",
Michal Vaskoc193ce92020-03-06 11:04:48 +01001477 lyd_owner_module(node)->name, lyd_owner_module(anchor)->name);
Michal Vasko0249f7c2020-03-05 16:36:40 +01001478 return LY_EINVAL;
1479 }
1480
Michal Vaskoc193ce92020-03-06 11:04:48 +01001481 if ((lyd_owner_module(node) == lyd_owner_module(anchor))
1482 || (anchor->next && (lyd_owner_module(node) == lyd_owner_module(anchor->next)))) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001483 /* inserting before/after its module data */
1484 return LY_SUCCESS;
1485 }
1486 }
1487
1488 /* find first sibling */
1489 while (sibling->prev->next) {
1490 sibling = sibling->prev;
1491 }
1492
1493 if (!anchor) {
Michal Vaskoc193ce92020-03-06 11:04:48 +01001494 if (lyd_owner_module(node) == lyd_owner_module(sibling)) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001495 /* inserting before its module data */
1496 return LY_SUCCESS;
1497 }
1498 }
1499
1500 /* check there are no data of this module */
1501 LY_LIST_FOR(sibling, sibling) {
Michal Vaskoc193ce92020-03-06 11:04:48 +01001502 if (lyd_owner_module(node) == lyd_owner_module(sibling)) {
Michal Vasko0249f7c2020-03-05 16:36:40 +01001503 /* some data of this module found */
1504 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Top-level data of module \"%s\" already exist,"
Michal Vaskoc193ce92020-03-06 11:04:48 +01001505 " they must be directly connected.", lyd_owner_module(node)->name);
Michal Vasko0249f7c2020-03-05 16:36:40 +01001506 return LY_EINVAL;
1507 }
1508 }
1509
1510 return LY_SUCCESS;
1511}
1512
Michal Vaskob1b5c262020-03-05 14:29:47 +01001513API LY_ERR
Michal Vaskof03ed032020-03-04 13:31:44 +01001514lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
1515{
1516 struct lyd_node *iter;
1517
1518 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1519
Michal Vasko62ed12d2020-05-21 10:08:25 +02001520 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskof03ed032020-03-04 13:31:44 +01001521
1522 if (node->schema->flags & LYS_KEY) {
1523 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1524 return LY_EINVAL;
1525 } else if (sibling->schema->flags & LYS_KEY) {
1526 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert into keys.");
1527 return LY_EINVAL;
1528 }
1529
Michal Vasko0249f7c2020-03-05 16:36:40 +01001530 LY_CHECK_RET(lyd_insert_after_check_place(sibling->prev->next ? sibling->prev : NULL, sibling, node));
1531
Michal Vaskof03ed032020-03-04 13:31:44 +01001532 if (node->parent || node->prev->next) {
1533 lyd_unlink_tree(node);
1534 }
1535
1536 /* insert in reverse order to get the original order */
1537 node = node->prev;
1538 while (node) {
1539 iter = node->prev;
1540 lyd_unlink_tree(node);
1541
1542 lyd_insert_before_node(sibling, node);
1543 /* move the anchor accordingly */
1544 sibling = node;
1545
1546 node = (iter == node) ? NULL : iter;
1547 }
1548 return LY_SUCCESS;
1549}
1550
1551API LY_ERR
1552lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
1553{
1554 struct lyd_node *iter;
1555
1556 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1557
Michal Vasko62ed12d2020-05-21 10:08:25 +02001558 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskof03ed032020-03-04 13:31:44 +01001559
1560 if (node->schema->flags & LYS_KEY) {
1561 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1562 return LY_EINVAL;
1563 } else if (sibling->next && (sibling->next->schema->flags & LYS_KEY)) {
1564 LOGERR(sibling->schema->module->ctx, LY_EINVAL, "Cannot insert into keys.");
1565 return LY_EINVAL;
1566 }
1567
Michal Vasko0249f7c2020-03-05 16:36:40 +01001568 LY_CHECK_RET(lyd_insert_after_check_place(sibling, sibling, node));
1569
Michal Vaskof03ed032020-03-04 13:31:44 +01001570 if (node->parent || node->prev->next) {
1571 lyd_unlink_tree(node);
1572 }
1573
1574 while (node) {
1575 iter = node->next;
1576 lyd_unlink_tree(node);
1577
1578 lyd_insert_after_node(sibling, node);
1579 /* move the anchor accordingly */
1580 sibling = node;
1581
1582 node = iter;
1583 }
1584 return LY_SUCCESS;
1585}
1586
1587API void
1588lyd_unlink_tree(struct lyd_node *node)
1589{
1590 struct lyd_node *iter;
1591
1592 if (!node) {
1593 return;
1594 }
1595
1596 /* unlink from siblings */
1597 if (node->prev->next) {
1598 node->prev->next = node->next;
1599 }
1600 if (node->next) {
1601 node->next->prev = node->prev;
1602 } else {
1603 /* unlinking the last node */
1604 if (node->parent) {
1605 iter = node->parent->child;
1606 } else {
1607 iter = node->prev;
1608 while (iter->prev != node) {
1609 iter = iter->prev;
1610 }
1611 }
1612 /* update the "last" pointer from the first node */
1613 iter->prev = node->prev;
1614 }
1615
1616 /* unlink from parent */
1617 if (node->parent) {
1618 if (node->parent->child == node) {
1619 /* the node is the first child */
1620 node->parent->child = node->next;
1621 }
1622
1623 lyd_unlink_hash(node);
1624
1625 /* check for keyless list and update its hash */
1626 for (iter = (struct lyd_node *)node->parent; iter; iter = (struct lyd_node *)iter->parent) {
Michal Vasko413c7f22020-05-05 12:34:06 +02001627 if (iter->schema && (iter->schema->flags & LYS_KEYLESS)) {
Michal Vaskof03ed032020-03-04 13:31:44 +01001628 lyd_hash(iter);
1629 }
1630 }
1631
1632 node->parent = NULL;
1633 }
1634
1635 node->next = NULL;
1636 node->prev = node;
1637}
1638
Michal Vasko90932a92020-02-12 14:33:03 +01001639LY_ERR
Michal Vasko9f96a052020-03-10 09:41:45 +01001640lyd_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 +01001641 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 +01001642 void *prefix_data, LYD_FORMAT format, const struct lysc_node *ctx_snode)
Michal Vasko90932a92020-02-12 14:33:03 +01001643{
1644 LY_ERR ret;
1645 struct lysc_ext_instance *ant = NULL;
Michal Vasko9f96a052020-03-10 09:41:45 +01001646 struct lyd_meta *mt, *last;
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001647 LY_ARRAY_SIZE_TYPE u;
Michal Vasko90932a92020-02-12 14:33:03 +01001648
Michal Vasko9f96a052020-03-10 09:41:45 +01001649 assert((parent || meta) && mod);
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001650
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001651 LY_ARRAY_FOR(mod->compiled->exts, u) {
1652 if (mod->compiled->exts[u].def->plugin == lyext_plugins_internal[LYEXT_PLUGIN_INTERNAL_ANNOTATION].plugin &&
1653 !ly_strncmp(mod->compiled->exts[u].argument, name, name_len)) {
Michal Vasko90932a92020-02-12 14:33:03 +01001654 /* we have the annotation definition */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001655 ant = &mod->compiled->exts[u];
Michal Vasko90932a92020-02-12 14:33:03 +01001656 break;
1657 }
1658 }
1659 if (!ant) {
1660 /* attribute is not defined as a metadata annotation (RFC 7952) */
1661 LOGERR(mod->ctx, LY_EINVAL, "Annotation definition for attribute \"%s:%.*s\" not found.",
1662 mod->name, name_len, name);
1663 return LY_EINVAL;
1664 }
1665
Michal Vasko9f96a052020-03-10 09:41:45 +01001666 mt = calloc(1, sizeof *mt);
1667 LY_CHECK_ERR_RET(!mt, LOGMEM(mod->ctx), LY_EMEM);
1668 mt->parent = parent;
1669 mt->annotation = ant;
Michal Vasko52927e22020-03-16 17:26:14 +01001670 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 +01001671 if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001672 free(mt);
Michal Vasko90932a92020-02-12 14:33:03 +01001673 return ret;
1674 }
Michal Vasko9f96a052020-03-10 09:41:45 +01001675 mt->name = lydict_insert(mod->ctx, name, name_len);
Michal Vasko90932a92020-02-12 14:33:03 +01001676
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001677 /* insert as the last attribute */
1678 if (parent) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001679 if (parent->meta) {
1680 for (last = parent->meta; last->next; last = last->next);
1681 last->next = mt;
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001682 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +01001683 parent->meta = mt;
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001684 }
Michal Vasko9f96a052020-03-10 09:41:45 +01001685 } else if (*meta) {
1686 for (last = *meta; last->next; last = last->next);
1687 last->next = mt;
Michal Vasko90932a92020-02-12 14:33:03 +01001688 }
1689
1690 /* remove default flags from NP containers */
1691 while (parent && (parent->flags & LYD_DEFAULT)) {
1692 parent->flags &= ~LYD_DEFAULT;
1693 parent = (struct lyd_node *)parent->parent;
1694 }
1695
Michal Vasko9f96a052020-03-10 09:41:45 +01001696 if (meta) {
1697 *meta = mt;
Michal Vasko90932a92020-02-12 14:33:03 +01001698 }
1699 return ret;
1700}
1701
Michal Vasko52927e22020-03-16 17:26:14 +01001702LY_ERR
1703ly_create_attr(struct lyd_node *parent, struct ly_attr **attr, const struct ly_ctx *ctx, const char *name,
1704 size_t name_len, const char *value, size_t value_len, int *dynamic, LYD_FORMAT format,
1705 struct ly_prefix *val_prefs, const char *prefix, size_t prefix_len, const char *ns)
1706{
1707 struct ly_attr *at, *last;
1708 struct lyd_node_opaq *opaq;
1709
1710 assert(ctx && (parent || attr) && (!parent || !parent->schema));
1711 assert(name && name_len);
1712 assert((prefix_len && ns) || (!prefix_len && !ns));
1713
1714 if (!value_len) {
1715 value = "";
1716 }
1717
1718 at = calloc(1, sizeof *at);
1719 LY_CHECK_ERR_RET(!at, LOGMEM(ctx), LY_EMEM);
1720 at->parent = (struct lyd_node_opaq *)parent;
1721 at->name = lydict_insert(ctx, name, name_len);
1722 if (dynamic && *dynamic) {
1723 at->value = lydict_insert_zc(ctx, (char *)value);
1724 *dynamic = 0;
1725 } else {
1726 at->value = lydict_insert(ctx, value, value_len);
1727 }
1728
1729 at->format = format;
1730 at->val_prefs = val_prefs;
1731 if (ns) {
1732 at->prefix.pref = lydict_insert(ctx, prefix, prefix_len);
1733 at->prefix.ns = lydict_insert(ctx, ns, 0);
1734 }
1735
1736 /* insert as the last attribute */
1737 if (parent) {
1738 opaq = (struct lyd_node_opaq *)parent;
1739 if (opaq->attr) {
1740 for (last = opaq->attr; last->next; last = last->next);
1741 last->next = at;
1742 } else {
1743 opaq->attr = at;
1744 }
1745 } else if (*attr) {
1746 for (last = *attr; last->next; last = last->next);
1747 last->next = at;
1748 }
1749
1750 if (attr) {
1751 *attr = at;
1752 }
1753 return LY_SUCCESS;
1754}
1755
Radek Krejci084289f2019-07-09 17:35:30 +02001756API const struct lyd_node_term *
Michal Vasko004d3152020-06-11 19:59:22 +02001757lyd_target(const struct ly_path *path, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +02001758{
Michal Vasko004d3152020-06-11 19:59:22 +02001759 struct lyd_node *target;
Radek Krejci084289f2019-07-09 17:35:30 +02001760
Michal Vasko004d3152020-06-11 19:59:22 +02001761 if (ly_path_eval(path, tree, &target)) {
1762 return NULL;
Radek Krejci084289f2019-07-09 17:35:30 +02001763 }
1764
Michal Vasko004d3152020-06-11 19:59:22 +02001765 return (struct lyd_node_term *)target;
Radek Krejci084289f2019-07-09 17:35:30 +02001766}
1767
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001768API LY_ERR
1769lyd_compare(const struct lyd_node *node1, const struct lyd_node *node2, int options)
1770{
1771 const struct lyd_node *iter1, *iter2;
1772 struct lyd_node_term *term1, *term2;
1773 struct lyd_node_any *any1, *any2;
Michal Vasko52927e22020-03-16 17:26:14 +01001774 struct lyd_node_opaq *opaq1, *opaq2;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001775 size_t len1, len2;
Radek Krejci084289f2019-07-09 17:35:30 +02001776
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001777 if (!node1 || !node2) {
1778 if (node1 == node2) {
1779 return LY_SUCCESS;
1780 } else {
1781 return LY_ENOT;
1782 }
1783 }
1784
Michal Vasko52927e22020-03-16 17:26:14 +01001785 if ((LYD_NODE_CTX(node1) != LYD_NODE_CTX(node2)) || (node1->schema != node2->schema)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001786 return LY_ENOT;
1787 }
1788
1789 if (node1->hash != node2->hash) {
1790 return LY_ENOT;
1791 }
Michal Vasko52927e22020-03-16 17:26:14 +01001792 /* 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 +02001793
Michal Vasko52927e22020-03-16 17:26:14 +01001794 if (!node1->schema) {
1795 opaq1 = (struct lyd_node_opaq *)node1;
1796 opaq2 = (struct lyd_node_opaq *)node2;
1797 if ((opaq1->name != opaq2->name) || (opaq1->prefix.ns != opaq2->prefix.ns) || (opaq1->format != opaq2->format)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001798 return LY_ENOT;
1799 }
Michal Vasko52927e22020-03-16 17:26:14 +01001800 switch (opaq1->format) {
1801 case LYD_XML:
1802 if (lyxml_value_compare(opaq1->value, opaq1->val_prefs, opaq2->value, opaq2->val_prefs)) {
1803 return LY_ENOT;
1804 }
1805 break;
1806 case LYD_SCHEMA:
1807 /* not allowed */
1808 LOGINT(LYD_NODE_CTX(node1));
1809 return LY_EINT;
1810 }
1811 if (options & LYD_COMPARE_FULL_RECURSION) {
1812 iter1 = opaq1->child;
1813 iter2 = opaq2->child;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001814 goto all_children_compare;
Michal Vasko52927e22020-03-16 17:26:14 +01001815 }
1816 return LY_SUCCESS;
1817 } else {
1818 switch (node1->schema->nodetype) {
1819 case LYS_LEAF:
1820 case LYS_LEAFLIST:
1821 if (options & LYD_COMPARE_DEFAULTS) {
1822 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
1823 return LY_ENOT;
1824 }
1825 }
1826
Michal Vasko1a2bf2e2020-06-16 13:07:48 +02001827 term1 = (struct lyd_node_term *)node1;
1828 term2 = (struct lyd_node_term *)node2;
1829 if (term1->value.realtype != term2->value.realtype) {
1830 return LY_ENOT;
1831 }
Michal Vasko52927e22020-03-16 17:26:14 +01001832
Michal Vasko1a2bf2e2020-06-16 13:07:48 +02001833 return term1->value.realtype->plugin->compare(&term1->value, &term2->value);
Michal Vasko52927e22020-03-16 17:26:14 +01001834 case LYS_CONTAINER:
1835 if (options & LYD_COMPARE_DEFAULTS) {
1836 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
1837 return LY_ENOT;
1838 }
1839 }
1840 if (options & LYD_COMPARE_FULL_RECURSION) {
1841 iter1 = ((struct lyd_node_inner*)node1)->child;
1842 iter2 = ((struct lyd_node_inner*)node2)->child;
1843 goto all_children_compare;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001844 }
1845 return LY_SUCCESS;
Michal Vasko1bf09392020-03-27 12:38:10 +01001846 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01001847 case LYS_ACTION:
1848 if (options & LYD_COMPARE_FULL_RECURSION) {
1849 /* TODO action/RPC
1850 goto all_children_compare;
1851 */
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001852 }
1853 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01001854 case LYS_NOTIF:
1855 if (options & LYD_COMPARE_FULL_RECURSION) {
1856 /* TODO Notification
1857 goto all_children_compare;
1858 */
1859 }
1860 return LY_SUCCESS;
1861 case LYS_LIST:
1862 iter1 = ((struct lyd_node_inner*)node1)->child;
1863 iter2 = ((struct lyd_node_inner*)node2)->child;
1864
1865 if (!(node1->schema->flags & LYS_KEYLESS) && !(options & LYD_COMPARE_FULL_RECURSION)) {
1866 /* lists with keys, their equivalence is based on their keys */
1867 for (struct lysc_node *key = ((struct lysc_node_list*)node1->schema)->child;
1868 key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
1869 key = key->next) {
1870 if (lyd_compare(iter1, iter2, options)) {
1871 return LY_ENOT;
1872 }
1873 iter1 = iter1->next;
1874 iter2 = iter2->next;
1875 }
1876 } else {
1877 /* lists without keys, their equivalence is based on equivalence of all the children (both direct and indirect) */
1878
1879 all_children_compare:
1880 if (!iter1 && !iter2) {
1881 /* no children, nothing to compare */
1882 return LY_SUCCESS;
1883 }
1884
1885 for (; iter1 && iter2; iter1 = iter1->next, iter2 = iter2->next) {
1886 if (lyd_compare(iter1, iter2, options | LYD_COMPARE_FULL_RECURSION)) {
1887 return LY_ENOT;
1888 }
1889 }
1890 if (iter1 || iter2) {
1891 return LY_ENOT;
1892 }
1893 }
1894 return LY_SUCCESS;
1895 case LYS_ANYXML:
1896 case LYS_ANYDATA:
1897 any1 = (struct lyd_node_any*)node1;
1898 any2 = (struct lyd_node_any*)node2;
1899
1900 if (any1->value_type != any2->value_type) {
1901 return LY_ENOT;
1902 }
1903 switch (any1->value_type) {
1904 case LYD_ANYDATA_DATATREE:
1905 iter1 = any1->value.tree;
1906 iter2 = any2->value.tree;
1907 goto all_children_compare;
1908 case LYD_ANYDATA_STRING:
1909 case LYD_ANYDATA_XML:
1910 case LYD_ANYDATA_JSON:
1911 len1 = strlen(any1->value.str);
1912 len2 = strlen(any2->value.str);
1913 if (len1 != len2 || strcmp(any1->value.str, any2->value.str)) {
1914 return LY_ENOT;
1915 }
1916 return LY_SUCCESS;
1917 #if 0 /* TODO LYB format */
1918 case LYD_ANYDATA_LYB:
1919 int len1 = lyd_lyb_data_length(any1->value.mem);
1920 int len2 = lyd_lyb_data_length(any2->value.mem);
1921 if (len1 != len2 || memcmp(any1->value.mem, any2->value.mem, len1)) {
1922 return LY_ENOT;
1923 }
1924 return LY_SUCCESS;
1925 #endif
1926 }
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001927 }
1928 }
1929
Michal Vasko52927e22020-03-16 17:26:14 +01001930 LOGINT(LYD_NODE_CTX(node1));
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001931 return LY_EINT;
1932}
Radek Krejci22ebdba2019-07-25 13:59:43 +02001933
1934/**
Michal Vasko52927e22020-03-16 17:26:14 +01001935 * @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 +02001936 *
1937 * 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 +02001938 *
1939 * @param[in] node Original node to duplicate
1940 * @param[in] parent Parent to insert into, NULL for top-level sibling.
1941 * @param[in,out] first First sibling, NULL if no top-level sibling exist yet. Can be also NULL if @p parent is set.
1942 * @param[in] options Bitmask of options flags, see @ref dupoptions.
1943 * @param[out] dup_p Pointer where the created duplicated node is placed (besides connecting it int @p parent / @p first sibling).
1944 * @return LY_ERR value
Radek Krejci22ebdba2019-07-25 13:59:43 +02001945 */
Michal Vasko52927e22020-03-16 17:26:14 +01001946static LY_ERR
1947lyd_dup_recursive(const struct lyd_node *node, struct lyd_node *parent, struct lyd_node **first, int options,
1948 struct lyd_node **dup_p)
Radek Krejci22ebdba2019-07-25 13:59:43 +02001949{
Michal Vasko52927e22020-03-16 17:26:14 +01001950 LY_ERR ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001951 struct lyd_node *dup = NULL;
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001952 LY_ARRAY_SIZE_TYPE u;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001953
Michal Vasko52927e22020-03-16 17:26:14 +01001954 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001955
Michal Vasko52927e22020-03-16 17:26:14 +01001956 if (!node->schema) {
1957 dup = calloc(1, sizeof(struct lyd_node_opaq));
1958 } else {
1959 switch (node->schema->nodetype) {
Michal Vasko1bf09392020-03-27 12:38:10 +01001960 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01001961 case LYS_ACTION:
1962 case LYS_NOTIF:
1963 case LYS_CONTAINER:
1964 case LYS_LIST:
1965 dup = calloc(1, sizeof(struct lyd_node_inner));
1966 break;
1967 case LYS_LEAF:
1968 case LYS_LEAFLIST:
1969 dup = calloc(1, sizeof(struct lyd_node_term));
1970 break;
1971 case LYS_ANYDATA:
1972 case LYS_ANYXML:
1973 dup = calloc(1, sizeof(struct lyd_node_any));
1974 break;
1975 default:
1976 LOGINT(LYD_NODE_CTX(node));
1977 ret = LY_EINT;
1978 goto error;
1979 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02001980 }
Michal Vasko52927e22020-03-16 17:26:14 +01001981 LY_CHECK_ERR_GOTO(!dup, LOGMEM(LYD_NODE_CTX(node)); ret = LY_EMEM, error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001982
1983 /* TODO implement LYD_DUP_WITH_WHEN */
1984 dup->flags = node->flags;
1985 dup->schema = node->schema;
Michal Vasko52927e22020-03-16 17:26:14 +01001986 dup->prev = dup;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001987
1988 /* TODO duplicate attributes, implement LYD_DUP_NO_ATTR */
1989
1990 /* nodetype-specific work */
Michal Vasko52927e22020-03-16 17:26:14 +01001991 if (!dup->schema) {
1992 struct lyd_node_opaq *opaq = (struct lyd_node_opaq *)dup;
1993 struct lyd_node_opaq *orig = (struct lyd_node_opaq *)node;
1994 struct lyd_node *child;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001995
1996 if (options & LYD_DUP_RECURSIVE) {
1997 /* duplicate all the children */
1998 LY_LIST_FOR(orig->child, child) {
Michal Vasko52927e22020-03-16 17:26:14 +01001999 LY_CHECK_GOTO(ret = lyd_dup_recursive(child, dup, NULL, options, NULL), error);
2000 }
2001 }
2002 opaq->name = lydict_insert(LYD_NODE_CTX(node), orig->name, 0);
2003 opaq->format = orig->format;
2004 if (orig->prefix.pref) {
2005 opaq->prefix.pref = lydict_insert(LYD_NODE_CTX(node), orig->prefix.pref, 0);
2006 }
2007 if (orig->prefix.ns) {
2008 opaq->prefix.ns = lydict_insert(LYD_NODE_CTX(node), orig->prefix.ns, 0);
2009 }
2010 if (orig->val_prefs) {
2011 LY_ARRAY_CREATE_GOTO(LYD_NODE_CTX(node), opaq->val_prefs, LY_ARRAY_SIZE(orig->val_prefs), ret, error);
2012 LY_ARRAY_FOR(orig->val_prefs, u) {
2013 opaq->val_prefs[u].pref = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].pref, 0);
2014 opaq->val_prefs[u].ns = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].ns, 0);
2015 LY_ARRAY_INCREMENT(opaq->val_prefs);
2016 }
2017 }
2018 opaq->value = lydict_insert(LYD_NODE_CTX(node), orig->value, 0);
2019 opaq->ctx = orig->ctx;
2020 } else if (dup->schema->nodetype & LYD_NODE_TERM) {
2021 struct lyd_node_term *term = (struct lyd_node_term *)dup;
2022 struct lyd_node_term *orig = (struct lyd_node_term *)node;
2023
2024 term->hash = orig->hash;
2025 term->value.realtype = orig->value.realtype;
2026 LY_CHECK_ERR_GOTO(term->value.realtype->plugin->duplicate(LYD_NODE_CTX(node), &orig->value, &term->value),
2027 LOGERR(LYD_NODE_CTX(node), LY_EINT, "Value duplication failed."); ret = LY_EINT, error);
2028 } else if (dup->schema->nodetype & LYD_NODE_INNER) {
2029 struct lyd_node_inner *orig = (struct lyd_node_inner *)node;
2030 struct lyd_node *child;
2031
2032 if (options & LYD_DUP_RECURSIVE) {
2033 /* duplicate all the children */
2034 LY_LIST_FOR(orig->child, child) {
2035 LY_CHECK_GOTO(ret = lyd_dup_recursive(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002036 }
Radek Krejci0fe9b512019-07-26 17:51:05 +02002037 } else if (dup->schema->nodetype == LYS_LIST && !(dup->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002038 /* always duplicate keys of a list */
Radek Krejci22ebdba2019-07-25 13:59:43 +02002039 child = orig->child;
Michal Vasko52927e22020-03-16 17:26:14 +01002040 for (struct lysc_node *key = ((struct lysc_node_list *)dup->schema)->child;
Radek Krejci0fe9b512019-07-26 17:51:05 +02002041 key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
2042 key = key->next) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002043 if (!child) {
2044 /* possibly not keys are present in filtered tree */
2045 break;
Radek Krejci0fe9b512019-07-26 17:51:05 +02002046 } else if (child->schema != key) {
2047 /* possibly not all keys are present in filtered tree,
2048 * but there can be also some non-key nodes */
2049 continue;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002050 }
Michal Vasko52927e22020-03-16 17:26:14 +01002051 LY_CHECK_GOTO(ret = lyd_dup_recursive(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002052 child = child->next;
2053 }
2054 }
2055 lyd_hash(dup);
2056 } else if (dup->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko52927e22020-03-16 17:26:14 +01002057 struct lyd_node_any *any = (struct lyd_node_any *)dup;
2058 struct lyd_node_any *orig = (struct lyd_node_any *)node;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002059
2060 any->hash = orig->hash;
2061 any->value_type = orig->value_type;
2062 switch (any->value_type) {
2063 case LYD_ANYDATA_DATATREE:
2064 if (orig->value.tree) {
2065 any->value.tree = lyd_dup(orig->value.tree, NULL, LYD_DUP_RECURSIVE | LYD_DUP_WITH_SIBLINGS);
Radek Krejci25dc3432020-05-15 14:42:12 +02002066 if (!any->value.tree) {
2067 /* get the last error's error code recorded by lyd_dup */
2068 struct ly_err_item *ei = ly_err_first(LYD_NODE_CTX(node));
2069 ret = ei ? ei->prev->no : LY_EOTHER;
2070 goto error;
2071 }
2072 LY_CHECK_ERR_GOTO(!any->value.tree, ret = 0 ,error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002073 }
2074 break;
2075 case LYD_ANYDATA_STRING:
2076 case LYD_ANYDATA_XML:
2077 case LYD_ANYDATA_JSON:
2078 if (orig->value.str) {
Michal Vasko52927e22020-03-16 17:26:14 +01002079 any->value.str = lydict_insert(LYD_NODE_CTX(node), orig->value.str, strlen(orig->value.str));
Radek Krejci22ebdba2019-07-25 13:59:43 +02002080 }
2081 break;
2082 }
2083 }
2084
Michal Vasko52927e22020-03-16 17:26:14 +01002085 /* insert */
2086 lyd_insert_node(parent, first, dup);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002087 lyd_insert_hash(dup);
Michal Vasko52927e22020-03-16 17:26:14 +01002088
2089 if (dup_p) {
2090 *dup_p = dup;
2091 }
2092 return LY_SUCCESS;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002093
2094error:
Michal Vasko52927e22020-03-16 17:26:14 +01002095 lyd_free_tree(dup);
2096 return ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002097}
2098
2099API struct lyd_node *
2100lyd_dup(const struct lyd_node *node, struct lyd_node_inner *parent, int options)
2101{
2102 struct ly_ctx *ctx;
2103 const struct lyd_node *orig; /* original node to be duplicated */
2104 struct lyd_node *first = NULL; /* the first duplicated node, this is returned */
Radek Krejci22ebdba2019-07-25 13:59:43 +02002105 struct lyd_node *top = NULL; /* the most higher created node */
2106 struct lyd_node_inner *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
2107 int keyless_parent_list = 0;
2108
2109 LY_CHECK_ARG_RET(NULL, node, NULL);
2110 ctx = node->schema->module->ctx;
2111
2112 if (options & LYD_DUP_WITH_PARENTS) {
2113 struct lyd_node_inner *orig_parent, *iter;
2114 int repeat = 1;
2115 for (top = NULL, orig_parent = node->parent; repeat && orig_parent; orig_parent = orig_parent->parent) {
2116 if (parent && parent->schema == orig_parent->schema) {
2117 /* stop creating parents, connect what we have into the provided parent */
2118 iter = parent;
2119 repeat = 0;
2120 /* get know if there is a keyless list which we will have to rehash */
2121 for (struct lyd_node_inner *piter = parent; piter; piter = piter->parent) {
Radek Krejci0fe9b512019-07-26 17:51:05 +02002122 if (piter->schema->nodetype == LYS_LIST && (piter->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002123 keyless_parent_list = 1;
2124 break;
2125 }
2126 }
2127 } else {
Michal Vasko52927e22020-03-16 17:26:14 +01002128 iter = NULL;
2129 LY_CHECK_GOTO(lyd_dup_recursive((struct lyd_node *)orig_parent, NULL, (struct lyd_node **)&iter, 0,
2130 (struct lyd_node **)&iter), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002131 }
2132 if (!local_parent) {
2133 local_parent = iter;
2134 }
2135 if (iter->child) {
2136 /* 1) list - add after keys
2137 * 2) provided parent with some children */
2138 iter->child->prev->next = top;
2139 if (top) {
2140 top->prev = iter->child->prev;
2141 iter->child->prev = top;
2142 }
2143 } else {
2144 iter->child = top;
2145 if (iter->schema->nodetype == LYS_LIST) {
2146 /* keyless list - we will need to rehash it since we are going to add nodes into it */
2147 keyless_parent_list = 1;
2148 }
2149 }
2150 if (top) {
2151 top->parent = iter;
2152 }
2153 top = (struct lyd_node*)iter;
2154 }
2155 if (repeat && parent) {
2156 /* given parent and created parents chain actually do not interconnect */
2157 LOGERR(ctx, LY_EINVAL, "Invalid argument parent (%s()) - does not interconnect with the created node's parents chain.", __func__);
2158 goto error;
2159 }
2160 } else {
2161 local_parent = parent;
2162 }
2163
Radek Krejci22ebdba2019-07-25 13:59:43 +02002164 LY_LIST_FOR(node, orig) {
Michal Vasko52927e22020-03-16 17:26:14 +01002165 /* if there is no local parent, it will be inserted into first */
2166 LY_CHECK_GOTO(lyd_dup_recursive(orig, (struct lyd_node *)local_parent, &first, options, first ? NULL : &first), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002167 if (!(options & LYD_DUP_WITH_SIBLINGS)) {
2168 break;
2169 }
2170 }
2171 if (keyless_parent_list) {
2172 /* rehash */
2173 for (; local_parent; local_parent = local_parent->parent) {
Radek Krejci0fe9b512019-07-26 17:51:05 +02002174 if (local_parent->schema->nodetype == LYS_LIST && (local_parent->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002175 lyd_hash((struct lyd_node*)local_parent);
2176 }
2177 }
2178 }
2179 return first;
2180
2181error:
2182 if (top) {
2183 lyd_free_tree(top);
2184 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +01002185 lyd_free_siblings(first);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002186 }
2187 return NULL;
2188}
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002189
2190static LY_ERR
2191lyd_path_str_enlarge(char **buffer, size_t *buflen, size_t reqlen, int is_static)
2192{
Michal Vasko14654712020-02-06 08:35:21 +01002193 /* ending \0 */
2194 ++reqlen;
2195
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002196 if (reqlen > *buflen) {
2197 if (is_static) {
2198 return LY_EINCOMPLETE;
2199 }
2200
2201 *buffer = ly_realloc(*buffer, reqlen * sizeof **buffer);
2202 if (!*buffer) {
2203 return LY_EMEM;
2204 }
2205
2206 *buflen = reqlen;
2207 }
2208
2209 return LY_SUCCESS;
2210}
2211
2212/**
2213 * @brief Append all list key predicates to path.
2214 *
2215 * @param[in] node Node with keys to print.
2216 * @param[in,out] buffer Buffer to print to.
2217 * @param[in,out] buflen Current buffer length.
2218 * @param[in,out] bufused Current number of characters used in @p buffer.
2219 * @param[in] is_static Whether buffer is static or can be reallocated.
2220 * @return LY_ERR
2221 */
2222static LY_ERR
2223lyd_path_list_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2224{
2225 const struct lyd_node *key;
2226 int dynamic = 0;
2227 size_t len;
2228 const char *val;
2229 char quot;
2230 LY_ERR rc;
2231
Michal Vasko14654712020-02-06 08:35:21 +01002232 for (key = lyd_node_children(node); key && (key->schema->flags & LYS_KEY); key = key->next) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002233 val = lyd_value2str((struct lyd_node_term *)key, &dynamic);
2234 len = 1 + strlen(key->schema->name) + 2 + strlen(val) + 2;
2235 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2236 if (rc != LY_SUCCESS) {
2237 if (dynamic) {
2238 free((char *)val);
2239 }
2240 return rc;
2241 }
2242
2243 quot = '\'';
2244 if (strchr(val, '\'')) {
2245 quot = '"';
2246 }
2247 *bufused += sprintf(*buffer + *bufused, "[%s=%c%s%c]", key->schema->name, quot, val, quot);
2248
2249 if (dynamic) {
2250 free((char *)val);
2251 }
2252 }
2253
2254 return LY_SUCCESS;
2255}
2256
2257/**
2258 * @brief Append leaf-list value predicate to path.
2259 *
2260 * @param[in] node Node to print.
2261 * @param[in,out] buffer Buffer to print to.
2262 * @param[in,out] buflen Current buffer length.
2263 * @param[in,out] bufused Current number of characters used in @p buffer.
2264 * @param[in] is_static Whether buffer is static or can be reallocated.
2265 * @return LY_ERR
2266 */
2267static LY_ERR
2268lyd_path_leaflist_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2269{
2270 int dynamic = 0;
2271 size_t len;
2272 const char *val;
2273 char quot;
2274 LY_ERR rc;
2275
2276 val = lyd_value2str((struct lyd_node_term *)node, &dynamic);
2277 len = 4 + strlen(val) + 2;
2278 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2279 if (rc != LY_SUCCESS) {
2280 goto cleanup;
2281 }
2282
2283 quot = '\'';
2284 if (strchr(val, '\'')) {
2285 quot = '"';
2286 }
2287 *bufused += sprintf(*buffer + *bufused, "[.=%c%s%c]", quot, val, quot);
2288
2289cleanup:
2290 if (dynamic) {
2291 free((char *)val);
2292 }
2293 return rc;
2294}
2295
2296/**
2297 * @brief Append node position (relative to its other instances) predicate to path.
2298 *
2299 * @param[in] node Node to print.
2300 * @param[in,out] buffer Buffer to print to.
2301 * @param[in,out] buflen Current buffer length.
2302 * @param[in,out] bufused Current number of characters used in @p buffer.
2303 * @param[in] is_static Whether buffer is static or can be reallocated.
2304 * @return LY_ERR
2305 */
2306static LY_ERR
2307lyd_path_position_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2308{
2309 const struct lyd_node *first, *iter;
2310 size_t len;
2311 int pos;
2312 char *val = NULL;
2313 LY_ERR rc;
2314
2315 if (node->parent) {
2316 first = node->parent->child;
2317 } else {
2318 for (first = node; node->prev->next; node = node->prev);
2319 }
2320 pos = 1;
2321 for (iter = first; iter != node; iter = iter->next) {
2322 if (iter->schema == node->schema) {
2323 ++pos;
2324 }
2325 }
2326 if (asprintf(&val, "%d", pos) == -1) {
2327 return LY_EMEM;
2328 }
2329
2330 len = 1 + strlen(val) + 1;
2331 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2332 if (rc != LY_SUCCESS) {
2333 goto cleanup;
2334 }
2335
2336 *bufused += sprintf(*buffer + *bufused, "[%s]", val);
2337
2338cleanup:
2339 free(val);
2340 return rc;
2341}
2342
2343API char *
2344lyd_path(const struct lyd_node *node, LYD_PATH_TYPE pathtype, char *buffer, size_t buflen)
2345{
Michal Vasko14654712020-02-06 08:35:21 +01002346 int is_static = 0, i, depth;
2347 size_t bufused = 0, len;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002348 const struct lyd_node *iter;
2349 const struct lys_module *mod;
2350 LY_ERR rc;
2351
2352 LY_CHECK_ARG_RET(NULL, node, NULL);
2353 if (buffer) {
2354 LY_CHECK_ARG_RET(node->schema->module->ctx, buflen > 1, NULL);
2355 is_static = 1;
Michal Vasko14654712020-02-06 08:35:21 +01002356 } else {
2357 buflen = 0;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002358 }
2359
2360 switch (pathtype) {
Michal Vasko14654712020-02-06 08:35:21 +01002361 case LYD_PATH_LOG:
2362 depth = 1;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002363 for (iter = node; iter->parent; iter = (const struct lyd_node *)iter->parent) {
2364 ++depth;
2365 }
2366
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002367 goto iter_print;
Michal Vasko14654712020-02-06 08:35:21 +01002368 while (depth) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002369 /* find the right node */
Michal Vasko14654712020-02-06 08:35:21 +01002370 for (iter = node, i = 1; i < depth; iter = (const struct lyd_node *)iter->parent, ++i);
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002371iter_print:
2372 /* print prefix and name */
2373 mod = NULL;
2374 if (!iter->parent || (iter->schema->module != iter->parent->schema->module)) {
2375 mod = iter->schema->module;
2376 }
2377
2378 /* realloc string */
2379 len = 1 + (mod ? strlen(mod->name) + 1 : 0) + strlen(iter->schema->name);
2380 rc = lyd_path_str_enlarge(&buffer, &buflen, bufused + len, is_static);
2381 if (rc != LY_SUCCESS) {
2382 break;
2383 }
2384
2385 /* print next node */
2386 bufused += sprintf(buffer + bufused, "/%s%s%s", mod ? mod->name : "", mod ? ":" : "", iter->schema->name);
2387
2388 switch (iter->schema->nodetype) {
2389 case LYS_LIST:
2390 if (iter->schema->flags & LYS_KEYLESS) {
2391 /* print its position */
2392 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2393 } else {
2394 /* print all list keys in predicates */
2395 rc = lyd_path_list_predicate(iter, &buffer, &buflen, &bufused, is_static);
2396 }
2397 break;
2398 case LYS_LEAFLIST:
2399 if (iter->schema->flags & LYS_CONFIG_W) {
2400 /* print leaf-list value */
2401 rc = lyd_path_leaflist_predicate(iter, &buffer, &buflen, &bufused, is_static);
2402 } else {
2403 /* print its position */
2404 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2405 }
2406 break;
2407 default:
2408 /* nothing to print more */
2409 rc = LY_SUCCESS;
2410 break;
2411 }
2412 if (rc != LY_SUCCESS) {
2413 break;
2414 }
2415
Michal Vasko14654712020-02-06 08:35:21 +01002416 --depth;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002417 }
2418 break;
2419 }
2420
2421 return buffer;
2422}
Michal Vaskoe444f752020-02-10 12:20:06 +01002423
Michal Vasko9b368d32020-02-14 13:53:31 +01002424LY_ERR
2425lyd_find_sibling_next2(const struct lyd_node *first, const struct lysc_node *schema, const char *key_or_value,
2426 size_t val_len, struct lyd_node **match)
Michal Vaskoe444f752020-02-10 12:20:06 +01002427{
2428 LY_ERR rc;
2429 const struct lyd_node *node = NULL;
2430 struct lyd_node_term *term;
Michal Vasko00cbf532020-06-15 13:58:47 +02002431 struct lyxp_expr *expr = NULL;
2432 uint16_t exp_idx = 0;
2433 struct ly_path_predicate *predicates = NULL;
2434 enum ly_path_pred_type pred_type = 0;
Michal Vasko90932a92020-02-12 14:33:03 +01002435 struct lyd_value val = {0};
Michal Vasko00cbf532020-06-15 13:58:47 +02002436 LY_ARRAY_SIZE_TYPE u;
Michal Vaskoe444f752020-02-10 12:20:06 +01002437
Michal Vasko9b368d32020-02-14 13:53:31 +01002438 LY_CHECK_ARG_RET(NULL, schema, LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01002439
2440 if (!first) {
2441 /* no data */
Michal Vasko9b368d32020-02-14 13:53:31 +01002442 if (match) {
2443 *match = NULL;
2444 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002445 return LY_ENOTFOUND;
2446 }
2447
Michal Vaskoe444f752020-02-10 12:20:06 +01002448 if (key_or_value && !val_len) {
2449 val_len = strlen(key_or_value);
2450 }
2451
2452 if (key_or_value && (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko90932a92020-02-12 14:33:03 +01002453 /* store the value */
Michal Vasko9b368d32020-02-14 13:53:31 +01002454 LY_CHECK_GOTO(rc = lyd_value_store(&val, schema, key_or_value, val_len, 0, lydjson_resolve_prefix, NULL, LYD_JSON), cleanup);
Michal Vaskoe444f752020-02-10 12:20:06 +01002455 } else if (key_or_value && (schema->nodetype == LYS_LIST)) {
Michal Vasko00cbf532020-06-15 13:58:47 +02002456 /* parse keys */
2457 LY_CHECK_GOTO(rc = ly_path_parse_predicate(schema->module->ctx, key_or_value, val_len, LY_PATH_PREFIX_OPTIONAL,
2458 LY_PATH_PRED_KEYS, &expr), cleanup);
2459
2460 /* compile them */
2461 LY_CHECK_GOTO(rc = ly_path_compile_predicate(schema->module->ctx, NULL, schema, expr, &exp_idx, lydjson_resolve_prefix,
2462 NULL, LYD_JSON, &predicates, &pred_type), cleanup);
Michal Vaskoe444f752020-02-10 12:20:06 +01002463 }
2464
2465 /* find first matching value */
2466 LY_LIST_FOR(first, node) {
2467 if (node->schema != schema) {
2468 continue;
2469 }
2470
Michal Vasko00cbf532020-06-15 13:58:47 +02002471 if ((schema->nodetype == LYS_LIST) && predicates) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002472 /* compare all set keys */
Michal Vasko00cbf532020-06-15 13:58:47 +02002473 LY_ARRAY_FOR(predicates, u) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002474 /* find key */
Michal Vasko00cbf532020-06-15 13:58:47 +02002475 rc = lyd_find_sibling_val(lyd_node_children(node), predicates[u].key, NULL, 0, (struct lyd_node **)&term);
Michal Vaskoe444f752020-02-10 12:20:06 +01002476 if (rc == LY_ENOTFOUND) {
2477 /* all keys must always exist */
Michal Vasko9b368d32020-02-14 13:53:31 +01002478 LOGINT_RET(schema->module->ctx);
Michal Vaskoe444f752020-02-10 12:20:06 +01002479 }
2480 LY_CHECK_GOTO(rc, cleanup);
2481
2482 /* compare values */
Michal Vasko00cbf532020-06-15 13:58:47 +02002483 if (!term->value.realtype->plugin->compare(&term->value, &predicates[u].value)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002484 break;
2485 }
2486 }
2487
Michal Vasko00cbf532020-06-15 13:58:47 +02002488 if (u < LY_ARRAY_SIZE(predicates)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002489 /* not a match */
2490 continue;
2491 }
Michal Vasko90932a92020-02-12 14:33:03 +01002492 } else if ((schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && val.realtype) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002493 term = (struct lyd_node_term *)node;
2494
2495 /* compare values */
Michal Vasko90932a92020-02-12 14:33:03 +01002496 if (!term->value.realtype->plugin->compare(&term->value, &val)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002497 /* not a match */
2498 continue;
2499 }
2500 }
2501
2502 /* all criteria passed */
2503 break;
2504 }
2505
2506 if (!node) {
2507 rc = LY_ENOTFOUND;
Michal Vasko9b368d32020-02-14 13:53:31 +01002508 if (match) {
2509 *match = NULL;
2510 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002511 goto cleanup;
2512 }
2513
2514 /* success */
Michal Vasko9b368d32020-02-14 13:53:31 +01002515 if (match) {
2516 *match = (struct lyd_node *)node;
2517 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002518 rc = LY_SUCCESS;
2519
2520cleanup:
Michal Vasko00cbf532020-06-15 13:58:47 +02002521 ly_path_predicates_free(schema->module->ctx, pred_type, NULL, predicates);
2522 lyxp_expr_free(schema->module->ctx, expr);
Michal Vasko90932a92020-02-12 14:33:03 +01002523 if (val.realtype) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002524 val.realtype->plugin->free(schema->module->ctx, &val);
Michal Vasko90932a92020-02-12 14:33:03 +01002525 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002526 return rc;
2527}
2528
2529API LY_ERR
Michal Vasko9b368d32020-02-14 13:53:31 +01002530lyd_find_sibling_next(const struct lyd_node *first, const struct lys_module *module, const char *name, size_t name_len,
2531 const char *key_or_value, size_t val_len, struct lyd_node **match)
2532{
2533 const struct lysc_node *schema;
2534
2535 LY_CHECK_ARG_RET(NULL, module, name, match, LY_EINVAL);
2536
2537 if (!first) {
2538 /* no data */
2539 *match = NULL;
2540 return LY_ENOTFOUND;
2541 }
2542
2543 /* find schema */
2544 schema = lys_find_child(first->parent ? first->parent->schema : NULL, module, name, name_len, 0, 0);
2545 if (!schema) {
2546 LOGERR(module->ctx, LY_EINVAL, "Schema node not found.");
2547 return LY_EINVAL;
2548 }
2549
2550 return lyd_find_sibling_next2(first, schema, key_or_value, val_len, match);
2551}
2552
2553API LY_ERR
Michal Vaskoe444f752020-02-10 12:20:06 +01002554lyd_find_sibling_first(const struct lyd_node *siblings, const struct lyd_node *target, struct lyd_node **match)
2555{
2556 struct lyd_node **match_p;
2557 struct lyd_node_inner *parent;
2558
Michal Vaskof03ed032020-03-04 13:31:44 +01002559 LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01002560
Michal Vasko62ed12d2020-05-21 10:08:25 +02002561 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(target->schema))) {
2562 /* no data or schema mismatch */
Michal Vasko9b368d32020-02-14 13:53:31 +01002563 if (match) {
2564 *match = NULL;
2565 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002566 return LY_ENOTFOUND;
2567 }
2568
2569 /* find first sibling */
2570 if (siblings->parent) {
2571 siblings = siblings->parent->child;
2572 } else {
2573 while (siblings->prev->next) {
2574 siblings = siblings->prev;
2575 }
2576 }
2577
2578 parent = (struct lyd_node_inner *)siblings->parent;
2579 if (parent && parent->children_ht) {
2580 assert(target->hash);
2581
2582 /* find by hash */
2583 if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
2584 siblings = *match_p;
2585 } else {
2586 /* not found */
2587 siblings = NULL;
2588 }
2589 } else {
2590 /* no children hash table */
2591 for (; siblings; siblings = siblings->next) {
2592 if (!lyd_compare(siblings, target, 0)) {
2593 break;
2594 }
2595 }
2596 }
2597
2598 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002599 if (match) {
2600 *match = NULL;
2601 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002602 return LY_ENOTFOUND;
2603 }
2604
Michal Vasko9b368d32020-02-14 13:53:31 +01002605 if (match) {
2606 *match = (struct lyd_node *)siblings;
2607 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002608 return LY_SUCCESS;
2609}
2610
2611API LY_ERR
2612lyd_find_sibling_set(const struct lyd_node *siblings, const struct lyd_node *target, struct ly_set **set)
2613{
2614 struct lyd_node_inner *parent;
2615 struct lyd_node *match;
2616 struct lyd_node **match_p;
2617 struct ly_set *ret;
2618
2619 LY_CHECK_ARG_RET(NULL, target, set, LY_EINVAL);
2620
Michal Vasko62ed12d2020-05-21 10:08:25 +02002621 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(target->schema))) {
2622 /* no data or schema mismatch */
Michal Vaskoe444f752020-02-10 12:20:06 +01002623 return LY_ENOTFOUND;
2624 }
2625
2626 ret = ly_set_new();
2627 LY_CHECK_ERR_RET(!ret, LOGMEM(target->schema->module->ctx), LY_EMEM);
2628
2629 /* find first sibling */
2630 if (siblings->parent) {
2631 siblings = siblings->parent->child;
2632 } else {
2633 while (siblings->prev->next) {
2634 siblings = siblings->prev;
2635 }
2636 }
2637
2638 parent = (struct lyd_node_inner *)siblings->parent;
2639 if (parent && parent->children_ht) {
2640 assert(target->hash);
2641
2642 /* find by hash */
2643 if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
2644 match = *match_p;
2645 } else {
2646 /* not found */
2647 match = NULL;
2648 }
2649 while (match) {
2650 /* add all found nodes into the return set */
2651 if (ly_set_add(ret, match, LY_SET_OPT_USEASLIST) == -1) {
2652 goto error;
2653 }
2654
2655 /* find next instance */
2656 if (lyht_find_next(parent->children_ht, &match, match->hash, (void **)&match_p)) {
2657 match = NULL;
2658 } else {
2659 match = *match_p;
2660 }
2661 }
2662 } else {
2663 /* no children hash table */
2664 for (; siblings; siblings = siblings->next) {
2665 if (!lyd_compare(siblings, target, 0)) {
2666 /* a match */
2667 if (ly_set_add(ret, (struct lyd_node *)siblings, LY_SET_OPT_USEASLIST) == -1) {
2668 goto error;
2669 }
2670 }
2671 }
2672 }
2673
2674 if (!ret->count) {
2675 ly_set_free(ret, NULL);
2676 return LY_ENOTFOUND;
2677 }
2678
2679 *set = ret;
2680 return LY_SUCCESS;
2681
2682error:
2683 ly_set_free(ret, NULL);
2684 return LY_EMEM;
2685}
2686
Michal Vasko90932a92020-02-12 14:33:03 +01002687static int
2688lyd_hash_table_schema_val_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *UNUSED(cb_data))
2689{
2690 struct lysc_node *val1;
2691 struct lyd_node *val2;
2692
2693 val1 = *((struct lysc_node **)val1_p);
2694 val2 = *((struct lyd_node **)val2_p);
2695
2696 assert(val1->nodetype & (LYD_NODE_INNER | LYS_LEAF));
2697
2698 if (val1 == val2->schema) {
2699 /* schema match is enough */
2700 return 1;
2701 } else {
2702 return 0;
2703 }
2704}
2705
2706static LY_ERR
2707lyd_find_sibling_schema(const struct lyd_node *siblings, const struct lysc_node *schema, struct lyd_node **match)
2708{
2709 struct lyd_node **match_p;
2710 struct lyd_node_inner *parent;
2711 uint32_t hash;
2712 values_equal_cb ht_cb;
2713
2714 assert(siblings && schema && (schema->nodetype & (LYD_NODE_INNER | LYS_LEAF)));
2715
2716 /* find first sibling */
2717 if (siblings->parent) {
2718 siblings = siblings->parent->child;
2719 } else {
2720 while (siblings->prev->next) {
2721 siblings = siblings->prev;
2722 }
2723 }
2724
2725 parent = (struct lyd_node_inner *)siblings->parent;
2726 if (parent && parent->children_ht) {
2727 /* calculate our hash */
2728 hash = dict_hash_multi(0, schema->module->name, strlen(schema->module->name));
2729 hash = dict_hash_multi(hash, schema->name, strlen(schema->name));
2730 hash = dict_hash_multi(hash, NULL, 0);
2731
2732 /* use special hash table function */
2733 ht_cb = lyht_set_cb(parent->children_ht, lyd_hash_table_schema_val_equal);
2734
2735 /* find by hash */
2736 if (!lyht_find(parent->children_ht, &schema, hash, (void **)&match_p)) {
2737 siblings = *match_p;
2738 } else {
2739 /* not found */
2740 siblings = NULL;
2741 }
2742
2743 /* set the original hash table compare function back */
2744 lyht_set_cb(parent->children_ht, ht_cb);
2745 } else {
2746 /* no children hash table */
2747 for (; siblings; siblings = siblings->next) {
2748 if (siblings->schema == schema) {
2749 /* schema match is enough */
2750 break;
2751 }
2752 }
2753 }
2754
2755 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002756 if (match) {
2757 *match = NULL;
2758 }
Michal Vasko90932a92020-02-12 14:33:03 +01002759 return LY_ENOTFOUND;
2760 }
2761
Michal Vasko9b368d32020-02-14 13:53:31 +01002762 if (match) {
2763 *match = (struct lyd_node *)siblings;
2764 }
Michal Vasko90932a92020-02-12 14:33:03 +01002765 return LY_SUCCESS;
2766}
2767
Michal Vaskoe444f752020-02-10 12:20:06 +01002768API LY_ERR
2769lyd_find_sibling_val(const struct lyd_node *siblings, const struct lysc_node *schema, const char *key_or_value,
2770 size_t val_len, struct lyd_node **match)
2771{
2772 LY_ERR rc;
2773 struct lyd_node *target = NULL;
2774
2775 LY_CHECK_ARG_RET(NULL, schema, LY_EINVAL);
Michal Vasko62ed12d2020-05-21 10:08:25 +02002776 if ((schema->nodetype == LYS_LIST) && (schema->flags & LYS_KEYLESS)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002777 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - key-less list (%s()).", __func__);
2778 return LY_EINVAL;
2779 } else if ((schema->nodetype & (LYS_LEAFLIST | LYS_LIST)) && !key_or_value) {
2780 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - no value/keys for a (leaf-)list (%s()).", __func__);
2781 return LY_EINVAL;
2782 } else if (schema->nodetype & (LYS_CHOICE | LYS_CASE)) {
2783 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - schema type %s (%s()).",
2784 lys_nodetype2str(schema->nodetype), __func__);
2785 return LY_EINVAL;
2786 }
2787
Michal Vasko62ed12d2020-05-21 10:08:25 +02002788 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(schema))) {
2789 /* no data or schema mismatch */
Michal Vasko9b368d32020-02-14 13:53:31 +01002790 if (match) {
2791 *match = NULL;
2792 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002793 return LY_ENOTFOUND;
2794 }
2795
Michal Vaskof03ed032020-03-04 13:31:44 +01002796 if (key_or_value && !val_len) {
2797 val_len = strlen(key_or_value);
2798 }
2799
Michal Vasko90932a92020-02-12 14:33:03 +01002800 /* create data node if needed and find it */
Michal Vaskoe444f752020-02-10 12:20:06 +01002801 switch (schema->nodetype) {
2802 case LYS_CONTAINER:
2803 case LYS_ANYXML:
2804 case LYS_ANYDATA:
2805 case LYS_NOTIF:
Michal Vasko1bf09392020-03-27 12:38:10 +01002806 case LYS_RPC:
Michal Vasko9b368d32020-02-14 13:53:31 +01002807 case LYS_ACTION:
Michal Vaskoe444f752020-02-10 12:20:06 +01002808 case LYS_LEAF:
Michal Vasko004d3152020-06-11 19:59:22 +02002809 /* find it based on schema only, there cannot be more instances */
Michal Vasko90932a92020-02-12 14:33:03 +01002810 rc = lyd_find_sibling_schema(siblings, schema, match);
Michal Vaskoe444f752020-02-10 12:20:06 +01002811 break;
2812 case LYS_LEAFLIST:
2813 /* target used attributes: schema, hash, value */
Michal Vaskocbff3e92020-05-27 12:56:41 +02002814 rc = lyd_create_term(schema, key_or_value, val_len, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &target);
2815 LY_CHECK_RET(rc && (rc != LY_EINCOMPLETE), rc);
2816 rc = LY_SUCCESS;
Michal Vasko90932a92020-02-12 14:33:03 +01002817 /* fallthrough */
Michal Vaskoe444f752020-02-10 12:20:06 +01002818 case LYS_LIST:
Michal Vasko90932a92020-02-12 14:33:03 +01002819 if (schema->nodetype == LYS_LIST) {
2820 /* target used attributes: schema, hash, child (all keys) */
Michal Vasko004d3152020-06-11 19:59:22 +02002821 LY_CHECK_RET(lyd_create_list2(schema, key_or_value, val_len, &target));
Michal Vasko90932a92020-02-12 14:33:03 +01002822 }
2823
2824 /* find it */
2825 rc = lyd_find_sibling_first(siblings, target, match);
Michal Vaskoe444f752020-02-10 12:20:06 +01002826 break;
2827 default:
2828 /* unreachable */
2829 LOGINT(schema->module->ctx);
2830 return LY_EINT;
2831 }
2832
Michal Vaskoe444f752020-02-10 12:20:06 +01002833 lyd_free_tree(target);
2834 return rc;
2835}
Michal Vaskoccc02342020-05-21 10:09:21 +02002836
2837API LY_ERR
2838lyd_find_xpath(const struct lyd_node *ctx_node, const char *xpath, struct ly_set **set)
2839{
2840 LY_ERR ret = LY_SUCCESS;
2841 struct lyxp_set xp_set;
2842 struct lyxp_expr *exp;
2843 uint32_t i;
2844
2845 LY_CHECK_ARG_RET(NULL, ctx_node, xpath, set, LY_EINVAL);
2846
2847 memset(&xp_set, 0, sizeof xp_set);
2848
2849 /* compile expression */
Michal Vasko004d3152020-06-11 19:59:22 +02002850 exp = lyxp_expr_parse((struct ly_ctx *)LYD_NODE_CTX(ctx_node), xpath, 0, 1);
Michal Vaskoccc02342020-05-21 10:09:21 +02002851 LY_CHECK_ERR_GOTO(!exp, ret = LY_EINVAL, cleanup);
2852
2853 /* evaluate expression */
2854 ret = lyxp_eval(exp, LYD_JSON, ctx_node->schema->module, ctx_node, LYXP_NODE_ELEM, ctx_node, &xp_set, 0);
2855 LY_CHECK_GOTO(ret, cleanup);
2856
2857 /* allocate return set */
2858 *set = ly_set_new();
2859 LY_CHECK_ERR_GOTO(!*set, LOGMEM(LYD_NODE_CTX(ctx_node)); ret = LY_EMEM, cleanup);
2860
2861 /* transform into ly_set */
2862 if (xp_set.type == LYXP_SET_NODE_SET) {
2863 /* allocate memory for all the elements once (even though not all items must be elements but most likely will be) */
2864 (*set)->objs = malloc(xp_set.used * sizeof *(*set)->objs);
2865 LY_CHECK_ERR_GOTO(!(*set)->objs, LOGMEM(LYD_NODE_CTX(ctx_node)); ret = LY_EMEM, cleanup);
2866 (*set)->size = xp_set.used;
2867
2868 for (i = 0; i < xp_set.used; ++i) {
2869 if (xp_set.val.nodes[i].type == LYXP_NODE_ELEM) {
2870 ly_set_add(*set, xp_set.val.nodes[i].node, LY_SET_OPT_USEASLIST);
2871 }
2872 }
2873 }
2874
2875cleanup:
Michal Vasko0691d522020-05-21 13:21:47 +02002876 lyxp_set_free_content(&xp_set);
Michal Vaskoccc02342020-05-21 10:09:21 +02002877 lyxp_expr_free((struct ly_ctx *)LYD_NODE_CTX(ctx_node), exp);
2878 return ret;
2879}