blob: 9f4781603f26fa5221a4264feadd130705ae08e6 [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 struct lysc_type *type;
1776 size_t len1, len2;
Radek Krejci084289f2019-07-09 17:35:30 +02001777
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001778 if (!node1 || !node2) {
1779 if (node1 == node2) {
1780 return LY_SUCCESS;
1781 } else {
1782 return LY_ENOT;
1783 }
1784 }
1785
Michal Vasko52927e22020-03-16 17:26:14 +01001786 if ((LYD_NODE_CTX(node1) != LYD_NODE_CTX(node2)) || (node1->schema != node2->schema)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001787 return LY_ENOT;
1788 }
1789
1790 if (node1->hash != node2->hash) {
1791 return LY_ENOT;
1792 }
Michal Vasko52927e22020-03-16 17:26:14 +01001793 /* 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 +02001794
Michal Vasko52927e22020-03-16 17:26:14 +01001795 if (!node1->schema) {
1796 opaq1 = (struct lyd_node_opaq *)node1;
1797 opaq2 = (struct lyd_node_opaq *)node2;
1798 if ((opaq1->name != opaq2->name) || (opaq1->prefix.ns != opaq2->prefix.ns) || (opaq1->format != opaq2->format)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001799 return LY_ENOT;
1800 }
Michal Vasko52927e22020-03-16 17:26:14 +01001801 switch (opaq1->format) {
1802 case LYD_XML:
1803 if (lyxml_value_compare(opaq1->value, opaq1->val_prefs, opaq2->value, opaq2->val_prefs)) {
1804 return LY_ENOT;
1805 }
1806 break;
1807 case LYD_SCHEMA:
1808 /* not allowed */
1809 LOGINT(LYD_NODE_CTX(node1));
1810 return LY_EINT;
1811 }
1812 if (options & LYD_COMPARE_FULL_RECURSION) {
1813 iter1 = opaq1->child;
1814 iter2 = opaq2->child;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001815 goto all_children_compare;
Michal Vasko52927e22020-03-16 17:26:14 +01001816 }
1817 return LY_SUCCESS;
1818 } else {
1819 switch (node1->schema->nodetype) {
1820 case LYS_LEAF:
1821 case LYS_LEAFLIST:
1822 if (options & LYD_COMPARE_DEFAULTS) {
1823 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
1824 return LY_ENOT;
1825 }
1826 }
1827
1828 term1 = (struct lyd_node_term*)node1;
1829 term2 = (struct lyd_node_term*)node2;
1830 type = ((struct lysc_node_leaf*)node1->schema)->type;
1831
1832 return type->plugin->compare(&term1->value, &term2->value);
1833 case LYS_CONTAINER:
1834 if (options & LYD_COMPARE_DEFAULTS) {
1835 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
1836 return LY_ENOT;
1837 }
1838 }
1839 if (options & LYD_COMPARE_FULL_RECURSION) {
1840 iter1 = ((struct lyd_node_inner*)node1)->child;
1841 iter2 = ((struct lyd_node_inner*)node2)->child;
1842 goto all_children_compare;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001843 }
1844 return LY_SUCCESS;
Michal Vasko1bf09392020-03-27 12:38:10 +01001845 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01001846 case LYS_ACTION:
1847 if (options & LYD_COMPARE_FULL_RECURSION) {
1848 /* TODO action/RPC
1849 goto all_children_compare;
1850 */
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001851 }
1852 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01001853 case LYS_NOTIF:
1854 if (options & LYD_COMPARE_FULL_RECURSION) {
1855 /* TODO Notification
1856 goto all_children_compare;
1857 */
1858 }
1859 return LY_SUCCESS;
1860 case LYS_LIST:
1861 iter1 = ((struct lyd_node_inner*)node1)->child;
1862 iter2 = ((struct lyd_node_inner*)node2)->child;
1863
1864 if (!(node1->schema->flags & LYS_KEYLESS) && !(options & LYD_COMPARE_FULL_RECURSION)) {
1865 /* lists with keys, their equivalence is based on their keys */
1866 for (struct lysc_node *key = ((struct lysc_node_list*)node1->schema)->child;
1867 key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
1868 key = key->next) {
1869 if (lyd_compare(iter1, iter2, options)) {
1870 return LY_ENOT;
1871 }
1872 iter1 = iter1->next;
1873 iter2 = iter2->next;
1874 }
1875 } else {
1876 /* lists without keys, their equivalence is based on equivalence of all the children (both direct and indirect) */
1877
1878 all_children_compare:
1879 if (!iter1 && !iter2) {
1880 /* no children, nothing to compare */
1881 return LY_SUCCESS;
1882 }
1883
1884 for (; iter1 && iter2; iter1 = iter1->next, iter2 = iter2->next) {
1885 if (lyd_compare(iter1, iter2, options | LYD_COMPARE_FULL_RECURSION)) {
1886 return LY_ENOT;
1887 }
1888 }
1889 if (iter1 || iter2) {
1890 return LY_ENOT;
1891 }
1892 }
1893 return LY_SUCCESS;
1894 case LYS_ANYXML:
1895 case LYS_ANYDATA:
1896 any1 = (struct lyd_node_any*)node1;
1897 any2 = (struct lyd_node_any*)node2;
1898
1899 if (any1->value_type != any2->value_type) {
1900 return LY_ENOT;
1901 }
1902 switch (any1->value_type) {
1903 case LYD_ANYDATA_DATATREE:
1904 iter1 = any1->value.tree;
1905 iter2 = any2->value.tree;
1906 goto all_children_compare;
1907 case LYD_ANYDATA_STRING:
1908 case LYD_ANYDATA_XML:
1909 case LYD_ANYDATA_JSON:
1910 len1 = strlen(any1->value.str);
1911 len2 = strlen(any2->value.str);
1912 if (len1 != len2 || strcmp(any1->value.str, any2->value.str)) {
1913 return LY_ENOT;
1914 }
1915 return LY_SUCCESS;
1916 #if 0 /* TODO LYB format */
1917 case LYD_ANYDATA_LYB:
1918 int len1 = lyd_lyb_data_length(any1->value.mem);
1919 int len2 = lyd_lyb_data_length(any2->value.mem);
1920 if (len1 != len2 || memcmp(any1->value.mem, any2->value.mem, len1)) {
1921 return LY_ENOT;
1922 }
1923 return LY_SUCCESS;
1924 #endif
1925 }
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001926 }
1927 }
1928
Michal Vasko52927e22020-03-16 17:26:14 +01001929 LOGINT(LYD_NODE_CTX(node1));
Radek Krejci1f05b6a2019-07-18 16:15:06 +02001930 return LY_EINT;
1931}
Radek Krejci22ebdba2019-07-25 13:59:43 +02001932
1933/**
Michal Vasko52927e22020-03-16 17:26:14 +01001934 * @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 +02001935 *
1936 * 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 +02001937 *
1938 * @param[in] node Original node to duplicate
1939 * @param[in] parent Parent to insert into, NULL for top-level sibling.
1940 * @param[in,out] first First sibling, NULL if no top-level sibling exist yet. Can be also NULL if @p parent is set.
1941 * @param[in] options Bitmask of options flags, see @ref dupoptions.
1942 * @param[out] dup_p Pointer where the created duplicated node is placed (besides connecting it int @p parent / @p first sibling).
1943 * @return LY_ERR value
Radek Krejci22ebdba2019-07-25 13:59:43 +02001944 */
Michal Vasko52927e22020-03-16 17:26:14 +01001945static LY_ERR
1946lyd_dup_recursive(const struct lyd_node *node, struct lyd_node *parent, struct lyd_node **first, int options,
1947 struct lyd_node **dup_p)
Radek Krejci22ebdba2019-07-25 13:59:43 +02001948{
Michal Vasko52927e22020-03-16 17:26:14 +01001949 LY_ERR ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001950 struct lyd_node *dup = NULL;
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001951 LY_ARRAY_SIZE_TYPE u;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001952
Michal Vasko52927e22020-03-16 17:26:14 +01001953 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001954
Michal Vasko52927e22020-03-16 17:26:14 +01001955 if (!node->schema) {
1956 dup = calloc(1, sizeof(struct lyd_node_opaq));
1957 } else {
1958 switch (node->schema->nodetype) {
Michal Vasko1bf09392020-03-27 12:38:10 +01001959 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01001960 case LYS_ACTION:
1961 case LYS_NOTIF:
1962 case LYS_CONTAINER:
1963 case LYS_LIST:
1964 dup = calloc(1, sizeof(struct lyd_node_inner));
1965 break;
1966 case LYS_LEAF:
1967 case LYS_LEAFLIST:
1968 dup = calloc(1, sizeof(struct lyd_node_term));
1969 break;
1970 case LYS_ANYDATA:
1971 case LYS_ANYXML:
1972 dup = calloc(1, sizeof(struct lyd_node_any));
1973 break;
1974 default:
1975 LOGINT(LYD_NODE_CTX(node));
1976 ret = LY_EINT;
1977 goto error;
1978 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02001979 }
Michal Vasko52927e22020-03-16 17:26:14 +01001980 LY_CHECK_ERR_GOTO(!dup, LOGMEM(LYD_NODE_CTX(node)); ret = LY_EMEM, error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02001981
1982 /* TODO implement LYD_DUP_WITH_WHEN */
1983 dup->flags = node->flags;
1984 dup->schema = node->schema;
Michal Vasko52927e22020-03-16 17:26:14 +01001985 dup->prev = dup;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001986
1987 /* TODO duplicate attributes, implement LYD_DUP_NO_ATTR */
1988
1989 /* nodetype-specific work */
Michal Vasko52927e22020-03-16 17:26:14 +01001990 if (!dup->schema) {
1991 struct lyd_node_opaq *opaq = (struct lyd_node_opaq *)dup;
1992 struct lyd_node_opaq *orig = (struct lyd_node_opaq *)node;
1993 struct lyd_node *child;
Radek Krejci22ebdba2019-07-25 13:59:43 +02001994
1995 if (options & LYD_DUP_RECURSIVE) {
1996 /* duplicate all the children */
1997 LY_LIST_FOR(orig->child, child) {
Michal Vasko52927e22020-03-16 17:26:14 +01001998 LY_CHECK_GOTO(ret = lyd_dup_recursive(child, dup, NULL, options, NULL), error);
1999 }
2000 }
2001 opaq->name = lydict_insert(LYD_NODE_CTX(node), orig->name, 0);
2002 opaq->format = orig->format;
2003 if (orig->prefix.pref) {
2004 opaq->prefix.pref = lydict_insert(LYD_NODE_CTX(node), orig->prefix.pref, 0);
2005 }
2006 if (orig->prefix.ns) {
2007 opaq->prefix.ns = lydict_insert(LYD_NODE_CTX(node), orig->prefix.ns, 0);
2008 }
2009 if (orig->val_prefs) {
2010 LY_ARRAY_CREATE_GOTO(LYD_NODE_CTX(node), opaq->val_prefs, LY_ARRAY_SIZE(orig->val_prefs), ret, error);
2011 LY_ARRAY_FOR(orig->val_prefs, u) {
2012 opaq->val_prefs[u].pref = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].pref, 0);
2013 opaq->val_prefs[u].ns = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].ns, 0);
2014 LY_ARRAY_INCREMENT(opaq->val_prefs);
2015 }
2016 }
2017 opaq->value = lydict_insert(LYD_NODE_CTX(node), orig->value, 0);
2018 opaq->ctx = orig->ctx;
2019 } else if (dup->schema->nodetype & LYD_NODE_TERM) {
2020 struct lyd_node_term *term = (struct lyd_node_term *)dup;
2021 struct lyd_node_term *orig = (struct lyd_node_term *)node;
2022
2023 term->hash = orig->hash;
2024 term->value.realtype = orig->value.realtype;
2025 LY_CHECK_ERR_GOTO(term->value.realtype->plugin->duplicate(LYD_NODE_CTX(node), &orig->value, &term->value),
2026 LOGERR(LYD_NODE_CTX(node), LY_EINT, "Value duplication failed."); ret = LY_EINT, error);
2027 } else if (dup->schema->nodetype & LYD_NODE_INNER) {
2028 struct lyd_node_inner *orig = (struct lyd_node_inner *)node;
2029 struct lyd_node *child;
2030
2031 if (options & LYD_DUP_RECURSIVE) {
2032 /* duplicate all the children */
2033 LY_LIST_FOR(orig->child, child) {
2034 LY_CHECK_GOTO(ret = lyd_dup_recursive(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002035 }
Radek Krejci0fe9b512019-07-26 17:51:05 +02002036 } else if (dup->schema->nodetype == LYS_LIST && !(dup->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002037 /* always duplicate keys of a list */
Radek Krejci22ebdba2019-07-25 13:59:43 +02002038 child = orig->child;
Michal Vasko52927e22020-03-16 17:26:14 +01002039 for (struct lysc_node *key = ((struct lysc_node_list *)dup->schema)->child;
Radek Krejci0fe9b512019-07-26 17:51:05 +02002040 key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
2041 key = key->next) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002042 if (!child) {
2043 /* possibly not keys are present in filtered tree */
2044 break;
Radek Krejci0fe9b512019-07-26 17:51:05 +02002045 } else if (child->schema != key) {
2046 /* possibly not all keys are present in filtered tree,
2047 * but there can be also some non-key nodes */
2048 continue;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002049 }
Michal Vasko52927e22020-03-16 17:26:14 +01002050 LY_CHECK_GOTO(ret = lyd_dup_recursive(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002051 child = child->next;
2052 }
2053 }
2054 lyd_hash(dup);
2055 } else if (dup->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko52927e22020-03-16 17:26:14 +01002056 struct lyd_node_any *any = (struct lyd_node_any *)dup;
2057 struct lyd_node_any *orig = (struct lyd_node_any *)node;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002058
2059 any->hash = orig->hash;
2060 any->value_type = orig->value_type;
2061 switch (any->value_type) {
2062 case LYD_ANYDATA_DATATREE:
2063 if (orig->value.tree) {
2064 any->value.tree = lyd_dup(orig->value.tree, NULL, LYD_DUP_RECURSIVE | LYD_DUP_WITH_SIBLINGS);
Radek Krejci25dc3432020-05-15 14:42:12 +02002065 if (!any->value.tree) {
2066 /* get the last error's error code recorded by lyd_dup */
2067 struct ly_err_item *ei = ly_err_first(LYD_NODE_CTX(node));
2068 ret = ei ? ei->prev->no : LY_EOTHER;
2069 goto error;
2070 }
2071 LY_CHECK_ERR_GOTO(!any->value.tree, ret = 0 ,error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002072 }
2073 break;
2074 case LYD_ANYDATA_STRING:
2075 case LYD_ANYDATA_XML:
2076 case LYD_ANYDATA_JSON:
2077 if (orig->value.str) {
Michal Vasko52927e22020-03-16 17:26:14 +01002078 any->value.str = lydict_insert(LYD_NODE_CTX(node), orig->value.str, strlen(orig->value.str));
Radek Krejci22ebdba2019-07-25 13:59:43 +02002079 }
2080 break;
2081 }
2082 }
2083
Michal Vasko52927e22020-03-16 17:26:14 +01002084 /* insert */
2085 lyd_insert_node(parent, first, dup);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002086 lyd_insert_hash(dup);
Michal Vasko52927e22020-03-16 17:26:14 +01002087
2088 if (dup_p) {
2089 *dup_p = dup;
2090 }
2091 return LY_SUCCESS;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002092
2093error:
Michal Vasko52927e22020-03-16 17:26:14 +01002094 lyd_free_tree(dup);
2095 return ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002096}
2097
2098API struct lyd_node *
2099lyd_dup(const struct lyd_node *node, struct lyd_node_inner *parent, int options)
2100{
2101 struct ly_ctx *ctx;
2102 const struct lyd_node *orig; /* original node to be duplicated */
2103 struct lyd_node *first = NULL; /* the first duplicated node, this is returned */
Radek Krejci22ebdba2019-07-25 13:59:43 +02002104 struct lyd_node *top = NULL; /* the most higher created node */
2105 struct lyd_node_inner *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
2106 int keyless_parent_list = 0;
2107
2108 LY_CHECK_ARG_RET(NULL, node, NULL);
2109 ctx = node->schema->module->ctx;
2110
2111 if (options & LYD_DUP_WITH_PARENTS) {
2112 struct lyd_node_inner *orig_parent, *iter;
2113 int repeat = 1;
2114 for (top = NULL, orig_parent = node->parent; repeat && orig_parent; orig_parent = orig_parent->parent) {
2115 if (parent && parent->schema == orig_parent->schema) {
2116 /* stop creating parents, connect what we have into the provided parent */
2117 iter = parent;
2118 repeat = 0;
2119 /* get know if there is a keyless list which we will have to rehash */
2120 for (struct lyd_node_inner *piter = parent; piter; piter = piter->parent) {
Radek Krejci0fe9b512019-07-26 17:51:05 +02002121 if (piter->schema->nodetype == LYS_LIST && (piter->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002122 keyless_parent_list = 1;
2123 break;
2124 }
2125 }
2126 } else {
Michal Vasko52927e22020-03-16 17:26:14 +01002127 iter = NULL;
2128 LY_CHECK_GOTO(lyd_dup_recursive((struct lyd_node *)orig_parent, NULL, (struct lyd_node **)&iter, 0,
2129 (struct lyd_node **)&iter), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002130 }
2131 if (!local_parent) {
2132 local_parent = iter;
2133 }
2134 if (iter->child) {
2135 /* 1) list - add after keys
2136 * 2) provided parent with some children */
2137 iter->child->prev->next = top;
2138 if (top) {
2139 top->prev = iter->child->prev;
2140 iter->child->prev = top;
2141 }
2142 } else {
2143 iter->child = top;
2144 if (iter->schema->nodetype == LYS_LIST) {
2145 /* keyless list - we will need to rehash it since we are going to add nodes into it */
2146 keyless_parent_list = 1;
2147 }
2148 }
2149 if (top) {
2150 top->parent = iter;
2151 }
2152 top = (struct lyd_node*)iter;
2153 }
2154 if (repeat && parent) {
2155 /* given parent and created parents chain actually do not interconnect */
2156 LOGERR(ctx, LY_EINVAL, "Invalid argument parent (%s()) - does not interconnect with the created node's parents chain.", __func__);
2157 goto error;
2158 }
2159 } else {
2160 local_parent = parent;
2161 }
2162
Radek Krejci22ebdba2019-07-25 13:59:43 +02002163 LY_LIST_FOR(node, orig) {
Michal Vasko52927e22020-03-16 17:26:14 +01002164 /* if there is no local parent, it will be inserted into first */
2165 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 +02002166 if (!(options & LYD_DUP_WITH_SIBLINGS)) {
2167 break;
2168 }
2169 }
2170 if (keyless_parent_list) {
2171 /* rehash */
2172 for (; local_parent; local_parent = local_parent->parent) {
Radek Krejci0fe9b512019-07-26 17:51:05 +02002173 if (local_parent->schema->nodetype == LYS_LIST && (local_parent->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002174 lyd_hash((struct lyd_node*)local_parent);
2175 }
2176 }
2177 }
2178 return first;
2179
2180error:
2181 if (top) {
2182 lyd_free_tree(top);
2183 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +01002184 lyd_free_siblings(first);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002185 }
2186 return NULL;
2187}
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002188
2189static LY_ERR
2190lyd_path_str_enlarge(char **buffer, size_t *buflen, size_t reqlen, int is_static)
2191{
Michal Vasko14654712020-02-06 08:35:21 +01002192 /* ending \0 */
2193 ++reqlen;
2194
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002195 if (reqlen > *buflen) {
2196 if (is_static) {
2197 return LY_EINCOMPLETE;
2198 }
2199
2200 *buffer = ly_realloc(*buffer, reqlen * sizeof **buffer);
2201 if (!*buffer) {
2202 return LY_EMEM;
2203 }
2204
2205 *buflen = reqlen;
2206 }
2207
2208 return LY_SUCCESS;
2209}
2210
2211/**
2212 * @brief Append all list key predicates to path.
2213 *
2214 * @param[in] node Node with keys to print.
2215 * @param[in,out] buffer Buffer to print to.
2216 * @param[in,out] buflen Current buffer length.
2217 * @param[in,out] bufused Current number of characters used in @p buffer.
2218 * @param[in] is_static Whether buffer is static or can be reallocated.
2219 * @return LY_ERR
2220 */
2221static LY_ERR
2222lyd_path_list_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2223{
2224 const struct lyd_node *key;
2225 int dynamic = 0;
2226 size_t len;
2227 const char *val;
2228 char quot;
2229 LY_ERR rc;
2230
Michal Vasko14654712020-02-06 08:35:21 +01002231 for (key = lyd_node_children(node); key && (key->schema->flags & LYS_KEY); key = key->next) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002232 val = lyd_value2str((struct lyd_node_term *)key, &dynamic);
2233 len = 1 + strlen(key->schema->name) + 2 + strlen(val) + 2;
2234 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2235 if (rc != LY_SUCCESS) {
2236 if (dynamic) {
2237 free((char *)val);
2238 }
2239 return rc;
2240 }
2241
2242 quot = '\'';
2243 if (strchr(val, '\'')) {
2244 quot = '"';
2245 }
2246 *bufused += sprintf(*buffer + *bufused, "[%s=%c%s%c]", key->schema->name, quot, val, quot);
2247
2248 if (dynamic) {
2249 free((char *)val);
2250 }
2251 }
2252
2253 return LY_SUCCESS;
2254}
2255
2256/**
2257 * @brief Append leaf-list value predicate to path.
2258 *
2259 * @param[in] node Node to print.
2260 * @param[in,out] buffer Buffer to print to.
2261 * @param[in,out] buflen Current buffer length.
2262 * @param[in,out] bufused Current number of characters used in @p buffer.
2263 * @param[in] is_static Whether buffer is static or can be reallocated.
2264 * @return LY_ERR
2265 */
2266static LY_ERR
2267lyd_path_leaflist_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2268{
2269 int dynamic = 0;
2270 size_t len;
2271 const char *val;
2272 char quot;
2273 LY_ERR rc;
2274
2275 val = lyd_value2str((struct lyd_node_term *)node, &dynamic);
2276 len = 4 + strlen(val) + 2;
2277 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2278 if (rc != LY_SUCCESS) {
2279 goto cleanup;
2280 }
2281
2282 quot = '\'';
2283 if (strchr(val, '\'')) {
2284 quot = '"';
2285 }
2286 *bufused += sprintf(*buffer + *bufused, "[.=%c%s%c]", quot, val, quot);
2287
2288cleanup:
2289 if (dynamic) {
2290 free((char *)val);
2291 }
2292 return rc;
2293}
2294
2295/**
2296 * @brief Append node position (relative to its other instances) predicate to path.
2297 *
2298 * @param[in] node Node to print.
2299 * @param[in,out] buffer Buffer to print to.
2300 * @param[in,out] buflen Current buffer length.
2301 * @param[in,out] bufused Current number of characters used in @p buffer.
2302 * @param[in] is_static Whether buffer is static or can be reallocated.
2303 * @return LY_ERR
2304 */
2305static LY_ERR
2306lyd_path_position_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2307{
2308 const struct lyd_node *first, *iter;
2309 size_t len;
2310 int pos;
2311 char *val = NULL;
2312 LY_ERR rc;
2313
2314 if (node->parent) {
2315 first = node->parent->child;
2316 } else {
2317 for (first = node; node->prev->next; node = node->prev);
2318 }
2319 pos = 1;
2320 for (iter = first; iter != node; iter = iter->next) {
2321 if (iter->schema == node->schema) {
2322 ++pos;
2323 }
2324 }
2325 if (asprintf(&val, "%d", pos) == -1) {
2326 return LY_EMEM;
2327 }
2328
2329 len = 1 + strlen(val) + 1;
2330 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2331 if (rc != LY_SUCCESS) {
2332 goto cleanup;
2333 }
2334
2335 *bufused += sprintf(*buffer + *bufused, "[%s]", val);
2336
2337cleanup:
2338 free(val);
2339 return rc;
2340}
2341
2342API char *
2343lyd_path(const struct lyd_node *node, LYD_PATH_TYPE pathtype, char *buffer, size_t buflen)
2344{
Michal Vasko14654712020-02-06 08:35:21 +01002345 int is_static = 0, i, depth;
2346 size_t bufused = 0, len;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002347 const struct lyd_node *iter;
2348 const struct lys_module *mod;
2349 LY_ERR rc;
2350
2351 LY_CHECK_ARG_RET(NULL, node, NULL);
2352 if (buffer) {
2353 LY_CHECK_ARG_RET(node->schema->module->ctx, buflen > 1, NULL);
2354 is_static = 1;
Michal Vasko14654712020-02-06 08:35:21 +01002355 } else {
2356 buflen = 0;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002357 }
2358
2359 switch (pathtype) {
Michal Vasko14654712020-02-06 08:35:21 +01002360 case LYD_PATH_LOG:
2361 depth = 1;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002362 for (iter = node; iter->parent; iter = (const struct lyd_node *)iter->parent) {
2363 ++depth;
2364 }
2365
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002366 goto iter_print;
Michal Vasko14654712020-02-06 08:35:21 +01002367 while (depth) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002368 /* find the right node */
Michal Vasko14654712020-02-06 08:35:21 +01002369 for (iter = node, i = 1; i < depth; iter = (const struct lyd_node *)iter->parent, ++i);
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002370iter_print:
2371 /* print prefix and name */
2372 mod = NULL;
2373 if (!iter->parent || (iter->schema->module != iter->parent->schema->module)) {
2374 mod = iter->schema->module;
2375 }
2376
2377 /* realloc string */
2378 len = 1 + (mod ? strlen(mod->name) + 1 : 0) + strlen(iter->schema->name);
2379 rc = lyd_path_str_enlarge(&buffer, &buflen, bufused + len, is_static);
2380 if (rc != LY_SUCCESS) {
2381 break;
2382 }
2383
2384 /* print next node */
2385 bufused += sprintf(buffer + bufused, "/%s%s%s", mod ? mod->name : "", mod ? ":" : "", iter->schema->name);
2386
2387 switch (iter->schema->nodetype) {
2388 case LYS_LIST:
2389 if (iter->schema->flags & LYS_KEYLESS) {
2390 /* print its position */
2391 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2392 } else {
2393 /* print all list keys in predicates */
2394 rc = lyd_path_list_predicate(iter, &buffer, &buflen, &bufused, is_static);
2395 }
2396 break;
2397 case LYS_LEAFLIST:
2398 if (iter->schema->flags & LYS_CONFIG_W) {
2399 /* print leaf-list value */
2400 rc = lyd_path_leaflist_predicate(iter, &buffer, &buflen, &bufused, is_static);
2401 } else {
2402 /* print its position */
2403 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2404 }
2405 break;
2406 default:
2407 /* nothing to print more */
2408 rc = LY_SUCCESS;
2409 break;
2410 }
2411 if (rc != LY_SUCCESS) {
2412 break;
2413 }
2414
Michal Vasko14654712020-02-06 08:35:21 +01002415 --depth;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002416 }
2417 break;
2418 }
2419
2420 return buffer;
2421}
Michal Vaskoe444f752020-02-10 12:20:06 +01002422
Michal Vasko9b368d32020-02-14 13:53:31 +01002423LY_ERR
2424lyd_find_sibling_next2(const struct lyd_node *first, const struct lysc_node *schema, const char *key_or_value,
2425 size_t val_len, struct lyd_node **match)
Michal Vaskoe444f752020-02-10 12:20:06 +01002426{
2427 LY_ERR rc;
2428 const struct lyd_node *node = NULL;
2429 struct lyd_node_term *term;
Michal Vasko00cbf532020-06-15 13:58:47 +02002430 struct lyxp_expr *expr = NULL;
2431 uint16_t exp_idx = 0;
2432 struct ly_path_predicate *predicates = NULL;
2433 enum ly_path_pred_type pred_type = 0;
Michal Vasko90932a92020-02-12 14:33:03 +01002434 struct lyd_value val = {0};
Michal Vasko00cbf532020-06-15 13:58:47 +02002435 LY_ARRAY_SIZE_TYPE u;
Michal Vaskoe444f752020-02-10 12:20:06 +01002436
Michal Vasko9b368d32020-02-14 13:53:31 +01002437 LY_CHECK_ARG_RET(NULL, schema, LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01002438
2439 if (!first) {
2440 /* no data */
Michal Vasko9b368d32020-02-14 13:53:31 +01002441 if (match) {
2442 *match = NULL;
2443 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002444 return LY_ENOTFOUND;
2445 }
2446
Michal Vaskoe444f752020-02-10 12:20:06 +01002447 if (key_or_value && !val_len) {
2448 val_len = strlen(key_or_value);
2449 }
2450
2451 if (key_or_value && (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
Michal Vasko90932a92020-02-12 14:33:03 +01002452 /* store the value */
Michal Vasko9b368d32020-02-14 13:53:31 +01002453 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 +01002454 } else if (key_or_value && (schema->nodetype == LYS_LIST)) {
Michal Vasko00cbf532020-06-15 13:58:47 +02002455 /* parse keys */
2456 LY_CHECK_GOTO(rc = ly_path_parse_predicate(schema->module->ctx, key_or_value, val_len, LY_PATH_PREFIX_OPTIONAL,
2457 LY_PATH_PRED_KEYS, &expr), cleanup);
2458
2459 /* compile them */
2460 LY_CHECK_GOTO(rc = ly_path_compile_predicate(schema->module->ctx, NULL, schema, expr, &exp_idx, lydjson_resolve_prefix,
2461 NULL, LYD_JSON, &predicates, &pred_type), cleanup);
Michal Vaskoe444f752020-02-10 12:20:06 +01002462 }
2463
2464 /* find first matching value */
2465 LY_LIST_FOR(first, node) {
2466 if (node->schema != schema) {
2467 continue;
2468 }
2469
Michal Vasko00cbf532020-06-15 13:58:47 +02002470 if ((schema->nodetype == LYS_LIST) && predicates) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002471 /* compare all set keys */
Michal Vasko00cbf532020-06-15 13:58:47 +02002472 LY_ARRAY_FOR(predicates, u) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002473 /* find key */
Michal Vasko00cbf532020-06-15 13:58:47 +02002474 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 +01002475 if (rc == LY_ENOTFOUND) {
2476 /* all keys must always exist */
Michal Vasko9b368d32020-02-14 13:53:31 +01002477 LOGINT_RET(schema->module->ctx);
Michal Vaskoe444f752020-02-10 12:20:06 +01002478 }
2479 LY_CHECK_GOTO(rc, cleanup);
2480
2481 /* compare values */
Michal Vasko00cbf532020-06-15 13:58:47 +02002482 if (!term->value.realtype->plugin->compare(&term->value, &predicates[u].value)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002483 break;
2484 }
2485 }
2486
Michal Vasko00cbf532020-06-15 13:58:47 +02002487 if (u < LY_ARRAY_SIZE(predicates)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002488 /* not a match */
2489 continue;
2490 }
Michal Vasko90932a92020-02-12 14:33:03 +01002491 } else if ((schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && val.realtype) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002492 term = (struct lyd_node_term *)node;
2493
2494 /* compare values */
Michal Vasko90932a92020-02-12 14:33:03 +01002495 if (!term->value.realtype->plugin->compare(&term->value, &val)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002496 /* not a match */
2497 continue;
2498 }
2499 }
2500
2501 /* all criteria passed */
2502 break;
2503 }
2504
2505 if (!node) {
2506 rc = LY_ENOTFOUND;
Michal Vasko9b368d32020-02-14 13:53:31 +01002507 if (match) {
2508 *match = NULL;
2509 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002510 goto cleanup;
2511 }
2512
2513 /* success */
Michal Vasko9b368d32020-02-14 13:53:31 +01002514 if (match) {
2515 *match = (struct lyd_node *)node;
2516 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002517 rc = LY_SUCCESS;
2518
2519cleanup:
Michal Vasko00cbf532020-06-15 13:58:47 +02002520 ly_path_predicates_free(schema->module->ctx, pred_type, NULL, predicates);
2521 lyxp_expr_free(schema->module->ctx, expr);
Michal Vasko90932a92020-02-12 14:33:03 +01002522 if (val.realtype) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002523 val.realtype->plugin->free(schema->module->ctx, &val);
Michal Vasko90932a92020-02-12 14:33:03 +01002524 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002525 return rc;
2526}
2527
2528API LY_ERR
Michal Vasko9b368d32020-02-14 13:53:31 +01002529lyd_find_sibling_next(const struct lyd_node *first, const struct lys_module *module, const char *name, size_t name_len,
2530 const char *key_or_value, size_t val_len, struct lyd_node **match)
2531{
2532 const struct lysc_node *schema;
2533
2534 LY_CHECK_ARG_RET(NULL, module, name, match, LY_EINVAL);
2535
2536 if (!first) {
2537 /* no data */
2538 *match = NULL;
2539 return LY_ENOTFOUND;
2540 }
2541
2542 /* find schema */
2543 schema = lys_find_child(first->parent ? first->parent->schema : NULL, module, name, name_len, 0, 0);
2544 if (!schema) {
2545 LOGERR(module->ctx, LY_EINVAL, "Schema node not found.");
2546 return LY_EINVAL;
2547 }
2548
2549 return lyd_find_sibling_next2(first, schema, key_or_value, val_len, match);
2550}
2551
2552API LY_ERR
Michal Vaskoe444f752020-02-10 12:20:06 +01002553lyd_find_sibling_first(const struct lyd_node *siblings, const struct lyd_node *target, struct lyd_node **match)
2554{
2555 struct lyd_node **match_p;
2556 struct lyd_node_inner *parent;
2557
Michal Vaskof03ed032020-03-04 13:31:44 +01002558 LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01002559
Michal Vasko62ed12d2020-05-21 10:08:25 +02002560 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(target->schema))) {
2561 /* no data or schema mismatch */
Michal Vasko9b368d32020-02-14 13:53:31 +01002562 if (match) {
2563 *match = NULL;
2564 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002565 return LY_ENOTFOUND;
2566 }
2567
2568 /* find first sibling */
2569 if (siblings->parent) {
2570 siblings = siblings->parent->child;
2571 } else {
2572 while (siblings->prev->next) {
2573 siblings = siblings->prev;
2574 }
2575 }
2576
2577 parent = (struct lyd_node_inner *)siblings->parent;
2578 if (parent && parent->children_ht) {
2579 assert(target->hash);
2580
2581 /* find by hash */
2582 if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
2583 siblings = *match_p;
2584 } else {
2585 /* not found */
2586 siblings = NULL;
2587 }
2588 } else {
2589 /* no children hash table */
2590 for (; siblings; siblings = siblings->next) {
2591 if (!lyd_compare(siblings, target, 0)) {
2592 break;
2593 }
2594 }
2595 }
2596
2597 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002598 if (match) {
2599 *match = NULL;
2600 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002601 return LY_ENOTFOUND;
2602 }
2603
Michal Vasko9b368d32020-02-14 13:53:31 +01002604 if (match) {
2605 *match = (struct lyd_node *)siblings;
2606 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002607 return LY_SUCCESS;
2608}
2609
2610API LY_ERR
2611lyd_find_sibling_set(const struct lyd_node *siblings, const struct lyd_node *target, struct ly_set **set)
2612{
2613 struct lyd_node_inner *parent;
2614 struct lyd_node *match;
2615 struct lyd_node **match_p;
2616 struct ly_set *ret;
2617
2618 LY_CHECK_ARG_RET(NULL, target, set, LY_EINVAL);
2619
Michal Vasko62ed12d2020-05-21 10:08:25 +02002620 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(target->schema))) {
2621 /* no data or schema mismatch */
Michal Vaskoe444f752020-02-10 12:20:06 +01002622 return LY_ENOTFOUND;
2623 }
2624
2625 ret = ly_set_new();
2626 LY_CHECK_ERR_RET(!ret, LOGMEM(target->schema->module->ctx), LY_EMEM);
2627
2628 /* find first sibling */
2629 if (siblings->parent) {
2630 siblings = siblings->parent->child;
2631 } else {
2632 while (siblings->prev->next) {
2633 siblings = siblings->prev;
2634 }
2635 }
2636
2637 parent = (struct lyd_node_inner *)siblings->parent;
2638 if (parent && parent->children_ht) {
2639 assert(target->hash);
2640
2641 /* find by hash */
2642 if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
2643 match = *match_p;
2644 } else {
2645 /* not found */
2646 match = NULL;
2647 }
2648 while (match) {
2649 /* add all found nodes into the return set */
2650 if (ly_set_add(ret, match, LY_SET_OPT_USEASLIST) == -1) {
2651 goto error;
2652 }
2653
2654 /* find next instance */
2655 if (lyht_find_next(parent->children_ht, &match, match->hash, (void **)&match_p)) {
2656 match = NULL;
2657 } else {
2658 match = *match_p;
2659 }
2660 }
2661 } else {
2662 /* no children hash table */
2663 for (; siblings; siblings = siblings->next) {
2664 if (!lyd_compare(siblings, target, 0)) {
2665 /* a match */
2666 if (ly_set_add(ret, (struct lyd_node *)siblings, LY_SET_OPT_USEASLIST) == -1) {
2667 goto error;
2668 }
2669 }
2670 }
2671 }
2672
2673 if (!ret->count) {
2674 ly_set_free(ret, NULL);
2675 return LY_ENOTFOUND;
2676 }
2677
2678 *set = ret;
2679 return LY_SUCCESS;
2680
2681error:
2682 ly_set_free(ret, NULL);
2683 return LY_EMEM;
2684}
2685
Michal Vasko90932a92020-02-12 14:33:03 +01002686static int
2687lyd_hash_table_schema_val_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *UNUSED(cb_data))
2688{
2689 struct lysc_node *val1;
2690 struct lyd_node *val2;
2691
2692 val1 = *((struct lysc_node **)val1_p);
2693 val2 = *((struct lyd_node **)val2_p);
2694
2695 assert(val1->nodetype & (LYD_NODE_INNER | LYS_LEAF));
2696
2697 if (val1 == val2->schema) {
2698 /* schema match is enough */
2699 return 1;
2700 } else {
2701 return 0;
2702 }
2703}
2704
2705static LY_ERR
2706lyd_find_sibling_schema(const struct lyd_node *siblings, const struct lysc_node *schema, struct lyd_node **match)
2707{
2708 struct lyd_node **match_p;
2709 struct lyd_node_inner *parent;
2710 uint32_t hash;
2711 values_equal_cb ht_cb;
2712
2713 assert(siblings && schema && (schema->nodetype & (LYD_NODE_INNER | LYS_LEAF)));
2714
2715 /* find first sibling */
2716 if (siblings->parent) {
2717 siblings = siblings->parent->child;
2718 } else {
2719 while (siblings->prev->next) {
2720 siblings = siblings->prev;
2721 }
2722 }
2723
2724 parent = (struct lyd_node_inner *)siblings->parent;
2725 if (parent && parent->children_ht) {
2726 /* calculate our hash */
2727 hash = dict_hash_multi(0, schema->module->name, strlen(schema->module->name));
2728 hash = dict_hash_multi(hash, schema->name, strlen(schema->name));
2729 hash = dict_hash_multi(hash, NULL, 0);
2730
2731 /* use special hash table function */
2732 ht_cb = lyht_set_cb(parent->children_ht, lyd_hash_table_schema_val_equal);
2733
2734 /* find by hash */
2735 if (!lyht_find(parent->children_ht, &schema, hash, (void **)&match_p)) {
2736 siblings = *match_p;
2737 } else {
2738 /* not found */
2739 siblings = NULL;
2740 }
2741
2742 /* set the original hash table compare function back */
2743 lyht_set_cb(parent->children_ht, ht_cb);
2744 } else {
2745 /* no children hash table */
2746 for (; siblings; siblings = siblings->next) {
2747 if (siblings->schema == schema) {
2748 /* schema match is enough */
2749 break;
2750 }
2751 }
2752 }
2753
2754 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01002755 if (match) {
2756 *match = NULL;
2757 }
Michal Vasko90932a92020-02-12 14:33:03 +01002758 return LY_ENOTFOUND;
2759 }
2760
Michal Vasko9b368d32020-02-14 13:53:31 +01002761 if (match) {
2762 *match = (struct lyd_node *)siblings;
2763 }
Michal Vasko90932a92020-02-12 14:33:03 +01002764 return LY_SUCCESS;
2765}
2766
Michal Vaskoe444f752020-02-10 12:20:06 +01002767API LY_ERR
2768lyd_find_sibling_val(const struct lyd_node *siblings, const struct lysc_node *schema, const char *key_or_value,
2769 size_t val_len, struct lyd_node **match)
2770{
2771 LY_ERR rc;
2772 struct lyd_node *target = NULL;
2773
2774 LY_CHECK_ARG_RET(NULL, schema, LY_EINVAL);
Michal Vasko62ed12d2020-05-21 10:08:25 +02002775 if ((schema->nodetype == LYS_LIST) && (schema->flags & LYS_KEYLESS)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01002776 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - key-less list (%s()).", __func__);
2777 return LY_EINVAL;
2778 } else if ((schema->nodetype & (LYS_LEAFLIST | LYS_LIST)) && !key_or_value) {
2779 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - no value/keys for a (leaf-)list (%s()).", __func__);
2780 return LY_EINVAL;
2781 } else if (schema->nodetype & (LYS_CHOICE | LYS_CASE)) {
2782 LOGERR(schema->module->ctx, LY_EINVAL, "Invalid arguments - schema type %s (%s()).",
2783 lys_nodetype2str(schema->nodetype), __func__);
2784 return LY_EINVAL;
2785 }
2786
Michal Vasko62ed12d2020-05-21 10:08:25 +02002787 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(schema))) {
2788 /* no data or schema mismatch */
Michal Vasko9b368d32020-02-14 13:53:31 +01002789 if (match) {
2790 *match = NULL;
2791 }
Michal Vaskoe444f752020-02-10 12:20:06 +01002792 return LY_ENOTFOUND;
2793 }
2794
Michal Vaskof03ed032020-03-04 13:31:44 +01002795 if (key_or_value && !val_len) {
2796 val_len = strlen(key_or_value);
2797 }
2798
Michal Vasko90932a92020-02-12 14:33:03 +01002799 /* create data node if needed and find it */
Michal Vaskoe444f752020-02-10 12:20:06 +01002800 switch (schema->nodetype) {
2801 case LYS_CONTAINER:
2802 case LYS_ANYXML:
2803 case LYS_ANYDATA:
2804 case LYS_NOTIF:
Michal Vasko1bf09392020-03-27 12:38:10 +01002805 case LYS_RPC:
Michal Vasko9b368d32020-02-14 13:53:31 +01002806 case LYS_ACTION:
Michal Vaskoe444f752020-02-10 12:20:06 +01002807 case LYS_LEAF:
Michal Vasko004d3152020-06-11 19:59:22 +02002808 /* find it based on schema only, there cannot be more instances */
Michal Vasko90932a92020-02-12 14:33:03 +01002809 rc = lyd_find_sibling_schema(siblings, schema, match);
Michal Vaskoe444f752020-02-10 12:20:06 +01002810 break;
2811 case LYS_LEAFLIST:
2812 /* target used attributes: schema, hash, value */
Michal Vaskocbff3e92020-05-27 12:56:41 +02002813 rc = lyd_create_term(schema, key_or_value, val_len, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &target);
2814 LY_CHECK_RET(rc && (rc != LY_EINCOMPLETE), rc);
2815 rc = LY_SUCCESS;
Michal Vasko90932a92020-02-12 14:33:03 +01002816 /* fallthrough */
Michal Vaskoe444f752020-02-10 12:20:06 +01002817 case LYS_LIST:
Michal Vasko90932a92020-02-12 14:33:03 +01002818 if (schema->nodetype == LYS_LIST) {
2819 /* target used attributes: schema, hash, child (all keys) */
Michal Vasko004d3152020-06-11 19:59:22 +02002820 LY_CHECK_RET(lyd_create_list2(schema, key_or_value, val_len, &target));
Michal Vasko90932a92020-02-12 14:33:03 +01002821 }
2822
2823 /* find it */
2824 rc = lyd_find_sibling_first(siblings, target, match);
Michal Vaskoe444f752020-02-10 12:20:06 +01002825 break;
2826 default:
2827 /* unreachable */
2828 LOGINT(schema->module->ctx);
2829 return LY_EINT;
2830 }
2831
Michal Vaskoe444f752020-02-10 12:20:06 +01002832 lyd_free_tree(target);
2833 return rc;
2834}
Michal Vaskoccc02342020-05-21 10:09:21 +02002835
2836API LY_ERR
2837lyd_find_xpath(const struct lyd_node *ctx_node, const char *xpath, struct ly_set **set)
2838{
2839 LY_ERR ret = LY_SUCCESS;
2840 struct lyxp_set xp_set;
2841 struct lyxp_expr *exp;
2842 uint32_t i;
2843
2844 LY_CHECK_ARG_RET(NULL, ctx_node, xpath, set, LY_EINVAL);
2845
2846 memset(&xp_set, 0, sizeof xp_set);
2847
2848 /* compile expression */
Michal Vasko004d3152020-06-11 19:59:22 +02002849 exp = lyxp_expr_parse((struct ly_ctx *)LYD_NODE_CTX(ctx_node), xpath, 0, 1);
Michal Vaskoccc02342020-05-21 10:09:21 +02002850 LY_CHECK_ERR_GOTO(!exp, ret = LY_EINVAL, cleanup);
2851
2852 /* evaluate expression */
2853 ret = lyxp_eval(exp, LYD_JSON, ctx_node->schema->module, ctx_node, LYXP_NODE_ELEM, ctx_node, &xp_set, 0);
2854 LY_CHECK_GOTO(ret, cleanup);
2855
2856 /* allocate return set */
2857 *set = ly_set_new();
2858 LY_CHECK_ERR_GOTO(!*set, LOGMEM(LYD_NODE_CTX(ctx_node)); ret = LY_EMEM, cleanup);
2859
2860 /* transform into ly_set */
2861 if (xp_set.type == LYXP_SET_NODE_SET) {
2862 /* allocate memory for all the elements once (even though not all items must be elements but most likely will be) */
2863 (*set)->objs = malloc(xp_set.used * sizeof *(*set)->objs);
2864 LY_CHECK_ERR_GOTO(!(*set)->objs, LOGMEM(LYD_NODE_CTX(ctx_node)); ret = LY_EMEM, cleanup);
2865 (*set)->size = xp_set.used;
2866
2867 for (i = 0; i < xp_set.used; ++i) {
2868 if (xp_set.val.nodes[i].type == LYXP_NODE_ELEM) {
2869 ly_set_add(*set, xp_set.val.nodes[i].node, LY_SET_OPT_USEASLIST);
2870 }
2871 }
2872 }
2873
2874cleanup:
Michal Vasko0691d522020-05-21 13:21:47 +02002875 lyxp_set_free_content(&xp_set);
Michal Vaskoccc02342020-05-21 10:09:21 +02002876 lyxp_expr_free((struct ly_ctx *)LYD_NODE_CTX(ctx_node), exp);
2877 return ret;
2878}