blob: 5ca3f4addcc8b125a95e965a839c5a4a6160a6ff [file] [log] [blame]
Radek Krejcie7b95092019-05-15 11:03:07 +02001/**
Michal Vaskob1b5c262020-03-05 14:29:47 +01002 * @file tree_data.c
Radek Krejcie7b95092019-05-15 11:03:07 +02003 * @author Radek Krejci <rkrejci@cesnet.cz>
Michal Vasko6cd9b6b2020-06-22 10:05:22 +02004 * @brief Data tree functions
Radek Krejcie7b95092019-05-15 11:03:07 +02005 *
Michal Vasko6cd9b6b2020-06-22 10:05:22 +02006 * Copyright (c) 2015 - 2020 CESNET, z.s.p.o.
Radek Krejcie7b95092019-05-15 11:03:07 +02007 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
Radek Krejci535ea9f2020-05-29 16:01:05 +020015#define _GNU_SOURCE
16
17#include "tree_data.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020018
Radek Krejci084289f2019-07-09 17:35:30 +020019#include <assert.h>
Radek Krejcie7b95092019-05-15 11:03:07 +020020#include <ctype.h>
21#include <errno.h>
22#include <fcntl.h>
23#include <stdarg.h>
24#include <stdint.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020025#include <stdio.h>
26#include <stdlib.h>
Radek Krejcie7b95092019-05-15 11:03:07 +020027#include <string.h>
28#include <unistd.h>
29
Radek Krejci535ea9f2020-05-29 16:01:05 +020030#include "common.h"
Michal Vasko5aa44c02020-06-29 11:47:02 +020031#include "compat.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020032#include "config.h"
33#include "context.h"
34#include "dict.h"
Michal Vaskoa6669ba2020-08-06 16:14:26 +020035#include "diff.h"
Michal Vasko90932a92020-02-12 14:33:03 +010036#include "hash_table.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020037#include "log.h"
Radek Krejci7931b192020-06-25 17:05:03 +020038#include "parser_data.h"
39#include "parser_internal.h"
Michal Vasko004d3152020-06-11 19:59:22 +020040#include "path.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020041#include "plugins_exts.h"
Radek Krejci38d85362019-09-05 16:26:38 +020042#include "plugins_exts_metadata.h"
Michal Vasko90932a92020-02-12 14:33:03 +010043#include "plugins_exts_internal.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020044#include "plugins_types.h"
45#include "set.h"
46#include "tree.h"
47#include "tree_data_internal.h"
48#include "tree_schema.h"
49#include "tree_schema_internal.h"
Michal Vaskoa6669ba2020-08-06 16:14:26 +020050#include "validation.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020051#include "xml.h"
52#include "xpath.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020053
Michal Vaskob104f112020-07-17 09:54:54 +020054static LY_ERR lyd_find_sibling_schema(const struct lyd_node *siblings, const struct lysc_node *schema,
55 struct lyd_node **match);
56
Radek Krejci084289f2019-07-09 17:35:30 +020057LY_ERR
Michal Vasko90932a92020-02-12 14:33:03 +010058lyd_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 +010059 ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +020060{
Michal Vasko90932a92020-02-12 14:33:03 +010061 LY_ERR ret = LY_SUCCESS;
Radek Krejci084289f2019-07-09 17:35:30 +020062 struct ly_err_item *err = NULL;
63 struct ly_ctx *ctx;
64 struct lysc_type *type;
Radek Krejci3c9758d2019-07-11 16:49:10 +020065 int options = LY_TYPE_OPTS_STORE | (second ? LY_TYPE_OPTS_SECOND_CALL : 0) |
Michal Vaskof03ed032020-03-04 13:31:44 +010066 (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci084289f2019-07-09 17:35:30 +020067 assert(node);
68
69 ctx = node->schema->module->ctx;
Radek Krejci084289f2019-07-09 17:35:30 +020070
Radek Krejci73dead22019-07-11 16:46:16 +020071 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci62903c32019-07-15 14:42:05 +020072 if (!second) {
73 node->value.realtype = type;
74 }
Michal Vasko90932a92020-02-12 14:33:03 +010075 ret = type->plugin->store(ctx, type, value, value_len, options, get_prefix, parser, format,
Michal Vasko004d3152020-06-11 19:59:22 +020076 tree ? (void *)node : (void *)node->schema, tree, &node->value, NULL, &err);
Michal Vasko90932a92020-02-12 14:33:03 +010077 if (ret && (ret != LY_EINCOMPLETE)) {
Radek Krejci73dead22019-07-11 16:46:16 +020078 if (err) {
Michal Vasko3544d1e2020-05-27 11:17:51 +020079 /* node may not be connected yet so use the schema node */
Michal Vaskof872e202020-05-27 11:49:06 +020080 if (!node->parent && lysc_data_parent(node->schema)) {
81 LOGVAL(ctx, LY_VLOG_LYSC, node->schema, err->vecode, err->msg);
82 } else {
83 LOGVAL(ctx, LY_VLOG_LYD, node, err->vecode, err->msg);
84 }
Radek Krejci73dead22019-07-11 16:46:16 +020085 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +020086 }
Radek Krejci73dead22019-07-11 16:46:16 +020087 goto error;
Michal Vasko90932a92020-02-12 14:33:03 +010088 } else if (dynamic) {
89 *dynamic = 0;
Radek Krejci084289f2019-07-09 17:35:30 +020090 }
91
92error:
93 return ret;
94}
95
Michal Vasko00cbf532020-06-15 13:58:47 +020096/* 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 +020097LY_ERR
Michal Vasko90932a92020-02-12 14:33:03 +010098lyd_value_store(struct lyd_value *val, const struct lysc_node *schema, const char *value, size_t value_len, int *dynamic,
99 ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format)
100{
101 LY_ERR ret = LY_SUCCESS;
102 struct ly_err_item *err = NULL;
103 struct ly_ctx *ctx;
104 struct lysc_type *type;
105 int options = LY_TYPE_OPTS_STORE | LY_TYPE_OPTS_INCOMPLETE_DATA | (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0);
106
107 assert(val && schema && (schema->nodetype & LYD_NODE_TERM));
108
109 ctx = schema->module->ctx;
110 type = ((struct lysc_node_leaf *)schema)->type;
111 val->realtype = type;
112 ret = type->plugin->store(ctx, type, value, value_len, options, get_prefix, parser, format, (void *)schema, NULL,
113 val, NULL, &err);
114 if (ret == LY_EINCOMPLETE) {
115 /* this is fine, we do not need it resolved */
116 ret = LY_SUCCESS;
117 } else if (ret && err) {
118 ly_err_print(err);
119 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
120 ly_err_free(err);
121 }
122 if (!ret && dynamic) {
123 *dynamic = 0;
124 }
125
126 return ret;
127}
128
Radek Krejci38d85362019-09-05 16:26:38 +0200129LY_ERR
Michal Vasko41586352020-07-13 13:54:25 +0200130lyd_value_parse_meta(const struct ly_ctx *ctx, struct lyd_meta *meta, const char *value, size_t value_len, int *dynamic,
Michal Vasko8d544252020-03-02 10:19:52 +0100131 int second, ly_clb_resolve_prefix get_prefix, void *parser, LYD_FORMAT format,
Michal Vaskof03ed032020-03-04 13:31:44 +0100132 const struct lysc_node *ctx_snode, const struct lyd_node *tree)
Radek Krejci38d85362019-09-05 16:26:38 +0200133{
Michal Vasko90932a92020-02-12 14:33:03 +0100134 LY_ERR ret = LY_SUCCESS;
Radek Krejci38d85362019-09-05 16:26:38 +0200135 struct ly_err_item *err = NULL;
Radek Krejci38d85362019-09-05 16:26:38 +0200136 struct lyext_metadata *ant;
137 int options = LY_TYPE_OPTS_STORE | (second ? LY_TYPE_OPTS_SECOND_CALL : 0) |
Michal Vaskof03ed032020-03-04 13:31:44 +0100138 (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci38d85362019-09-05 16:26:38 +0200139
Michal Vasko9f96a052020-03-10 09:41:45 +0100140 assert(ctx && meta && ((tree && meta->parent) || ctx_snode));
Michal Vasko8d544252020-03-02 10:19:52 +0100141
Michal Vasko9f96a052020-03-10 09:41:45 +0100142 ant = meta->annotation->data;
Radek Krejci38d85362019-09-05 16:26:38 +0200143
144 if (!second) {
Michal Vasko9f96a052020-03-10 09:41:45 +0100145 meta->value.realtype = ant->type;
Radek Krejci38d85362019-09-05 16:26:38 +0200146 }
Michal Vasko90932a92020-02-12 14:33:03 +0100147 ret = ant->type->plugin->store(ctx, ant->type, value, value_len, options, get_prefix, parser, format,
Michal Vasko9f96a052020-03-10 09:41:45 +0100148 tree ? (void *)meta->parent : (void *)ctx_snode, tree, &meta->value, NULL, &err);
Michal Vasko90932a92020-02-12 14:33:03 +0100149 if (ret && (ret != LY_EINCOMPLETE)) {
Radek Krejci38d85362019-09-05 16:26:38 +0200150 if (err) {
151 ly_err_print(err);
152 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
153 ly_err_free(err);
154 }
155 goto error;
Michal Vasko90932a92020-02-12 14:33:03 +0100156 } else if (dynamic) {
157 *dynamic = 0;
Radek Krejci38d85362019-09-05 16:26:38 +0200158 }
159
160error:
161 return ret;
162}
163
Michal Vaskof937cfe2020-08-03 16:07:12 +0200164LY_ERR
165_lys_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const char *value, size_t value_len,
166 ly_clb_resolve_prefix resolve_prefix, void *prefix_data, LYD_FORMAT format)
Radek Krejci084289f2019-07-09 17:35:30 +0200167{
168 LY_ERR rc = LY_SUCCESS;
169 struct ly_err_item *err = NULL;
170 struct lysc_type *type;
Radek Krejci084289f2019-07-09 17:35:30 +0200171
172 LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
173
174 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
175 LOGARG(ctx, node);
176 return LY_EINVAL;
177 }
178
179 type = ((struct lysc_node_leaf*)node)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200180 /* just validate, no storing of enything */
181 rc = type->plugin->store(ctx ? ctx : node->module->ctx, type, value, value_len, LY_TYPE_OPTS_INCOMPLETE_DATA,
Michal Vaskof937cfe2020-08-03 16:07:12 +0200182 resolve_prefix, prefix_data, format, node, NULL, NULL, NULL, &err);
Radek Krejci73dead22019-07-11 16:46:16 +0200183 if (rc == LY_EINCOMPLETE) {
184 /* actually success since we do not provide the context tree and call validation with
185 * LY_TYPE_OPTS_INCOMPLETE_DATA */
186 rc = LY_SUCCESS;
187 } else if (rc && err) {
188 if (ctx) {
189 /* log only in case the ctx was provided as input parameter */
190 ly_err_print(err);
191 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
Radek Krejci084289f2019-07-09 17:35:30 +0200192 }
Radek Krejci73dead22019-07-11 16:46:16 +0200193 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200194 }
195
196 return rc;
197}
198
199API LY_ERR
Michal Vaskof937cfe2020-08-03 16:07:12 +0200200lys_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const char *value, size_t value_len)
201{
202 return _lys_value_validate(ctx, node, value, value_len, lydjson_resolve_prefix, NULL, LYD_JSON);
203}
204
205API LY_ERR
Michal Vasko44685da2020-03-17 15:38:06 +0100206lyd_value_validate(const struct ly_ctx *ctx, const struct lyd_node_term *node, const char *value, size_t value_len,
Michal Vasko3701af52020-08-03 14:29:38 +0200207 const struct lyd_node *tree, struct lysc_type **realtype)
Radek Krejci084289f2019-07-09 17:35:30 +0200208{
209 LY_ERR rc;
210 struct ly_err_item *err = NULL;
211 struct lysc_type *type;
Michal Vasko3701af52020-08-03 14:29:38 +0200212 struct lyd_value val = {0};
213 int options = (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA) | (realtype ? LY_TYPE_OPTS_STORE : 0);
Radek Krejci084289f2019-07-09 17:35:30 +0200214
215 LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
216
217 type = ((struct lysc_node_leaf*)node->schema)->type;
Radek Krejci73dead22019-07-11 16:46:16 +0200218 rc = type->plugin->store(ctx ? ctx : node->schema->module->ctx, type, value, value_len, options,
Michal Vaskof937cfe2020-08-03 16:07:12 +0200219 lydjson_resolve_prefix, NULL, LYD_JSON, tree ? (void*)node : (void*)node->schema, tree,
Michal Vasko3701af52020-08-03 14:29:38 +0200220 &val, NULL, &err);
Radek Krejci73dead22019-07-11 16:46:16 +0200221 if (rc == LY_EINCOMPLETE) {
222 return rc;
223 } else if (rc) {
224 if (err) {
225 if (ctx) {
226 ly_err_print(err);
227 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
Radek Krejci084289f2019-07-09 17:35:30 +0200228 }
Radek Krejci73dead22019-07-11 16:46:16 +0200229 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200230 }
Radek Krejci73dead22019-07-11 16:46:16 +0200231 return rc;
Radek Krejci084289f2019-07-09 17:35:30 +0200232 }
233
Michal Vasko3701af52020-08-03 14:29:38 +0200234 if (realtype) {
235 *realtype = val.realtype;
236 }
237
238 type->plugin->free(ctx ? ctx : node->schema->module->ctx, &val);
Radek Krejci084289f2019-07-09 17:35:30 +0200239 return LY_SUCCESS;
240}
241
242API LY_ERR
Michal Vaskof937cfe2020-08-03 16:07:12 +0200243lyd_value_compare(const struct lyd_node_term *node, const char *value, size_t value_len, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +0200244{
245 LY_ERR ret = LY_SUCCESS, rc;
246 struct ly_err_item *err = NULL;
247 struct ly_ctx *ctx;
248 struct lysc_type *type;
Radek Krejci084289f2019-07-09 17:35:30 +0200249 struct lyd_value data = {0};
Michal Vaskof03ed032020-03-04 13:31:44 +0100250 int options = LY_TYPE_OPTS_STORE | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
Radek Krejci084289f2019-07-09 17:35:30 +0200251
252 LY_CHECK_ARG_RET(node ? node->schema->module->ctx : NULL, node, value, LY_EINVAL);
253
254 ctx = node->schema->module->ctx;
255 type = ((struct lysc_node_leaf*)node->schema)->type;
Michal Vaskof937cfe2020-08-03 16:07:12 +0200256 rc = type->plugin->store(ctx, type, value, value_len, options, lydjson_resolve_prefix, NULL, LYD_JSON,
257 (struct lyd_node *)node, tree, &data, NULL, &err);
Radek Krejci73dead22019-07-11 16:46:16 +0200258 if (rc == LY_EINCOMPLETE) {
259 ret = rc;
260 /* continue with comparing, just remember what to return if storing is ok */
261 } else if (rc) {
262 /* value to compare is invalid */
263 ret = LY_EINVAL;
264 if (err) {
265 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200266 }
Radek Krejci73dead22019-07-11 16:46:16 +0200267 goto cleanup;
Radek Krejci084289f2019-07-09 17:35:30 +0200268 }
269
270 /* compare data */
Radek Krejci5af04842019-07-12 11:32:07 +0200271 if (type->plugin->compare(&node->value, &data)) {
272 /* do not assign it directly from the compare callback to keep possible LY_EINCOMPLETE from validation */
Michal Vaskob3ddccb2020-07-09 15:43:05 +0200273 ret = LY_ENOT;
Radek Krejci5af04842019-07-12 11:32:07 +0200274 }
Radek Krejci084289f2019-07-09 17:35:30 +0200275
276cleanup:
Radek Krejci62903c32019-07-15 14:42:05 +0200277 type->plugin->free(ctx, &data);
Radek Krejci084289f2019-07-09 17:35:30 +0200278
279 return ret;
280}
281
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200282API const char *
283lyd_value2str(const struct lyd_node_term *node, int *dynamic)
284{
285 LY_CHECK_ARG_RET(node ? node->schema->module->ctx : NULL, node, dynamic, NULL);
286
287 return node->value.realtype->plugin->print(&node->value, LYD_JSON, json_print_get_prefix, NULL, dynamic);
288}
289
290API const char *
Michal Vasko9f96a052020-03-10 09:41:45 +0100291lyd_meta2str(const struct lyd_meta *meta, int *dynamic)
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200292{
Michal Vasko9f96a052020-03-10 09:41:45 +0100293 LY_CHECK_ARG_RET(meta ? meta->parent->schema->module->ctx : NULL, meta, dynamic, NULL);
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200294
Michal Vasko9f96a052020-03-10 09:41:45 +0100295 return meta->value.realtype->plugin->print(&meta->value, LYD_JSON, json_print_get_prefix, NULL, dynamic);
Michal Vasko5ec7cda2019-09-11 13:43:08 +0200296}
297
Radek Krejci7931b192020-06-25 17:05:03 +0200298static LYD_FORMAT
Michal Vasko63f3d842020-07-08 10:10:14 +0200299lyd_parse_get_format(const struct ly_in *in, LYD_FORMAT format)
Radek Krejcie7b95092019-05-15 11:03:07 +0200300{
Radek Krejcie7b95092019-05-15 11:03:07 +0200301
Radek Krejci7931b192020-06-25 17:05:03 +0200302 if (!format && in->type == LY_IN_FILEPATH) {
Radek Krejcie7b95092019-05-15 11:03:07 +0200303 /* unknown format - try to detect it from filename's suffix */
Radek Krejci7931b192020-06-25 17:05:03 +0200304 const char *path = in->method.fpath.filepath;
305 size_t len = strlen(path);
Radek Krejcie7b95092019-05-15 11:03:07 +0200306
307 /* ignore trailing whitespaces */
308 for (; len > 0 && isspace(path[len - 1]); len--);
309
310 if (len >= 5 && !strncmp(&path[len - 4], ".xml", 4)) {
311 format = LYD_XML;
312#if 0
313 } else if (len >= 6 && !strncmp(&path[len - 5], ".json", 5)) {
314 format = LYD_JSON;
Radek Krejci7931b192020-06-25 17:05:03 +0200315#endif
Radek Krejcie7b95092019-05-15 11:03:07 +0200316 } else if (len >= 5 && !strncmp(&path[len - 4], ".lyb", 4)) {
317 format = LYD_LYB;
Radek Krejci7931b192020-06-25 17:05:03 +0200318 } /* else still unknown */
Radek Krejcie7b95092019-05-15 11:03:07 +0200319 }
320
Radek Krejci7931b192020-06-25 17:05:03 +0200321 return format;
322}
Radek Krejcie7b95092019-05-15 11:03:07 +0200323
Radek Krejci7931b192020-06-25 17:05:03 +0200324API LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +0200325lyd_parse_data(const struct ly_ctx *ctx, struct ly_in *in, LYD_FORMAT format, int parse_options, int validate_options,
326 struct lyd_node **tree)
Radek Krejci7931b192020-06-25 17:05:03 +0200327{
328 LY_CHECK_ARG_RET(ctx, ctx, in, tree, LY_EINVAL);
329 LY_CHECK_ARG_RET(ctx, !(parse_options & ~LYD_PARSE_OPTS_MASK), LY_EINVAL);
330 LY_CHECK_ARG_RET(ctx, !(validate_options & ~LYD_VALIDATE_OPTS_MASK), LY_EINVAL);
331
332 format = lyd_parse_get_format(in, format);
333 LY_CHECK_ARG_RET(ctx, format, LY_EINVAL);
334
Michal Vasko63f3d842020-07-08 10:10:14 +0200335 /* remember input position */
336 in->func_start = in->current;
Radek Krejci7931b192020-06-25 17:05:03 +0200337
338 switch (format) {
339 case LYD_XML:
Michal Vasko63f3d842020-07-08 10:10:14 +0200340 return lyd_parse_xml_data(ctx, in, parse_options, validate_options, tree);
Radek Krejci7931b192020-06-25 17:05:03 +0200341#if 0
342 case LYD_JSON:
Michal Vasko63f3d842020-07-08 10:10:14 +0200343 return lyd_parse_json_data(ctx, in, parse_options, validate_options, tree);
Radek Krejci7931b192020-06-25 17:05:03 +0200344#endif
345 case LYD_LYB:
Michal Vasko63f3d842020-07-08 10:10:14 +0200346 return lyd_parse_lyb_data(ctx, in, parse_options, validate_options, tree);
Radek Krejci7931b192020-06-25 17:05:03 +0200347 case LYD_SCHEMA:
348 LOGINT_RET(ctx);
349 }
350
351 /* TODO move here the top-level validation from parser_xml.c's lyd_parse_xml_data() and make
352 * it common for all the lyd_parse_*_data() functions */
353
354 LOGINT_RET(ctx);
355}
356
357API LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +0200358lyd_parse_data_mem(const struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int parse_options, int validate_options,
359 struct lyd_node **tree)
Radek Krejci7931b192020-06-25 17:05:03 +0200360{
361 LY_ERR ret;
362 struct ly_in *in;
363
364 LY_CHECK_RET(ly_in_new_memory(data, &in));
365 ret = lyd_parse_data(ctx, in, format, parse_options, validate_options, tree);
366
367 ly_in_free(in, 0);
368 return ret;
369}
370
371API LY_ERR
Michal Vaskob104f112020-07-17 09:54:54 +0200372lyd_parse_data_fd(const struct ly_ctx *ctx, int fd, LYD_FORMAT format, int parse_options, int validate_options,
373 struct lyd_node **tree)
Radek Krejci7931b192020-06-25 17:05:03 +0200374{
375 LY_ERR ret;
376 struct ly_in *in;
377
378 LY_CHECK_RET(ly_in_new_fd(fd, &in));
379 ret = lyd_parse_data(ctx, in, format, parse_options, validate_options, tree);
380
381 ly_in_free(in, 0);
382 return ret;
383}
384
385API LY_ERR
Michal Vaskob104f112020-07-17 09:54:54 +0200386lyd_parse_data_path(const struct ly_ctx *ctx, const char *path, LYD_FORMAT format, int parse_options,
387 int validate_options, struct lyd_node **tree)
Radek Krejci7931b192020-06-25 17:05:03 +0200388{
389 LY_ERR ret;
390 struct ly_in *in;
391
392 LY_CHECK_RET(ly_in_new_filepath(path, 0, &in));
393 ret = lyd_parse_data(ctx, in, format, parse_options, validate_options, tree);
394
395 ly_in_free(in, 0);
396 return ret;
397}
398
Radek Krejci7931b192020-06-25 17:05:03 +0200399API LY_ERR
400lyd_parse_rpc(const struct ly_ctx *ctx, struct ly_in *in, LYD_FORMAT format, struct lyd_node **tree, struct lyd_node **op)
401{
402 LY_CHECK_ARG_RET(ctx, ctx, in, tree, LY_EINVAL);
403
404 format = lyd_parse_get_format(in, format);
405 LY_CHECK_ARG_RET(ctx, format, LY_EINVAL);
406
Michal Vasko63f3d842020-07-08 10:10:14 +0200407 /* remember input position */
408 in->func_start = in->current;
409
Radek Krejci7931b192020-06-25 17:05:03 +0200410 switch (format) {
411 case LYD_XML:
Michal Vasko63f3d842020-07-08 10:10:14 +0200412 return lyd_parse_xml_rpc(ctx, in, tree, op);
Radek Krejci7931b192020-06-25 17:05:03 +0200413#if 0
414 case LYD_JSON:
Michal Vasko63f3d842020-07-08 10:10:14 +0200415 return lyd_parse_json_rpc(ctx, in, tree, op);
Radek Krejci7931b192020-06-25 17:05:03 +0200416#endif
417 case LYD_LYB:
Michal Vasko63f3d842020-07-08 10:10:14 +0200418 return lyd_parse_lyb_rpc(ctx, in, tree, op);
Radek Krejci7931b192020-06-25 17:05:03 +0200419 case LYD_SCHEMA:
420 LOGINT_RET(ctx);
421 }
422
423 LOGINT_RET(ctx);
424}
425
426API LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +0200427lyd_parse_reply(const struct lyd_node *request, struct ly_in *in, LYD_FORMAT format, struct lyd_node **tree,
428 struct lyd_node **op)
Radek Krejci7931b192020-06-25 17:05:03 +0200429{
430 LY_CHECK_ARG_RET(NULL, request, LY_EINVAL);
431 LY_CHECK_ARG_RET(LYD_NODE_CTX(request), in, tree, LY_EINVAL);
432
433 format = lyd_parse_get_format(in, format);
434 LY_CHECK_ARG_RET(LYD_NODE_CTX(request), format, LY_EINVAL);
435
Michal Vasko63f3d842020-07-08 10:10:14 +0200436 /* remember input position */
437 in->func_start = in->current;
438
Radek Krejci7931b192020-06-25 17:05:03 +0200439 switch (format) {
440 case LYD_XML:
Michal Vasko63f3d842020-07-08 10:10:14 +0200441 return lyd_parse_xml_reply(request, in, tree, op);
Radek Krejci7931b192020-06-25 17:05:03 +0200442#if 0
443 case LYD_JSON:
Michal Vasko63f3d842020-07-08 10:10:14 +0200444 return lyd_parse_json_reply(request, in, tree, op);
Radek Krejci7931b192020-06-25 17:05:03 +0200445#endif
446 case LYD_LYB:
Michal Vasko63f3d842020-07-08 10:10:14 +0200447 return lyd_parse_lyb_reply(request, in, tree, op);
Radek Krejci7931b192020-06-25 17:05:03 +0200448 case LYD_SCHEMA:
449 LOGINT_RET(LYD_NODE_CTX(request));
450 }
451
452 LOGINT_RET(LYD_NODE_CTX(request));
453}
454
455API LY_ERR
456lyd_parse_notif(const struct ly_ctx *ctx, struct ly_in *in, LYD_FORMAT format, struct lyd_node **tree, struct lyd_node **ntf)
457{
458 LY_CHECK_ARG_RET(ctx, ctx, in, tree, LY_EINVAL);
459
460 format = lyd_parse_get_format(in, format);
461 LY_CHECK_ARG_RET(ctx, format, LY_EINVAL);
462
Michal Vasko63f3d842020-07-08 10:10:14 +0200463 /* remember input position */
464 in->func_start = in->current;
465
Radek Krejci7931b192020-06-25 17:05:03 +0200466 switch (format) {
467 case LYD_XML:
Michal Vasko63f3d842020-07-08 10:10:14 +0200468 return lyd_parse_xml_notif(ctx, in, tree, ntf);
Radek Krejci7931b192020-06-25 17:05:03 +0200469#if 0
470 case LYD_JSON:
Michal Vasko63f3d842020-07-08 10:10:14 +0200471 return lyd_parse_json_notif(ctx, in, tree, ntf);
Radek Krejci7931b192020-06-25 17:05:03 +0200472#endif
473 case LYD_LYB:
Michal Vasko63f3d842020-07-08 10:10:14 +0200474 return lyd_parse_lyb_notif(ctx, in, tree, ntf);
Radek Krejci7931b192020-06-25 17:05:03 +0200475 case LYD_SCHEMA:
476 LOGINT_RET(ctx);
477 }
478
479 LOGINT_RET(ctx);
Radek Krejcie7b95092019-05-15 11:03:07 +0200480}
Radek Krejci084289f2019-07-09 17:35:30 +0200481
Michal Vasko90932a92020-02-12 14:33:03 +0100482LY_ERR
483lyd_create_term(const struct lysc_node *schema, const char *value, size_t value_len, int *dynamic,
484 ly_clb_resolve_prefix get_prefix, void *prefix_data, LYD_FORMAT format, struct lyd_node **node)
485{
486 LY_ERR ret;
487 struct lyd_node_term *term;
488
Michal Vasko9b368d32020-02-14 13:53:31 +0100489 assert(schema->nodetype & LYD_NODE_TERM);
490
Michal Vasko90932a92020-02-12 14:33:03 +0100491 term = calloc(1, sizeof *term);
492 LY_CHECK_ERR_RET(!term, LOGMEM(schema->module->ctx), LY_EMEM);
493
494 term->schema = schema;
495 term->prev = (struct lyd_node *)term;
Michal Vasko9b368d32020-02-14 13:53:31 +0100496 term->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100497
498 ret = lyd_value_parse(term, value, value_len, dynamic, 0, get_prefix, prefix_data, format, NULL);
499 if (ret && (ret != LY_EINCOMPLETE)) {
500 free(term);
501 return ret;
502 }
Michal Vasko9b368d32020-02-14 13:53:31 +0100503 lyd_hash((struct lyd_node *)term);
504
505 *node = (struct lyd_node *)term;
506 return ret;
507}
508
509LY_ERR
510lyd_create_term2(const struct lysc_node *schema, const struct lyd_value *val, struct lyd_node **node)
511{
512 LY_ERR ret;
513 struct lyd_node_term *term;
514 struct lysc_type *type;
515
516 assert(schema->nodetype & LYD_NODE_TERM);
Michal Vasko00cbf532020-06-15 13:58:47 +0200517 assert(val && val->realtype);
Michal Vasko9b368d32020-02-14 13:53:31 +0100518
519 term = calloc(1, sizeof *term);
520 LY_CHECK_ERR_RET(!term, LOGMEM(schema->module->ctx), LY_EMEM);
521
522 term->schema = schema;
523 term->prev = (struct lyd_node *)term;
524 term->flags = LYD_NEW;
525
526 type = ((struct lysc_node_leaf *)schema)->type;
527 ret = type->plugin->duplicate(schema->module->ctx, val, &term->value);
528 if (ret) {
529 LOGERR(schema->module->ctx, ret, "Value duplication failed.");
530 free(term);
531 return ret;
532 }
Michal Vasko00cbf532020-06-15 13:58:47 +0200533 term->value.realtype = val->realtype;
Michal Vasko9b368d32020-02-14 13:53:31 +0100534 lyd_hash((struct lyd_node *)term);
Michal Vasko90932a92020-02-12 14:33:03 +0100535
536 *node = (struct lyd_node *)term;
537 return ret;
538}
539
540LY_ERR
541lyd_create_inner(const struct lysc_node *schema, struct lyd_node **node)
542{
543 struct lyd_node_inner *in;
544
Michal Vasko9b368d32020-02-14 13:53:31 +0100545 assert(schema->nodetype & LYD_NODE_INNER);
546
Michal Vasko90932a92020-02-12 14:33:03 +0100547 in = calloc(1, sizeof *in);
548 LY_CHECK_ERR_RET(!in, LOGMEM(schema->module->ctx), LY_EMEM);
549
550 in->schema = schema;
551 in->prev = (struct lyd_node *)in;
Michal Vasko9b368d32020-02-14 13:53:31 +0100552 in->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100553
Michal Vasko9b368d32020-02-14 13:53:31 +0100554 /* do not hash list with keys, we need them for the hash */
555 if ((schema->nodetype != LYS_LIST) || (schema->flags & LYS_KEYLESS)) {
556 lyd_hash((struct lyd_node *)in);
557 }
Michal Vasko90932a92020-02-12 14:33:03 +0100558
559 *node = (struct lyd_node *)in;
560 return LY_SUCCESS;
561}
562
Michal Vasko90932a92020-02-12 14:33:03 +0100563LY_ERR
Michal Vasko004d3152020-06-11 19:59:22 +0200564lyd_create_list(const struct lysc_node *schema, const struct ly_path_predicate *predicates, struct lyd_node **node)
Michal Vasko90932a92020-02-12 14:33:03 +0100565{
566 LY_ERR ret = LY_SUCCESS;
Michal Vasko90932a92020-02-12 14:33:03 +0100567 struct lyd_node *list = NULL, *key;
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200568 LY_ARRAY_COUNT_TYPE u;
Michal Vasko90932a92020-02-12 14:33:03 +0100569
Michal Vasko004d3152020-06-11 19:59:22 +0200570 assert((schema->nodetype == LYS_LIST) && !(schema->flags & LYS_KEYLESS));
Michal Vasko90932a92020-02-12 14:33:03 +0100571
572 /* create list */
573 LY_CHECK_GOTO(ret = lyd_create_inner(schema, &list), cleanup);
574
Michal Vasko90932a92020-02-12 14:33:03 +0100575 /* create and insert all the keys */
Michal Vasko004d3152020-06-11 19:59:22 +0200576 LY_ARRAY_FOR(predicates, u) {
577 LY_CHECK_GOTO(ret = lyd_create_term2(predicates[u].key, &predicates[u].value, &key), cleanup);
Michal Vasko90932a92020-02-12 14:33:03 +0100578 lyd_insert_node(list, NULL, key);
579 }
580
Michal Vasko9b368d32020-02-14 13:53:31 +0100581 /* hash having all the keys */
582 lyd_hash(list);
583
Michal Vasko90932a92020-02-12 14:33:03 +0100584 /* success */
585 *node = list;
586 list = NULL;
587
588cleanup:
589 lyd_free_tree(list);
Michal Vasko004d3152020-06-11 19:59:22 +0200590 return ret;
591}
592
593static LY_ERR
594lyd_create_list2(const struct lysc_node *schema, const char *keys, size_t keys_len, struct lyd_node **node)
595{
596 LY_ERR ret = LY_SUCCESS;
597 struct lyxp_expr *expr = NULL;
598 uint16_t exp_idx = 0;
599 enum ly_path_pred_type pred_type = 0;
600 struct ly_path_predicate *predicates = NULL;
601
602 /* parse keys */
Michal Vasko6b26e742020-07-17 15:02:10 +0200603 LY_CHECK_GOTO(ret = ly_path_parse_predicate(schema->module->ctx, NULL, keys, keys_len, LY_PATH_PREFIX_OPTIONAL,
Michal Vasko004d3152020-06-11 19:59:22 +0200604 LY_PATH_PRED_KEYS, &expr), cleanup);
605
606 /* compile them */
Michal Vasko6b26e742020-07-17 15:02:10 +0200607 LY_CHECK_GOTO(ret = ly_path_compile_predicate(schema->module->ctx, NULL, NULL, schema, expr, &exp_idx,
608 lydjson_resolve_prefix, NULL, LYD_JSON, &predicates, &pred_type), cleanup);
Michal Vasko004d3152020-06-11 19:59:22 +0200609
610 /* create the list node */
611 LY_CHECK_GOTO(ret = lyd_create_list(schema, predicates, node), cleanup);
612
613cleanup:
614 lyxp_expr_free(schema->module->ctx, expr);
615 ly_path_predicates_free(schema->module->ctx, pred_type, NULL, predicates);
Michal Vasko90932a92020-02-12 14:33:03 +0100616 return ret;
617}
618
619LY_ERR
620lyd_create_any(const struct lysc_node *schema, const void *value, LYD_ANYDATA_VALUETYPE value_type, struct lyd_node **node)
621{
622 struct lyd_node_any *any;
623
Michal Vasko9b368d32020-02-14 13:53:31 +0100624 assert(schema->nodetype & LYD_NODE_ANY);
625
Michal Vasko90932a92020-02-12 14:33:03 +0100626 any = calloc(1, sizeof *any);
627 LY_CHECK_ERR_RET(!any, LOGMEM(schema->module->ctx), LY_EMEM);
628
629 any->schema = schema;
630 any->prev = (struct lyd_node *)any;
Michal Vasko9b368d32020-02-14 13:53:31 +0100631 any->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100632
633 any->value.xml = value;
634 any->value_type = value_type;
Michal Vasko9b368d32020-02-14 13:53:31 +0100635 lyd_hash((struct lyd_node *)any);
Michal Vasko90932a92020-02-12 14:33:03 +0100636
637 *node = (struct lyd_node *)any;
638 return LY_SUCCESS;
639}
640
Michal Vasko52927e22020-03-16 17:26:14 +0100641LY_ERR
642lyd_create_opaq(const struct ly_ctx *ctx, const char *name, size_t name_len, const char *value, size_t value_len,
643 int *dynamic, LYD_FORMAT format, struct ly_prefix *val_prefs, const char *prefix, size_t pref_len,
644 const char *ns, struct lyd_node **node)
645{
646 struct lyd_node_opaq *opaq;
647
648 assert(ctx && name && name_len && ns);
649
650 if (!value_len) {
651 value = "";
652 }
653
654 opaq = calloc(1, sizeof *opaq);
655 LY_CHECK_ERR_RET(!opaq, LOGMEM(ctx), LY_EMEM);
656
657 opaq->prev = (struct lyd_node *)opaq;
658
659 opaq->name = lydict_insert(ctx, name, name_len);
660 opaq->format = format;
661 if (pref_len) {
662 opaq->prefix.pref = lydict_insert(ctx, prefix, pref_len);
663 }
664 opaq->prefix.ns = lydict_insert(ctx, ns, 0);
665 opaq->val_prefs = val_prefs;
666 if (dynamic && *dynamic) {
667 opaq->value = lydict_insert_zc(ctx, (char *)value);
668 *dynamic = 0;
669 } else {
670 opaq->value = lydict_insert(ctx, value, value_len);
671 }
672 opaq->ctx = ctx;
673
674 *node = (struct lyd_node *)opaq;
675 return LY_SUCCESS;
676}
677
Michal Vasko3a41dff2020-07-15 14:30:28 +0200678API LY_ERR
679lyd_new_inner(struct lyd_node *parent, const struct lys_module *module, const char *name, struct lyd_node **node)
Michal Vasko013a8182020-03-03 10:46:53 +0100680{
681 struct lyd_node *ret = NULL;
682 const struct lysc_node *schema;
683 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
684
Michal Vasko6027eb92020-07-15 16:37:30 +0200685 LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
Michal Vasko013a8182020-03-03 10:46:53 +0100686
Michal Vaskof03ed032020-03-04 13:31:44 +0100687 if (!module) {
688 module = parent->schema->module;
689 }
690
Michal Vasko3a41dff2020-07-15 14:30:28 +0200691 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0,
692 LYS_CONTAINER | LYS_NOTIF | LYS_RPC | LYS_ACTION, 0);
693 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Inner node (and not a list) \"%s\" not found.", name), LY_ENOTFOUND);
Michal Vasko013a8182020-03-03 10:46:53 +0100694
Michal Vasko3a41dff2020-07-15 14:30:28 +0200695 LY_CHECK_RET(lyd_create_inner(schema, &ret));
696 if (parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100697 lyd_insert_node(parent, NULL, ret);
698 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200699
700 if (node) {
701 *node = ret;
702 }
703 return LY_SUCCESS;
Michal Vasko013a8182020-03-03 10:46:53 +0100704}
705
Michal Vasko3a41dff2020-07-15 14:30:28 +0200706API LY_ERR
707lyd_new_list(struct lyd_node *parent, const struct lys_module *module, const char *name, struct lyd_node **node, ...)
Michal Vasko013a8182020-03-03 10:46:53 +0100708{
709 struct lyd_node *ret = NULL, *key;
710 const struct lysc_node *schema, *key_s;
711 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
712 va_list ap;
713 const char *key_val;
714 LY_ERR rc = LY_SUCCESS;
715
Michal Vasko6027eb92020-07-15 16:37:30 +0200716 LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
Michal Vasko013a8182020-03-03 10:46:53 +0100717
Michal Vaskof03ed032020-03-04 13:31:44 +0100718 if (!module) {
719 module = parent->schema->module;
720 }
721
Michal Vasko013a8182020-03-03 10:46:53 +0100722 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, 0);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200723 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), LY_ENOTFOUND);
Michal Vasko013a8182020-03-03 10:46:53 +0100724
725 /* create list inner node */
Michal Vasko3a41dff2020-07-15 14:30:28 +0200726 LY_CHECK_RET(lyd_create_inner(schema, &ret));
Michal Vasko013a8182020-03-03 10:46:53 +0100727
Michal Vasko3a41dff2020-07-15 14:30:28 +0200728 va_start(ap, node);
Michal Vasko013a8182020-03-03 10:46:53 +0100729
730 /* create and insert all the keys */
731 for (key_s = lysc_node_children(schema, 0); key_s && (key_s->flags & LYS_KEY); key_s = key_s->next) {
732 key_val = va_arg(ap, const char *);
733
Michal Vaskof03ed032020-03-04 13:31:44 +0100734 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 +0200735 LY_CHECK_GOTO(rc && (rc != LY_EINCOMPLETE), cleanup);
736 rc = LY_SUCCESS;
Michal Vasko013a8182020-03-03 10:46:53 +0100737 lyd_insert_node(ret, NULL, key);
738 }
739
Michal Vasko013a8182020-03-03 10:46:53 +0100740 if (parent) {
741 lyd_insert_node(parent, NULL, ret);
742 }
743
744cleanup:
Michal Vasko3a41dff2020-07-15 14:30:28 +0200745 va_end(ap);
Michal Vasko013a8182020-03-03 10:46:53 +0100746 if (rc) {
747 lyd_free_tree(ret);
748 ret = NULL;
Michal Vasko3a41dff2020-07-15 14:30:28 +0200749 } else if (node) {
750 *node = ret;
Michal Vasko013a8182020-03-03 10:46:53 +0100751 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200752 return rc;
Michal Vasko013a8182020-03-03 10:46:53 +0100753}
754
Michal Vasko3a41dff2020-07-15 14:30:28 +0200755API LY_ERR
756lyd_new_list2(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *keys,
757 struct lyd_node **node)
Michal Vasko013a8182020-03-03 10:46:53 +0100758{
759 struct lyd_node *ret = NULL;
760 const struct lysc_node *schema;
761 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
762
Michal Vasko6027eb92020-07-15 16:37:30 +0200763 LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
Michal Vasko013a8182020-03-03 10:46:53 +0100764
Michal Vaskof03ed032020-03-04 13:31:44 +0100765 if (!module) {
766 module = parent->schema->module;
767 }
Michal Vasko004d3152020-06-11 19:59:22 +0200768 if (!keys) {
769 keys = "";
770 }
Michal Vaskof03ed032020-03-04 13:31:44 +0100771
Michal Vasko004d3152020-06-11 19:59:22 +0200772 /* find schema node */
Michal Vasko013a8182020-03-03 10:46:53 +0100773 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, 0);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200774 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), LY_ENOTFOUND);
Michal Vasko013a8182020-03-03 10:46:53 +0100775
Michal Vasko004d3152020-06-11 19:59:22 +0200776 if ((schema->flags & LYS_KEYLESS) && !keys[0]) {
777 /* key-less list */
Michal Vasko3a41dff2020-07-15 14:30:28 +0200778 LY_CHECK_RET(lyd_create_inner(schema, &ret));
Michal Vasko004d3152020-06-11 19:59:22 +0200779 } else {
780 /* create the list node */
Michal Vasko3a41dff2020-07-15 14:30:28 +0200781 LY_CHECK_RET(lyd_create_list2(schema, keys, strlen(keys), &ret));
Michal Vasko004d3152020-06-11 19:59:22 +0200782 }
Michal Vasko004d3152020-06-11 19:59:22 +0200783 if (parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100784 lyd_insert_node(parent, NULL, ret);
785 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200786
787 if (node) {
788 *node = ret;
789 }
790 return LY_SUCCESS;
Michal Vasko013a8182020-03-03 10:46:53 +0100791}
792
Michal Vasko3a41dff2020-07-15 14:30:28 +0200793API LY_ERR
794lyd_new_term(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str,
795 struct lyd_node **node)
Michal Vasko013a8182020-03-03 10:46:53 +0100796{
Michal Vaskocbff3e92020-05-27 12:56:41 +0200797 LY_ERR rc;
Michal Vasko013a8182020-03-03 10:46:53 +0100798 struct lyd_node *ret = NULL;
799 const struct lysc_node *schema;
800 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
801
Michal Vasko6027eb92020-07-15 16:37:30 +0200802 LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
Michal Vasko013a8182020-03-03 10:46:53 +0100803
Michal Vaskof03ed032020-03-04 13:31:44 +0100804 if (!module) {
805 module = parent->schema->module;
806 }
807
Michal Vasko013a8182020-03-03 10:46:53 +0100808 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_TERM, 0);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200809 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Term node \"%s\" not found.", name), LY_ENOTFOUND);
Michal Vasko013a8182020-03-03 10:46:53 +0100810
Michal Vaskocbff3e92020-05-27 12:56:41 +0200811 rc = lyd_create_term(schema, val_str, val_str ? strlen(val_str) : 0, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &ret);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200812 LY_CHECK_RET(rc && (rc != LY_EINCOMPLETE), rc);
Michal Vaskocbff3e92020-05-27 12:56:41 +0200813 if (parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100814 lyd_insert_node(parent, NULL, ret);
815 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200816
817 if (node) {
818 *node = ret;
819 }
820 return LY_SUCCESS;
Michal Vasko013a8182020-03-03 10:46:53 +0100821}
822
Michal Vasko3a41dff2020-07-15 14:30:28 +0200823API LY_ERR
Michal Vasko013a8182020-03-03 10:46:53 +0100824lyd_new_any(struct lyd_node *parent, const struct lys_module *module, const char *name, const void *value,
Michal Vasko3a41dff2020-07-15 14:30:28 +0200825 LYD_ANYDATA_VALUETYPE value_type, struct lyd_node **node)
Michal Vasko013a8182020-03-03 10:46:53 +0100826{
827 struct lyd_node *ret = NULL;
828 const struct lysc_node *schema;
829 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
830
Michal Vasko6027eb92020-07-15 16:37:30 +0200831 LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
Michal Vasko013a8182020-03-03 10:46:53 +0100832
Michal Vaskof03ed032020-03-04 13:31:44 +0100833 if (!module) {
834 module = parent->schema->module;
835 }
836
Michal Vasko013a8182020-03-03 10:46:53 +0100837 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_ANY, 0);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200838 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Any node \"%s\" not found.", name), LY_ENOTFOUND);
Michal Vasko013a8182020-03-03 10:46:53 +0100839
Michal Vasko3a41dff2020-07-15 14:30:28 +0200840 LY_CHECK_RET(lyd_create_any(schema, value, value_type, &ret));
841 if (parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100842 lyd_insert_node(parent, NULL, ret);
843 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200844
845 if (node) {
846 *node = ret;
847 }
848 return LY_SUCCESS;
Michal Vasko013a8182020-03-03 10:46:53 +0100849}
850
Michal Vasko4490d312020-06-16 13:08:55 +0200851/**
852 * @brief Update node value.
853 *
854 * @param[in] node Node to update.
855 * @param[in] value New value to set.
856 * @param[in] value_type Type of @p value for any node.
857 * @param[out] new_parent Set to @p node if the value was updated, otherwise set to NULL.
858 * @param[out] new_node Set to @p node if the value was updated, otherwise set to NULL.
859 * @return LY_ERR value.
860 */
Michal Vasko00cbf532020-06-15 13:58:47 +0200861static LY_ERR
862lyd_new_path_update(struct lyd_node *node, const void *value, LYD_ANYDATA_VALUETYPE value_type,
863 struct lyd_node **new_parent, struct lyd_node **new_node)
864{
865 LY_ERR ret = LY_SUCCESS;
866 struct lyd_node *new_any;
867
868 switch (node->schema->nodetype) {
869 case LYS_CONTAINER:
870 case LYS_NOTIF:
871 case LYS_RPC:
872 case LYS_ACTION:
873 case LYS_LIST:
874 case LYS_LEAFLIST:
875 /* if it exists, there is nothing to update */
876 *new_parent = NULL;
877 *new_node = NULL;
878 break;
879 case LYS_LEAF:
880 ret = lyd_change_term(node, value);
881 if ((ret == LY_SUCCESS) || (ret == LY_EEXIST)) {
882 /* there was an actual change (at least of the default flag) */
883 *new_parent = node;
884 *new_node = node;
885 ret = LY_SUCCESS;
886 } else if (ret == LY_ENOT) {
887 /* no change */
888 *new_parent = NULL;
889 *new_node = NULL;
890 ret = LY_SUCCESS;
891 } /* else error */
892 break;
893 case LYS_ANYDATA:
894 case LYS_ANYXML:
895 /* create a new any node */
896 LY_CHECK_RET(lyd_create_any(node->schema, value, value_type, &new_any));
897
898 /* compare with the existing one */
Michal Vasko8f359bf2020-07-28 10:41:15 +0200899 if (lyd_compare_single(node, new_any, 0)) {
Michal Vasko00cbf532020-06-15 13:58:47 +0200900 /* not equal, switch values (so that we can use generic node free) */
901 ((struct lyd_node_any *)new_any)->value = ((struct lyd_node_any *)node)->value;
902 ((struct lyd_node_any *)new_any)->value_type = ((struct lyd_node_any *)node)->value_type;
903 ((struct lyd_node_any *)node)->value.str = value;
904 ((struct lyd_node_any *)node)->value_type = value_type;
905
906 *new_parent = node;
907 *new_node = node;
908 } else {
909 /* they are equal */
910 *new_parent = NULL;
911 *new_node = NULL;
912 }
913 lyd_free_tree(new_any);
914 break;
915 default:
916 LOGINT(LYD_NODE_CTX(node));
917 ret = LY_EINT;
918 break;
919 }
920
921 return ret;
922}
923
Michal Vasko3a41dff2020-07-15 14:30:28 +0200924API LY_ERR
925lyd_new_meta(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str,
926 struct lyd_meta **meta)
Michal Vaskod86997b2020-05-26 15:19:54 +0200927{
928 struct lyd_meta *ret = NULL;
Michal Vasko00cbf532020-06-15 13:58:47 +0200929 const struct ly_ctx *ctx;
Michal Vaskod86997b2020-05-26 15:19:54 +0200930 const char *prefix, *tmp;
Michal Vaskod86997b2020-05-26 15:19:54 +0200931 size_t pref_len, name_len;
932
Michal Vasko3a41dff2020-07-15 14:30:28 +0200933 LY_CHECK_ARG_RET(NULL, parent, name, module || strchr(name, ':'), LY_EINVAL);
Michal Vasko00cbf532020-06-15 13:58:47 +0200934
935 ctx = LYD_NODE_CTX(parent);
Michal Vaskod86997b2020-05-26 15:19:54 +0200936
937 /* parse the name */
938 tmp = name;
939 if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
940 LOGERR(ctx, LY_EINVAL, "Metadata name \"%s\" is not valid.", name);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200941 return LY_EVALID;
Michal Vaskod86997b2020-05-26 15:19:54 +0200942 }
943
944 /* find the module */
945 if (prefix) {
Radek Krejci0ad51f12020-07-16 12:08:12 +0200946 module = ly_ctx_get_module_implemented2(ctx, prefix, pref_len);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200947 LY_CHECK_ERR_RET(!module, LOGERR(ctx, LY_EINVAL, "Module \"%.*s\" not found.", pref_len, prefix), LY_ENOTFOUND);
Michal Vaskod86997b2020-05-26 15:19:54 +0200948 }
949
950 /* set value if none */
951 if (!val_str) {
952 val_str = "";
953 }
954
Michal Vasko3a41dff2020-07-15 14:30:28 +0200955 LY_CHECK_RET(lyd_create_meta(parent, &ret, module, name, name_len, val_str, strlen(val_str), NULL,
956 lydjson_resolve_prefix, NULL, LYD_JSON, parent->schema));
957
958 if (meta) {
959 *meta = ret;
960 }
961 return LY_SUCCESS;
Michal Vaskod86997b2020-05-26 15:19:54 +0200962}
963
Michal Vasko3a41dff2020-07-15 14:30:28 +0200964API LY_ERR
Michal Vasko00cbf532020-06-15 13:58:47 +0200965lyd_new_opaq(struct lyd_node *parent, const struct ly_ctx *ctx, const char *name, const char *value,
Michal Vasko3a41dff2020-07-15 14:30:28 +0200966 const char *module_name, struct lyd_node **node)
Michal Vasko00cbf532020-06-15 13:58:47 +0200967{
968 struct lyd_node *ret = NULL;
969
Michal Vasko6027eb92020-07-15 16:37:30 +0200970 LY_CHECK_ARG_RET(ctx, parent || ctx, parent || node, name, module_name, LY_EINVAL);
Michal Vasko00cbf532020-06-15 13:58:47 +0200971
972 if (!ctx) {
973 ctx = LYD_NODE_CTX(parent);
974 }
975 if (!value) {
976 value = "";
977 }
978
Michal Vasko3a41dff2020-07-15 14:30:28 +0200979 LY_CHECK_RET(lyd_create_opaq(ctx, name, strlen(name), value, strlen(value), NULL, LYD_JSON, NULL, NULL, 0,
980 module_name, &ret));
981 if (parent) {
Michal Vasko00cbf532020-06-15 13:58:47 +0200982 lyd_insert_node(parent, NULL, ret);
983 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200984
985 if (node) {
986 *node = ret;
987 }
988 return LY_SUCCESS;
Michal Vasko00cbf532020-06-15 13:58:47 +0200989}
990
Michal Vasko3a41dff2020-07-15 14:30:28 +0200991API LY_ERR
992lyd_new_attr(struct lyd_node *parent, const char *module_name, const char *name, const char *val_str,
993 struct ly_attr **attr)
Michal Vasko00cbf532020-06-15 13:58:47 +0200994{
995 struct ly_attr *ret = NULL;
996 const struct ly_ctx *ctx;
997 const char *prefix, *tmp;
998 size_t pref_len, name_len;
999
Michal Vasko3a41dff2020-07-15 14:30:28 +02001000 LY_CHECK_ARG_RET(NULL, parent, !parent->schema, name, LY_EINVAL);
Michal Vasko00cbf532020-06-15 13:58:47 +02001001
1002 ctx = LYD_NODE_CTX(parent);
1003
1004 /* parse the name */
1005 tmp = name;
1006 if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
1007 LOGERR(ctx, LY_EINVAL, "Metadata name \"%s\" is not valid.", name);
Michal Vasko3a41dff2020-07-15 14:30:28 +02001008 return LY_EVALID;
Michal Vasko00cbf532020-06-15 13:58:47 +02001009 }
1010
1011 /* set value if none */
1012 if (!val_str) {
1013 val_str = "";
1014 }
1015
Michal Vasko3a41dff2020-07-15 14:30:28 +02001016 LY_CHECK_RET(ly_create_attr(parent, &ret, ctx, name, name_len, val_str, strlen(val_str), NULL, LYD_JSON, NULL,
1017 prefix, pref_len, module_name));
1018
1019 if (attr) {
1020 *attr = ret;
1021 }
1022 return LY_SUCCESS;
Michal Vasko00cbf532020-06-15 13:58:47 +02001023}
1024
1025API LY_ERR
1026lyd_change_term(struct lyd_node *term, const char *val_str)
1027{
1028 LY_ERR ret = LY_SUCCESS;
1029 struct lysc_type *type;
1030 struct lyd_node_term *t;
1031 struct lyd_node *parent;
1032 struct lyd_value val = {0};
1033 int dflt_change, val_change;
1034
1035 LY_CHECK_ARG_RET(NULL, term, term->schema, term->schema->nodetype & LYD_NODE_TERM, LY_EINVAL);
1036
1037 if (!val_str) {
1038 val_str = "";
1039 }
1040 t = (struct lyd_node_term *)term;
1041 type = ((struct lysc_node_leaf *)term->schema)->type;
1042
1043 /* parse the new value */
1044 LY_CHECK_GOTO(ret = lyd_value_store(&val, term->schema, val_str, strlen(val_str), NULL, lydjson_resolve_prefix, NULL,
1045 LYD_JSON), cleanup);
1046
1047 /* compare original and new value */
1048 if (type->plugin->compare(&t->value, &val)) {
1049 /* values differ, switch them */
1050 type->plugin->free(LYD_NODE_CTX(term), &t->value);
1051 t->value = val;
1052 memset(&val, 0, sizeof val);
1053 val_change = 1;
1054 } else {
1055 val_change = 0;
1056 }
1057
1058 /* always clear the default flag */
1059 if (term->flags & LYD_DEFAULT) {
1060 for (parent = term; parent; parent = (struct lyd_node *)parent->parent) {
1061 parent->flags &= ~LYD_DEFAULT;
1062 }
1063 dflt_change = 1;
1064 } else {
1065 dflt_change = 0;
1066 }
1067
1068 if (val_change || dflt_change) {
1069 /* make the node non-validated */
1070 term->flags &= LYD_NEW;
1071 }
1072
1073 if (val_change) {
1074 if (term->schema->nodetype == LYS_LEAFLIST) {
1075 /* leaf-list needs to be hashed again and re-inserted into parent */
1076 lyd_unlink_hash(term);
1077 lyd_hash(term);
1078 LY_CHECK_GOTO(ret = lyd_insert_hash(term), cleanup);
1079 } else if ((term->schema->flags & LYS_KEY) && term->parent) {
1080 /* list needs to be updated if its key was changed */
1081 assert(term->parent->schema->nodetype == LYS_LIST);
1082 lyd_unlink_hash((struct lyd_node *)term->parent);
1083 lyd_hash((struct lyd_node *)term->parent);
1084 LY_CHECK_GOTO(ret = lyd_insert_hash((struct lyd_node *)term->parent), cleanup);
1085 } /* else leaf that is not a key, its value is not used for its hash so it does not change */
1086 }
1087
1088 /* retrun value */
1089 if (!val_change) {
1090 if (dflt_change) {
1091 /* only default flag change */
1092 ret = LY_EEXIST;
1093 } else {
1094 /* no change */
1095 ret = LY_ENOT;
1096 }
1097 } /* else value changed, LY_SUCCESS */
1098
1099cleanup:
1100 type->plugin->free(LYD_NODE_CTX(term), &val);
1101 return ret;
1102}
1103
Michal Vasko41586352020-07-13 13:54:25 +02001104API LY_ERR
1105lyd_change_meta(struct lyd_meta *meta, const char *val_str)
1106{
1107 LY_ERR ret = LY_SUCCESS;
1108 struct lyd_meta *m2;
1109 struct lyd_value val;
1110 int val_change;
1111
1112 LY_CHECK_ARG_RET(NULL, meta, LY_EINVAL);
1113
1114 if (!val_str) {
1115 val_str = "";
1116 }
1117
1118 /* parse the new value into a new meta structure */
1119 LY_CHECK_GOTO(ret = lyd_create_meta(NULL, &m2, meta->annotation->module, meta->name, strlen(meta->name), val_str,
1120 strlen(val_str), NULL, lydjson_resolve_prefix, NULL, LYD_JSON, NULL), cleanup);
1121
1122 /* compare original and new value */
1123 if (lyd_compare_meta(meta, m2)) {
1124 /* values differ, switch them */
1125 val = meta->value;
1126 meta->value = m2->value;
1127 m2->value = val;
1128 val_change = 1;
1129 } else {
1130 val_change = 0;
1131 }
1132
1133 /* retrun value */
1134 if (!val_change) {
1135 /* no change */
1136 ret = LY_ENOT;
1137 } /* else value changed, LY_SUCCESS */
1138
1139cleanup:
1140 return ret;
1141}
1142
Michal Vasko3a41dff2020-07-15 14:30:28 +02001143API LY_ERR
1144lyd_new_path(struct lyd_node *parent, const struct ly_ctx *ctx, const char *path, const char *value, int options,
1145 struct lyd_node **node)
Michal Vasko00cbf532020-06-15 13:58:47 +02001146{
Michal Vasko3a41dff2020-07-15 14:30:28 +02001147 return lyd_new_path2(parent, ctx, path, value, 0, options, node, NULL);
Michal Vasko00cbf532020-06-15 13:58:47 +02001148}
1149
1150API LY_ERR
1151lyd_new_path2(struct lyd_node *parent, const struct ly_ctx *ctx, const char *path, const void *value,
1152 LYD_ANYDATA_VALUETYPE value_type, int options, struct lyd_node **new_parent, struct lyd_node **new_node)
1153{
1154 LY_ERR ret = LY_SUCCESS, r;
1155 struct lyxp_expr *exp = NULL;
1156 struct ly_path *p = NULL;
1157 struct lyd_node *nparent = NULL, *nnode = NULL, *node = NULL, *cur_parent;
1158 const struct lysc_node *schema;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001159 LY_ARRAY_COUNT_TYPE path_idx = 0;
Michal Vasko00cbf532020-06-15 13:58:47 +02001160 struct ly_path_predicate *pred;
1161
1162 LY_CHECK_ARG_RET(ctx, parent || ctx, path, (path[0] == '/') || parent, LY_EINVAL);
1163
1164 if (!ctx) {
1165 ctx = LYD_NODE_CTX(parent);
1166 }
1167
1168 /* parse path */
Michal Vasko6b26e742020-07-17 15:02:10 +02001169 LY_CHECK_GOTO(ret = ly_path_parse(ctx, NULL, path, strlen(path), LY_PATH_BEGIN_EITHER, LY_PATH_LREF_FALSE,
Michal Vasko00cbf532020-06-15 13:58:47 +02001170 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_SIMPLE, &exp), cleanup);
1171
1172 /* compile path */
1173 LY_CHECK_GOTO(ret = ly_path_compile(ctx, NULL, parent ? parent->schema : NULL, exp, LY_PATH_LREF_FALSE,
1174 options & LYD_NEWOPT_OUTPUT ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT,
1175 LY_PATH_TARGET_MANY, lydjson_resolve_prefix, NULL, LYD_JSON, &p), cleanup);
1176
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001177 schema = p[LY_ARRAY_COUNT(p) - 1].node;
1178 if ((schema->nodetype == LYS_LIST) && (p[LY_ARRAY_COUNT(p) - 1].pred_type == LY_PATH_PREDTYPE_NONE)
Michal Vasko00cbf532020-06-15 13:58:47 +02001179 && !(options & LYD_NEWOPT_OPAQ)) {
1180 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_XPATH, "Predicate missing for %s \"%s\" in path.",
1181 lys_nodetype2str(schema->nodetype), schema->name);
1182 ret = LY_EINVAL;
1183 goto cleanup;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001184 } else if ((schema->nodetype == LYS_LEAFLIST) && (p[LY_ARRAY_COUNT(p) - 1].pred_type == LY_PATH_PREDTYPE_NONE)) {
Michal Vasko00cbf532020-06-15 13:58:47 +02001185 /* parse leafref value into a predicate, if not defined in the path */
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001186 p[LY_ARRAY_COUNT(p) - 1].pred_type = LY_PATH_PREDTYPE_LEAFLIST;
1187 LY_ARRAY_NEW_GOTO(ctx, p[LY_ARRAY_COUNT(p) - 1].predicates, pred, ret, cleanup);
Michal Vasko00cbf532020-06-15 13:58:47 +02001188
1189 if (!value) {
1190 value = "";
1191 }
1192
1193 r = LY_SUCCESS;
1194 if (options & LYD_NEWOPT_OPAQ) {
Michal Vaskof937cfe2020-08-03 16:07:12 +02001195 r = lys_value_validate(NULL, schema, value, strlen(value));
Michal Vasko00cbf532020-06-15 13:58:47 +02001196 }
1197 if (!r) {
1198 LY_CHECK_GOTO(ret = lyd_value_store(&pred->value, schema, value, strlen(value), NULL, lydjson_resolve_prefix,
1199 NULL, LYD_JSON), cleanup);
1200 } /* else we have opaq flag and the value is not valid, leavne no predicate and then create an opaque node */
1201 }
1202
1203 /* try to find any existing nodes in the path */
1204 if (parent) {
1205 ret = ly_path_eval_partial(p, parent, &path_idx, &node);
1206 if (ret == LY_SUCCESS) {
1207 /* the node exists, are we supposed to update it or is it just a default? */
1208 if (!(options & LYD_NEWOPT_UPDATE) && !(node->flags & LYD_DEFAULT)) {
1209 LOGERR(ctx, LY_EEXIST, "Path \"%s\" already exists", path);
1210 ret = LY_EEXIST;
1211 goto cleanup;
1212 }
1213
1214 /* update the existing node */
1215 ret = lyd_new_path_update(node, value, value_type, &nparent, &nnode);
1216 goto cleanup;
1217 } else if (ret == LY_EINCOMPLETE) {
1218 /* some nodes were found, adjust the iterator to the next segment */
1219 ++path_idx;
1220 } else if (ret == LY_ENOTFOUND) {
1221 /* we will create the nodes from top-level, default behavior (absolute path), or from the parent (relative path) */
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001222 if (lysc_data_parent(p[LY_ARRAY_COUNT(p) - 1].node)) {
Michal Vasko00cbf532020-06-15 13:58:47 +02001223 node = parent;
1224 }
1225 } else {
1226 /* error */
1227 goto cleanup;
1228 }
1229 }
1230
1231 /* create all the non-existing nodes in a loop */
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001232 for (; path_idx < LY_ARRAY_COUNT(p); ++path_idx) {
Michal Vasko00cbf532020-06-15 13:58:47 +02001233 cur_parent = node;
1234 schema = p[path_idx].node;
1235
1236 switch (schema->nodetype) {
1237 case LYS_LIST:
1238 if (!(schema->flags & LYS_KEYLESS)) {
1239 if ((options & LYD_NEWOPT_OPAQ) && (p[path_idx].pred_type == LY_PATH_PREDTYPE_NONE)) {
1240 /* creating opaque list without keys */
1241 LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, NULL,
1242 LYD_JSON, NULL, NULL, 0, schema->module->name, &node), cleanup);
1243 } else {
1244 assert(p[path_idx].pred_type == LY_PATH_PREDTYPE_LIST);
1245 LY_CHECK_GOTO(ret = lyd_create_list(schema, p[path_idx].predicates, &node), cleanup);
1246 }
1247 break;
1248 }
1249 /* fallthrough */
1250 case LYS_CONTAINER:
1251 case LYS_NOTIF:
1252 case LYS_RPC:
1253 case LYS_ACTION:
1254 LY_CHECK_GOTO(ret = lyd_create_inner(schema, &node), cleanup);
1255 break;
1256 case LYS_LEAFLIST:
1257 if ((options & LYD_NEWOPT_OPAQ) && (p[path_idx].pred_type == LY_PATH_PREDTYPE_NONE)) {
1258 /* creating opaque leaf-list without value */
1259 LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, NULL,
1260 LYD_JSON, NULL, NULL, 0, schema->module->name, &node), cleanup);
1261 } else {
1262 assert(p[path_idx].pred_type == LY_PATH_PREDTYPE_LEAFLIST);
1263 LY_CHECK_GOTO(ret = lyd_create_term2(schema, &p[path_idx].predicates[0].value, &node), cleanup);
1264 }
1265 break;
1266 case LYS_LEAF:
1267 /* make there is some value */
1268 if (!value) {
1269 value = "";
1270 }
1271
1272 r = LY_SUCCESS;
1273 if (options & LYD_NEWOPT_OPAQ) {
Michal Vaskof937cfe2020-08-03 16:07:12 +02001274 r = lys_value_validate(NULL, schema, value, strlen(value));
Michal Vasko00cbf532020-06-15 13:58:47 +02001275 }
1276 if (!r) {
1277 LY_CHECK_GOTO(ret = lyd_create_term(schema, value, strlen(value), NULL, lydjson_resolve_prefix, NULL,
1278 LYD_JSON, &node), cleanup);
1279 } else {
1280 /* creating opaque leaf without value */
1281 LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, NULL,
1282 LYD_JSON, NULL, NULL, 0, schema->module->name, &node), cleanup);
1283 }
1284 break;
1285 case LYS_ANYDATA:
1286 case LYS_ANYXML:
1287 LY_CHECK_GOTO(ret = lyd_create_any(schema, value, value_type, &node), cleanup);
1288 break;
1289 default:
1290 LOGINT(ctx);
1291 ret = LY_EINT;
1292 goto cleanup;
1293 }
1294
1295 if (cur_parent) {
1296 /* connect to the parent */
1297 lyd_insert_node(cur_parent, NULL, node);
1298 } else if (parent) {
1299 /* connect to top-level siblings */
1300 lyd_insert_node(NULL, &parent, node);
1301 }
1302
1303 /* update remembered nodes */
1304 if (!nparent) {
1305 nparent = node;
1306 }
1307 nnode = node;
1308 }
1309
1310cleanup:
1311 lyxp_expr_free(ctx, exp);
1312 ly_path_free(ctx, p);
1313 if (!ret) {
1314 /* set out params only on success */
1315 if (new_parent) {
1316 *new_parent = nparent;
1317 }
1318 if (new_node) {
1319 *new_node = nnode;
1320 }
1321 }
1322 return ret;
1323}
1324
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001325LY_ERR
1326lyd_new_implicit_r(struct lyd_node *parent, struct lyd_node **first, const struct lysc_node *sparent,
1327 const struct lys_module *mod, struct ly_set *node_types, struct ly_set *node_when, int impl_opts,
1328 struct lyd_node **diff)
1329{
1330 LY_ERR ret;
1331 const struct lysc_node *iter = NULL;
1332 struct lyd_node *node;
1333 struct lyd_value **dflts;
1334 LY_ARRAY_COUNT_TYPE u;
1335
1336 assert(first && (parent || sparent || mod));
1337
1338 if (!sparent && parent) {
1339 sparent = parent->schema;
1340 }
1341
1342 while ((iter = lys_getnext(iter, sparent, mod ? mod->compiled : NULL, LYS_GETNEXT_WITHCHOICE))) {
1343 if ((impl_opts & LYD_IMPLICIT_NO_STATE) && (iter->flags & LYS_CONFIG_R)) {
1344 continue;
Michal Vasko44b19a12020-08-07 09:21:30 +02001345 } else if ((impl_opts & LYD_IMPLICIT_NO_CONFIG) && (iter->flags & LYS_CONFIG_W)) {
1346 continue;
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001347 }
1348
1349 switch (iter->nodetype) {
1350 case LYS_CHOICE:
1351 if (((struct lysc_node_choice *)iter)->dflt && !lys_getnext_data(NULL, *first, NULL, iter, NULL)) {
1352 /* create default case data */
1353 LY_CHECK_RET(lyd_new_implicit_r(parent, first, (struct lysc_node *)((struct lysc_node_choice *)iter)->dflt,
1354 NULL, node_types, node_when, impl_opts, diff));
1355 }
1356 break;
1357 case LYS_CONTAINER:
1358 if (!(iter->flags & LYS_PRESENCE) && lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
1359 /* create default NP container */
1360 LY_CHECK_RET(lyd_create_inner(iter, &node));
1361 node->flags = LYD_DEFAULT;
1362 lyd_insert_node(parent, first, node);
1363
1364 /* cannot be a NP container with when */
1365 assert(!iter->when);
1366
1367 /* create any default children */
1368 LY_CHECK_RET(lyd_new_implicit_r(node, lyd_node_children_p(node), NULL, NULL, node_types, node_when,
1369 impl_opts, diff));
1370 }
1371 break;
1372 case LYS_LEAF:
1373 if (!(impl_opts & LYD_IMPLICIT_NO_DEFAULTS) && ((struct lysc_node_leaf *)iter)->dflt
1374 && lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
1375 /* create default leaf */
1376 ret = lyd_create_term2(iter, ((struct lysc_node_leaf *)iter)->dflt, &node);
1377 if (ret == LY_EINCOMPLETE) {
1378 if (node_types) {
1379 /* remember to resolve type */
1380 ly_set_add(node_types, node, LY_SET_OPT_USEASLIST);
1381 }
1382 } else if (ret) {
1383 return ret;
1384 }
1385 node->flags = LYD_DEFAULT;
1386 lyd_insert_node(parent, first, node);
1387
1388 if (iter->when && node_when) {
1389 /* remember to resolve when */
1390 ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
1391 }
1392 if (diff) {
1393 /* add into diff */
1394 LY_CHECK_RET(lyd_val_diff_add(node, LYD_DIFF_OP_CREATE, diff));
1395 }
1396 }
1397 break;
1398 case LYS_LEAFLIST:
1399 if (!(impl_opts & LYD_IMPLICIT_NO_DEFAULTS) && ((struct lysc_node_leaflist *)iter)->dflts
1400 && lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
1401 /* create all default leaf-lists */
1402 dflts = ((struct lysc_node_leaflist *)iter)->dflts;
1403 LY_ARRAY_FOR(dflts, u) {
1404 ret = lyd_create_term2(iter, dflts[u], &node);
1405 if (ret == LY_EINCOMPLETE) {
1406 if (node_types) {
1407 /* remember to resolve type */
1408 ly_set_add(node_types, node, LY_SET_OPT_USEASLIST);
1409 }
1410 } else if (ret) {
1411 return ret;
1412 }
1413 node->flags = LYD_DEFAULT;
1414 lyd_insert_node(parent, first, node);
1415
1416 if (iter->when && node_when) {
1417 /* remember to resolve when */
1418 ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
1419 }
1420 if (diff) {
1421 /* add into diff */
1422 LY_CHECK_RET(lyd_val_diff_add(node, LYD_DIFF_OP_CREATE, diff));
1423 }
1424 }
1425 }
1426 break;
1427 default:
1428 /* without defaults */
1429 break;
1430 }
1431 }
1432
1433 return LY_SUCCESS;
1434}
1435
1436API LY_ERR
1437lyd_new_implicit_tree(struct lyd_node *tree, int implicit_options, struct lyd_node **diff)
1438{
Michal Vasko56daf732020-08-10 10:57:18 +02001439 struct lyd_node *node;
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001440 LY_ERR ret = LY_SUCCESS;
1441
1442 LY_CHECK_ARG_RET(NULL, tree, LY_EINVAL);
1443 if (diff) {
1444 *diff = NULL;
1445 }
1446
Michal Vasko56daf732020-08-10 10:57:18 +02001447 LYD_TREE_DFS_BEGIN(tree, node) {
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001448 /* skip added default nodes */
1449 if (((node->flags & (LYD_DEFAULT | LYD_NEW)) != (LYD_DEFAULT | LYD_NEW))
1450 && (node->schema->nodetype & LYD_NODE_INNER)) {
1451 LY_CHECK_GOTO(ret = lyd_new_implicit_r(node, lyd_node_children_p((struct lyd_node *)node), NULL, NULL, NULL,
1452 NULL, implicit_options, diff), cleanup);
1453 }
1454
Michal Vasko56daf732020-08-10 10:57:18 +02001455 LYD_TREE_DFS_END(tree, node);
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001456 }
1457
1458cleanup:
1459 if (ret && diff) {
1460 lyd_free_all(*diff);
1461 *diff = NULL;
1462 }
1463 return ret;
1464}
1465
1466API LY_ERR
1467lyd_new_implicit_all(struct lyd_node **tree, const struct ly_ctx *ctx, int implicit_options, struct lyd_node **diff)
1468{
1469 const struct lys_module *mod;
1470 struct lyd_node *d = NULL;
1471 uint32_t i = 0;
1472 LY_ERR ret = LY_SUCCESS;
1473
1474 LY_CHECK_ARG_RET(ctx, tree, *tree || ctx, LY_EINVAL);
1475 if (diff) {
1476 *diff = NULL;
1477 }
1478 if (!ctx) {
1479 ctx = LYD_NODE_CTX(*tree);
1480 }
1481
1482 /* add nodes for each module one-by-one */
1483 while ((mod = ly_ctx_get_module_iter(ctx, &i))) {
1484 if (!mod->implemented) {
1485 continue;
1486 }
1487
1488 LY_CHECK_GOTO(ret = lyd_new_implicit_module(tree, mod, implicit_options, diff ? &d : NULL), cleanup);
1489 if (d) {
1490 /* merge into one diff */
1491 lyd_insert_sibling(*diff, d, diff);
1492
1493 d = NULL;
1494 }
1495 }
1496
1497cleanup:
1498 if (ret && diff) {
1499 lyd_free_all(*diff);
1500 *diff = NULL;
1501 }
1502 return ret;
1503}
1504
1505API LY_ERR
1506lyd_new_implicit_module(struct lyd_node **tree, const struct lys_module *module, int implicit_options, struct lyd_node **diff)
1507{
1508 struct lyd_node *root, *d = NULL;
1509 LY_ERR ret = LY_SUCCESS;
1510
1511 LY_CHECK_ARG_RET(NULL, tree, module, LY_EINVAL);
1512 if (diff) {
1513 *diff = NULL;
1514 }
1515
1516 /* add all top-level defaults for this module */
1517 LY_CHECK_GOTO(ret = lyd_new_implicit_r(NULL, tree, NULL, module, NULL, NULL, implicit_options, diff), cleanup);
1518
1519 /* process nested nodes */
1520 LY_LIST_FOR(*tree, root) {
1521 /* skip added default nodes */
1522 if ((root->flags & (LYD_DEFAULT | LYD_NEW)) != (LYD_DEFAULT | LYD_NEW)) {
1523 LY_CHECK_GOTO(ret = lyd_new_implicit_tree(root, implicit_options, diff ? &d : NULL), cleanup);
1524
1525 if (d) {
1526 /* merge into one diff */
1527 lyd_insert_sibling(*diff, d, diff);
1528
1529 d = NULL;
1530 }
1531 }
1532 }
1533
1534cleanup:
1535 if (ret && diff) {
1536 lyd_free_all(*diff);
1537 *diff = NULL;
1538 }
1539 return ret;
1540}
1541
Michal Vasko90932a92020-02-12 14:33:03 +01001542struct lyd_node *
Michal Vaskob104f112020-07-17 09:54:54 +02001543lyd_insert_get_next_anchor(const struct lyd_node *first_sibling, const struct lyd_node *new_node)
Michal Vasko90932a92020-02-12 14:33:03 +01001544{
Michal Vaskob104f112020-07-17 09:54:54 +02001545 const struct lysc_node *schema, *sparent;
Michal Vasko90932a92020-02-12 14:33:03 +01001546 struct lyd_node *match = NULL;
Michal Vaskob104f112020-07-17 09:54:54 +02001547 int found;
Michal Vasko90932a92020-02-12 14:33:03 +01001548
Michal Vaskob104f112020-07-17 09:54:54 +02001549 assert(new_node);
1550
1551 if (!first_sibling || !new_node->schema) {
1552 /* insert at the end, no next anchor */
Michal Vasko90932a92020-02-12 14:33:03 +01001553 return NULL;
1554 }
1555
Michal Vaskob104f112020-07-17 09:54:54 +02001556 if (first_sibling->parent && first_sibling->parent->children_ht) {
1557 /* find the anchor using hashes */
1558 sparent = first_sibling->parent->schema;
1559 schema = lys_getnext(new_node->schema, sparent, NULL, 0);
1560 while (schema) {
1561 /* keep trying to find the first existing instance of the closest following schema sibling,
1562 * otherwise return NULL - inserting at the end */
1563 if (!lyd_find_sibling_schema(first_sibling, schema, &match)) {
1564 break;
1565 }
1566
1567 schema = lys_getnext(schema, sparent, NULL, 0);
1568 }
1569 } else {
1570 /* find the anchor without hashes */
1571 match = (struct lyd_node *)first_sibling;
1572 if (!lysc_data_parent(new_node->schema)) {
1573 /* we are in top-level, skip all the data from preceding modules */
1574 LY_LIST_FOR(match, match) {
1575 if (!match->schema || (strcmp(lyd_owner_module(match)->name, lyd_owner_module(new_node)->name) >= 0)) {
1576 break;
1577 }
1578 }
1579 }
1580
1581 /* get the first schema sibling */
1582 sparent = lysc_data_parent(new_node->schema);
1583 schema = lys_getnext(NULL, sparent, new_node->schema->module->compiled, 0);
1584
1585 found = 0;
1586 LY_LIST_FOR(match, match) {
1587 if (!match->schema || (lyd_owner_module(match) != lyd_owner_module(new_node))) {
1588 /* we have found an opaque node, which must be at the end, so use it OR
1589 * modules do not match, so we must have traversed all the data from new_node module (if any),
1590 * we have found the first node of the next module, that is what we want */
1591 break;
1592 }
1593
1594 /* skip schema nodes until we find the instantiated one */
1595 while (!found) {
1596 if (new_node->schema == schema) {
1597 /* we have found the schema of the new node, continue search to find the first
1598 * data node with a different schema (after our schema) */
1599 found = 1;
1600 break;
1601 }
1602 if (match->schema == schema) {
1603 /* current node (match) is a data node still before the new node, continue search in data */
1604 break;
1605 }
1606 schema = lys_getnext(schema, sparent, new_node->schema->module->compiled, 0);
1607 assert(schema);
1608 }
1609
1610 if (found && (match->schema != new_node->schema)) {
1611 /* find the next node after we have found our node schema data instance */
1612 break;
1613 }
1614 }
Michal Vasko90932a92020-02-12 14:33:03 +01001615 }
1616
1617 return match;
1618}
1619
1620/**
1621 * @brief Insert node after a sibling.
1622 *
Michal Vasko9f96a052020-03-10 09:41:45 +01001623 * Handles inserting into NP containers and key-less lists.
1624 *
Michal Vasko90932a92020-02-12 14:33:03 +01001625 * @param[in] sibling Sibling to insert after.
1626 * @param[in] node Node to insert.
1627 */
1628static void
Michal Vaskof03ed032020-03-04 13:31:44 +01001629lyd_insert_after_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001630{
Michal Vasko0249f7c2020-03-05 16:36:40 +01001631 struct lyd_node_inner *par;
1632
Michal Vasko90932a92020-02-12 14:33:03 +01001633 assert(!node->next && (node->prev == node));
1634
1635 node->next = sibling->next;
1636 node->prev = sibling;
1637 sibling->next = node;
1638 if (node->next) {
1639 /* sibling had a succeeding node */
1640 node->next->prev = node;
1641 } else {
1642 /* sibling was last, find first sibling and change its prev */
1643 if (sibling->parent) {
1644 sibling = sibling->parent->child;
1645 } else {
1646 for (; sibling->prev->next != node; sibling = sibling->prev);
1647 }
1648 sibling->prev = node;
1649 }
1650 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001651
Michal Vasko9f96a052020-03-10 09:41:45 +01001652 for (par = node->parent; par; par = par->parent) {
1653 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
1654 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +01001655 par->flags &= ~LYD_DEFAULT;
1656 }
Michal Vaskob104f112020-07-17 09:54:54 +02001657 if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001658 /* rehash key-less list */
1659 lyd_hash((struct lyd_node *)par);
1660 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001661 }
Michal Vasko90932a92020-02-12 14:33:03 +01001662}
1663
1664/**
1665 * @brief Insert node before a sibling.
1666 *
Michal Vasko9f96a052020-03-10 09:41:45 +01001667 * Handles inserting into NP containers and key-less lists.
1668 *
Michal Vasko90932a92020-02-12 14:33:03 +01001669 * @param[in] sibling Sibling to insert before.
1670 * @param[in] node Node to insert.
1671 */
1672static void
Michal Vaskof03ed032020-03-04 13:31:44 +01001673lyd_insert_before_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001674{
Michal Vasko0249f7c2020-03-05 16:36:40 +01001675 struct lyd_node_inner *par;
1676
Michal Vasko90932a92020-02-12 14:33:03 +01001677 assert(!node->next && (node->prev == node));
1678
1679 node->next = sibling;
1680 /* covers situation of sibling being first */
1681 node->prev = sibling->prev;
1682 sibling->prev = node;
1683 if (node->prev->next) {
1684 /* sibling had a preceding node */
1685 node->prev->next = node;
1686 } else if (sibling->parent) {
1687 /* sibling was first and we must also change parent child pointer */
1688 sibling->parent->child = node;
1689 }
1690 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001691
Michal Vasko9f96a052020-03-10 09:41:45 +01001692 for (par = node->parent; par; par = par->parent) {
1693 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
1694 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +01001695 par->flags &= ~LYD_DEFAULT;
1696 }
Michal Vaskob104f112020-07-17 09:54:54 +02001697 if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001698 /* rehash key-less list */
1699 lyd_hash((struct lyd_node *)par);
1700 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001701 }
Michal Vasko90932a92020-02-12 14:33:03 +01001702}
1703
1704/**
Michal Vaskob104f112020-07-17 09:54:54 +02001705 * @brief Insert node as the first and only child of a parent.
Michal Vasko90932a92020-02-12 14:33:03 +01001706 *
Michal Vasko9f96a052020-03-10 09:41:45 +01001707 * Handles inserting into NP containers and key-less lists.
1708 *
Michal Vasko90932a92020-02-12 14:33:03 +01001709 * @param[in] parent Parent to insert into.
1710 * @param[in] node Node to insert.
1711 */
1712static void
Michal Vaskob104f112020-07-17 09:54:54 +02001713lyd_insert_only_child(struct lyd_node *parent, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001714{
1715 struct lyd_node_inner *par;
1716
Michal Vaskob104f112020-07-17 09:54:54 +02001717 assert(parent && !lyd_node_children(parent, 0) && !node->next && (node->prev == node));
Michal Vasko52927e22020-03-16 17:26:14 +01001718 assert(!parent->schema || (parent->schema->nodetype & LYD_NODE_INNER));
Michal Vasko90932a92020-02-12 14:33:03 +01001719
1720 par = (struct lyd_node_inner *)parent;
1721
Michal Vaskob104f112020-07-17 09:54:54 +02001722 par->child = node;
Michal Vasko90932a92020-02-12 14:33:03 +01001723 node->parent = par;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001724
Michal Vasko9f96a052020-03-10 09:41:45 +01001725 for (; par; par = par->parent) {
1726 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
1727 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +01001728 par->flags &= ~LYD_DEFAULT;
1729 }
Michal Vasko52927e22020-03-16 17:26:14 +01001730 if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001731 /* rehash key-less list */
1732 lyd_hash((struct lyd_node *)par);
1733 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001734 }
Michal Vasko751cb4d2020-07-14 12:25:28 +02001735}
Michal Vasko0249f7c2020-03-05 16:36:40 +01001736
Michal Vasko751cb4d2020-07-14 12:25:28 +02001737/**
1738 * @brief Learn whether a list instance has all the keys.
1739 *
1740 * @param[in] list List instance to check.
1741 * @return non-zero if all the keys were found,
1742 * @return 0 otherwise.
1743 */
1744static int
1745lyd_insert_has_keys(const struct lyd_node *list)
1746{
1747 const struct lyd_node *key;
1748 const struct lysc_node *skey = NULL;
1749
1750 assert(list->schema->nodetype == LYS_LIST);
1751 key = lyd_node_children(list, 0);
1752 while ((skey = lys_getnext(skey, list->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
1753 if (!key || (key->schema != skey)) {
1754 /* key missing */
1755 return 0;
1756 }
1757
1758 key = key->next;
1759 }
1760
1761 /* all keys found */
1762 return 1;
Michal Vasko90932a92020-02-12 14:33:03 +01001763}
1764
1765void
Michal Vaskob104f112020-07-17 09:54:54 +02001766lyd_insert_node(struct lyd_node *parent, struct lyd_node **first_sibling_p, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001767{
Michal Vaskob104f112020-07-17 09:54:54 +02001768 struct lyd_node *anchor, *first_sibling;
Michal Vasko90932a92020-02-12 14:33:03 +01001769
Michal Vaskob104f112020-07-17 09:54:54 +02001770 /* inserting list without its keys is not supported */
1771 assert((parent || first_sibling_p) && node && (node->hash || !node->schema));
Michal Vasko9b368d32020-02-14 13:53:31 +01001772
Michal Vaskob104f112020-07-17 09:54:54 +02001773 if (!parent && first_sibling_p && (*first_sibling_p) && (*first_sibling_p)->parent) {
1774 parent = (struct lyd_node *)(*first_sibling_p)->parent;
Michal Vasko9b368d32020-02-14 13:53:31 +01001775 }
Michal Vasko90932a92020-02-12 14:33:03 +01001776
Michal Vaskob104f112020-07-17 09:54:54 +02001777 /* get first sibling */
1778 first_sibling = parent ? ((struct lyd_node_inner *)parent)->child : *first_sibling_p;
Michal Vasko9f96a052020-03-10 09:41:45 +01001779
Michal Vaskob104f112020-07-17 09:54:54 +02001780 /* find the anchor, our next node, so we can insert before it */
1781 anchor = lyd_insert_get_next_anchor(first_sibling, node);
1782 if (anchor) {
1783 lyd_insert_before_node(anchor, node);
1784 } else if (first_sibling) {
1785 lyd_insert_after_node(first_sibling->prev, node);
1786 } else if (parent) {
1787 lyd_insert_only_child(parent, node);
Michal Vasko90932a92020-02-12 14:33:03 +01001788 } else {
Michal Vaskob104f112020-07-17 09:54:54 +02001789 *first_sibling_p = node;
1790 }
1791
1792 /* insert into parent HT */
1793 lyd_insert_hash(node);
1794
1795 /* finish hashes for our parent, if needed and possible */
1796 if (node->schema && (node->schema->flags & LYS_KEY) && lyd_insert_has_keys(parent)) {
1797 lyd_hash(parent);
1798
1799 /* now we can insert even the list into its parent HT */
1800 lyd_insert_hash(parent);
Michal Vasko90932a92020-02-12 14:33:03 +01001801 }
Michal Vasko90932a92020-02-12 14:33:03 +01001802}
1803
Michal Vaskof03ed032020-03-04 13:31:44 +01001804static LY_ERR
1805lyd_insert_check_schema(const struct lysc_node *parent, const struct lysc_node *schema)
1806{
1807 const struct lysc_node *par2;
1808
1809 assert(schema);
Michal Vasko62ed12d2020-05-21 10:08:25 +02001810 assert(!parent || !(parent->nodetype & (LYS_CASE | LYS_CHOICE)));
Michal Vaskof03ed032020-03-04 13:31:44 +01001811
1812 /* find schema parent */
Michal Vasko62ed12d2020-05-21 10:08:25 +02001813 par2 = lysc_data_parent(schema);
Michal Vaskof03ed032020-03-04 13:31:44 +01001814
1815 if (parent) {
1816 /* inner node */
1817 if (par2 != parent) {
Michal Vaskob104f112020-07-17 09:54:54 +02001818 LOGERR(schema->module->ctx, LY_EINVAL, "Cannot insert, parent of \"%s\" is not \"%s\".", schema->name,
1819 parent->name);
Michal Vaskof03ed032020-03-04 13:31:44 +01001820 return LY_EINVAL;
1821 }
1822 } else {
1823 /* top-level node */
1824 if (par2) {
Radek Krejcif6d14cb2020-07-02 16:11:45 +02001825 LOGERR(schema->module->ctx, LY_EINVAL, "Cannot insert, node \"%s\" is not top-level.", schema->name);
Michal Vaskof03ed032020-03-04 13:31:44 +01001826 return LY_EINVAL;
1827 }
1828 }
1829
1830 return LY_SUCCESS;
1831}
1832
1833API LY_ERR
Michal Vaskob104f112020-07-17 09:54:54 +02001834lyd_insert_child(struct lyd_node *parent, struct lyd_node *node)
Michal Vaskof03ed032020-03-04 13:31:44 +01001835{
1836 struct lyd_node *iter;
1837
Michal Vasko654bc852020-06-23 13:28:06 +02001838 LY_CHECK_ARG_RET(NULL, parent, node, parent->schema->nodetype & LYD_NODE_INNER, LY_EINVAL);
Michal Vaskof03ed032020-03-04 13:31:44 +01001839
1840 LY_CHECK_RET(lyd_insert_check_schema(parent->schema, node->schema));
1841
1842 if (node->schema->flags & LYS_KEY) {
1843 LOGERR(parent->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1844 return LY_EINVAL;
1845 }
1846
1847 if (node->parent || node->prev->next) {
1848 lyd_unlink_tree(node);
1849 }
1850
1851 while (node) {
1852 iter = node->next;
1853 lyd_unlink_tree(node);
1854 lyd_insert_node(parent, NULL, node);
1855 node = iter;
1856 }
1857 return LY_SUCCESS;
1858}
1859
1860API LY_ERR
Michal Vaskob104f112020-07-17 09:54:54 +02001861lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, struct lyd_node **first)
Michal Vaskob1b5c262020-03-05 14:29:47 +01001862{
1863 struct lyd_node *iter;
1864
Michal Vaskob104f112020-07-17 09:54:54 +02001865 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Michal Vaskob1b5c262020-03-05 14:29:47 +01001866
Michal Vaskob104f112020-07-17 09:54:54 +02001867 if (sibling) {
1868 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskob1b5c262020-03-05 14:29:47 +01001869 }
1870
1871 if (node->parent || node->prev->next) {
1872 lyd_unlink_tree(node);
1873 }
1874
1875 while (node) {
Michal Vaskob104f112020-07-17 09:54:54 +02001876 if (node->schema->flags & LYS_KEY) {
1877 LOGERR(LYD_NODE_CTX(node), LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1878 return LY_EINVAL;
1879 }
1880
Michal Vaskob1b5c262020-03-05 14:29:47 +01001881 iter = node->next;
1882 lyd_unlink_tree(node);
1883 lyd_insert_node(NULL, &sibling, node);
1884 node = iter;
1885 }
Michal Vaskob1b5c262020-03-05 14:29:47 +01001886
Michal Vaskob104f112020-07-17 09:54:54 +02001887 if (first) {
1888 /* find the first sibling */
1889 *first = sibling;
1890 while ((*first)->prev->next) {
1891 *first = (*first)->prev;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001892 }
1893 }
1894
1895 return LY_SUCCESS;
1896}
1897
Michal Vaskob1b5c262020-03-05 14:29:47 +01001898API LY_ERR
Michal Vaskof03ed032020-03-04 13:31:44 +01001899lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
1900{
1901 struct lyd_node *iter;
1902
1903 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1904
Michal Vasko62ed12d2020-05-21 10:08:25 +02001905 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskof03ed032020-03-04 13:31:44 +01001906
Michal Vaskob104f112020-07-17 09:54:54 +02001907 if (!(node->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(node->schema->flags & LYS_ORDBY_USER)) {
1908 LOGERR(LYD_NODE_CTX(sibling), LY_EINVAL, "Can be used only for user-ordered nodes.");
Michal Vaskof03ed032020-03-04 13:31:44 +01001909 return LY_EINVAL;
1910 }
1911
1912 if (node->parent || node->prev->next) {
1913 lyd_unlink_tree(node);
1914 }
1915
1916 /* insert in reverse order to get the original order */
1917 node = node->prev;
1918 while (node) {
1919 iter = node->prev;
1920 lyd_unlink_tree(node);
1921
1922 lyd_insert_before_node(sibling, node);
Michal Vasko751cb4d2020-07-14 12:25:28 +02001923 lyd_insert_hash(node);
1924
Michal Vaskof03ed032020-03-04 13:31:44 +01001925 /* move the anchor accordingly */
1926 sibling = node;
1927
1928 node = (iter == node) ? NULL : iter;
1929 }
1930 return LY_SUCCESS;
1931}
1932
1933API LY_ERR
1934lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
1935{
1936 struct lyd_node *iter;
1937
1938 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1939
Michal Vasko62ed12d2020-05-21 10:08:25 +02001940 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskof03ed032020-03-04 13:31:44 +01001941
Michal Vaskob104f112020-07-17 09:54:54 +02001942 if (!(node->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(node->schema->flags & LYS_ORDBY_USER)) {
1943 LOGERR(LYD_NODE_CTX(sibling), LY_EINVAL, "Can be used only for user-ordered nodes.");
Michal Vaskof03ed032020-03-04 13:31:44 +01001944 return LY_EINVAL;
1945 }
1946
1947 if (node->parent || node->prev->next) {
1948 lyd_unlink_tree(node);
1949 }
1950
1951 while (node) {
1952 iter = node->next;
1953 lyd_unlink_tree(node);
1954
1955 lyd_insert_after_node(sibling, node);
Michal Vasko751cb4d2020-07-14 12:25:28 +02001956 lyd_insert_hash(node);
1957
Michal Vaskof03ed032020-03-04 13:31:44 +01001958 /* move the anchor accordingly */
1959 sibling = node;
1960
1961 node = iter;
1962 }
1963 return LY_SUCCESS;
1964}
1965
1966API void
1967lyd_unlink_tree(struct lyd_node *node)
1968{
1969 struct lyd_node *iter;
1970
1971 if (!node) {
1972 return;
1973 }
1974
Michal Vaskob104f112020-07-17 09:54:54 +02001975 /* update hashes while still linked into the tree */
1976 lyd_unlink_hash(node);
1977
Michal Vaskof03ed032020-03-04 13:31:44 +01001978 /* unlink from siblings */
1979 if (node->prev->next) {
1980 node->prev->next = node->next;
1981 }
1982 if (node->next) {
1983 node->next->prev = node->prev;
1984 } else {
1985 /* unlinking the last node */
1986 if (node->parent) {
1987 iter = node->parent->child;
1988 } else {
1989 iter = node->prev;
1990 while (iter->prev != node) {
1991 iter = iter->prev;
1992 }
1993 }
1994 /* update the "last" pointer from the first node */
1995 iter->prev = node->prev;
1996 }
1997
1998 /* unlink from parent */
1999 if (node->parent) {
2000 if (node->parent->child == node) {
2001 /* the node is the first child */
2002 node->parent->child = node->next;
2003 }
2004
Michal Vaskoab49dbe2020-07-17 12:32:47 +02002005 /* check for NP container whether its last non-default node is not being unlinked */
2006 if (node->parent->schema && (node->parent->schema->nodetype == LYS_CONTAINER)
2007 && !(node->parent->flags & LYD_DEFAULT) && !(node->parent->schema->flags & LYS_PRESENCE)) {
2008 LY_LIST_FOR(node->parent->child, iter) {
2009 if ((iter != node) && !(iter->flags & LYD_DEFAULT)) {
2010 break;
2011 }
2012 }
2013 if (!iter) {
2014 node->parent->flags |= LYD_DEFAULT;
2015 }
2016 }
2017
Michal Vaskof03ed032020-03-04 13:31:44 +01002018 /* check for keyless list and update its hash */
2019 for (iter = (struct lyd_node *)node->parent; iter; iter = (struct lyd_node *)iter->parent) {
Michal Vasko413c7f22020-05-05 12:34:06 +02002020 if (iter->schema && (iter->schema->flags & LYS_KEYLESS)) {
Michal Vaskof03ed032020-03-04 13:31:44 +01002021 lyd_hash(iter);
2022 }
2023 }
2024
2025 node->parent = NULL;
2026 }
2027
2028 node->next = NULL;
2029 node->prev = node;
2030}
2031
Michal Vasko90932a92020-02-12 14:33:03 +01002032LY_ERR
Michal Vasko9f96a052020-03-10 09:41:45 +01002033lyd_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 +01002034 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 +01002035 void *prefix_data, LYD_FORMAT format, const struct lysc_node *ctx_snode)
Michal Vasko90932a92020-02-12 14:33:03 +01002036{
2037 LY_ERR ret;
2038 struct lysc_ext_instance *ant = NULL;
Michal Vasko9f96a052020-03-10 09:41:45 +01002039 struct lyd_meta *mt, *last;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002040 LY_ARRAY_COUNT_TYPE u;
Michal Vasko90932a92020-02-12 14:33:03 +01002041
Michal Vasko9f96a052020-03-10 09:41:45 +01002042 assert((parent || meta) && mod);
Michal Vasko6f4cbb62020-02-28 11:15:47 +01002043
Radek Krejci7eb54ba2020-05-18 16:30:04 +02002044 LY_ARRAY_FOR(mod->compiled->exts, u) {
2045 if (mod->compiled->exts[u].def->plugin == lyext_plugins_internal[LYEXT_PLUGIN_INTERNAL_ANNOTATION].plugin &&
2046 !ly_strncmp(mod->compiled->exts[u].argument, name, name_len)) {
Michal Vasko90932a92020-02-12 14:33:03 +01002047 /* we have the annotation definition */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02002048 ant = &mod->compiled->exts[u];
Michal Vasko90932a92020-02-12 14:33:03 +01002049 break;
2050 }
2051 }
2052 if (!ant) {
2053 /* attribute is not defined as a metadata annotation (RFC 7952) */
2054 LOGERR(mod->ctx, LY_EINVAL, "Annotation definition for attribute \"%s:%.*s\" not found.",
2055 mod->name, name_len, name);
2056 return LY_EINVAL;
2057 }
2058
Michal Vasko9f96a052020-03-10 09:41:45 +01002059 mt = calloc(1, sizeof *mt);
2060 LY_CHECK_ERR_RET(!mt, LOGMEM(mod->ctx), LY_EMEM);
2061 mt->parent = parent;
2062 mt->annotation = ant;
Michal Vasko52927e22020-03-16 17:26:14 +01002063 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 +01002064 if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01002065 free(mt);
Michal Vasko90932a92020-02-12 14:33:03 +01002066 return ret;
2067 }
Michal Vasko9f96a052020-03-10 09:41:45 +01002068 mt->name = lydict_insert(mod->ctx, name, name_len);
Michal Vasko90932a92020-02-12 14:33:03 +01002069
Michal Vasko6f4cbb62020-02-28 11:15:47 +01002070 /* insert as the last attribute */
2071 if (parent) {
Michal Vasko9f96a052020-03-10 09:41:45 +01002072 if (parent->meta) {
2073 for (last = parent->meta; last->next; last = last->next);
2074 last->next = mt;
Michal Vasko6f4cbb62020-02-28 11:15:47 +01002075 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +01002076 parent->meta = mt;
Michal Vasko6f4cbb62020-02-28 11:15:47 +01002077 }
Michal Vasko9f96a052020-03-10 09:41:45 +01002078 } else if (*meta) {
2079 for (last = *meta; last->next; last = last->next);
2080 last->next = mt;
Michal Vasko90932a92020-02-12 14:33:03 +01002081 }
2082
2083 /* remove default flags from NP containers */
Michal Vasko4ba6aef2020-07-09 15:44:23 +02002084 while (parent && (parent->schema->nodetype == LYS_CONTAINER) && (parent->flags & LYD_DEFAULT)) {
Michal Vasko90932a92020-02-12 14:33:03 +01002085 parent->flags &= ~LYD_DEFAULT;
2086 parent = (struct lyd_node *)parent->parent;
2087 }
2088
Michal Vasko9f96a052020-03-10 09:41:45 +01002089 if (meta) {
2090 *meta = mt;
Michal Vasko90932a92020-02-12 14:33:03 +01002091 }
2092 return ret;
2093}
2094
Michal Vasko52927e22020-03-16 17:26:14 +01002095LY_ERR
2096ly_create_attr(struct lyd_node *parent, struct ly_attr **attr, const struct ly_ctx *ctx, const char *name,
2097 size_t name_len, const char *value, size_t value_len, int *dynamic, LYD_FORMAT format,
2098 struct ly_prefix *val_prefs, const char *prefix, size_t prefix_len, const char *ns)
2099{
2100 struct ly_attr *at, *last;
2101 struct lyd_node_opaq *opaq;
2102
2103 assert(ctx && (parent || attr) && (!parent || !parent->schema));
2104 assert(name && name_len);
2105 assert((prefix_len && ns) || (!prefix_len && !ns));
2106
2107 if (!value_len) {
2108 value = "";
2109 }
2110
2111 at = calloc(1, sizeof *at);
2112 LY_CHECK_ERR_RET(!at, LOGMEM(ctx), LY_EMEM);
2113 at->parent = (struct lyd_node_opaq *)parent;
2114 at->name = lydict_insert(ctx, name, name_len);
2115 if (dynamic && *dynamic) {
2116 at->value = lydict_insert_zc(ctx, (char *)value);
2117 *dynamic = 0;
2118 } else {
2119 at->value = lydict_insert(ctx, value, value_len);
2120 }
2121
2122 at->format = format;
2123 at->val_prefs = val_prefs;
2124 if (ns) {
2125 at->prefix.pref = lydict_insert(ctx, prefix, prefix_len);
2126 at->prefix.ns = lydict_insert(ctx, ns, 0);
2127 }
2128
2129 /* insert as the last attribute */
2130 if (parent) {
2131 opaq = (struct lyd_node_opaq *)parent;
2132 if (opaq->attr) {
2133 for (last = opaq->attr; last->next; last = last->next);
2134 last->next = at;
2135 } else {
2136 opaq->attr = at;
2137 }
2138 } else if (*attr) {
2139 for (last = *attr; last->next; last = last->next);
2140 last->next = at;
2141 }
2142
2143 if (attr) {
2144 *attr = at;
2145 }
2146 return LY_SUCCESS;
2147}
2148
Radek Krejci084289f2019-07-09 17:35:30 +02002149API const struct lyd_node_term *
Michal Vasko004d3152020-06-11 19:59:22 +02002150lyd_target(const struct ly_path *path, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +02002151{
Michal Vasko004d3152020-06-11 19:59:22 +02002152 struct lyd_node *target;
Radek Krejci084289f2019-07-09 17:35:30 +02002153
Michal Vasko004d3152020-06-11 19:59:22 +02002154 if (ly_path_eval(path, tree, &target)) {
2155 return NULL;
Radek Krejci084289f2019-07-09 17:35:30 +02002156 }
2157
Michal Vasko004d3152020-06-11 19:59:22 +02002158 return (struct lyd_node_term *)target;
Radek Krejci084289f2019-07-09 17:35:30 +02002159}
2160
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002161API LY_ERR
Michal Vasko8f359bf2020-07-28 10:41:15 +02002162lyd_compare_single(const struct lyd_node *node1, const struct lyd_node *node2, int options)
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002163{
2164 const struct lyd_node *iter1, *iter2;
2165 struct lyd_node_term *term1, *term2;
2166 struct lyd_node_any *any1, *any2;
Michal Vasko52927e22020-03-16 17:26:14 +01002167 struct lyd_node_opaq *opaq1, *opaq2;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002168 size_t len1, len2;
Radek Krejci084289f2019-07-09 17:35:30 +02002169
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002170 if (!node1 || !node2) {
2171 if (node1 == node2) {
2172 return LY_SUCCESS;
2173 } else {
2174 return LY_ENOT;
2175 }
2176 }
2177
Michal Vasko52927e22020-03-16 17:26:14 +01002178 if ((LYD_NODE_CTX(node1) != LYD_NODE_CTX(node2)) || (node1->schema != node2->schema)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002179 return LY_ENOT;
2180 }
2181
2182 if (node1->hash != node2->hash) {
2183 return LY_ENOT;
2184 }
Michal Vasko52927e22020-03-16 17:26:14 +01002185 /* 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 +02002186
Michal Vasko52927e22020-03-16 17:26:14 +01002187 if (!node1->schema) {
2188 opaq1 = (struct lyd_node_opaq *)node1;
2189 opaq2 = (struct lyd_node_opaq *)node2;
2190 if ((opaq1->name != opaq2->name) || (opaq1->prefix.ns != opaq2->prefix.ns) || (opaq1->format != opaq2->format)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002191 return LY_ENOT;
2192 }
Michal Vasko52927e22020-03-16 17:26:14 +01002193 switch (opaq1->format) {
2194 case LYD_XML:
2195 if (lyxml_value_compare(opaq1->value, opaq1->val_prefs, opaq2->value, opaq2->val_prefs)) {
2196 return LY_ENOT;
2197 }
2198 break;
2199 case LYD_SCHEMA:
Michal Vasko60ea6352020-06-29 13:39:39 +02002200 case LYD_LYB:
Michal Vasko52927e22020-03-16 17:26:14 +01002201 /* not allowed */
2202 LOGINT(LYD_NODE_CTX(node1));
2203 return LY_EINT;
2204 }
2205 if (options & LYD_COMPARE_FULL_RECURSION) {
2206 iter1 = opaq1->child;
2207 iter2 = opaq2->child;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002208 goto all_children_compare;
Michal Vasko52927e22020-03-16 17:26:14 +01002209 }
2210 return LY_SUCCESS;
2211 } else {
2212 switch (node1->schema->nodetype) {
2213 case LYS_LEAF:
2214 case LYS_LEAFLIST:
2215 if (options & LYD_COMPARE_DEFAULTS) {
2216 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
2217 return LY_ENOT;
2218 }
2219 }
2220
Michal Vasko1a2bf2e2020-06-16 13:07:48 +02002221 term1 = (struct lyd_node_term *)node1;
2222 term2 = (struct lyd_node_term *)node2;
2223 if (term1->value.realtype != term2->value.realtype) {
2224 return LY_ENOT;
2225 }
Michal Vasko52927e22020-03-16 17:26:14 +01002226
Michal Vasko1a2bf2e2020-06-16 13:07:48 +02002227 return term1->value.realtype->plugin->compare(&term1->value, &term2->value);
Michal Vasko52927e22020-03-16 17:26:14 +01002228 case LYS_CONTAINER:
2229 if (options & LYD_COMPARE_DEFAULTS) {
2230 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
2231 return LY_ENOT;
2232 }
2233 }
2234 if (options & LYD_COMPARE_FULL_RECURSION) {
2235 iter1 = ((struct lyd_node_inner*)node1)->child;
2236 iter2 = ((struct lyd_node_inner*)node2)->child;
2237 goto all_children_compare;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002238 }
2239 return LY_SUCCESS;
Michal Vasko1bf09392020-03-27 12:38:10 +01002240 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01002241 case LYS_ACTION:
2242 if (options & LYD_COMPARE_FULL_RECURSION) {
2243 /* TODO action/RPC
2244 goto all_children_compare;
2245 */
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002246 }
2247 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01002248 case LYS_NOTIF:
2249 if (options & LYD_COMPARE_FULL_RECURSION) {
2250 /* TODO Notification
2251 goto all_children_compare;
2252 */
2253 }
2254 return LY_SUCCESS;
2255 case LYS_LIST:
2256 iter1 = ((struct lyd_node_inner*)node1)->child;
2257 iter2 = ((struct lyd_node_inner*)node2)->child;
2258
2259 if (!(node1->schema->flags & LYS_KEYLESS) && !(options & LYD_COMPARE_FULL_RECURSION)) {
2260 /* lists with keys, their equivalence is based on their keys */
2261 for (struct lysc_node *key = ((struct lysc_node_list*)node1->schema)->child;
Michal Vaskoc57d9a92020-06-23 13:28:27 +02002262 key && (key->flags & LYS_KEY);
Michal Vasko52927e22020-03-16 17:26:14 +01002263 key = key->next) {
Michal Vasko8f359bf2020-07-28 10:41:15 +02002264 if (lyd_compare_single(iter1, iter2, options)) {
Michal Vasko52927e22020-03-16 17:26:14 +01002265 return LY_ENOT;
2266 }
2267 iter1 = iter1->next;
2268 iter2 = iter2->next;
2269 }
2270 } else {
2271 /* lists without keys, their equivalence is based on equivalence of all the children (both direct and indirect) */
2272
2273 all_children_compare:
2274 if (!iter1 && !iter2) {
2275 /* no children, nothing to compare */
2276 return LY_SUCCESS;
2277 }
2278
2279 for (; iter1 && iter2; iter1 = iter1->next, iter2 = iter2->next) {
Michal Vasko8f359bf2020-07-28 10:41:15 +02002280 if (lyd_compare_single(iter1, iter2, options | LYD_COMPARE_FULL_RECURSION)) {
Michal Vasko52927e22020-03-16 17:26:14 +01002281 return LY_ENOT;
2282 }
2283 }
2284 if (iter1 || iter2) {
2285 return LY_ENOT;
2286 }
2287 }
2288 return LY_SUCCESS;
2289 case LYS_ANYXML:
2290 case LYS_ANYDATA:
2291 any1 = (struct lyd_node_any*)node1;
2292 any2 = (struct lyd_node_any*)node2;
2293
2294 if (any1->value_type != any2->value_type) {
2295 return LY_ENOT;
2296 }
2297 switch (any1->value_type) {
2298 case LYD_ANYDATA_DATATREE:
2299 iter1 = any1->value.tree;
2300 iter2 = any2->value.tree;
2301 goto all_children_compare;
2302 case LYD_ANYDATA_STRING:
2303 case LYD_ANYDATA_XML:
2304 case LYD_ANYDATA_JSON:
2305 len1 = strlen(any1->value.str);
2306 len2 = strlen(any2->value.str);
2307 if (len1 != len2 || strcmp(any1->value.str, any2->value.str)) {
2308 return LY_ENOT;
2309 }
2310 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01002311 case LYD_ANYDATA_LYB:
Michal Vasko60ea6352020-06-29 13:39:39 +02002312 len1 = lyd_lyb_data_length(any1->value.mem);
2313 len2 = lyd_lyb_data_length(any2->value.mem);
Michal Vasko52927e22020-03-16 17:26:14 +01002314 if (len1 != len2 || memcmp(any1->value.mem, any2->value.mem, len1)) {
2315 return LY_ENOT;
2316 }
2317 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01002318 }
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002319 }
2320 }
2321
Michal Vasko52927e22020-03-16 17:26:14 +01002322 LOGINT(LYD_NODE_CTX(node1));
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002323 return LY_EINT;
2324}
Radek Krejci22ebdba2019-07-25 13:59:43 +02002325
Michal Vasko21725742020-06-29 11:49:25 +02002326API LY_ERR
Michal Vasko8f359bf2020-07-28 10:41:15 +02002327lyd_compare_siblings(const struct lyd_node *node1, const struct lyd_node *node2, int options)
2328{
2329 for (; node1 && node2; node1 = node1->next, node2 = node2->next) {
2330 LY_CHECK_RET(lyd_compare_single(node1, node2, options));
2331 }
2332
Michal Vasko11a81432020-07-28 16:31:29 +02002333 if (node1 == node2) {
2334 return LY_SUCCESS;
Michal Vasko8f359bf2020-07-28 10:41:15 +02002335 }
Michal Vasko11a81432020-07-28 16:31:29 +02002336 return LY_ENOT;
Michal Vasko8f359bf2020-07-28 10:41:15 +02002337}
2338
2339API LY_ERR
Michal Vasko21725742020-06-29 11:49:25 +02002340lyd_compare_meta(const struct lyd_meta *meta1, const struct lyd_meta *meta2)
2341{
2342 if (!meta1 || !meta2) {
2343 if (meta1 == meta2) {
2344 return LY_SUCCESS;
2345 } else {
2346 return LY_ENOT;
2347 }
2348 }
2349
2350 if ((LYD_NODE_CTX(meta1->parent) != LYD_NODE_CTX(meta2->parent)) || (meta1->annotation != meta2->annotation)) {
2351 return LY_ENOT;
2352 }
2353
2354 if (meta1->value.realtype != meta2->value.realtype) {
2355 return LY_ENOT;
2356 }
2357
2358 return meta1->value.realtype->plugin->compare(&meta1->value, &meta2->value);
2359}
2360
Radek Krejci22ebdba2019-07-25 13:59:43 +02002361/**
Michal Vasko52927e22020-03-16 17:26:14 +01002362 * @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 +02002363 *
2364 * 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 +02002365 *
2366 * @param[in] node Original node to duplicate
2367 * @param[in] parent Parent to insert into, NULL for top-level sibling.
2368 * @param[in,out] first First sibling, NULL if no top-level sibling exist yet. Can be also NULL if @p parent is set.
2369 * @param[in] options Bitmask of options flags, see @ref dupoptions.
2370 * @param[out] dup_p Pointer where the created duplicated node is placed (besides connecting it int @p parent / @p first sibling).
2371 * @return LY_ERR value
Radek Krejci22ebdba2019-07-25 13:59:43 +02002372 */
Michal Vasko52927e22020-03-16 17:26:14 +01002373static LY_ERR
Michal Vasko3a41dff2020-07-15 14:30:28 +02002374lyd_dup_r(const struct lyd_node *node, struct lyd_node *parent, struct lyd_node **first, int options,
2375 struct lyd_node **dup_p)
Radek Krejci22ebdba2019-07-25 13:59:43 +02002376{
Michal Vasko52927e22020-03-16 17:26:14 +01002377 LY_ERR ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002378 struct lyd_node *dup = NULL;
Michal Vasko61551fa2020-07-09 15:45:45 +02002379 struct lyd_meta *meta;
2380 struct lyd_node_any *any;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002381 LY_ARRAY_COUNT_TYPE u;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002382
Michal Vasko52927e22020-03-16 17:26:14 +01002383 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002384
Michal Vasko52927e22020-03-16 17:26:14 +01002385 if (!node->schema) {
2386 dup = calloc(1, sizeof(struct lyd_node_opaq));
2387 } else {
2388 switch (node->schema->nodetype) {
Michal Vasko1bf09392020-03-27 12:38:10 +01002389 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01002390 case LYS_ACTION:
2391 case LYS_NOTIF:
2392 case LYS_CONTAINER:
2393 case LYS_LIST:
2394 dup = calloc(1, sizeof(struct lyd_node_inner));
2395 break;
2396 case LYS_LEAF:
2397 case LYS_LEAFLIST:
2398 dup = calloc(1, sizeof(struct lyd_node_term));
2399 break;
2400 case LYS_ANYDATA:
2401 case LYS_ANYXML:
2402 dup = calloc(1, sizeof(struct lyd_node_any));
2403 break;
2404 default:
2405 LOGINT(LYD_NODE_CTX(node));
2406 ret = LY_EINT;
2407 goto error;
2408 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02002409 }
Michal Vasko52927e22020-03-16 17:26:14 +01002410 LY_CHECK_ERR_GOTO(!dup, LOGMEM(LYD_NODE_CTX(node)); ret = LY_EMEM, error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002411
Michal Vaskof6df0a02020-06-16 13:08:34 +02002412 if (options & LYD_DUP_WITH_FLAGS) {
2413 dup->flags = node->flags;
2414 } else {
2415 dup->flags = (node->flags & LYD_DEFAULT) | LYD_NEW;
2416 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02002417 dup->schema = node->schema;
Michal Vasko52927e22020-03-16 17:26:14 +01002418 dup->prev = dup;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002419
Michal Vasko25a32822020-07-09 15:48:22 +02002420 /* duplicate metadata */
2421 if (!(options & LYD_DUP_NO_META)) {
2422 LY_LIST_FOR(node->meta, meta) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002423 LY_CHECK_GOTO(ret = lyd_dup_meta_single(meta, dup, NULL), error);
Michal Vasko25a32822020-07-09 15:48:22 +02002424 }
2425 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02002426
2427 /* nodetype-specific work */
Michal Vasko52927e22020-03-16 17:26:14 +01002428 if (!dup->schema) {
2429 struct lyd_node_opaq *opaq = (struct lyd_node_opaq *)dup;
2430 struct lyd_node_opaq *orig = (struct lyd_node_opaq *)node;
2431 struct lyd_node *child;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002432
2433 if (options & LYD_DUP_RECURSIVE) {
2434 /* duplicate all the children */
2435 LY_LIST_FOR(orig->child, child) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002436 LY_CHECK_GOTO(ret = lyd_dup_r(child, dup, NULL, options, NULL), error);
Michal Vasko52927e22020-03-16 17:26:14 +01002437 }
2438 }
2439 opaq->name = lydict_insert(LYD_NODE_CTX(node), orig->name, 0);
2440 opaq->format = orig->format;
2441 if (orig->prefix.pref) {
2442 opaq->prefix.pref = lydict_insert(LYD_NODE_CTX(node), orig->prefix.pref, 0);
2443 }
2444 if (orig->prefix.ns) {
2445 opaq->prefix.ns = lydict_insert(LYD_NODE_CTX(node), orig->prefix.ns, 0);
2446 }
2447 if (orig->val_prefs) {
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002448 LY_ARRAY_CREATE_GOTO(LYD_NODE_CTX(node), opaq->val_prefs, LY_ARRAY_COUNT(orig->val_prefs), ret, error);
Michal Vasko52927e22020-03-16 17:26:14 +01002449 LY_ARRAY_FOR(orig->val_prefs, u) {
2450 opaq->val_prefs[u].pref = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].pref, 0);
2451 opaq->val_prefs[u].ns = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].ns, 0);
2452 LY_ARRAY_INCREMENT(opaq->val_prefs);
2453 }
2454 }
2455 opaq->value = lydict_insert(LYD_NODE_CTX(node), orig->value, 0);
2456 opaq->ctx = orig->ctx;
2457 } else if (dup->schema->nodetype & LYD_NODE_TERM) {
2458 struct lyd_node_term *term = (struct lyd_node_term *)dup;
2459 struct lyd_node_term *orig = (struct lyd_node_term *)node;
2460
2461 term->hash = orig->hash;
2462 term->value.realtype = orig->value.realtype;
2463 LY_CHECK_ERR_GOTO(term->value.realtype->plugin->duplicate(LYD_NODE_CTX(node), &orig->value, &term->value),
2464 LOGERR(LYD_NODE_CTX(node), LY_EINT, "Value duplication failed."); ret = LY_EINT, error);
2465 } else if (dup->schema->nodetype & LYD_NODE_INNER) {
2466 struct lyd_node_inner *orig = (struct lyd_node_inner *)node;
2467 struct lyd_node *child;
2468
2469 if (options & LYD_DUP_RECURSIVE) {
2470 /* duplicate all the children */
2471 LY_LIST_FOR(orig->child, child) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002472 LY_CHECK_GOTO(ret = lyd_dup_r(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002473 }
Radek Krejci0fe9b512019-07-26 17:51:05 +02002474 } else if (dup->schema->nodetype == LYS_LIST && !(dup->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002475 /* always duplicate keys of a list */
Radek Krejci22ebdba2019-07-25 13:59:43 +02002476 child = orig->child;
Michal Vasko52927e22020-03-16 17:26:14 +01002477 for (struct lysc_node *key = ((struct lysc_node_list *)dup->schema)->child;
Michal Vaskoc57d9a92020-06-23 13:28:27 +02002478 key && (key->flags & LYS_KEY);
Radek Krejci0fe9b512019-07-26 17:51:05 +02002479 key = key->next) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002480 if (!child) {
2481 /* possibly not keys are present in filtered tree */
2482 break;
Radek Krejci0fe9b512019-07-26 17:51:05 +02002483 } else if (child->schema != key) {
2484 /* possibly not all keys are present in filtered tree,
2485 * but there can be also some non-key nodes */
2486 continue;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002487 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002488 LY_CHECK_GOTO(ret = lyd_dup_r(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002489 child = child->next;
2490 }
2491 }
2492 lyd_hash(dup);
2493 } else if (dup->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko61551fa2020-07-09 15:45:45 +02002494 dup->hash = node->hash;
2495 any = (struct lyd_node_any *)node;
2496 LY_CHECK_GOTO(ret = lyd_any_copy_value(dup, &any->value, any->value_type), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002497 }
2498
Michal Vasko52927e22020-03-16 17:26:14 +01002499 /* insert */
2500 lyd_insert_node(parent, first, dup);
Michal Vasko52927e22020-03-16 17:26:14 +01002501
2502 if (dup_p) {
2503 *dup_p = dup;
2504 }
2505 return LY_SUCCESS;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002506
2507error:
Michal Vasko52927e22020-03-16 17:26:14 +01002508 lyd_free_tree(dup);
2509 return ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002510}
2511
Michal Vasko3a41dff2020-07-15 14:30:28 +02002512static LY_ERR
2513lyd_dup_get_local_parent(const struct lyd_node *node, const struct lyd_node_inner *parent, struct lyd_node **dup_parent,
2514 struct lyd_node_inner **local_parent)
Radek Krejci22ebdba2019-07-25 13:59:43 +02002515{
Michal Vasko3a41dff2020-07-15 14:30:28 +02002516 const struct lyd_node_inner *orig_parent, *iter;
2517 int repeat = 1;
2518
2519 *dup_parent = NULL;
2520 *local_parent = NULL;
2521
2522 for (orig_parent = node->parent; repeat && orig_parent; orig_parent = orig_parent->parent) {
2523 if (parent && (parent->schema == orig_parent->schema)) {
2524 /* stop creating parents, connect what we have into the provided parent */
2525 iter = parent;
2526 repeat = 0;
2527 } else {
2528 iter = NULL;
2529 LY_CHECK_RET(lyd_dup_r((struct lyd_node *)orig_parent, NULL, (struct lyd_node **)&iter, 0,
2530 (struct lyd_node **)&iter));
2531 }
2532 if (!*local_parent) {
2533 *local_parent = (struct lyd_node_inner *)iter;
2534 }
2535 if (iter->child) {
2536 /* 1) list - add after keys
2537 * 2) provided parent with some children */
2538 iter->child->prev->next = *dup_parent;
2539 if (*dup_parent) {
2540 (*dup_parent)->prev = iter->child->prev;
2541 iter->child->prev = *dup_parent;
2542 }
2543 } else {
2544 ((struct lyd_node_inner *)iter)->child = *dup_parent;
2545 }
2546 if (*dup_parent) {
2547 (*dup_parent)->parent = (struct lyd_node_inner *)iter;
2548 }
2549 *dup_parent = (struct lyd_node *)iter;
2550 }
2551
2552 if (repeat && parent) {
2553 /* given parent and created parents chain actually do not interconnect */
2554 LOGERR(LYD_NODE_CTX(node), LY_EINVAL,
2555 "Invalid argument parent (%s()) - does not interconnect with the created node's parents chain.", __func__);
2556 return LY_EINVAL;
2557 }
2558
2559 return LY_SUCCESS;
2560}
2561
2562static LY_ERR
2563lyd_dup(const struct lyd_node *node, struct lyd_node_inner *parent, int options, int nosiblings, struct lyd_node **dup)
2564{
2565 LY_ERR rc;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002566 const struct lyd_node *orig; /* original node to be duplicated */
2567 struct lyd_node *first = NULL; /* the first duplicated node, this is returned */
Radek Krejci22ebdba2019-07-25 13:59:43 +02002568 struct lyd_node *top = NULL; /* the most higher created node */
2569 struct lyd_node_inner *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
Radek Krejci22ebdba2019-07-25 13:59:43 +02002570
Michal Vasko3a41dff2020-07-15 14:30:28 +02002571 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002572
2573 if (options & LYD_DUP_WITH_PARENTS) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002574 LY_CHECK_GOTO(rc = lyd_dup_get_local_parent(node, parent, &top, &local_parent), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002575 } else {
2576 local_parent = parent;
2577 }
2578
Radek Krejci22ebdba2019-07-25 13:59:43 +02002579 LY_LIST_FOR(node, orig) {
Michal Vasko52927e22020-03-16 17:26:14 +01002580 /* if there is no local parent, it will be inserted into first */
Michal Vasko3a41dff2020-07-15 14:30:28 +02002581 LY_CHECK_GOTO(rc = lyd_dup_r(orig, (struct lyd_node *)local_parent, &first, options, first ? NULL : &first), error);
2582 if (nosiblings) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002583 break;
2584 }
2585 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002586
2587 /* rehash if needed */
2588 for (; local_parent; local_parent = local_parent->parent) {
2589 if (local_parent->schema->nodetype == LYS_LIST && (local_parent->schema->flags & LYS_KEYLESS)) {
2590 lyd_hash((struct lyd_node *)local_parent);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002591 }
2592 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002593
2594 if (dup) {
2595 *dup = first;
2596 }
2597 return LY_SUCCESS;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002598
2599error:
2600 if (top) {
2601 lyd_free_tree(top);
2602 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +01002603 lyd_free_siblings(first);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002604 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002605 return rc;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002606}
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002607
Michal Vasko3a41dff2020-07-15 14:30:28 +02002608API LY_ERR
2609lyd_dup_single(const struct lyd_node *node, struct lyd_node_inner *parent, int options, struct lyd_node **dup)
2610{
2611 return lyd_dup(node, parent, options, 1, dup);
2612}
2613
2614API LY_ERR
2615lyd_dup_siblings(const struct lyd_node *node, struct lyd_node_inner *parent, int options, struct lyd_node **dup)
2616{
2617 return lyd_dup(node, parent, options, 0, dup);
2618}
2619
2620API LY_ERR
2621lyd_dup_meta_single(const struct lyd_meta *meta, struct lyd_node *node, struct lyd_meta **dup)
Michal Vasko25a32822020-07-09 15:48:22 +02002622{
2623 LY_ERR ret;
2624 struct lyd_meta *mt, *last;
2625
Michal Vasko3a41dff2020-07-15 14:30:28 +02002626 LY_CHECK_ARG_RET(NULL, meta, node, LY_EINVAL);
Michal Vasko25a32822020-07-09 15:48:22 +02002627
2628 /* create a copy */
2629 mt = calloc(1, sizeof *mt);
Michal Vasko3a41dff2020-07-15 14:30:28 +02002630 LY_CHECK_ERR_RET(!mt, LOGMEM(LYD_NODE_CTX(node)), LY_EMEM);
Michal Vasko25a32822020-07-09 15:48:22 +02002631 mt->parent = node;
2632 mt->annotation = meta->annotation;
2633 mt->value.realtype = meta->value.realtype;
2634 ret = mt->value.realtype->plugin->duplicate(LYD_NODE_CTX(node), &meta->value, &mt->value);
Michal Vasko3a41dff2020-07-15 14:30:28 +02002635 LY_CHECK_ERR_RET(ret, LOGERR(LYD_NODE_CTX(node), LY_EINT, "Value duplication failed."), ret);
Michal Vasko25a32822020-07-09 15:48:22 +02002636 mt->name = lydict_insert(LYD_NODE_CTX(node), meta->name, 0);
2637
2638 /* insert as the last attribute */
2639 if (node->meta) {
2640 for (last = node->meta; last->next; last = last->next);
2641 last->next = mt;
2642 } else {
2643 node->meta = mt;
2644 }
2645
Michal Vasko3a41dff2020-07-15 14:30:28 +02002646 if (dup) {
2647 *dup = mt;
2648 }
2649 return LY_SUCCESS;
Michal Vasko25a32822020-07-09 15:48:22 +02002650}
2651
Michal Vasko4490d312020-06-16 13:08:55 +02002652/**
2653 * @brief Merge a source sibling into target siblings.
2654 *
2655 * @param[in,out] first_trg First target sibling, is updated if top-level.
2656 * @param[in] parent_trg Target parent.
2657 * @param[in,out] sibling_src Source sibling to merge, set to NULL if spent.
2658 * @param[in] options Merge options.
2659 * @return LY_ERR value.
2660 */
2661static LY_ERR
2662lyd_merge_sibling_r(struct lyd_node **first_trg, struct lyd_node *parent_trg, const struct lyd_node **sibling_src_p,
2663 int options)
2664{
2665 LY_ERR ret;
2666 const struct lyd_node *child_src, *tmp, *sibling_src;
Michal Vasko56daf732020-08-10 10:57:18 +02002667 struct lyd_node *match_trg, *dup_src, *elem;
Michal Vasko4490d312020-06-16 13:08:55 +02002668 struct lysc_type *type;
Michal Vasko4490d312020-06-16 13:08:55 +02002669
2670 sibling_src = *sibling_src_p;
2671 if (sibling_src->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
2672 /* try to find the exact instance */
2673 ret = lyd_find_sibling_first(*first_trg, sibling_src, &match_trg);
2674 } else {
2675 /* try to simply find the node, there cannot be more instances */
2676 ret = lyd_find_sibling_val(*first_trg, sibling_src->schema, NULL, 0, &match_trg);
2677 }
2678
2679 if (!ret) {
2680 /* node found, make sure even value matches for all node types */
Michal Vasko8f359bf2020-07-28 10:41:15 +02002681 if ((match_trg->schema->nodetype == LYS_LEAF) && lyd_compare_single(sibling_src, match_trg, LYD_COMPARE_DEFAULTS)) {
Michal Vasko4490d312020-06-16 13:08:55 +02002682 /* since they are different, they cannot both be default */
2683 assert(!(sibling_src->flags & LYD_DEFAULT) || !(match_trg->flags & LYD_DEFAULT));
2684
Michal Vasko3a41dff2020-07-15 14:30:28 +02002685 /* update value (or only LYD_DEFAULT flag) only if flag set or the source node is not default */
2686 if ((options & LYD_MERGE_DEFAULTS) || !(sibling_src->flags & LYD_DEFAULT)) {
Michal Vasko4490d312020-06-16 13:08:55 +02002687 type = ((struct lysc_node_leaf *)match_trg->schema)->type;
2688 type->plugin->free(LYD_NODE_CTX(match_trg), &((struct lyd_node_term *)match_trg)->value);
2689 LY_CHECK_RET(type->plugin->duplicate(LYD_NODE_CTX(match_trg), &((struct lyd_node_term *)sibling_src)->value,
2690 &((struct lyd_node_term *)match_trg)->value));
2691
2692 /* copy flags and add LYD_NEW */
2693 match_trg->flags = sibling_src->flags | LYD_NEW;
2694 }
Michal Vasko8f359bf2020-07-28 10:41:15 +02002695 } else if ((match_trg->schema->nodetype & LYS_ANYDATA) && lyd_compare_single(sibling_src, match_trg, 0)) {
Michal Vasko4c583e82020-07-17 12:16:14 +02002696 /* update value */
2697 LY_CHECK_RET(lyd_any_copy_value(match_trg, &((struct lyd_node_any *)sibling_src)->value,
2698 ((struct lyd_node_any *)sibling_src)->value_type));
Michal Vasko4490d312020-06-16 13:08:55 +02002699
2700 /* copy flags and add LYD_NEW */
2701 match_trg->flags = sibling_src->flags | LYD_NEW;
Michal Vasko4490d312020-06-16 13:08:55 +02002702 } else {
2703 /* check descendants, recursively */
Michal Vasko8ee464a2020-08-11 14:12:50 +02002704 LY_LIST_FOR_SAFE(LYD_CHILD_NO_KEYS(sibling_src), tmp, child_src) {
Michal Vasko4490d312020-06-16 13:08:55 +02002705 LY_CHECK_RET(lyd_merge_sibling_r(lyd_node_children_p(match_trg), match_trg, &child_src, options));
2706 }
2707 }
2708 } else {
2709 /* node not found, merge it */
2710 if (options & LYD_MERGE_DESTRUCT) {
2711 dup_src = (struct lyd_node *)sibling_src;
2712 lyd_unlink_tree(dup_src);
2713 /* spend it */
2714 *sibling_src_p = NULL;
2715 } else {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002716 LY_CHECK_RET(lyd_dup_single(sibling_src, NULL, LYD_DUP_RECURSIVE | LYD_DUP_WITH_FLAGS, &dup_src));
Michal Vasko4490d312020-06-16 13:08:55 +02002717 }
2718
2719 /* set LYD_NEW for all the new nodes, required for validation */
Michal Vasko56daf732020-08-10 10:57:18 +02002720 LYD_TREE_DFS_BEGIN(dup_src, elem) {
Michal Vasko4490d312020-06-16 13:08:55 +02002721 elem->flags |= LYD_NEW;
Michal Vasko56daf732020-08-10 10:57:18 +02002722 LYD_TREE_DFS_END(dup_src, elem);
Michal Vasko4490d312020-06-16 13:08:55 +02002723 }
2724
2725 lyd_insert_node(parent_trg, first_trg, dup_src);
2726 }
2727
2728 return LY_SUCCESS;
2729}
2730
Michal Vasko3a41dff2020-07-15 14:30:28 +02002731static LY_ERR
2732lyd_merge(struct lyd_node **target, const struct lyd_node *source, int options, int nosiblings)
Michal Vasko4490d312020-06-16 13:08:55 +02002733{
2734 const struct lyd_node *sibling_src, *tmp;
2735 int first;
2736
2737 LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
2738
2739 if (!source) {
2740 /* nothing to merge */
2741 return LY_SUCCESS;
2742 }
2743
2744 if (lysc_data_parent((*target)->schema) || lysc_data_parent(source->schema)) {
2745 LOGERR(LYD_NODE_CTX(source), LY_EINVAL, "Invalid arguments - can merge only 2 top-level subtrees (%s()).", __func__);
2746 return LY_EINVAL;
2747 }
2748
2749 LY_LIST_FOR_SAFE(source, tmp, sibling_src) {
2750 first = sibling_src == source ? 1 : 0;
2751 LY_CHECK_RET(lyd_merge_sibling_r(target, NULL, &sibling_src, options));
2752 if (first && !sibling_src) {
2753 /* source was spent (unlinked), move to the next node */
2754 source = tmp;
2755 }
2756
Michal Vasko3a41dff2020-07-15 14:30:28 +02002757 if (nosiblings) {
Michal Vasko4490d312020-06-16 13:08:55 +02002758 break;
2759 }
2760 }
2761
2762 if (options & LYD_MERGE_DESTRUCT) {
2763 /* free any leftover source data that were not merged */
2764 lyd_free_siblings((struct lyd_node *)source);
2765 }
2766
2767 return LY_SUCCESS;
2768}
2769
Michal Vasko3a41dff2020-07-15 14:30:28 +02002770API LY_ERR
2771lyd_merge_tree(struct lyd_node **target, const struct lyd_node *source, int options)
2772{
2773 return lyd_merge(target, source, options, 1);
2774}
2775
2776API LY_ERR
2777lyd_merge_siblings(struct lyd_node **target, const struct lyd_node *source, int options)
2778{
2779 return lyd_merge(target, source, options, 0);
2780}
2781
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002782static LY_ERR
2783lyd_path_str_enlarge(char **buffer, size_t *buflen, size_t reqlen, int is_static)
2784{
Michal Vasko14654712020-02-06 08:35:21 +01002785 /* ending \0 */
2786 ++reqlen;
2787
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002788 if (reqlen > *buflen) {
2789 if (is_static) {
2790 return LY_EINCOMPLETE;
2791 }
2792
2793 *buffer = ly_realloc(*buffer, reqlen * sizeof **buffer);
2794 if (!*buffer) {
2795 return LY_EMEM;
2796 }
2797
2798 *buflen = reqlen;
2799 }
2800
2801 return LY_SUCCESS;
2802}
2803
Michal Vaskod59035b2020-07-08 12:00:06 +02002804LY_ERR
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002805lyd_path_list_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2806{
2807 const struct lyd_node *key;
2808 int dynamic = 0;
2809 size_t len;
2810 const char *val;
2811 char quot;
2812 LY_ERR rc;
2813
Michal Vasko5bfd4be2020-06-23 13:26:19 +02002814 for (key = lyd_node_children(node, 0); key && (key->schema->flags & LYS_KEY); key = key->next) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002815 val = lyd_value2str((struct lyd_node_term *)key, &dynamic);
2816 len = 1 + strlen(key->schema->name) + 2 + strlen(val) + 2;
2817 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2818 if (rc != LY_SUCCESS) {
2819 if (dynamic) {
2820 free((char *)val);
2821 }
2822 return rc;
2823 }
2824
2825 quot = '\'';
2826 if (strchr(val, '\'')) {
2827 quot = '"';
2828 }
2829 *bufused += sprintf(*buffer + *bufused, "[%s=%c%s%c]", key->schema->name, quot, val, quot);
2830
2831 if (dynamic) {
2832 free((char *)val);
2833 }
2834 }
2835
2836 return LY_SUCCESS;
2837}
2838
2839/**
2840 * @brief Append leaf-list value predicate to path.
2841 *
2842 * @param[in] node Node to print.
2843 * @param[in,out] buffer Buffer to print to.
2844 * @param[in,out] buflen Current buffer length.
2845 * @param[in,out] bufused Current number of characters used in @p buffer.
2846 * @param[in] is_static Whether buffer is static or can be reallocated.
2847 * @return LY_ERR
2848 */
2849static LY_ERR
2850lyd_path_leaflist_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2851{
2852 int dynamic = 0;
2853 size_t len;
2854 const char *val;
2855 char quot;
2856 LY_ERR rc;
2857
2858 val = lyd_value2str((struct lyd_node_term *)node, &dynamic);
2859 len = 4 + strlen(val) + 2;
2860 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2861 if (rc != LY_SUCCESS) {
2862 goto cleanup;
2863 }
2864
2865 quot = '\'';
2866 if (strchr(val, '\'')) {
2867 quot = '"';
2868 }
2869 *bufused += sprintf(*buffer + *bufused, "[.=%c%s%c]", quot, val, quot);
2870
2871cleanup:
2872 if (dynamic) {
2873 free((char *)val);
2874 }
2875 return rc;
2876}
2877
2878/**
2879 * @brief Append node position (relative to its other instances) predicate to path.
2880 *
2881 * @param[in] node Node to print.
2882 * @param[in,out] buffer Buffer to print to.
2883 * @param[in,out] buflen Current buffer length.
2884 * @param[in,out] bufused Current number of characters used in @p buffer.
2885 * @param[in] is_static Whether buffer is static or can be reallocated.
2886 * @return LY_ERR
2887 */
2888static LY_ERR
2889lyd_path_position_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2890{
2891 const struct lyd_node *first, *iter;
2892 size_t len;
2893 int pos;
2894 char *val = NULL;
2895 LY_ERR rc;
2896
2897 if (node->parent) {
2898 first = node->parent->child;
2899 } else {
2900 for (first = node; node->prev->next; node = node->prev);
2901 }
2902 pos = 1;
2903 for (iter = first; iter != node; iter = iter->next) {
2904 if (iter->schema == node->schema) {
2905 ++pos;
2906 }
2907 }
2908 if (asprintf(&val, "%d", pos) == -1) {
2909 return LY_EMEM;
2910 }
2911
2912 len = 1 + strlen(val) + 1;
2913 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2914 if (rc != LY_SUCCESS) {
2915 goto cleanup;
2916 }
2917
2918 *bufused += sprintf(*buffer + *bufused, "[%s]", val);
2919
2920cleanup:
2921 free(val);
2922 return rc;
2923}
2924
2925API char *
2926lyd_path(const struct lyd_node *node, LYD_PATH_TYPE pathtype, char *buffer, size_t buflen)
2927{
Michal Vasko14654712020-02-06 08:35:21 +01002928 int is_static = 0, i, depth;
2929 size_t bufused = 0, len;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002930 const struct lyd_node *iter;
2931 const struct lys_module *mod;
Michal Vasko790b2bc2020-08-03 13:35:06 +02002932 LY_ERR rc = LY_SUCCESS;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002933
2934 LY_CHECK_ARG_RET(NULL, node, NULL);
2935 if (buffer) {
2936 LY_CHECK_ARG_RET(node->schema->module->ctx, buflen > 1, NULL);
2937 is_static = 1;
Michal Vasko14654712020-02-06 08:35:21 +01002938 } else {
2939 buflen = 0;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002940 }
2941
2942 switch (pathtype) {
Michal Vasko14654712020-02-06 08:35:21 +01002943 case LYD_PATH_LOG:
Michal Vasko790b2bc2020-08-03 13:35:06 +02002944 case LYD_PATH_LOG_NO_LAST_PRED:
Michal Vasko14654712020-02-06 08:35:21 +01002945 depth = 1;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002946 for (iter = node; iter->parent; iter = (const struct lyd_node *)iter->parent) {
2947 ++depth;
2948 }
2949
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002950 goto iter_print;
Michal Vasko14654712020-02-06 08:35:21 +01002951 while (depth) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002952 /* find the right node */
Michal Vasko14654712020-02-06 08:35:21 +01002953 for (iter = node, i = 1; i < depth; iter = (const struct lyd_node *)iter->parent, ++i);
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002954iter_print:
2955 /* print prefix and name */
2956 mod = NULL;
2957 if (!iter->parent || (iter->schema->module != iter->parent->schema->module)) {
2958 mod = iter->schema->module;
2959 }
2960
2961 /* realloc string */
2962 len = 1 + (mod ? strlen(mod->name) + 1 : 0) + strlen(iter->schema->name);
2963 rc = lyd_path_str_enlarge(&buffer, &buflen, bufused + len, is_static);
2964 if (rc != LY_SUCCESS) {
2965 break;
2966 }
2967
2968 /* print next node */
2969 bufused += sprintf(buffer + bufused, "/%s%s%s", mod ? mod->name : "", mod ? ":" : "", iter->schema->name);
2970
Michal Vasko790b2bc2020-08-03 13:35:06 +02002971 /* do not always print the last (first) predicate */
2972 if (bufused || (pathtype == LYD_PATH_LOG)) {
2973 switch (iter->schema->nodetype) {
2974 case LYS_LIST:
2975 if (iter->schema->flags & LYS_KEYLESS) {
2976 /* print its position */
2977 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2978 } else {
2979 /* print all list keys in predicates */
2980 rc = lyd_path_list_predicate(iter, &buffer, &buflen, &bufused, is_static);
2981 }
2982 break;
2983 case LYS_LEAFLIST:
2984 if (iter->schema->flags & LYS_CONFIG_W) {
2985 /* print leaf-list value */
2986 rc = lyd_path_leaflist_predicate(iter, &buffer, &buflen, &bufused, is_static);
2987 } else {
2988 /* print its position */
2989 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2990 }
2991 break;
2992 default:
2993 /* nothing to print more */
2994 break;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002995 }
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002996 }
2997 if (rc != LY_SUCCESS) {
2998 break;
2999 }
3000
Michal Vasko14654712020-02-06 08:35:21 +01003001 --depth;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003002 }
3003 break;
3004 }
3005
3006 return buffer;
3007}
Michal Vaskoe444f752020-02-10 12:20:06 +01003008
Michal Vasko25a32822020-07-09 15:48:22 +02003009API struct lyd_meta *
3010lyd_find_meta(const struct lyd_meta *first, const struct lys_module *module, const char *name)
3011{
3012 struct lyd_meta *ret = NULL;
3013 const struct ly_ctx *ctx;
3014 const char *prefix, *tmp;
3015 char *str;
3016 size_t pref_len, name_len;
3017
3018 LY_CHECK_ARG_RET(NULL, module || strchr(name, ':'), name, NULL);
3019
3020 if (!first) {
3021 return NULL;
3022 }
3023
3024 ctx = first->annotation->module->ctx;
3025
3026 /* parse the name */
3027 tmp = name;
3028 if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
3029 LOGERR(ctx, LY_EINVAL, "Metadata name \"%s\" is not valid.", name);
3030 return NULL;
3031 }
3032
3033 /* find the module */
3034 if (prefix) {
3035 str = strndup(prefix, pref_len);
3036 module = ly_ctx_get_module_latest(ctx, str);
3037 free(str);
3038 LY_CHECK_ERR_RET(!module, LOGERR(ctx, LY_EINVAL, "Module \"%.*s\" not found.", pref_len, prefix), NULL);
3039 }
3040
3041 /* find the metadata */
3042 LY_LIST_FOR(first, first) {
3043 if ((first->annotation->module == module) && !strcmp(first->name, name)) {
3044 ret = (struct lyd_meta *)first;
3045 break;
3046 }
3047 }
3048
3049 return ret;
3050}
3051
Michal Vasko9b368d32020-02-14 13:53:31 +01003052API LY_ERR
Michal Vaskoe444f752020-02-10 12:20:06 +01003053lyd_find_sibling_first(const struct lyd_node *siblings, const struct lyd_node *target, struct lyd_node **match)
3054{
3055 struct lyd_node **match_p;
3056 struct lyd_node_inner *parent;
3057
Michal Vaskof03ed032020-03-04 13:31:44 +01003058 LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01003059
Michal Vasko62ed12d2020-05-21 10:08:25 +02003060 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(target->schema))) {
3061 /* no data or schema mismatch */
Michal Vasko9b368d32020-02-14 13:53:31 +01003062 if (match) {
3063 *match = NULL;
3064 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003065 return LY_ENOTFOUND;
3066 }
3067
3068 /* find first sibling */
3069 if (siblings->parent) {
3070 siblings = siblings->parent->child;
3071 } else {
3072 while (siblings->prev->next) {
3073 siblings = siblings->prev;
3074 }
3075 }
3076
3077 parent = (struct lyd_node_inner *)siblings->parent;
3078 if (parent && parent->children_ht) {
3079 assert(target->hash);
3080
3081 /* find by hash */
3082 if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
Michal Vaskoda859032020-07-14 12:20:14 +02003083 /* check even value when needed */
Michal Vasko8f359bf2020-07-28 10:41:15 +02003084 if (!(target->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !lyd_compare_single(target, *match_p, 0)) {
Michal Vaskoda859032020-07-14 12:20:14 +02003085 siblings = *match_p;
3086 } else {
3087 siblings = NULL;
3088 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003089 } else {
3090 /* not found */
3091 siblings = NULL;
3092 }
3093 } else {
3094 /* no children hash table */
3095 for (; siblings; siblings = siblings->next) {
Michal Vasko8f359bf2020-07-28 10:41:15 +02003096 if (!lyd_compare_single(siblings, target, 0)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01003097 break;
3098 }
3099 }
3100 }
3101
3102 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01003103 if (match) {
3104 *match = NULL;
3105 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003106 return LY_ENOTFOUND;
3107 }
3108
Michal Vasko9b368d32020-02-14 13:53:31 +01003109 if (match) {
3110 *match = (struct lyd_node *)siblings;
3111 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003112 return LY_SUCCESS;
3113}
3114
Michal Vasko90932a92020-02-12 14:33:03 +01003115static int
3116lyd_hash_table_schema_val_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *UNUSED(cb_data))
3117{
3118 struct lysc_node *val1;
3119 struct lyd_node *val2;
3120
3121 val1 = *((struct lysc_node **)val1_p);
3122 val2 = *((struct lyd_node **)val2_p);
3123
Michal Vasko90932a92020-02-12 14:33:03 +01003124 if (val1 == val2->schema) {
3125 /* schema match is enough */
3126 return 1;
3127 } else {
3128 return 0;
3129 }
3130}
3131
3132static LY_ERR
3133lyd_find_sibling_schema(const struct lyd_node *siblings, const struct lysc_node *schema, struct lyd_node **match)
3134{
3135 struct lyd_node **match_p;
3136 struct lyd_node_inner *parent;
3137 uint32_t hash;
3138 values_equal_cb ht_cb;
3139
Michal Vaskob104f112020-07-17 09:54:54 +02003140 assert(siblings && schema);
Michal Vasko90932a92020-02-12 14:33:03 +01003141
3142 parent = (struct lyd_node_inner *)siblings->parent;
3143 if (parent && parent->children_ht) {
3144 /* calculate our hash */
3145 hash = dict_hash_multi(0, schema->module->name, strlen(schema->module->name));
3146 hash = dict_hash_multi(hash, schema->name, strlen(schema->name));
3147 hash = dict_hash_multi(hash, NULL, 0);
3148
3149 /* use special hash table function */
3150 ht_cb = lyht_set_cb(parent->children_ht, lyd_hash_table_schema_val_equal);
3151
3152 /* find by hash */
3153 if (!lyht_find(parent->children_ht, &schema, hash, (void **)&match_p)) {
3154 siblings = *match_p;
3155 } else {
3156 /* not found */
3157 siblings = NULL;
3158 }
3159
3160 /* set the original hash table compare function back */
3161 lyht_set_cb(parent->children_ht, ht_cb);
3162 } else {
Michal Vaskob104f112020-07-17 09:54:54 +02003163 /* find first sibling */
3164 if (siblings->parent) {
3165 siblings = siblings->parent->child;
3166 } else {
3167 while (siblings->prev->next) {
3168 siblings = siblings->prev;
3169 }
3170 }
3171
3172 /* search manually without hashes */
Michal Vasko90932a92020-02-12 14:33:03 +01003173 for (; siblings; siblings = siblings->next) {
3174 if (siblings->schema == schema) {
3175 /* schema match is enough */
3176 break;
3177 }
3178 }
3179 }
3180
3181 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01003182 if (match) {
3183 *match = NULL;
3184 }
Michal Vasko90932a92020-02-12 14:33:03 +01003185 return LY_ENOTFOUND;
3186 }
3187
Michal Vasko9b368d32020-02-14 13:53:31 +01003188 if (match) {
3189 *match = (struct lyd_node *)siblings;
3190 }
Michal Vasko90932a92020-02-12 14:33:03 +01003191 return LY_SUCCESS;
3192}
3193
Michal Vaskoe444f752020-02-10 12:20:06 +01003194API LY_ERR
3195lyd_find_sibling_val(const struct lyd_node *siblings, const struct lysc_node *schema, const char *key_or_value,
3196 size_t val_len, struct lyd_node **match)
3197{
3198 LY_ERR rc;
3199 struct lyd_node *target = NULL;
3200
Michal Vasko4c583e82020-07-17 12:16:14 +02003201 LY_CHECK_ARG_RET(NULL, schema, !(schema->nodetype & (LYS_CHOICE | LYS_CASE)), LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01003202
Michal Vasko62ed12d2020-05-21 10:08:25 +02003203 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(schema))) {
3204 /* no data or schema mismatch */
Michal Vasko9b368d32020-02-14 13:53:31 +01003205 if (match) {
3206 *match = NULL;
3207 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003208 return LY_ENOTFOUND;
3209 }
3210
Michal Vaskof03ed032020-03-04 13:31:44 +01003211 if (key_or_value && !val_len) {
3212 val_len = strlen(key_or_value);
3213 }
3214
Michal Vaskob104f112020-07-17 09:54:54 +02003215 if ((schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) && key_or_value) {
3216 /* create a data node and find the instance */
3217 if (schema->nodetype == LYS_LEAFLIST) {
3218 /* target used attributes: schema, hash, value */
3219 rc = lyd_create_term(schema, key_or_value, val_len, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &target);
3220 LY_CHECK_RET(rc && (rc != LY_EINCOMPLETE), rc);
3221 } else {
Michal Vasko90932a92020-02-12 14:33:03 +01003222 /* target used attributes: schema, hash, child (all keys) */
Michal Vasko004d3152020-06-11 19:59:22 +02003223 LY_CHECK_RET(lyd_create_list2(schema, key_or_value, val_len, &target));
Michal Vasko90932a92020-02-12 14:33:03 +01003224 }
3225
3226 /* find it */
3227 rc = lyd_find_sibling_first(siblings, target, match);
Michal Vaskob104f112020-07-17 09:54:54 +02003228 } else {
3229 /* find the first schema node instance */
3230 rc = lyd_find_sibling_schema(siblings, schema, match);
Michal Vaskoe444f752020-02-10 12:20:06 +01003231 }
3232
Michal Vaskoe444f752020-02-10 12:20:06 +01003233 lyd_free_tree(target);
3234 return rc;
3235}
Michal Vaskoccc02342020-05-21 10:09:21 +02003236
3237API LY_ERR
3238lyd_find_xpath(const struct lyd_node *ctx_node, const char *xpath, struct ly_set **set)
3239{
3240 LY_ERR ret = LY_SUCCESS;
3241 struct lyxp_set xp_set;
3242 struct lyxp_expr *exp;
3243 uint32_t i;
3244
3245 LY_CHECK_ARG_RET(NULL, ctx_node, xpath, set, LY_EINVAL);
3246
3247 memset(&xp_set, 0, sizeof xp_set);
3248
3249 /* compile expression */
Michal Vasko004d3152020-06-11 19:59:22 +02003250 exp = lyxp_expr_parse((struct ly_ctx *)LYD_NODE_CTX(ctx_node), xpath, 0, 1);
Michal Vaskoccc02342020-05-21 10:09:21 +02003251 LY_CHECK_ERR_GOTO(!exp, ret = LY_EINVAL, cleanup);
3252
3253 /* evaluate expression */
3254 ret = lyxp_eval(exp, LYD_JSON, ctx_node->schema->module, ctx_node, LYXP_NODE_ELEM, ctx_node, &xp_set, 0);
3255 LY_CHECK_GOTO(ret, cleanup);
3256
3257 /* allocate return set */
3258 *set = ly_set_new();
3259 LY_CHECK_ERR_GOTO(!*set, LOGMEM(LYD_NODE_CTX(ctx_node)); ret = LY_EMEM, cleanup);
3260
3261 /* transform into ly_set */
3262 if (xp_set.type == LYXP_SET_NODE_SET) {
3263 /* allocate memory for all the elements once (even though not all items must be elements but most likely will be) */
3264 (*set)->objs = malloc(xp_set.used * sizeof *(*set)->objs);
3265 LY_CHECK_ERR_GOTO(!(*set)->objs, LOGMEM(LYD_NODE_CTX(ctx_node)); ret = LY_EMEM, cleanup);
3266 (*set)->size = xp_set.used;
3267
3268 for (i = 0; i < xp_set.used; ++i) {
3269 if (xp_set.val.nodes[i].type == LYXP_NODE_ELEM) {
3270 ly_set_add(*set, xp_set.val.nodes[i].node, LY_SET_OPT_USEASLIST);
3271 }
3272 }
3273 }
3274
3275cleanup:
Michal Vasko0691d522020-05-21 13:21:47 +02003276 lyxp_set_free_content(&xp_set);
Michal Vaskoccc02342020-05-21 10:09:21 +02003277 lyxp_expr_free((struct ly_ctx *)LYD_NODE_CTX(ctx_node), exp);
3278 return ret;
3279}