blob: 8bfaaa38b808b84c2a44ce895827962647b061ba [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;
931 char *str;
932 size_t pref_len, name_len;
933
Michal Vasko3a41dff2020-07-15 14:30:28 +0200934 LY_CHECK_ARG_RET(NULL, parent, name, module || strchr(name, ':'), LY_EINVAL);
Michal Vasko00cbf532020-06-15 13:58:47 +0200935
936 ctx = LYD_NODE_CTX(parent);
Michal Vaskod86997b2020-05-26 15:19:54 +0200937
938 /* parse the name */
939 tmp = name;
940 if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
941 LOGERR(ctx, LY_EINVAL, "Metadata name \"%s\" is not valid.", name);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200942 return LY_EVALID;
Michal Vaskod86997b2020-05-26 15:19:54 +0200943 }
944
945 /* find the module */
946 if (prefix) {
Michal Vasko0b245382020-07-09 15:43:52 +0200947 str = strndup(prefix, pref_len);
Michal Vaskod86997b2020-05-26 15:19:54 +0200948 module = ly_ctx_get_module_implemented(ctx, str);
949 free(str);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200950 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 +0200951 }
952
953 /* set value if none */
954 if (!val_str) {
955 val_str = "";
956 }
957
Michal Vasko3a41dff2020-07-15 14:30:28 +0200958 LY_CHECK_RET(lyd_create_meta(parent, &ret, module, name, name_len, val_str, strlen(val_str), NULL,
959 lydjson_resolve_prefix, NULL, LYD_JSON, parent->schema));
960
961 if (meta) {
962 *meta = ret;
963 }
964 return LY_SUCCESS;
Michal Vaskod86997b2020-05-26 15:19:54 +0200965}
966
Michal Vasko3a41dff2020-07-15 14:30:28 +0200967API LY_ERR
Michal Vasko00cbf532020-06-15 13:58:47 +0200968lyd_new_opaq(struct lyd_node *parent, const struct ly_ctx *ctx, const char *name, const char *value,
Michal Vasko3a41dff2020-07-15 14:30:28 +0200969 const char *module_name, struct lyd_node **node)
Michal Vasko00cbf532020-06-15 13:58:47 +0200970{
971 struct lyd_node *ret = NULL;
972
Michal Vasko6027eb92020-07-15 16:37:30 +0200973 LY_CHECK_ARG_RET(ctx, parent || ctx, parent || node, name, module_name, LY_EINVAL);
Michal Vasko00cbf532020-06-15 13:58:47 +0200974
975 if (!ctx) {
976 ctx = LYD_NODE_CTX(parent);
977 }
978 if (!value) {
979 value = "";
980 }
981
Michal Vasko3a41dff2020-07-15 14:30:28 +0200982 LY_CHECK_RET(lyd_create_opaq(ctx, name, strlen(name), value, strlen(value), NULL, LYD_JSON, NULL, NULL, 0,
983 module_name, &ret));
984 if (parent) {
Michal Vasko00cbf532020-06-15 13:58:47 +0200985 lyd_insert_node(parent, NULL, ret);
986 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200987
988 if (node) {
989 *node = ret;
990 }
991 return LY_SUCCESS;
Michal Vasko00cbf532020-06-15 13:58:47 +0200992}
993
Michal Vasko3a41dff2020-07-15 14:30:28 +0200994API LY_ERR
995lyd_new_attr(struct lyd_node *parent, const char *module_name, const char *name, const char *val_str,
996 struct ly_attr **attr)
Michal Vasko00cbf532020-06-15 13:58:47 +0200997{
998 struct ly_attr *ret = NULL;
999 const struct ly_ctx *ctx;
1000 const char *prefix, *tmp;
1001 size_t pref_len, name_len;
1002
Michal Vasko3a41dff2020-07-15 14:30:28 +02001003 LY_CHECK_ARG_RET(NULL, parent, !parent->schema, name, LY_EINVAL);
Michal Vasko00cbf532020-06-15 13:58:47 +02001004
1005 ctx = LYD_NODE_CTX(parent);
1006
1007 /* parse the name */
1008 tmp = name;
1009 if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
1010 LOGERR(ctx, LY_EINVAL, "Metadata name \"%s\" is not valid.", name);
Michal Vasko3a41dff2020-07-15 14:30:28 +02001011 return LY_EVALID;
Michal Vasko00cbf532020-06-15 13:58:47 +02001012 }
1013
1014 /* set value if none */
1015 if (!val_str) {
1016 val_str = "";
1017 }
1018
Michal Vasko3a41dff2020-07-15 14:30:28 +02001019 LY_CHECK_RET(ly_create_attr(parent, &ret, ctx, name, name_len, val_str, strlen(val_str), NULL, LYD_JSON, NULL,
1020 prefix, pref_len, module_name));
1021
1022 if (attr) {
1023 *attr = ret;
1024 }
1025 return LY_SUCCESS;
Michal Vasko00cbf532020-06-15 13:58:47 +02001026}
1027
1028API LY_ERR
1029lyd_change_term(struct lyd_node *term, const char *val_str)
1030{
1031 LY_ERR ret = LY_SUCCESS;
1032 struct lysc_type *type;
1033 struct lyd_node_term *t;
1034 struct lyd_node *parent;
1035 struct lyd_value val = {0};
1036 int dflt_change, val_change;
1037
1038 LY_CHECK_ARG_RET(NULL, term, term->schema, term->schema->nodetype & LYD_NODE_TERM, LY_EINVAL);
1039
1040 if (!val_str) {
1041 val_str = "";
1042 }
1043 t = (struct lyd_node_term *)term;
1044 type = ((struct lysc_node_leaf *)term->schema)->type;
1045
1046 /* parse the new value */
1047 LY_CHECK_GOTO(ret = lyd_value_store(&val, term->schema, val_str, strlen(val_str), NULL, lydjson_resolve_prefix, NULL,
1048 LYD_JSON), cleanup);
1049
1050 /* compare original and new value */
1051 if (type->plugin->compare(&t->value, &val)) {
1052 /* values differ, switch them */
1053 type->plugin->free(LYD_NODE_CTX(term), &t->value);
1054 t->value = val;
1055 memset(&val, 0, sizeof val);
1056 val_change = 1;
1057 } else {
1058 val_change = 0;
1059 }
1060
1061 /* always clear the default flag */
1062 if (term->flags & LYD_DEFAULT) {
1063 for (parent = term; parent; parent = (struct lyd_node *)parent->parent) {
1064 parent->flags &= ~LYD_DEFAULT;
1065 }
1066 dflt_change = 1;
1067 } else {
1068 dflt_change = 0;
1069 }
1070
1071 if (val_change || dflt_change) {
1072 /* make the node non-validated */
1073 term->flags &= LYD_NEW;
1074 }
1075
1076 if (val_change) {
1077 if (term->schema->nodetype == LYS_LEAFLIST) {
1078 /* leaf-list needs to be hashed again and re-inserted into parent */
1079 lyd_unlink_hash(term);
1080 lyd_hash(term);
1081 LY_CHECK_GOTO(ret = lyd_insert_hash(term), cleanup);
1082 } else if ((term->schema->flags & LYS_KEY) && term->parent) {
1083 /* list needs to be updated if its key was changed */
1084 assert(term->parent->schema->nodetype == LYS_LIST);
1085 lyd_unlink_hash((struct lyd_node *)term->parent);
1086 lyd_hash((struct lyd_node *)term->parent);
1087 LY_CHECK_GOTO(ret = lyd_insert_hash((struct lyd_node *)term->parent), cleanup);
1088 } /* else leaf that is not a key, its value is not used for its hash so it does not change */
1089 }
1090
1091 /* retrun value */
1092 if (!val_change) {
1093 if (dflt_change) {
1094 /* only default flag change */
1095 ret = LY_EEXIST;
1096 } else {
1097 /* no change */
1098 ret = LY_ENOT;
1099 }
1100 } /* else value changed, LY_SUCCESS */
1101
1102cleanup:
1103 type->plugin->free(LYD_NODE_CTX(term), &val);
1104 return ret;
1105}
1106
Michal Vasko41586352020-07-13 13:54:25 +02001107API LY_ERR
1108lyd_change_meta(struct lyd_meta *meta, const char *val_str)
1109{
1110 LY_ERR ret = LY_SUCCESS;
1111 struct lyd_meta *m2;
1112 struct lyd_value val;
1113 int val_change;
1114
1115 LY_CHECK_ARG_RET(NULL, meta, LY_EINVAL);
1116
1117 if (!val_str) {
1118 val_str = "";
1119 }
1120
1121 /* parse the new value into a new meta structure */
1122 LY_CHECK_GOTO(ret = lyd_create_meta(NULL, &m2, meta->annotation->module, meta->name, strlen(meta->name), val_str,
1123 strlen(val_str), NULL, lydjson_resolve_prefix, NULL, LYD_JSON, NULL), cleanup);
1124
1125 /* compare original and new value */
1126 if (lyd_compare_meta(meta, m2)) {
1127 /* values differ, switch them */
1128 val = meta->value;
1129 meta->value = m2->value;
1130 m2->value = val;
1131 val_change = 1;
1132 } else {
1133 val_change = 0;
1134 }
1135
1136 /* retrun value */
1137 if (!val_change) {
1138 /* no change */
1139 ret = LY_ENOT;
1140 } /* else value changed, LY_SUCCESS */
1141
1142cleanup:
1143 return ret;
1144}
1145
Michal Vasko3a41dff2020-07-15 14:30:28 +02001146API LY_ERR
1147lyd_new_path(struct lyd_node *parent, const struct ly_ctx *ctx, const char *path, const char *value, int options,
1148 struct lyd_node **node)
Michal Vasko00cbf532020-06-15 13:58:47 +02001149{
Michal Vasko3a41dff2020-07-15 14:30:28 +02001150 return lyd_new_path2(parent, ctx, path, value, 0, options, node, NULL);
Michal Vasko00cbf532020-06-15 13:58:47 +02001151}
1152
1153API LY_ERR
1154lyd_new_path2(struct lyd_node *parent, const struct ly_ctx *ctx, const char *path, const void *value,
1155 LYD_ANYDATA_VALUETYPE value_type, int options, struct lyd_node **new_parent, struct lyd_node **new_node)
1156{
1157 LY_ERR ret = LY_SUCCESS, r;
1158 struct lyxp_expr *exp = NULL;
1159 struct ly_path *p = NULL;
1160 struct lyd_node *nparent = NULL, *nnode = NULL, *node = NULL, *cur_parent;
1161 const struct lysc_node *schema;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001162 LY_ARRAY_COUNT_TYPE path_idx = 0;
Michal Vasko00cbf532020-06-15 13:58:47 +02001163 struct ly_path_predicate *pred;
1164
1165 LY_CHECK_ARG_RET(ctx, parent || ctx, path, (path[0] == '/') || parent, LY_EINVAL);
1166
1167 if (!ctx) {
1168 ctx = LYD_NODE_CTX(parent);
1169 }
1170
1171 /* parse path */
Michal Vasko6b26e742020-07-17 15:02:10 +02001172 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 +02001173 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_SIMPLE, &exp), cleanup);
1174
1175 /* compile path */
1176 LY_CHECK_GOTO(ret = ly_path_compile(ctx, NULL, parent ? parent->schema : NULL, exp, LY_PATH_LREF_FALSE,
1177 options & LYD_NEWOPT_OUTPUT ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT,
1178 LY_PATH_TARGET_MANY, lydjson_resolve_prefix, NULL, LYD_JSON, &p), cleanup);
1179
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001180 schema = p[LY_ARRAY_COUNT(p) - 1].node;
1181 if ((schema->nodetype == LYS_LIST) && (p[LY_ARRAY_COUNT(p) - 1].pred_type == LY_PATH_PREDTYPE_NONE)
Michal Vasko00cbf532020-06-15 13:58:47 +02001182 && !(options & LYD_NEWOPT_OPAQ)) {
1183 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_XPATH, "Predicate missing for %s \"%s\" in path.",
1184 lys_nodetype2str(schema->nodetype), schema->name);
1185 ret = LY_EINVAL;
1186 goto cleanup;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001187 } 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 +02001188 /* parse leafref value into a predicate, if not defined in the path */
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001189 p[LY_ARRAY_COUNT(p) - 1].pred_type = LY_PATH_PREDTYPE_LEAFLIST;
1190 LY_ARRAY_NEW_GOTO(ctx, p[LY_ARRAY_COUNT(p) - 1].predicates, pred, ret, cleanup);
Michal Vasko00cbf532020-06-15 13:58:47 +02001191
1192 if (!value) {
1193 value = "";
1194 }
1195
1196 r = LY_SUCCESS;
1197 if (options & LYD_NEWOPT_OPAQ) {
Michal Vaskof937cfe2020-08-03 16:07:12 +02001198 r = lys_value_validate(NULL, schema, value, strlen(value));
Michal Vasko00cbf532020-06-15 13:58:47 +02001199 }
1200 if (!r) {
1201 LY_CHECK_GOTO(ret = lyd_value_store(&pred->value, schema, value, strlen(value), NULL, lydjson_resolve_prefix,
1202 NULL, LYD_JSON), cleanup);
1203 } /* else we have opaq flag and the value is not valid, leavne no predicate and then create an opaque node */
1204 }
1205
1206 /* try to find any existing nodes in the path */
1207 if (parent) {
1208 ret = ly_path_eval_partial(p, parent, &path_idx, &node);
1209 if (ret == LY_SUCCESS) {
1210 /* the node exists, are we supposed to update it or is it just a default? */
1211 if (!(options & LYD_NEWOPT_UPDATE) && !(node->flags & LYD_DEFAULT)) {
1212 LOGERR(ctx, LY_EEXIST, "Path \"%s\" already exists", path);
1213 ret = LY_EEXIST;
1214 goto cleanup;
1215 }
1216
1217 /* update the existing node */
1218 ret = lyd_new_path_update(node, value, value_type, &nparent, &nnode);
1219 goto cleanup;
1220 } else if (ret == LY_EINCOMPLETE) {
1221 /* some nodes were found, adjust the iterator to the next segment */
1222 ++path_idx;
1223 } else if (ret == LY_ENOTFOUND) {
1224 /* 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 +02001225 if (lysc_data_parent(p[LY_ARRAY_COUNT(p) - 1].node)) {
Michal Vasko00cbf532020-06-15 13:58:47 +02001226 node = parent;
1227 }
1228 } else {
1229 /* error */
1230 goto cleanup;
1231 }
1232 }
1233
1234 /* create all the non-existing nodes in a loop */
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001235 for (; path_idx < LY_ARRAY_COUNT(p); ++path_idx) {
Michal Vasko00cbf532020-06-15 13:58:47 +02001236 cur_parent = node;
1237 schema = p[path_idx].node;
1238
1239 switch (schema->nodetype) {
1240 case LYS_LIST:
1241 if (!(schema->flags & LYS_KEYLESS)) {
1242 if ((options & LYD_NEWOPT_OPAQ) && (p[path_idx].pred_type == LY_PATH_PREDTYPE_NONE)) {
1243 /* creating opaque list without keys */
1244 LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, NULL,
1245 LYD_JSON, NULL, NULL, 0, schema->module->name, &node), cleanup);
1246 } else {
1247 assert(p[path_idx].pred_type == LY_PATH_PREDTYPE_LIST);
1248 LY_CHECK_GOTO(ret = lyd_create_list(schema, p[path_idx].predicates, &node), cleanup);
1249 }
1250 break;
1251 }
1252 /* fallthrough */
1253 case LYS_CONTAINER:
1254 case LYS_NOTIF:
1255 case LYS_RPC:
1256 case LYS_ACTION:
1257 LY_CHECK_GOTO(ret = lyd_create_inner(schema, &node), cleanup);
1258 break;
1259 case LYS_LEAFLIST:
1260 if ((options & LYD_NEWOPT_OPAQ) && (p[path_idx].pred_type == LY_PATH_PREDTYPE_NONE)) {
1261 /* creating opaque leaf-list without value */
1262 LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, NULL,
1263 LYD_JSON, NULL, NULL, 0, schema->module->name, &node), cleanup);
1264 } else {
1265 assert(p[path_idx].pred_type == LY_PATH_PREDTYPE_LEAFLIST);
1266 LY_CHECK_GOTO(ret = lyd_create_term2(schema, &p[path_idx].predicates[0].value, &node), cleanup);
1267 }
1268 break;
1269 case LYS_LEAF:
1270 /* make there is some value */
1271 if (!value) {
1272 value = "";
1273 }
1274
1275 r = LY_SUCCESS;
1276 if (options & LYD_NEWOPT_OPAQ) {
Michal Vaskof937cfe2020-08-03 16:07:12 +02001277 r = lys_value_validate(NULL, schema, value, strlen(value));
Michal Vasko00cbf532020-06-15 13:58:47 +02001278 }
1279 if (!r) {
1280 LY_CHECK_GOTO(ret = lyd_create_term(schema, value, strlen(value), NULL, lydjson_resolve_prefix, NULL,
1281 LYD_JSON, &node), cleanup);
1282 } else {
1283 /* creating opaque leaf without value */
1284 LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, NULL,
1285 LYD_JSON, NULL, NULL, 0, schema->module->name, &node), cleanup);
1286 }
1287 break;
1288 case LYS_ANYDATA:
1289 case LYS_ANYXML:
1290 LY_CHECK_GOTO(ret = lyd_create_any(schema, value, value_type, &node), cleanup);
1291 break;
1292 default:
1293 LOGINT(ctx);
1294 ret = LY_EINT;
1295 goto cleanup;
1296 }
1297
1298 if (cur_parent) {
1299 /* connect to the parent */
1300 lyd_insert_node(cur_parent, NULL, node);
1301 } else if (parent) {
1302 /* connect to top-level siblings */
1303 lyd_insert_node(NULL, &parent, node);
1304 }
1305
1306 /* update remembered nodes */
1307 if (!nparent) {
1308 nparent = node;
1309 }
1310 nnode = node;
1311 }
1312
1313cleanup:
1314 lyxp_expr_free(ctx, exp);
1315 ly_path_free(ctx, p);
1316 if (!ret) {
1317 /* set out params only on success */
1318 if (new_parent) {
1319 *new_parent = nparent;
1320 }
1321 if (new_node) {
1322 *new_node = nnode;
1323 }
1324 }
1325 return ret;
1326}
1327
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001328LY_ERR
1329lyd_new_implicit_r(struct lyd_node *parent, struct lyd_node **first, const struct lysc_node *sparent,
1330 const struct lys_module *mod, struct ly_set *node_types, struct ly_set *node_when, int impl_opts,
1331 struct lyd_node **diff)
1332{
1333 LY_ERR ret;
1334 const struct lysc_node *iter = NULL;
1335 struct lyd_node *node;
1336 struct lyd_value **dflts;
1337 LY_ARRAY_COUNT_TYPE u;
1338
1339 assert(first && (parent || sparent || mod));
1340
1341 if (!sparent && parent) {
1342 sparent = parent->schema;
1343 }
1344
1345 while ((iter = lys_getnext(iter, sparent, mod ? mod->compiled : NULL, LYS_GETNEXT_WITHCHOICE))) {
1346 if ((impl_opts & LYD_IMPLICIT_NO_STATE) && (iter->flags & LYS_CONFIG_R)) {
1347 continue;
Michal Vasko44b19a12020-08-07 09:21:30 +02001348 } else if ((impl_opts & LYD_IMPLICIT_NO_CONFIG) && (iter->flags & LYS_CONFIG_W)) {
1349 continue;
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001350 }
1351
1352 switch (iter->nodetype) {
1353 case LYS_CHOICE:
1354 if (((struct lysc_node_choice *)iter)->dflt && !lys_getnext_data(NULL, *first, NULL, iter, NULL)) {
1355 /* create default case data */
1356 LY_CHECK_RET(lyd_new_implicit_r(parent, first, (struct lysc_node *)((struct lysc_node_choice *)iter)->dflt,
1357 NULL, node_types, node_when, impl_opts, diff));
1358 }
1359 break;
1360 case LYS_CONTAINER:
1361 if (!(iter->flags & LYS_PRESENCE) && lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
1362 /* create default NP container */
1363 LY_CHECK_RET(lyd_create_inner(iter, &node));
1364 node->flags = LYD_DEFAULT;
1365 lyd_insert_node(parent, first, node);
1366
1367 /* cannot be a NP container with when */
1368 assert(!iter->when);
1369
1370 /* create any default children */
1371 LY_CHECK_RET(lyd_new_implicit_r(node, lyd_node_children_p(node), NULL, NULL, node_types, node_when,
1372 impl_opts, diff));
1373 }
1374 break;
1375 case LYS_LEAF:
1376 if (!(impl_opts & LYD_IMPLICIT_NO_DEFAULTS) && ((struct lysc_node_leaf *)iter)->dflt
1377 && lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
1378 /* create default leaf */
1379 ret = lyd_create_term2(iter, ((struct lysc_node_leaf *)iter)->dflt, &node);
1380 if (ret == LY_EINCOMPLETE) {
1381 if (node_types) {
1382 /* remember to resolve type */
1383 ly_set_add(node_types, node, LY_SET_OPT_USEASLIST);
1384 }
1385 } else if (ret) {
1386 return ret;
1387 }
1388 node->flags = LYD_DEFAULT;
1389 lyd_insert_node(parent, first, node);
1390
1391 if (iter->when && node_when) {
1392 /* remember to resolve when */
1393 ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
1394 }
1395 if (diff) {
1396 /* add into diff */
1397 LY_CHECK_RET(lyd_val_diff_add(node, LYD_DIFF_OP_CREATE, diff));
1398 }
1399 }
1400 break;
1401 case LYS_LEAFLIST:
1402 if (!(impl_opts & LYD_IMPLICIT_NO_DEFAULTS) && ((struct lysc_node_leaflist *)iter)->dflts
1403 && lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
1404 /* create all default leaf-lists */
1405 dflts = ((struct lysc_node_leaflist *)iter)->dflts;
1406 LY_ARRAY_FOR(dflts, u) {
1407 ret = lyd_create_term2(iter, dflts[u], &node);
1408 if (ret == LY_EINCOMPLETE) {
1409 if (node_types) {
1410 /* remember to resolve type */
1411 ly_set_add(node_types, node, LY_SET_OPT_USEASLIST);
1412 }
1413 } else if (ret) {
1414 return ret;
1415 }
1416 node->flags = LYD_DEFAULT;
1417 lyd_insert_node(parent, first, node);
1418
1419 if (iter->when && node_when) {
1420 /* remember to resolve when */
1421 ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
1422 }
1423 if (diff) {
1424 /* add into diff */
1425 LY_CHECK_RET(lyd_val_diff_add(node, LYD_DIFF_OP_CREATE, diff));
1426 }
1427 }
1428 }
1429 break;
1430 default:
1431 /* without defaults */
1432 break;
1433 }
1434 }
1435
1436 return LY_SUCCESS;
1437}
1438
1439API LY_ERR
1440lyd_new_implicit_tree(struct lyd_node *tree, int implicit_options, struct lyd_node **diff)
1441{
Michal Vasko56daf732020-08-10 10:57:18 +02001442 struct lyd_node *node;
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001443 LY_ERR ret = LY_SUCCESS;
1444
1445 LY_CHECK_ARG_RET(NULL, tree, LY_EINVAL);
1446 if (diff) {
1447 *diff = NULL;
1448 }
1449
Michal Vasko56daf732020-08-10 10:57:18 +02001450 LYD_TREE_DFS_BEGIN(tree, node) {
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001451 /* skip added default nodes */
1452 if (((node->flags & (LYD_DEFAULT | LYD_NEW)) != (LYD_DEFAULT | LYD_NEW))
1453 && (node->schema->nodetype & LYD_NODE_INNER)) {
1454 LY_CHECK_GOTO(ret = lyd_new_implicit_r(node, lyd_node_children_p((struct lyd_node *)node), NULL, NULL, NULL,
1455 NULL, implicit_options, diff), cleanup);
1456 }
1457
Michal Vasko56daf732020-08-10 10:57:18 +02001458 LYD_TREE_DFS_END(tree, node);
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001459 }
1460
1461cleanup:
1462 if (ret && diff) {
1463 lyd_free_all(*diff);
1464 *diff = NULL;
1465 }
1466 return ret;
1467}
1468
1469API LY_ERR
1470lyd_new_implicit_all(struct lyd_node **tree, const struct ly_ctx *ctx, int implicit_options, struct lyd_node **diff)
1471{
1472 const struct lys_module *mod;
1473 struct lyd_node *d = NULL;
1474 uint32_t i = 0;
1475 LY_ERR ret = LY_SUCCESS;
1476
1477 LY_CHECK_ARG_RET(ctx, tree, *tree || ctx, LY_EINVAL);
1478 if (diff) {
1479 *diff = NULL;
1480 }
1481 if (!ctx) {
1482 ctx = LYD_NODE_CTX(*tree);
1483 }
1484
1485 /* add nodes for each module one-by-one */
1486 while ((mod = ly_ctx_get_module_iter(ctx, &i))) {
1487 if (!mod->implemented) {
1488 continue;
1489 }
1490
1491 LY_CHECK_GOTO(ret = lyd_new_implicit_module(tree, mod, implicit_options, diff ? &d : NULL), cleanup);
1492 if (d) {
1493 /* merge into one diff */
1494 lyd_insert_sibling(*diff, d, diff);
1495
1496 d = NULL;
1497 }
1498 }
1499
1500cleanup:
1501 if (ret && diff) {
1502 lyd_free_all(*diff);
1503 *diff = NULL;
1504 }
1505 return ret;
1506}
1507
1508API LY_ERR
1509lyd_new_implicit_module(struct lyd_node **tree, const struct lys_module *module, int implicit_options, struct lyd_node **diff)
1510{
1511 struct lyd_node *root, *d = NULL;
1512 LY_ERR ret = LY_SUCCESS;
1513
1514 LY_CHECK_ARG_RET(NULL, tree, module, LY_EINVAL);
1515 if (diff) {
1516 *diff = NULL;
1517 }
1518
1519 /* add all top-level defaults for this module */
1520 LY_CHECK_GOTO(ret = lyd_new_implicit_r(NULL, tree, NULL, module, NULL, NULL, implicit_options, diff), cleanup);
1521
1522 /* process nested nodes */
1523 LY_LIST_FOR(*tree, root) {
1524 /* skip added default nodes */
1525 if ((root->flags & (LYD_DEFAULT | LYD_NEW)) != (LYD_DEFAULT | LYD_NEW)) {
1526 LY_CHECK_GOTO(ret = lyd_new_implicit_tree(root, implicit_options, diff ? &d : NULL), cleanup);
1527
1528 if (d) {
1529 /* merge into one diff */
1530 lyd_insert_sibling(*diff, d, diff);
1531
1532 d = NULL;
1533 }
1534 }
1535 }
1536
1537cleanup:
1538 if (ret && diff) {
1539 lyd_free_all(*diff);
1540 *diff = NULL;
1541 }
1542 return ret;
1543}
1544
Michal Vasko90932a92020-02-12 14:33:03 +01001545struct lyd_node *
Michal Vaskob104f112020-07-17 09:54:54 +02001546lyd_insert_get_next_anchor(const struct lyd_node *first_sibling, const struct lyd_node *new_node)
Michal Vasko90932a92020-02-12 14:33:03 +01001547{
Michal Vaskob104f112020-07-17 09:54:54 +02001548 const struct lysc_node *schema, *sparent;
Michal Vasko90932a92020-02-12 14:33:03 +01001549 struct lyd_node *match = NULL;
Michal Vaskob104f112020-07-17 09:54:54 +02001550 int found;
Michal Vasko90932a92020-02-12 14:33:03 +01001551
Michal Vaskob104f112020-07-17 09:54:54 +02001552 assert(new_node);
1553
1554 if (!first_sibling || !new_node->schema) {
1555 /* insert at the end, no next anchor */
Michal Vasko90932a92020-02-12 14:33:03 +01001556 return NULL;
1557 }
1558
Michal Vaskob104f112020-07-17 09:54:54 +02001559 if (first_sibling->parent && first_sibling->parent->children_ht) {
1560 /* find the anchor using hashes */
1561 sparent = first_sibling->parent->schema;
1562 schema = lys_getnext(new_node->schema, sparent, NULL, 0);
1563 while (schema) {
1564 /* keep trying to find the first existing instance of the closest following schema sibling,
1565 * otherwise return NULL - inserting at the end */
1566 if (!lyd_find_sibling_schema(first_sibling, schema, &match)) {
1567 break;
1568 }
1569
1570 schema = lys_getnext(schema, sparent, NULL, 0);
1571 }
1572 } else {
1573 /* find the anchor without hashes */
1574 match = (struct lyd_node *)first_sibling;
1575 if (!lysc_data_parent(new_node->schema)) {
1576 /* we are in top-level, skip all the data from preceding modules */
1577 LY_LIST_FOR(match, match) {
1578 if (!match->schema || (strcmp(lyd_owner_module(match)->name, lyd_owner_module(new_node)->name) >= 0)) {
1579 break;
1580 }
1581 }
1582 }
1583
1584 /* get the first schema sibling */
1585 sparent = lysc_data_parent(new_node->schema);
1586 schema = lys_getnext(NULL, sparent, new_node->schema->module->compiled, 0);
1587
1588 found = 0;
1589 LY_LIST_FOR(match, match) {
1590 if (!match->schema || (lyd_owner_module(match) != lyd_owner_module(new_node))) {
1591 /* we have found an opaque node, which must be at the end, so use it OR
1592 * modules do not match, so we must have traversed all the data from new_node module (if any),
1593 * we have found the first node of the next module, that is what we want */
1594 break;
1595 }
1596
1597 /* skip schema nodes until we find the instantiated one */
1598 while (!found) {
1599 if (new_node->schema == schema) {
1600 /* we have found the schema of the new node, continue search to find the first
1601 * data node with a different schema (after our schema) */
1602 found = 1;
1603 break;
1604 }
1605 if (match->schema == schema) {
1606 /* current node (match) is a data node still before the new node, continue search in data */
1607 break;
1608 }
1609 schema = lys_getnext(schema, sparent, new_node->schema->module->compiled, 0);
1610 assert(schema);
1611 }
1612
1613 if (found && (match->schema != new_node->schema)) {
1614 /* find the next node after we have found our node schema data instance */
1615 break;
1616 }
1617 }
Michal Vasko90932a92020-02-12 14:33:03 +01001618 }
1619
1620 return match;
1621}
1622
1623/**
1624 * @brief Insert node after a sibling.
1625 *
Michal Vasko9f96a052020-03-10 09:41:45 +01001626 * Handles inserting into NP containers and key-less lists.
1627 *
Michal Vasko90932a92020-02-12 14:33:03 +01001628 * @param[in] sibling Sibling to insert after.
1629 * @param[in] node Node to insert.
1630 */
1631static void
Michal Vaskof03ed032020-03-04 13:31:44 +01001632lyd_insert_after_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001633{
Michal Vasko0249f7c2020-03-05 16:36:40 +01001634 struct lyd_node_inner *par;
1635
Michal Vasko90932a92020-02-12 14:33:03 +01001636 assert(!node->next && (node->prev == node));
1637
1638 node->next = sibling->next;
1639 node->prev = sibling;
1640 sibling->next = node;
1641 if (node->next) {
1642 /* sibling had a succeeding node */
1643 node->next->prev = node;
1644 } else {
1645 /* sibling was last, find first sibling and change its prev */
1646 if (sibling->parent) {
1647 sibling = sibling->parent->child;
1648 } else {
1649 for (; sibling->prev->next != node; sibling = sibling->prev);
1650 }
1651 sibling->prev = node;
1652 }
1653 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001654
Michal Vasko9f96a052020-03-10 09:41:45 +01001655 for (par = node->parent; par; par = par->parent) {
1656 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
1657 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +01001658 par->flags &= ~LYD_DEFAULT;
1659 }
Michal Vaskob104f112020-07-17 09:54:54 +02001660 if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001661 /* rehash key-less list */
1662 lyd_hash((struct lyd_node *)par);
1663 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001664 }
Michal Vasko90932a92020-02-12 14:33:03 +01001665}
1666
1667/**
1668 * @brief Insert node before a sibling.
1669 *
Michal Vasko9f96a052020-03-10 09:41:45 +01001670 * Handles inserting into NP containers and key-less lists.
1671 *
Michal Vasko90932a92020-02-12 14:33:03 +01001672 * @param[in] sibling Sibling to insert before.
1673 * @param[in] node Node to insert.
1674 */
1675static void
Michal Vaskof03ed032020-03-04 13:31:44 +01001676lyd_insert_before_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001677{
Michal Vasko0249f7c2020-03-05 16:36:40 +01001678 struct lyd_node_inner *par;
1679
Michal Vasko90932a92020-02-12 14:33:03 +01001680 assert(!node->next && (node->prev == node));
1681
1682 node->next = sibling;
1683 /* covers situation of sibling being first */
1684 node->prev = sibling->prev;
1685 sibling->prev = node;
1686 if (node->prev->next) {
1687 /* sibling had a preceding node */
1688 node->prev->next = node;
1689 } else if (sibling->parent) {
1690 /* sibling was first and we must also change parent child pointer */
1691 sibling->parent->child = node;
1692 }
1693 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001694
Michal Vasko9f96a052020-03-10 09:41:45 +01001695 for (par = node->parent; par; par = par->parent) {
1696 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
1697 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +01001698 par->flags &= ~LYD_DEFAULT;
1699 }
Michal Vaskob104f112020-07-17 09:54:54 +02001700 if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001701 /* rehash key-less list */
1702 lyd_hash((struct lyd_node *)par);
1703 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001704 }
Michal Vasko90932a92020-02-12 14:33:03 +01001705}
1706
1707/**
Michal Vaskob104f112020-07-17 09:54:54 +02001708 * @brief Insert node as the first and only child of a parent.
Michal Vasko90932a92020-02-12 14:33:03 +01001709 *
Michal Vasko9f96a052020-03-10 09:41:45 +01001710 * Handles inserting into NP containers and key-less lists.
1711 *
Michal Vasko90932a92020-02-12 14:33:03 +01001712 * @param[in] parent Parent to insert into.
1713 * @param[in] node Node to insert.
1714 */
1715static void
Michal Vaskob104f112020-07-17 09:54:54 +02001716lyd_insert_only_child(struct lyd_node *parent, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001717{
1718 struct lyd_node_inner *par;
1719
Michal Vaskob104f112020-07-17 09:54:54 +02001720 assert(parent && !lyd_node_children(parent, 0) && !node->next && (node->prev == node));
Michal Vasko52927e22020-03-16 17:26:14 +01001721 assert(!parent->schema || (parent->schema->nodetype & LYD_NODE_INNER));
Michal Vasko90932a92020-02-12 14:33:03 +01001722
1723 par = (struct lyd_node_inner *)parent;
1724
Michal Vaskob104f112020-07-17 09:54:54 +02001725 par->child = node;
Michal Vasko90932a92020-02-12 14:33:03 +01001726 node->parent = par;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001727
Michal Vasko9f96a052020-03-10 09:41:45 +01001728 for (; par; par = par->parent) {
1729 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
1730 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +01001731 par->flags &= ~LYD_DEFAULT;
1732 }
Michal Vasko52927e22020-03-16 17:26:14 +01001733 if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001734 /* rehash key-less list */
1735 lyd_hash((struct lyd_node *)par);
1736 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001737 }
Michal Vasko751cb4d2020-07-14 12:25:28 +02001738}
Michal Vasko0249f7c2020-03-05 16:36:40 +01001739
Michal Vasko751cb4d2020-07-14 12:25:28 +02001740/**
1741 * @brief Learn whether a list instance has all the keys.
1742 *
1743 * @param[in] list List instance to check.
1744 * @return non-zero if all the keys were found,
1745 * @return 0 otherwise.
1746 */
1747static int
1748lyd_insert_has_keys(const struct lyd_node *list)
1749{
1750 const struct lyd_node *key;
1751 const struct lysc_node *skey = NULL;
1752
1753 assert(list->schema->nodetype == LYS_LIST);
1754 key = lyd_node_children(list, 0);
1755 while ((skey = lys_getnext(skey, list->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
1756 if (!key || (key->schema != skey)) {
1757 /* key missing */
1758 return 0;
1759 }
1760
1761 key = key->next;
1762 }
1763
1764 /* all keys found */
1765 return 1;
Michal Vasko90932a92020-02-12 14:33:03 +01001766}
1767
1768void
Michal Vaskob104f112020-07-17 09:54:54 +02001769lyd_insert_node(struct lyd_node *parent, struct lyd_node **first_sibling_p, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001770{
Michal Vaskob104f112020-07-17 09:54:54 +02001771 struct lyd_node *anchor, *first_sibling;
Michal Vasko90932a92020-02-12 14:33:03 +01001772
Michal Vaskob104f112020-07-17 09:54:54 +02001773 /* inserting list without its keys is not supported */
1774 assert((parent || first_sibling_p) && node && (node->hash || !node->schema));
Michal Vasko9b368d32020-02-14 13:53:31 +01001775
Michal Vaskob104f112020-07-17 09:54:54 +02001776 if (!parent && first_sibling_p && (*first_sibling_p) && (*first_sibling_p)->parent) {
1777 parent = (struct lyd_node *)(*first_sibling_p)->parent;
Michal Vasko9b368d32020-02-14 13:53:31 +01001778 }
Michal Vasko90932a92020-02-12 14:33:03 +01001779
Michal Vaskob104f112020-07-17 09:54:54 +02001780 /* get first sibling */
1781 first_sibling = parent ? ((struct lyd_node_inner *)parent)->child : *first_sibling_p;
Michal Vasko9f96a052020-03-10 09:41:45 +01001782
Michal Vaskob104f112020-07-17 09:54:54 +02001783 /* find the anchor, our next node, so we can insert before it */
1784 anchor = lyd_insert_get_next_anchor(first_sibling, node);
1785 if (anchor) {
1786 lyd_insert_before_node(anchor, node);
1787 } else if (first_sibling) {
1788 lyd_insert_after_node(first_sibling->prev, node);
1789 } else if (parent) {
1790 lyd_insert_only_child(parent, node);
Michal Vasko90932a92020-02-12 14:33:03 +01001791 } else {
Michal Vaskob104f112020-07-17 09:54:54 +02001792 *first_sibling_p = node;
1793 }
1794
1795 /* insert into parent HT */
1796 lyd_insert_hash(node);
1797
1798 /* finish hashes for our parent, if needed and possible */
1799 if (node->schema && (node->schema->flags & LYS_KEY) && lyd_insert_has_keys(parent)) {
1800 lyd_hash(parent);
1801
1802 /* now we can insert even the list into its parent HT */
1803 lyd_insert_hash(parent);
Michal Vasko90932a92020-02-12 14:33:03 +01001804 }
Michal Vasko90932a92020-02-12 14:33:03 +01001805}
1806
Michal Vaskof03ed032020-03-04 13:31:44 +01001807static LY_ERR
1808lyd_insert_check_schema(const struct lysc_node *parent, const struct lysc_node *schema)
1809{
1810 const struct lysc_node *par2;
1811
1812 assert(schema);
Michal Vasko62ed12d2020-05-21 10:08:25 +02001813 assert(!parent || !(parent->nodetype & (LYS_CASE | LYS_CHOICE)));
Michal Vaskof03ed032020-03-04 13:31:44 +01001814
1815 /* find schema parent */
Michal Vasko62ed12d2020-05-21 10:08:25 +02001816 par2 = lysc_data_parent(schema);
Michal Vaskof03ed032020-03-04 13:31:44 +01001817
1818 if (parent) {
1819 /* inner node */
1820 if (par2 != parent) {
Michal Vaskob104f112020-07-17 09:54:54 +02001821 LOGERR(schema->module->ctx, LY_EINVAL, "Cannot insert, parent of \"%s\" is not \"%s\".", schema->name,
1822 parent->name);
Michal Vaskof03ed032020-03-04 13:31:44 +01001823 return LY_EINVAL;
1824 }
1825 } else {
1826 /* top-level node */
1827 if (par2) {
Radek Krejcif6d14cb2020-07-02 16:11:45 +02001828 LOGERR(schema->module->ctx, LY_EINVAL, "Cannot insert, node \"%s\" is not top-level.", schema->name);
Michal Vaskof03ed032020-03-04 13:31:44 +01001829 return LY_EINVAL;
1830 }
1831 }
1832
1833 return LY_SUCCESS;
1834}
1835
1836API LY_ERR
Michal Vaskob104f112020-07-17 09:54:54 +02001837lyd_insert_child(struct lyd_node *parent, struct lyd_node *node)
Michal Vaskof03ed032020-03-04 13:31:44 +01001838{
1839 struct lyd_node *iter;
1840
Michal Vasko654bc852020-06-23 13:28:06 +02001841 LY_CHECK_ARG_RET(NULL, parent, node, parent->schema->nodetype & LYD_NODE_INNER, LY_EINVAL);
Michal Vaskof03ed032020-03-04 13:31:44 +01001842
1843 LY_CHECK_RET(lyd_insert_check_schema(parent->schema, node->schema));
1844
1845 if (node->schema->flags & LYS_KEY) {
1846 LOGERR(parent->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1847 return LY_EINVAL;
1848 }
1849
1850 if (node->parent || node->prev->next) {
1851 lyd_unlink_tree(node);
1852 }
1853
1854 while (node) {
1855 iter = node->next;
1856 lyd_unlink_tree(node);
1857 lyd_insert_node(parent, NULL, node);
1858 node = iter;
1859 }
1860 return LY_SUCCESS;
1861}
1862
1863API LY_ERR
Michal Vaskob104f112020-07-17 09:54:54 +02001864lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, struct lyd_node **first)
Michal Vaskob1b5c262020-03-05 14:29:47 +01001865{
1866 struct lyd_node *iter;
1867
Michal Vaskob104f112020-07-17 09:54:54 +02001868 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Michal Vaskob1b5c262020-03-05 14:29:47 +01001869
Michal Vaskob104f112020-07-17 09:54:54 +02001870 if (sibling) {
1871 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskob1b5c262020-03-05 14:29:47 +01001872 }
1873
1874 if (node->parent || node->prev->next) {
1875 lyd_unlink_tree(node);
1876 }
1877
1878 while (node) {
Michal Vaskob104f112020-07-17 09:54:54 +02001879 if (node->schema->flags & LYS_KEY) {
1880 LOGERR(LYD_NODE_CTX(node), LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1881 return LY_EINVAL;
1882 }
1883
Michal Vaskob1b5c262020-03-05 14:29:47 +01001884 iter = node->next;
1885 lyd_unlink_tree(node);
1886 lyd_insert_node(NULL, &sibling, node);
1887 node = iter;
1888 }
Michal Vaskob1b5c262020-03-05 14:29:47 +01001889
Michal Vaskob104f112020-07-17 09:54:54 +02001890 if (first) {
1891 /* find the first sibling */
1892 *first = sibling;
1893 while ((*first)->prev->next) {
1894 *first = (*first)->prev;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001895 }
1896 }
1897
1898 return LY_SUCCESS;
1899}
1900
Michal Vaskob1b5c262020-03-05 14:29:47 +01001901API LY_ERR
Michal Vaskof03ed032020-03-04 13:31:44 +01001902lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
1903{
1904 struct lyd_node *iter;
1905
1906 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1907
Michal Vasko62ed12d2020-05-21 10:08:25 +02001908 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskof03ed032020-03-04 13:31:44 +01001909
Michal Vaskob104f112020-07-17 09:54:54 +02001910 if (!(node->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(node->schema->flags & LYS_ORDBY_USER)) {
1911 LOGERR(LYD_NODE_CTX(sibling), LY_EINVAL, "Can be used only for user-ordered nodes.");
Michal Vaskof03ed032020-03-04 13:31:44 +01001912 return LY_EINVAL;
1913 }
1914
1915 if (node->parent || node->prev->next) {
1916 lyd_unlink_tree(node);
1917 }
1918
1919 /* insert in reverse order to get the original order */
1920 node = node->prev;
1921 while (node) {
1922 iter = node->prev;
1923 lyd_unlink_tree(node);
1924
1925 lyd_insert_before_node(sibling, node);
Michal Vasko751cb4d2020-07-14 12:25:28 +02001926 lyd_insert_hash(node);
1927
Michal Vaskof03ed032020-03-04 13:31:44 +01001928 /* move the anchor accordingly */
1929 sibling = node;
1930
1931 node = (iter == node) ? NULL : iter;
1932 }
1933 return LY_SUCCESS;
1934}
1935
1936API LY_ERR
1937lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
1938{
1939 struct lyd_node *iter;
1940
1941 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1942
Michal Vasko62ed12d2020-05-21 10:08:25 +02001943 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskof03ed032020-03-04 13:31:44 +01001944
Michal Vaskob104f112020-07-17 09:54:54 +02001945 if (!(node->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(node->schema->flags & LYS_ORDBY_USER)) {
1946 LOGERR(LYD_NODE_CTX(sibling), LY_EINVAL, "Can be used only for user-ordered nodes.");
Michal Vaskof03ed032020-03-04 13:31:44 +01001947 return LY_EINVAL;
1948 }
1949
1950 if (node->parent || node->prev->next) {
1951 lyd_unlink_tree(node);
1952 }
1953
1954 while (node) {
1955 iter = node->next;
1956 lyd_unlink_tree(node);
1957
1958 lyd_insert_after_node(sibling, node);
Michal Vasko751cb4d2020-07-14 12:25:28 +02001959 lyd_insert_hash(node);
1960
Michal Vaskof03ed032020-03-04 13:31:44 +01001961 /* move the anchor accordingly */
1962 sibling = node;
1963
1964 node = iter;
1965 }
1966 return LY_SUCCESS;
1967}
1968
1969API void
1970lyd_unlink_tree(struct lyd_node *node)
1971{
1972 struct lyd_node *iter;
1973
1974 if (!node) {
1975 return;
1976 }
1977
Michal Vaskob104f112020-07-17 09:54:54 +02001978 /* update hashes while still linked into the tree */
1979 lyd_unlink_hash(node);
1980
Michal Vaskof03ed032020-03-04 13:31:44 +01001981 /* unlink from siblings */
1982 if (node->prev->next) {
1983 node->prev->next = node->next;
1984 }
1985 if (node->next) {
1986 node->next->prev = node->prev;
1987 } else {
1988 /* unlinking the last node */
1989 if (node->parent) {
1990 iter = node->parent->child;
1991 } else {
1992 iter = node->prev;
1993 while (iter->prev != node) {
1994 iter = iter->prev;
1995 }
1996 }
1997 /* update the "last" pointer from the first node */
1998 iter->prev = node->prev;
1999 }
2000
2001 /* unlink from parent */
2002 if (node->parent) {
2003 if (node->parent->child == node) {
2004 /* the node is the first child */
2005 node->parent->child = node->next;
2006 }
2007
Michal Vaskoab49dbe2020-07-17 12:32:47 +02002008 /* check for NP container whether its last non-default node is not being unlinked */
2009 if (node->parent->schema && (node->parent->schema->nodetype == LYS_CONTAINER)
2010 && !(node->parent->flags & LYD_DEFAULT) && !(node->parent->schema->flags & LYS_PRESENCE)) {
2011 LY_LIST_FOR(node->parent->child, iter) {
2012 if ((iter != node) && !(iter->flags & LYD_DEFAULT)) {
2013 break;
2014 }
2015 }
2016 if (!iter) {
2017 node->parent->flags |= LYD_DEFAULT;
2018 }
2019 }
2020
Michal Vaskof03ed032020-03-04 13:31:44 +01002021 /* check for keyless list and update its hash */
2022 for (iter = (struct lyd_node *)node->parent; iter; iter = (struct lyd_node *)iter->parent) {
Michal Vasko413c7f22020-05-05 12:34:06 +02002023 if (iter->schema && (iter->schema->flags & LYS_KEYLESS)) {
Michal Vaskof03ed032020-03-04 13:31:44 +01002024 lyd_hash(iter);
2025 }
2026 }
2027
2028 node->parent = NULL;
2029 }
2030
2031 node->next = NULL;
2032 node->prev = node;
2033}
2034
Michal Vasko90932a92020-02-12 14:33:03 +01002035LY_ERR
Michal Vasko9f96a052020-03-10 09:41:45 +01002036lyd_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 +01002037 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 +01002038 void *prefix_data, LYD_FORMAT format, const struct lysc_node *ctx_snode)
Michal Vasko90932a92020-02-12 14:33:03 +01002039{
2040 LY_ERR ret;
2041 struct lysc_ext_instance *ant = NULL;
Michal Vasko9f96a052020-03-10 09:41:45 +01002042 struct lyd_meta *mt, *last;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002043 LY_ARRAY_COUNT_TYPE u;
Michal Vasko90932a92020-02-12 14:33:03 +01002044
Michal Vasko9f96a052020-03-10 09:41:45 +01002045 assert((parent || meta) && mod);
Michal Vasko6f4cbb62020-02-28 11:15:47 +01002046
Radek Krejci7eb54ba2020-05-18 16:30:04 +02002047 LY_ARRAY_FOR(mod->compiled->exts, u) {
2048 if (mod->compiled->exts[u].def->plugin == lyext_plugins_internal[LYEXT_PLUGIN_INTERNAL_ANNOTATION].plugin &&
2049 !ly_strncmp(mod->compiled->exts[u].argument, name, name_len)) {
Michal Vasko90932a92020-02-12 14:33:03 +01002050 /* we have the annotation definition */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02002051 ant = &mod->compiled->exts[u];
Michal Vasko90932a92020-02-12 14:33:03 +01002052 break;
2053 }
2054 }
2055 if (!ant) {
2056 /* attribute is not defined as a metadata annotation (RFC 7952) */
2057 LOGERR(mod->ctx, LY_EINVAL, "Annotation definition for attribute \"%s:%.*s\" not found.",
2058 mod->name, name_len, name);
2059 return LY_EINVAL;
2060 }
2061
Michal Vasko9f96a052020-03-10 09:41:45 +01002062 mt = calloc(1, sizeof *mt);
2063 LY_CHECK_ERR_RET(!mt, LOGMEM(mod->ctx), LY_EMEM);
2064 mt->parent = parent;
2065 mt->annotation = ant;
Michal Vasko52927e22020-03-16 17:26:14 +01002066 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 +01002067 if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01002068 free(mt);
Michal Vasko90932a92020-02-12 14:33:03 +01002069 return ret;
2070 }
Michal Vasko9f96a052020-03-10 09:41:45 +01002071 mt->name = lydict_insert(mod->ctx, name, name_len);
Michal Vasko90932a92020-02-12 14:33:03 +01002072
Michal Vasko6f4cbb62020-02-28 11:15:47 +01002073 /* insert as the last attribute */
2074 if (parent) {
Michal Vasko9f96a052020-03-10 09:41:45 +01002075 if (parent->meta) {
2076 for (last = parent->meta; last->next; last = last->next);
2077 last->next = mt;
Michal Vasko6f4cbb62020-02-28 11:15:47 +01002078 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +01002079 parent->meta = mt;
Michal Vasko6f4cbb62020-02-28 11:15:47 +01002080 }
Michal Vasko9f96a052020-03-10 09:41:45 +01002081 } else if (*meta) {
2082 for (last = *meta; last->next; last = last->next);
2083 last->next = mt;
Michal Vasko90932a92020-02-12 14:33:03 +01002084 }
2085
2086 /* remove default flags from NP containers */
Michal Vasko4ba6aef2020-07-09 15:44:23 +02002087 while (parent && (parent->schema->nodetype == LYS_CONTAINER) && (parent->flags & LYD_DEFAULT)) {
Michal Vasko90932a92020-02-12 14:33:03 +01002088 parent->flags &= ~LYD_DEFAULT;
2089 parent = (struct lyd_node *)parent->parent;
2090 }
2091
Michal Vasko9f96a052020-03-10 09:41:45 +01002092 if (meta) {
2093 *meta = mt;
Michal Vasko90932a92020-02-12 14:33:03 +01002094 }
2095 return ret;
2096}
2097
Michal Vasko52927e22020-03-16 17:26:14 +01002098LY_ERR
2099ly_create_attr(struct lyd_node *parent, struct ly_attr **attr, const struct ly_ctx *ctx, const char *name,
2100 size_t name_len, const char *value, size_t value_len, int *dynamic, LYD_FORMAT format,
2101 struct ly_prefix *val_prefs, const char *prefix, size_t prefix_len, const char *ns)
2102{
2103 struct ly_attr *at, *last;
2104 struct lyd_node_opaq *opaq;
2105
2106 assert(ctx && (parent || attr) && (!parent || !parent->schema));
2107 assert(name && name_len);
2108 assert((prefix_len && ns) || (!prefix_len && !ns));
2109
2110 if (!value_len) {
2111 value = "";
2112 }
2113
2114 at = calloc(1, sizeof *at);
2115 LY_CHECK_ERR_RET(!at, LOGMEM(ctx), LY_EMEM);
2116 at->parent = (struct lyd_node_opaq *)parent;
2117 at->name = lydict_insert(ctx, name, name_len);
2118 if (dynamic && *dynamic) {
2119 at->value = lydict_insert_zc(ctx, (char *)value);
2120 *dynamic = 0;
2121 } else {
2122 at->value = lydict_insert(ctx, value, value_len);
2123 }
2124
2125 at->format = format;
2126 at->val_prefs = val_prefs;
2127 if (ns) {
2128 at->prefix.pref = lydict_insert(ctx, prefix, prefix_len);
2129 at->prefix.ns = lydict_insert(ctx, ns, 0);
2130 }
2131
2132 /* insert as the last attribute */
2133 if (parent) {
2134 opaq = (struct lyd_node_opaq *)parent;
2135 if (opaq->attr) {
2136 for (last = opaq->attr; last->next; last = last->next);
2137 last->next = at;
2138 } else {
2139 opaq->attr = at;
2140 }
2141 } else if (*attr) {
2142 for (last = *attr; last->next; last = last->next);
2143 last->next = at;
2144 }
2145
2146 if (attr) {
2147 *attr = at;
2148 }
2149 return LY_SUCCESS;
2150}
2151
Radek Krejci084289f2019-07-09 17:35:30 +02002152API const struct lyd_node_term *
Michal Vasko004d3152020-06-11 19:59:22 +02002153lyd_target(const struct ly_path *path, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +02002154{
Michal Vasko004d3152020-06-11 19:59:22 +02002155 struct lyd_node *target;
Radek Krejci084289f2019-07-09 17:35:30 +02002156
Michal Vasko004d3152020-06-11 19:59:22 +02002157 if (ly_path_eval(path, tree, &target)) {
2158 return NULL;
Radek Krejci084289f2019-07-09 17:35:30 +02002159 }
2160
Michal Vasko004d3152020-06-11 19:59:22 +02002161 return (struct lyd_node_term *)target;
Radek Krejci084289f2019-07-09 17:35:30 +02002162}
2163
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002164API LY_ERR
Michal Vasko8f359bf2020-07-28 10:41:15 +02002165lyd_compare_single(const struct lyd_node *node1, const struct lyd_node *node2, int options)
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002166{
2167 const struct lyd_node *iter1, *iter2;
2168 struct lyd_node_term *term1, *term2;
2169 struct lyd_node_any *any1, *any2;
Michal Vasko52927e22020-03-16 17:26:14 +01002170 struct lyd_node_opaq *opaq1, *opaq2;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002171 size_t len1, len2;
Radek Krejci084289f2019-07-09 17:35:30 +02002172
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002173 if (!node1 || !node2) {
2174 if (node1 == node2) {
2175 return LY_SUCCESS;
2176 } else {
2177 return LY_ENOT;
2178 }
2179 }
2180
Michal Vasko52927e22020-03-16 17:26:14 +01002181 if ((LYD_NODE_CTX(node1) != LYD_NODE_CTX(node2)) || (node1->schema != node2->schema)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002182 return LY_ENOT;
2183 }
2184
2185 if (node1->hash != node2->hash) {
2186 return LY_ENOT;
2187 }
Michal Vasko52927e22020-03-16 17:26:14 +01002188 /* 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 +02002189
Michal Vasko52927e22020-03-16 17:26:14 +01002190 if (!node1->schema) {
2191 opaq1 = (struct lyd_node_opaq *)node1;
2192 opaq2 = (struct lyd_node_opaq *)node2;
2193 if ((opaq1->name != opaq2->name) || (opaq1->prefix.ns != opaq2->prefix.ns) || (opaq1->format != opaq2->format)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002194 return LY_ENOT;
2195 }
Michal Vasko52927e22020-03-16 17:26:14 +01002196 switch (opaq1->format) {
2197 case LYD_XML:
2198 if (lyxml_value_compare(opaq1->value, opaq1->val_prefs, opaq2->value, opaq2->val_prefs)) {
2199 return LY_ENOT;
2200 }
2201 break;
2202 case LYD_SCHEMA:
Michal Vasko60ea6352020-06-29 13:39:39 +02002203 case LYD_LYB:
Michal Vasko52927e22020-03-16 17:26:14 +01002204 /* not allowed */
2205 LOGINT(LYD_NODE_CTX(node1));
2206 return LY_EINT;
2207 }
2208 if (options & LYD_COMPARE_FULL_RECURSION) {
2209 iter1 = opaq1->child;
2210 iter2 = opaq2->child;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002211 goto all_children_compare;
Michal Vasko52927e22020-03-16 17:26:14 +01002212 }
2213 return LY_SUCCESS;
2214 } else {
2215 switch (node1->schema->nodetype) {
2216 case LYS_LEAF:
2217 case LYS_LEAFLIST:
2218 if (options & LYD_COMPARE_DEFAULTS) {
2219 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
2220 return LY_ENOT;
2221 }
2222 }
2223
Michal Vasko1a2bf2e2020-06-16 13:07:48 +02002224 term1 = (struct lyd_node_term *)node1;
2225 term2 = (struct lyd_node_term *)node2;
2226 if (term1->value.realtype != term2->value.realtype) {
2227 return LY_ENOT;
2228 }
Michal Vasko52927e22020-03-16 17:26:14 +01002229
Michal Vasko1a2bf2e2020-06-16 13:07:48 +02002230 return term1->value.realtype->plugin->compare(&term1->value, &term2->value);
Michal Vasko52927e22020-03-16 17:26:14 +01002231 case LYS_CONTAINER:
2232 if (options & LYD_COMPARE_DEFAULTS) {
2233 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
2234 return LY_ENOT;
2235 }
2236 }
2237 if (options & LYD_COMPARE_FULL_RECURSION) {
2238 iter1 = ((struct lyd_node_inner*)node1)->child;
2239 iter2 = ((struct lyd_node_inner*)node2)->child;
2240 goto all_children_compare;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002241 }
2242 return LY_SUCCESS;
Michal Vasko1bf09392020-03-27 12:38:10 +01002243 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01002244 case LYS_ACTION:
2245 if (options & LYD_COMPARE_FULL_RECURSION) {
2246 /* TODO action/RPC
2247 goto all_children_compare;
2248 */
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002249 }
2250 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01002251 case LYS_NOTIF:
2252 if (options & LYD_COMPARE_FULL_RECURSION) {
2253 /* TODO Notification
2254 goto all_children_compare;
2255 */
2256 }
2257 return LY_SUCCESS;
2258 case LYS_LIST:
2259 iter1 = ((struct lyd_node_inner*)node1)->child;
2260 iter2 = ((struct lyd_node_inner*)node2)->child;
2261
2262 if (!(node1->schema->flags & LYS_KEYLESS) && !(options & LYD_COMPARE_FULL_RECURSION)) {
2263 /* lists with keys, their equivalence is based on their keys */
2264 for (struct lysc_node *key = ((struct lysc_node_list*)node1->schema)->child;
Michal Vaskoc57d9a92020-06-23 13:28:27 +02002265 key && (key->flags & LYS_KEY);
Michal Vasko52927e22020-03-16 17:26:14 +01002266 key = key->next) {
Michal Vasko8f359bf2020-07-28 10:41:15 +02002267 if (lyd_compare_single(iter1, iter2, options)) {
Michal Vasko52927e22020-03-16 17:26:14 +01002268 return LY_ENOT;
2269 }
2270 iter1 = iter1->next;
2271 iter2 = iter2->next;
2272 }
2273 } else {
2274 /* lists without keys, their equivalence is based on equivalence of all the children (both direct and indirect) */
2275
2276 all_children_compare:
2277 if (!iter1 && !iter2) {
2278 /* no children, nothing to compare */
2279 return LY_SUCCESS;
2280 }
2281
2282 for (; iter1 && iter2; iter1 = iter1->next, iter2 = iter2->next) {
Michal Vasko8f359bf2020-07-28 10:41:15 +02002283 if (lyd_compare_single(iter1, iter2, options | LYD_COMPARE_FULL_RECURSION)) {
Michal Vasko52927e22020-03-16 17:26:14 +01002284 return LY_ENOT;
2285 }
2286 }
2287 if (iter1 || iter2) {
2288 return LY_ENOT;
2289 }
2290 }
2291 return LY_SUCCESS;
2292 case LYS_ANYXML:
2293 case LYS_ANYDATA:
2294 any1 = (struct lyd_node_any*)node1;
2295 any2 = (struct lyd_node_any*)node2;
2296
2297 if (any1->value_type != any2->value_type) {
2298 return LY_ENOT;
2299 }
2300 switch (any1->value_type) {
2301 case LYD_ANYDATA_DATATREE:
2302 iter1 = any1->value.tree;
2303 iter2 = any2->value.tree;
2304 goto all_children_compare;
2305 case LYD_ANYDATA_STRING:
2306 case LYD_ANYDATA_XML:
2307 case LYD_ANYDATA_JSON:
2308 len1 = strlen(any1->value.str);
2309 len2 = strlen(any2->value.str);
2310 if (len1 != len2 || strcmp(any1->value.str, any2->value.str)) {
2311 return LY_ENOT;
2312 }
2313 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01002314 case LYD_ANYDATA_LYB:
Michal Vasko60ea6352020-06-29 13:39:39 +02002315 len1 = lyd_lyb_data_length(any1->value.mem);
2316 len2 = lyd_lyb_data_length(any2->value.mem);
Michal Vasko52927e22020-03-16 17:26:14 +01002317 if (len1 != len2 || memcmp(any1->value.mem, any2->value.mem, len1)) {
2318 return LY_ENOT;
2319 }
2320 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01002321 }
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002322 }
2323 }
2324
Michal Vasko52927e22020-03-16 17:26:14 +01002325 LOGINT(LYD_NODE_CTX(node1));
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002326 return LY_EINT;
2327}
Radek Krejci22ebdba2019-07-25 13:59:43 +02002328
Michal Vasko21725742020-06-29 11:49:25 +02002329API LY_ERR
Michal Vasko8f359bf2020-07-28 10:41:15 +02002330lyd_compare_siblings(const struct lyd_node *node1, const struct lyd_node *node2, int options)
2331{
2332 for (; node1 && node2; node1 = node1->next, node2 = node2->next) {
2333 LY_CHECK_RET(lyd_compare_single(node1, node2, options));
2334 }
2335
Michal Vasko11a81432020-07-28 16:31:29 +02002336 if (node1 == node2) {
2337 return LY_SUCCESS;
Michal Vasko8f359bf2020-07-28 10:41:15 +02002338 }
Michal Vasko11a81432020-07-28 16:31:29 +02002339 return LY_ENOT;
Michal Vasko8f359bf2020-07-28 10:41:15 +02002340}
2341
2342API LY_ERR
Michal Vasko21725742020-06-29 11:49:25 +02002343lyd_compare_meta(const struct lyd_meta *meta1, const struct lyd_meta *meta2)
2344{
2345 if (!meta1 || !meta2) {
2346 if (meta1 == meta2) {
2347 return LY_SUCCESS;
2348 } else {
2349 return LY_ENOT;
2350 }
2351 }
2352
2353 if ((LYD_NODE_CTX(meta1->parent) != LYD_NODE_CTX(meta2->parent)) || (meta1->annotation != meta2->annotation)) {
2354 return LY_ENOT;
2355 }
2356
2357 if (meta1->value.realtype != meta2->value.realtype) {
2358 return LY_ENOT;
2359 }
2360
2361 return meta1->value.realtype->plugin->compare(&meta1->value, &meta2->value);
2362}
2363
Radek Krejci22ebdba2019-07-25 13:59:43 +02002364/**
Michal Vasko52927e22020-03-16 17:26:14 +01002365 * @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 +02002366 *
2367 * 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 +02002368 *
2369 * @param[in] node Original node to duplicate
2370 * @param[in] parent Parent to insert into, NULL for top-level sibling.
2371 * @param[in,out] first First sibling, NULL if no top-level sibling exist yet. Can be also NULL if @p parent is set.
2372 * @param[in] options Bitmask of options flags, see @ref dupoptions.
2373 * @param[out] dup_p Pointer where the created duplicated node is placed (besides connecting it int @p parent / @p first sibling).
2374 * @return LY_ERR value
Radek Krejci22ebdba2019-07-25 13:59:43 +02002375 */
Michal Vasko52927e22020-03-16 17:26:14 +01002376static LY_ERR
Michal Vasko3a41dff2020-07-15 14:30:28 +02002377lyd_dup_r(const struct lyd_node *node, struct lyd_node *parent, struct lyd_node **first, int options,
2378 struct lyd_node **dup_p)
Radek Krejci22ebdba2019-07-25 13:59:43 +02002379{
Michal Vasko52927e22020-03-16 17:26:14 +01002380 LY_ERR ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002381 struct lyd_node *dup = NULL;
Michal Vasko61551fa2020-07-09 15:45:45 +02002382 struct lyd_meta *meta;
2383 struct lyd_node_any *any;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002384 LY_ARRAY_COUNT_TYPE u;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002385
Michal Vasko52927e22020-03-16 17:26:14 +01002386 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002387
Michal Vasko52927e22020-03-16 17:26:14 +01002388 if (!node->schema) {
2389 dup = calloc(1, sizeof(struct lyd_node_opaq));
2390 } else {
2391 switch (node->schema->nodetype) {
Michal Vasko1bf09392020-03-27 12:38:10 +01002392 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01002393 case LYS_ACTION:
2394 case LYS_NOTIF:
2395 case LYS_CONTAINER:
2396 case LYS_LIST:
2397 dup = calloc(1, sizeof(struct lyd_node_inner));
2398 break;
2399 case LYS_LEAF:
2400 case LYS_LEAFLIST:
2401 dup = calloc(1, sizeof(struct lyd_node_term));
2402 break;
2403 case LYS_ANYDATA:
2404 case LYS_ANYXML:
2405 dup = calloc(1, sizeof(struct lyd_node_any));
2406 break;
2407 default:
2408 LOGINT(LYD_NODE_CTX(node));
2409 ret = LY_EINT;
2410 goto error;
2411 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02002412 }
Michal Vasko52927e22020-03-16 17:26:14 +01002413 LY_CHECK_ERR_GOTO(!dup, LOGMEM(LYD_NODE_CTX(node)); ret = LY_EMEM, error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002414
Michal Vaskof6df0a02020-06-16 13:08:34 +02002415 if (options & LYD_DUP_WITH_FLAGS) {
2416 dup->flags = node->flags;
2417 } else {
2418 dup->flags = (node->flags & LYD_DEFAULT) | LYD_NEW;
2419 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02002420 dup->schema = node->schema;
Michal Vasko52927e22020-03-16 17:26:14 +01002421 dup->prev = dup;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002422
Michal Vasko25a32822020-07-09 15:48:22 +02002423 /* duplicate metadata */
2424 if (!(options & LYD_DUP_NO_META)) {
2425 LY_LIST_FOR(node->meta, meta) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002426 LY_CHECK_GOTO(ret = lyd_dup_meta_single(meta, dup, NULL), error);
Michal Vasko25a32822020-07-09 15:48:22 +02002427 }
2428 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02002429
2430 /* nodetype-specific work */
Michal Vasko52927e22020-03-16 17:26:14 +01002431 if (!dup->schema) {
2432 struct lyd_node_opaq *opaq = (struct lyd_node_opaq *)dup;
2433 struct lyd_node_opaq *orig = (struct lyd_node_opaq *)node;
2434 struct lyd_node *child;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002435
2436 if (options & LYD_DUP_RECURSIVE) {
2437 /* duplicate all the children */
2438 LY_LIST_FOR(orig->child, child) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002439 LY_CHECK_GOTO(ret = lyd_dup_r(child, dup, NULL, options, NULL), error);
Michal Vasko52927e22020-03-16 17:26:14 +01002440 }
2441 }
2442 opaq->name = lydict_insert(LYD_NODE_CTX(node), orig->name, 0);
2443 opaq->format = orig->format;
2444 if (orig->prefix.pref) {
2445 opaq->prefix.pref = lydict_insert(LYD_NODE_CTX(node), orig->prefix.pref, 0);
2446 }
2447 if (orig->prefix.ns) {
2448 opaq->prefix.ns = lydict_insert(LYD_NODE_CTX(node), orig->prefix.ns, 0);
2449 }
2450 if (orig->val_prefs) {
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002451 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 +01002452 LY_ARRAY_FOR(orig->val_prefs, u) {
2453 opaq->val_prefs[u].pref = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].pref, 0);
2454 opaq->val_prefs[u].ns = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].ns, 0);
2455 LY_ARRAY_INCREMENT(opaq->val_prefs);
2456 }
2457 }
2458 opaq->value = lydict_insert(LYD_NODE_CTX(node), orig->value, 0);
2459 opaq->ctx = orig->ctx;
2460 } else if (dup->schema->nodetype & LYD_NODE_TERM) {
2461 struct lyd_node_term *term = (struct lyd_node_term *)dup;
2462 struct lyd_node_term *orig = (struct lyd_node_term *)node;
2463
2464 term->hash = orig->hash;
2465 term->value.realtype = orig->value.realtype;
2466 LY_CHECK_ERR_GOTO(term->value.realtype->plugin->duplicate(LYD_NODE_CTX(node), &orig->value, &term->value),
2467 LOGERR(LYD_NODE_CTX(node), LY_EINT, "Value duplication failed."); ret = LY_EINT, error);
2468 } else if (dup->schema->nodetype & LYD_NODE_INNER) {
2469 struct lyd_node_inner *orig = (struct lyd_node_inner *)node;
2470 struct lyd_node *child;
2471
2472 if (options & LYD_DUP_RECURSIVE) {
2473 /* duplicate all the children */
2474 LY_LIST_FOR(orig->child, child) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002475 LY_CHECK_GOTO(ret = lyd_dup_r(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002476 }
Radek Krejci0fe9b512019-07-26 17:51:05 +02002477 } else if (dup->schema->nodetype == LYS_LIST && !(dup->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002478 /* always duplicate keys of a list */
Radek Krejci22ebdba2019-07-25 13:59:43 +02002479 child = orig->child;
Michal Vasko52927e22020-03-16 17:26:14 +01002480 for (struct lysc_node *key = ((struct lysc_node_list *)dup->schema)->child;
Michal Vaskoc57d9a92020-06-23 13:28:27 +02002481 key && (key->flags & LYS_KEY);
Radek Krejci0fe9b512019-07-26 17:51:05 +02002482 key = key->next) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002483 if (!child) {
2484 /* possibly not keys are present in filtered tree */
2485 break;
Radek Krejci0fe9b512019-07-26 17:51:05 +02002486 } else if (child->schema != key) {
2487 /* possibly not all keys are present in filtered tree,
2488 * but there can be also some non-key nodes */
2489 continue;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002490 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002491 LY_CHECK_GOTO(ret = lyd_dup_r(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002492 child = child->next;
2493 }
2494 }
2495 lyd_hash(dup);
2496 } else if (dup->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko61551fa2020-07-09 15:45:45 +02002497 dup->hash = node->hash;
2498 any = (struct lyd_node_any *)node;
2499 LY_CHECK_GOTO(ret = lyd_any_copy_value(dup, &any->value, any->value_type), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002500 }
2501
Michal Vasko52927e22020-03-16 17:26:14 +01002502 /* insert */
2503 lyd_insert_node(parent, first, dup);
Michal Vasko52927e22020-03-16 17:26:14 +01002504
2505 if (dup_p) {
2506 *dup_p = dup;
2507 }
2508 return LY_SUCCESS;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002509
2510error:
Michal Vasko52927e22020-03-16 17:26:14 +01002511 lyd_free_tree(dup);
2512 return ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002513}
2514
Michal Vasko3a41dff2020-07-15 14:30:28 +02002515static LY_ERR
2516lyd_dup_get_local_parent(const struct lyd_node *node, const struct lyd_node_inner *parent, struct lyd_node **dup_parent,
2517 struct lyd_node_inner **local_parent)
Radek Krejci22ebdba2019-07-25 13:59:43 +02002518{
Michal Vasko3a41dff2020-07-15 14:30:28 +02002519 const struct lyd_node_inner *orig_parent, *iter;
2520 int repeat = 1;
2521
2522 *dup_parent = NULL;
2523 *local_parent = NULL;
2524
2525 for (orig_parent = node->parent; repeat && orig_parent; orig_parent = orig_parent->parent) {
2526 if (parent && (parent->schema == orig_parent->schema)) {
2527 /* stop creating parents, connect what we have into the provided parent */
2528 iter = parent;
2529 repeat = 0;
2530 } else {
2531 iter = NULL;
2532 LY_CHECK_RET(lyd_dup_r((struct lyd_node *)orig_parent, NULL, (struct lyd_node **)&iter, 0,
2533 (struct lyd_node **)&iter));
2534 }
2535 if (!*local_parent) {
2536 *local_parent = (struct lyd_node_inner *)iter;
2537 }
2538 if (iter->child) {
2539 /* 1) list - add after keys
2540 * 2) provided parent with some children */
2541 iter->child->prev->next = *dup_parent;
2542 if (*dup_parent) {
2543 (*dup_parent)->prev = iter->child->prev;
2544 iter->child->prev = *dup_parent;
2545 }
2546 } else {
2547 ((struct lyd_node_inner *)iter)->child = *dup_parent;
2548 }
2549 if (*dup_parent) {
2550 (*dup_parent)->parent = (struct lyd_node_inner *)iter;
2551 }
2552 *dup_parent = (struct lyd_node *)iter;
2553 }
2554
2555 if (repeat && parent) {
2556 /* given parent and created parents chain actually do not interconnect */
2557 LOGERR(LYD_NODE_CTX(node), LY_EINVAL,
2558 "Invalid argument parent (%s()) - does not interconnect with the created node's parents chain.", __func__);
2559 return LY_EINVAL;
2560 }
2561
2562 return LY_SUCCESS;
2563}
2564
2565static LY_ERR
2566lyd_dup(const struct lyd_node *node, struct lyd_node_inner *parent, int options, int nosiblings, struct lyd_node **dup)
2567{
2568 LY_ERR rc;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002569 const struct lyd_node *orig; /* original node to be duplicated */
2570 struct lyd_node *first = NULL; /* the first duplicated node, this is returned */
Radek Krejci22ebdba2019-07-25 13:59:43 +02002571 struct lyd_node *top = NULL; /* the most higher created node */
2572 struct lyd_node_inner *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
Radek Krejci22ebdba2019-07-25 13:59:43 +02002573
Michal Vasko3a41dff2020-07-15 14:30:28 +02002574 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002575
2576 if (options & LYD_DUP_WITH_PARENTS) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002577 LY_CHECK_GOTO(rc = lyd_dup_get_local_parent(node, parent, &top, &local_parent), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002578 } else {
2579 local_parent = parent;
2580 }
2581
Radek Krejci22ebdba2019-07-25 13:59:43 +02002582 LY_LIST_FOR(node, orig) {
Michal Vasko52927e22020-03-16 17:26:14 +01002583 /* if there is no local parent, it will be inserted into first */
Michal Vasko3a41dff2020-07-15 14:30:28 +02002584 LY_CHECK_GOTO(rc = lyd_dup_r(orig, (struct lyd_node *)local_parent, &first, options, first ? NULL : &first), error);
2585 if (nosiblings) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002586 break;
2587 }
2588 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002589
2590 /* rehash if needed */
2591 for (; local_parent; local_parent = local_parent->parent) {
2592 if (local_parent->schema->nodetype == LYS_LIST && (local_parent->schema->flags & LYS_KEYLESS)) {
2593 lyd_hash((struct lyd_node *)local_parent);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002594 }
2595 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002596
2597 if (dup) {
2598 *dup = first;
2599 }
2600 return LY_SUCCESS;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002601
2602error:
2603 if (top) {
2604 lyd_free_tree(top);
2605 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +01002606 lyd_free_siblings(first);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002607 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002608 return rc;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002609}
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002610
Michal Vasko3a41dff2020-07-15 14:30:28 +02002611API LY_ERR
2612lyd_dup_single(const struct lyd_node *node, struct lyd_node_inner *parent, int options, struct lyd_node **dup)
2613{
2614 return lyd_dup(node, parent, options, 1, dup);
2615}
2616
2617API LY_ERR
2618lyd_dup_siblings(const struct lyd_node *node, struct lyd_node_inner *parent, int options, struct lyd_node **dup)
2619{
2620 return lyd_dup(node, parent, options, 0, dup);
2621}
2622
2623API LY_ERR
2624lyd_dup_meta_single(const struct lyd_meta *meta, struct lyd_node *node, struct lyd_meta **dup)
Michal Vasko25a32822020-07-09 15:48:22 +02002625{
2626 LY_ERR ret;
2627 struct lyd_meta *mt, *last;
2628
Michal Vasko3a41dff2020-07-15 14:30:28 +02002629 LY_CHECK_ARG_RET(NULL, meta, node, LY_EINVAL);
Michal Vasko25a32822020-07-09 15:48:22 +02002630
2631 /* create a copy */
2632 mt = calloc(1, sizeof *mt);
Michal Vasko3a41dff2020-07-15 14:30:28 +02002633 LY_CHECK_ERR_RET(!mt, LOGMEM(LYD_NODE_CTX(node)), LY_EMEM);
Michal Vasko25a32822020-07-09 15:48:22 +02002634 mt->parent = node;
2635 mt->annotation = meta->annotation;
2636 mt->value.realtype = meta->value.realtype;
2637 ret = mt->value.realtype->plugin->duplicate(LYD_NODE_CTX(node), &meta->value, &mt->value);
Michal Vasko3a41dff2020-07-15 14:30:28 +02002638 LY_CHECK_ERR_RET(ret, LOGERR(LYD_NODE_CTX(node), LY_EINT, "Value duplication failed."), ret);
Michal Vasko25a32822020-07-09 15:48:22 +02002639 mt->name = lydict_insert(LYD_NODE_CTX(node), meta->name, 0);
2640
2641 /* insert as the last attribute */
2642 if (node->meta) {
2643 for (last = node->meta; last->next; last = last->next);
2644 last->next = mt;
2645 } else {
2646 node->meta = mt;
2647 }
2648
Michal Vasko3a41dff2020-07-15 14:30:28 +02002649 if (dup) {
2650 *dup = mt;
2651 }
2652 return LY_SUCCESS;
Michal Vasko25a32822020-07-09 15:48:22 +02002653}
2654
Michal Vasko4490d312020-06-16 13:08:55 +02002655/**
2656 * @brief Merge a source sibling into target siblings.
2657 *
2658 * @param[in,out] first_trg First target sibling, is updated if top-level.
2659 * @param[in] parent_trg Target parent.
2660 * @param[in,out] sibling_src Source sibling to merge, set to NULL if spent.
2661 * @param[in] options Merge options.
2662 * @return LY_ERR value.
2663 */
2664static LY_ERR
2665lyd_merge_sibling_r(struct lyd_node **first_trg, struct lyd_node *parent_trg, const struct lyd_node **sibling_src_p,
2666 int options)
2667{
2668 LY_ERR ret;
2669 const struct lyd_node *child_src, *tmp, *sibling_src;
Michal Vasko56daf732020-08-10 10:57:18 +02002670 struct lyd_node *match_trg, *dup_src, *elem;
Michal Vasko4490d312020-06-16 13:08:55 +02002671 struct lysc_type *type;
Michal Vasko4490d312020-06-16 13:08:55 +02002672
2673 sibling_src = *sibling_src_p;
2674 if (sibling_src->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
2675 /* try to find the exact instance */
2676 ret = lyd_find_sibling_first(*first_trg, sibling_src, &match_trg);
2677 } else {
2678 /* try to simply find the node, there cannot be more instances */
2679 ret = lyd_find_sibling_val(*first_trg, sibling_src->schema, NULL, 0, &match_trg);
2680 }
2681
2682 if (!ret) {
2683 /* node found, make sure even value matches for all node types */
Michal Vasko8f359bf2020-07-28 10:41:15 +02002684 if ((match_trg->schema->nodetype == LYS_LEAF) && lyd_compare_single(sibling_src, match_trg, LYD_COMPARE_DEFAULTS)) {
Michal Vasko4490d312020-06-16 13:08:55 +02002685 /* since they are different, they cannot both be default */
2686 assert(!(sibling_src->flags & LYD_DEFAULT) || !(match_trg->flags & LYD_DEFAULT));
2687
Michal Vasko3a41dff2020-07-15 14:30:28 +02002688 /* update value (or only LYD_DEFAULT flag) only if flag set or the source node is not default */
2689 if ((options & LYD_MERGE_DEFAULTS) || !(sibling_src->flags & LYD_DEFAULT)) {
Michal Vasko4490d312020-06-16 13:08:55 +02002690 type = ((struct lysc_node_leaf *)match_trg->schema)->type;
2691 type->plugin->free(LYD_NODE_CTX(match_trg), &((struct lyd_node_term *)match_trg)->value);
2692 LY_CHECK_RET(type->plugin->duplicate(LYD_NODE_CTX(match_trg), &((struct lyd_node_term *)sibling_src)->value,
2693 &((struct lyd_node_term *)match_trg)->value));
2694
2695 /* copy flags and add LYD_NEW */
2696 match_trg->flags = sibling_src->flags | LYD_NEW;
2697 }
Michal Vasko8f359bf2020-07-28 10:41:15 +02002698 } else if ((match_trg->schema->nodetype & LYS_ANYDATA) && lyd_compare_single(sibling_src, match_trg, 0)) {
Michal Vasko4c583e82020-07-17 12:16:14 +02002699 /* update value */
2700 LY_CHECK_RET(lyd_any_copy_value(match_trg, &((struct lyd_node_any *)sibling_src)->value,
2701 ((struct lyd_node_any *)sibling_src)->value_type));
Michal Vasko4490d312020-06-16 13:08:55 +02002702
2703 /* copy flags and add LYD_NEW */
2704 match_trg->flags = sibling_src->flags | LYD_NEW;
Michal Vasko4490d312020-06-16 13:08:55 +02002705 } else {
2706 /* check descendants, recursively */
Michal Vasko5bfd4be2020-06-23 13:26:19 +02002707 LY_LIST_FOR_SAFE(LYD_CHILD(sibling_src), tmp, child_src) {
Michal Vasko4490d312020-06-16 13:08:55 +02002708 LY_CHECK_RET(lyd_merge_sibling_r(lyd_node_children_p(match_trg), match_trg, &child_src, options));
2709 }
2710 }
2711 } else {
2712 /* node not found, merge it */
2713 if (options & LYD_MERGE_DESTRUCT) {
2714 dup_src = (struct lyd_node *)sibling_src;
2715 lyd_unlink_tree(dup_src);
2716 /* spend it */
2717 *sibling_src_p = NULL;
2718 } else {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002719 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 +02002720 }
2721
2722 /* set LYD_NEW for all the new nodes, required for validation */
Michal Vasko56daf732020-08-10 10:57:18 +02002723 LYD_TREE_DFS_BEGIN(dup_src, elem) {
Michal Vasko4490d312020-06-16 13:08:55 +02002724 elem->flags |= LYD_NEW;
Michal Vasko56daf732020-08-10 10:57:18 +02002725 LYD_TREE_DFS_END(dup_src, elem);
Michal Vasko4490d312020-06-16 13:08:55 +02002726 }
2727
2728 lyd_insert_node(parent_trg, first_trg, dup_src);
2729 }
2730
2731 return LY_SUCCESS;
2732}
2733
Michal Vasko3a41dff2020-07-15 14:30:28 +02002734static LY_ERR
2735lyd_merge(struct lyd_node **target, const struct lyd_node *source, int options, int nosiblings)
Michal Vasko4490d312020-06-16 13:08:55 +02002736{
2737 const struct lyd_node *sibling_src, *tmp;
2738 int first;
2739
2740 LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
2741
2742 if (!source) {
2743 /* nothing to merge */
2744 return LY_SUCCESS;
2745 }
2746
2747 if (lysc_data_parent((*target)->schema) || lysc_data_parent(source->schema)) {
2748 LOGERR(LYD_NODE_CTX(source), LY_EINVAL, "Invalid arguments - can merge only 2 top-level subtrees (%s()).", __func__);
2749 return LY_EINVAL;
2750 }
2751
2752 LY_LIST_FOR_SAFE(source, tmp, sibling_src) {
2753 first = sibling_src == source ? 1 : 0;
2754 LY_CHECK_RET(lyd_merge_sibling_r(target, NULL, &sibling_src, options));
2755 if (first && !sibling_src) {
2756 /* source was spent (unlinked), move to the next node */
2757 source = tmp;
2758 }
2759
Michal Vasko3a41dff2020-07-15 14:30:28 +02002760 if (nosiblings) {
Michal Vasko4490d312020-06-16 13:08:55 +02002761 break;
2762 }
2763 }
2764
2765 if (options & LYD_MERGE_DESTRUCT) {
2766 /* free any leftover source data that were not merged */
2767 lyd_free_siblings((struct lyd_node *)source);
2768 }
2769
2770 return LY_SUCCESS;
2771}
2772
Michal Vasko3a41dff2020-07-15 14:30:28 +02002773API LY_ERR
2774lyd_merge_tree(struct lyd_node **target, const struct lyd_node *source, int options)
2775{
2776 return lyd_merge(target, source, options, 1);
2777}
2778
2779API LY_ERR
2780lyd_merge_siblings(struct lyd_node **target, const struct lyd_node *source, int options)
2781{
2782 return lyd_merge(target, source, options, 0);
2783}
2784
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002785static LY_ERR
2786lyd_path_str_enlarge(char **buffer, size_t *buflen, size_t reqlen, int is_static)
2787{
Michal Vasko14654712020-02-06 08:35:21 +01002788 /* ending \0 */
2789 ++reqlen;
2790
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002791 if (reqlen > *buflen) {
2792 if (is_static) {
2793 return LY_EINCOMPLETE;
2794 }
2795
2796 *buffer = ly_realloc(*buffer, reqlen * sizeof **buffer);
2797 if (!*buffer) {
2798 return LY_EMEM;
2799 }
2800
2801 *buflen = reqlen;
2802 }
2803
2804 return LY_SUCCESS;
2805}
2806
Michal Vaskod59035b2020-07-08 12:00:06 +02002807LY_ERR
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002808lyd_path_list_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2809{
2810 const struct lyd_node *key;
2811 int dynamic = 0;
2812 size_t len;
2813 const char *val;
2814 char quot;
2815 LY_ERR rc;
2816
Michal Vasko5bfd4be2020-06-23 13:26:19 +02002817 for (key = lyd_node_children(node, 0); key && (key->schema->flags & LYS_KEY); key = key->next) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002818 val = lyd_value2str((struct lyd_node_term *)key, &dynamic);
2819 len = 1 + strlen(key->schema->name) + 2 + strlen(val) + 2;
2820 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2821 if (rc != LY_SUCCESS) {
2822 if (dynamic) {
2823 free((char *)val);
2824 }
2825 return rc;
2826 }
2827
2828 quot = '\'';
2829 if (strchr(val, '\'')) {
2830 quot = '"';
2831 }
2832 *bufused += sprintf(*buffer + *bufused, "[%s=%c%s%c]", key->schema->name, quot, val, quot);
2833
2834 if (dynamic) {
2835 free((char *)val);
2836 }
2837 }
2838
2839 return LY_SUCCESS;
2840}
2841
2842/**
2843 * @brief Append leaf-list value predicate to path.
2844 *
2845 * @param[in] node Node to print.
2846 * @param[in,out] buffer Buffer to print to.
2847 * @param[in,out] buflen Current buffer length.
2848 * @param[in,out] bufused Current number of characters used in @p buffer.
2849 * @param[in] is_static Whether buffer is static or can be reallocated.
2850 * @return LY_ERR
2851 */
2852static LY_ERR
2853lyd_path_leaflist_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2854{
2855 int dynamic = 0;
2856 size_t len;
2857 const char *val;
2858 char quot;
2859 LY_ERR rc;
2860
2861 val = lyd_value2str((struct lyd_node_term *)node, &dynamic);
2862 len = 4 + strlen(val) + 2;
2863 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2864 if (rc != LY_SUCCESS) {
2865 goto cleanup;
2866 }
2867
2868 quot = '\'';
2869 if (strchr(val, '\'')) {
2870 quot = '"';
2871 }
2872 *bufused += sprintf(*buffer + *bufused, "[.=%c%s%c]", quot, val, quot);
2873
2874cleanup:
2875 if (dynamic) {
2876 free((char *)val);
2877 }
2878 return rc;
2879}
2880
2881/**
2882 * @brief Append node position (relative to its other instances) predicate to path.
2883 *
2884 * @param[in] node Node to print.
2885 * @param[in,out] buffer Buffer to print to.
2886 * @param[in,out] buflen Current buffer length.
2887 * @param[in,out] bufused Current number of characters used in @p buffer.
2888 * @param[in] is_static Whether buffer is static or can be reallocated.
2889 * @return LY_ERR
2890 */
2891static LY_ERR
2892lyd_path_position_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2893{
2894 const struct lyd_node *first, *iter;
2895 size_t len;
2896 int pos;
2897 char *val = NULL;
2898 LY_ERR rc;
2899
2900 if (node->parent) {
2901 first = node->parent->child;
2902 } else {
2903 for (first = node; node->prev->next; node = node->prev);
2904 }
2905 pos = 1;
2906 for (iter = first; iter != node; iter = iter->next) {
2907 if (iter->schema == node->schema) {
2908 ++pos;
2909 }
2910 }
2911 if (asprintf(&val, "%d", pos) == -1) {
2912 return LY_EMEM;
2913 }
2914
2915 len = 1 + strlen(val) + 1;
2916 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2917 if (rc != LY_SUCCESS) {
2918 goto cleanup;
2919 }
2920
2921 *bufused += sprintf(*buffer + *bufused, "[%s]", val);
2922
2923cleanup:
2924 free(val);
2925 return rc;
2926}
2927
2928API char *
2929lyd_path(const struct lyd_node *node, LYD_PATH_TYPE pathtype, char *buffer, size_t buflen)
2930{
Michal Vasko14654712020-02-06 08:35:21 +01002931 int is_static = 0, i, depth;
2932 size_t bufused = 0, len;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002933 const struct lyd_node *iter;
2934 const struct lys_module *mod;
Michal Vasko790b2bc2020-08-03 13:35:06 +02002935 LY_ERR rc = LY_SUCCESS;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002936
2937 LY_CHECK_ARG_RET(NULL, node, NULL);
2938 if (buffer) {
2939 LY_CHECK_ARG_RET(node->schema->module->ctx, buflen > 1, NULL);
2940 is_static = 1;
Michal Vasko14654712020-02-06 08:35:21 +01002941 } else {
2942 buflen = 0;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002943 }
2944
2945 switch (pathtype) {
Michal Vasko14654712020-02-06 08:35:21 +01002946 case LYD_PATH_LOG:
Michal Vasko790b2bc2020-08-03 13:35:06 +02002947 case LYD_PATH_LOG_NO_LAST_PRED:
Michal Vasko14654712020-02-06 08:35:21 +01002948 depth = 1;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002949 for (iter = node; iter->parent; iter = (const struct lyd_node *)iter->parent) {
2950 ++depth;
2951 }
2952
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002953 goto iter_print;
Michal Vasko14654712020-02-06 08:35:21 +01002954 while (depth) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002955 /* find the right node */
Michal Vasko14654712020-02-06 08:35:21 +01002956 for (iter = node, i = 1; i < depth; iter = (const struct lyd_node *)iter->parent, ++i);
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002957iter_print:
2958 /* print prefix and name */
2959 mod = NULL;
2960 if (!iter->parent || (iter->schema->module != iter->parent->schema->module)) {
2961 mod = iter->schema->module;
2962 }
2963
2964 /* realloc string */
2965 len = 1 + (mod ? strlen(mod->name) + 1 : 0) + strlen(iter->schema->name);
2966 rc = lyd_path_str_enlarge(&buffer, &buflen, bufused + len, is_static);
2967 if (rc != LY_SUCCESS) {
2968 break;
2969 }
2970
2971 /* print next node */
2972 bufused += sprintf(buffer + bufused, "/%s%s%s", mod ? mod->name : "", mod ? ":" : "", iter->schema->name);
2973
Michal Vasko790b2bc2020-08-03 13:35:06 +02002974 /* do not always print the last (first) predicate */
2975 if (bufused || (pathtype == LYD_PATH_LOG)) {
2976 switch (iter->schema->nodetype) {
2977 case LYS_LIST:
2978 if (iter->schema->flags & LYS_KEYLESS) {
2979 /* print its position */
2980 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2981 } else {
2982 /* print all list keys in predicates */
2983 rc = lyd_path_list_predicate(iter, &buffer, &buflen, &bufused, is_static);
2984 }
2985 break;
2986 case LYS_LEAFLIST:
2987 if (iter->schema->flags & LYS_CONFIG_W) {
2988 /* print leaf-list value */
2989 rc = lyd_path_leaflist_predicate(iter, &buffer, &buflen, &bufused, is_static);
2990 } else {
2991 /* print its position */
2992 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2993 }
2994 break;
2995 default:
2996 /* nothing to print more */
2997 break;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002998 }
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002999 }
3000 if (rc != LY_SUCCESS) {
3001 break;
3002 }
3003
Michal Vasko14654712020-02-06 08:35:21 +01003004 --depth;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003005 }
3006 break;
3007 }
3008
3009 return buffer;
3010}
Michal Vaskoe444f752020-02-10 12:20:06 +01003011
Michal Vasko25a32822020-07-09 15:48:22 +02003012API struct lyd_meta *
3013lyd_find_meta(const struct lyd_meta *first, const struct lys_module *module, const char *name)
3014{
3015 struct lyd_meta *ret = NULL;
3016 const struct ly_ctx *ctx;
3017 const char *prefix, *tmp;
3018 char *str;
3019 size_t pref_len, name_len;
3020
3021 LY_CHECK_ARG_RET(NULL, module || strchr(name, ':'), name, NULL);
3022
3023 if (!first) {
3024 return NULL;
3025 }
3026
3027 ctx = first->annotation->module->ctx;
3028
3029 /* parse the name */
3030 tmp = name;
3031 if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
3032 LOGERR(ctx, LY_EINVAL, "Metadata name \"%s\" is not valid.", name);
3033 return NULL;
3034 }
3035
3036 /* find the module */
3037 if (prefix) {
3038 str = strndup(prefix, pref_len);
3039 module = ly_ctx_get_module_latest(ctx, str);
3040 free(str);
3041 LY_CHECK_ERR_RET(!module, LOGERR(ctx, LY_EINVAL, "Module \"%.*s\" not found.", pref_len, prefix), NULL);
3042 }
3043
3044 /* find the metadata */
3045 LY_LIST_FOR(first, first) {
3046 if ((first->annotation->module == module) && !strcmp(first->name, name)) {
3047 ret = (struct lyd_meta *)first;
3048 break;
3049 }
3050 }
3051
3052 return ret;
3053}
3054
Michal Vasko9b368d32020-02-14 13:53:31 +01003055API LY_ERR
Michal Vaskoe444f752020-02-10 12:20:06 +01003056lyd_find_sibling_first(const struct lyd_node *siblings, const struct lyd_node *target, struct lyd_node **match)
3057{
3058 struct lyd_node **match_p;
3059 struct lyd_node_inner *parent;
3060
Michal Vaskof03ed032020-03-04 13:31:44 +01003061 LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01003062
Michal Vasko62ed12d2020-05-21 10:08:25 +02003063 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(target->schema))) {
3064 /* no data or schema mismatch */
Michal Vasko9b368d32020-02-14 13:53:31 +01003065 if (match) {
3066 *match = NULL;
3067 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003068 return LY_ENOTFOUND;
3069 }
3070
3071 /* find first sibling */
3072 if (siblings->parent) {
3073 siblings = siblings->parent->child;
3074 } else {
3075 while (siblings->prev->next) {
3076 siblings = siblings->prev;
3077 }
3078 }
3079
3080 parent = (struct lyd_node_inner *)siblings->parent;
3081 if (parent && parent->children_ht) {
3082 assert(target->hash);
3083
3084 /* find by hash */
3085 if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
Michal Vaskoda859032020-07-14 12:20:14 +02003086 /* check even value when needed */
Michal Vasko8f359bf2020-07-28 10:41:15 +02003087 if (!(target->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !lyd_compare_single(target, *match_p, 0)) {
Michal Vaskoda859032020-07-14 12:20:14 +02003088 siblings = *match_p;
3089 } else {
3090 siblings = NULL;
3091 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003092 } else {
3093 /* not found */
3094 siblings = NULL;
3095 }
3096 } else {
3097 /* no children hash table */
3098 for (; siblings; siblings = siblings->next) {
Michal Vasko8f359bf2020-07-28 10:41:15 +02003099 if (!lyd_compare_single(siblings, target, 0)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01003100 break;
3101 }
3102 }
3103 }
3104
3105 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01003106 if (match) {
3107 *match = NULL;
3108 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003109 return LY_ENOTFOUND;
3110 }
3111
Michal Vasko9b368d32020-02-14 13:53:31 +01003112 if (match) {
3113 *match = (struct lyd_node *)siblings;
3114 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003115 return LY_SUCCESS;
3116}
3117
Michal Vasko90932a92020-02-12 14:33:03 +01003118static int
3119lyd_hash_table_schema_val_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *UNUSED(cb_data))
3120{
3121 struct lysc_node *val1;
3122 struct lyd_node *val2;
3123
3124 val1 = *((struct lysc_node **)val1_p);
3125 val2 = *((struct lyd_node **)val2_p);
3126
Michal Vasko90932a92020-02-12 14:33:03 +01003127 if (val1 == val2->schema) {
3128 /* schema match is enough */
3129 return 1;
3130 } else {
3131 return 0;
3132 }
3133}
3134
3135static LY_ERR
3136lyd_find_sibling_schema(const struct lyd_node *siblings, const struct lysc_node *schema, struct lyd_node **match)
3137{
3138 struct lyd_node **match_p;
3139 struct lyd_node_inner *parent;
3140 uint32_t hash;
3141 values_equal_cb ht_cb;
3142
Michal Vaskob104f112020-07-17 09:54:54 +02003143 assert(siblings && schema);
Michal Vasko90932a92020-02-12 14:33:03 +01003144
3145 parent = (struct lyd_node_inner *)siblings->parent;
3146 if (parent && parent->children_ht) {
3147 /* calculate our hash */
3148 hash = dict_hash_multi(0, schema->module->name, strlen(schema->module->name));
3149 hash = dict_hash_multi(hash, schema->name, strlen(schema->name));
3150 hash = dict_hash_multi(hash, NULL, 0);
3151
3152 /* use special hash table function */
3153 ht_cb = lyht_set_cb(parent->children_ht, lyd_hash_table_schema_val_equal);
3154
3155 /* find by hash */
3156 if (!lyht_find(parent->children_ht, &schema, hash, (void **)&match_p)) {
3157 siblings = *match_p;
3158 } else {
3159 /* not found */
3160 siblings = NULL;
3161 }
3162
3163 /* set the original hash table compare function back */
3164 lyht_set_cb(parent->children_ht, ht_cb);
3165 } else {
Michal Vaskob104f112020-07-17 09:54:54 +02003166 /* find first sibling */
3167 if (siblings->parent) {
3168 siblings = siblings->parent->child;
3169 } else {
3170 while (siblings->prev->next) {
3171 siblings = siblings->prev;
3172 }
3173 }
3174
3175 /* search manually without hashes */
Michal Vasko90932a92020-02-12 14:33:03 +01003176 for (; siblings; siblings = siblings->next) {
3177 if (siblings->schema == schema) {
3178 /* schema match is enough */
3179 break;
3180 }
3181 }
3182 }
3183
3184 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01003185 if (match) {
3186 *match = NULL;
3187 }
Michal Vasko90932a92020-02-12 14:33:03 +01003188 return LY_ENOTFOUND;
3189 }
3190
Michal Vasko9b368d32020-02-14 13:53:31 +01003191 if (match) {
3192 *match = (struct lyd_node *)siblings;
3193 }
Michal Vasko90932a92020-02-12 14:33:03 +01003194 return LY_SUCCESS;
3195}
3196
Michal Vaskoe444f752020-02-10 12:20:06 +01003197API LY_ERR
3198lyd_find_sibling_val(const struct lyd_node *siblings, const struct lysc_node *schema, const char *key_or_value,
3199 size_t val_len, struct lyd_node **match)
3200{
3201 LY_ERR rc;
3202 struct lyd_node *target = NULL;
3203
Michal Vasko4c583e82020-07-17 12:16:14 +02003204 LY_CHECK_ARG_RET(NULL, schema, !(schema->nodetype & (LYS_CHOICE | LYS_CASE)), LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01003205
Michal Vasko62ed12d2020-05-21 10:08:25 +02003206 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(schema))) {
3207 /* no data or schema mismatch */
Michal Vasko9b368d32020-02-14 13:53:31 +01003208 if (match) {
3209 *match = NULL;
3210 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003211 return LY_ENOTFOUND;
3212 }
3213
Michal Vaskof03ed032020-03-04 13:31:44 +01003214 if (key_or_value && !val_len) {
3215 val_len = strlen(key_or_value);
3216 }
3217
Michal Vaskob104f112020-07-17 09:54:54 +02003218 if ((schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) && key_or_value) {
3219 /* create a data node and find the instance */
3220 if (schema->nodetype == LYS_LEAFLIST) {
3221 /* target used attributes: schema, hash, value */
3222 rc = lyd_create_term(schema, key_or_value, val_len, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &target);
3223 LY_CHECK_RET(rc && (rc != LY_EINCOMPLETE), rc);
3224 } else {
Michal Vasko90932a92020-02-12 14:33:03 +01003225 /* target used attributes: schema, hash, child (all keys) */
Michal Vasko004d3152020-06-11 19:59:22 +02003226 LY_CHECK_RET(lyd_create_list2(schema, key_or_value, val_len, &target));
Michal Vasko90932a92020-02-12 14:33:03 +01003227 }
3228
3229 /* find it */
3230 rc = lyd_find_sibling_first(siblings, target, match);
Michal Vaskob104f112020-07-17 09:54:54 +02003231 } else {
3232 /* find the first schema node instance */
3233 rc = lyd_find_sibling_schema(siblings, schema, match);
Michal Vaskoe444f752020-02-10 12:20:06 +01003234 }
3235
Michal Vaskoe444f752020-02-10 12:20:06 +01003236 lyd_free_tree(target);
3237 return rc;
3238}
Michal Vaskoccc02342020-05-21 10:09:21 +02003239
3240API LY_ERR
3241lyd_find_xpath(const struct lyd_node *ctx_node, const char *xpath, struct ly_set **set)
3242{
3243 LY_ERR ret = LY_SUCCESS;
3244 struct lyxp_set xp_set;
3245 struct lyxp_expr *exp;
3246 uint32_t i;
3247
3248 LY_CHECK_ARG_RET(NULL, ctx_node, xpath, set, LY_EINVAL);
3249
3250 memset(&xp_set, 0, sizeof xp_set);
3251
3252 /* compile expression */
Michal Vasko004d3152020-06-11 19:59:22 +02003253 exp = lyxp_expr_parse((struct ly_ctx *)LYD_NODE_CTX(ctx_node), xpath, 0, 1);
Michal Vaskoccc02342020-05-21 10:09:21 +02003254 LY_CHECK_ERR_GOTO(!exp, ret = LY_EINVAL, cleanup);
3255
3256 /* evaluate expression */
3257 ret = lyxp_eval(exp, LYD_JSON, ctx_node->schema->module, ctx_node, LYXP_NODE_ELEM, ctx_node, &xp_set, 0);
3258 LY_CHECK_GOTO(ret, cleanup);
3259
3260 /* allocate return set */
3261 *set = ly_set_new();
3262 LY_CHECK_ERR_GOTO(!*set, LOGMEM(LYD_NODE_CTX(ctx_node)); ret = LY_EMEM, cleanup);
3263
3264 /* transform into ly_set */
3265 if (xp_set.type == LYXP_SET_NODE_SET) {
3266 /* allocate memory for all the elements once (even though not all items must be elements but most likely will be) */
3267 (*set)->objs = malloc(xp_set.used * sizeof *(*set)->objs);
3268 LY_CHECK_ERR_GOTO(!(*set)->objs, LOGMEM(LYD_NODE_CTX(ctx_node)); ret = LY_EMEM, cleanup);
3269 (*set)->size = xp_set.used;
3270
3271 for (i = 0; i < xp_set.used; ++i) {
3272 if (xp_set.val.nodes[i].type == LYXP_NODE_ELEM) {
3273 ly_set_add(*set, xp_set.val.nodes[i].node, LY_SET_OPT_USEASLIST);
3274 }
3275 }
3276 }
3277
3278cleanup:
Michal Vasko0691d522020-05-21 13:21:47 +02003279 lyxp_set_free_content(&xp_set);
Michal Vaskoccc02342020-05-21 10:09:21 +02003280 lyxp_expr_free((struct ly_ctx *)LYD_NODE_CTX(ctx_node), exp);
3281 return ret;
3282}