blob: df4ca433daf1ef9a7a1e11793a7fdd0ea6351875 [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;
1348 }
1349
1350 switch (iter->nodetype) {
1351 case LYS_CHOICE:
1352 if (((struct lysc_node_choice *)iter)->dflt && !lys_getnext_data(NULL, *first, NULL, iter, NULL)) {
1353 /* create default case data */
1354 LY_CHECK_RET(lyd_new_implicit_r(parent, first, (struct lysc_node *)((struct lysc_node_choice *)iter)->dflt,
1355 NULL, node_types, node_when, impl_opts, diff));
1356 }
1357 break;
1358 case LYS_CONTAINER:
1359 if (!(iter->flags & LYS_PRESENCE) && lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
1360 /* create default NP container */
1361 LY_CHECK_RET(lyd_create_inner(iter, &node));
1362 node->flags = LYD_DEFAULT;
1363 lyd_insert_node(parent, first, node);
1364
1365 /* cannot be a NP container with when */
1366 assert(!iter->when);
1367
1368 /* create any default children */
1369 LY_CHECK_RET(lyd_new_implicit_r(node, lyd_node_children_p(node), NULL, NULL, node_types, node_when,
1370 impl_opts, diff));
1371 }
1372 break;
1373 case LYS_LEAF:
1374 if (!(impl_opts & LYD_IMPLICIT_NO_DEFAULTS) && ((struct lysc_node_leaf *)iter)->dflt
1375 && lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
1376 /* create default leaf */
1377 ret = lyd_create_term2(iter, ((struct lysc_node_leaf *)iter)->dflt, &node);
1378 if (ret == LY_EINCOMPLETE) {
1379 if (node_types) {
1380 /* remember to resolve type */
1381 ly_set_add(node_types, node, LY_SET_OPT_USEASLIST);
1382 }
1383 } else if (ret) {
1384 return ret;
1385 }
1386 node->flags = LYD_DEFAULT;
1387 lyd_insert_node(parent, first, node);
1388
1389 if (iter->when && node_when) {
1390 /* remember to resolve when */
1391 ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
1392 }
1393 if (diff) {
1394 /* add into diff */
1395 LY_CHECK_RET(lyd_val_diff_add(node, LYD_DIFF_OP_CREATE, diff));
1396 }
1397 }
1398 break;
1399 case LYS_LEAFLIST:
1400 if (!(impl_opts & LYD_IMPLICIT_NO_DEFAULTS) && ((struct lysc_node_leaflist *)iter)->dflts
1401 && lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
1402 /* create all default leaf-lists */
1403 dflts = ((struct lysc_node_leaflist *)iter)->dflts;
1404 LY_ARRAY_FOR(dflts, u) {
1405 ret = lyd_create_term2(iter, dflts[u], &node);
1406 if (ret == LY_EINCOMPLETE) {
1407 if (node_types) {
1408 /* remember to resolve type */
1409 ly_set_add(node_types, node, LY_SET_OPT_USEASLIST);
1410 }
1411 } else if (ret) {
1412 return ret;
1413 }
1414 node->flags = LYD_DEFAULT;
1415 lyd_insert_node(parent, first, node);
1416
1417 if (iter->when && node_when) {
1418 /* remember to resolve when */
1419 ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
1420 }
1421 if (diff) {
1422 /* add into diff */
1423 LY_CHECK_RET(lyd_val_diff_add(node, LYD_DIFF_OP_CREATE, diff));
1424 }
1425 }
1426 }
1427 break;
1428 default:
1429 /* without defaults */
1430 break;
1431 }
1432 }
1433
1434 return LY_SUCCESS;
1435}
1436
1437API LY_ERR
1438lyd_new_implicit_tree(struct lyd_node *tree, int implicit_options, struct lyd_node **diff)
1439{
1440 struct lyd_node *next, *node;
1441 LY_ERR ret = LY_SUCCESS;
1442
1443 LY_CHECK_ARG_RET(NULL, tree, LY_EINVAL);
1444 if (diff) {
1445 *diff = NULL;
1446 }
1447
1448 LYD_TREE_DFS_BEGIN(tree, next, node) {
1449 /* skip added default nodes */
1450 if (((node->flags & (LYD_DEFAULT | LYD_NEW)) != (LYD_DEFAULT | LYD_NEW))
1451 && (node->schema->nodetype & LYD_NODE_INNER)) {
1452 LY_CHECK_GOTO(ret = lyd_new_implicit_r(node, lyd_node_children_p((struct lyd_node *)node), NULL, NULL, NULL,
1453 NULL, implicit_options, diff), cleanup);
1454 }
1455
1456 LYD_TREE_DFS_END(tree, next, node);
1457 }
1458
1459cleanup:
1460 if (ret && diff) {
1461 lyd_free_all(*diff);
1462 *diff = NULL;
1463 }
1464 return ret;
1465}
1466
1467API LY_ERR
1468lyd_new_implicit_all(struct lyd_node **tree, const struct ly_ctx *ctx, int implicit_options, struct lyd_node **diff)
1469{
1470 const struct lys_module *mod;
1471 struct lyd_node *d = NULL;
1472 uint32_t i = 0;
1473 LY_ERR ret = LY_SUCCESS;
1474
1475 LY_CHECK_ARG_RET(ctx, tree, *tree || ctx, LY_EINVAL);
1476 if (diff) {
1477 *diff = NULL;
1478 }
1479 if (!ctx) {
1480 ctx = LYD_NODE_CTX(*tree);
1481 }
1482
1483 /* add nodes for each module one-by-one */
1484 while ((mod = ly_ctx_get_module_iter(ctx, &i))) {
1485 if (!mod->implemented) {
1486 continue;
1487 }
1488
1489 LY_CHECK_GOTO(ret = lyd_new_implicit_module(tree, mod, implicit_options, diff ? &d : NULL), cleanup);
1490 if (d) {
1491 /* merge into one diff */
1492 lyd_insert_sibling(*diff, d, diff);
1493
1494 d = NULL;
1495 }
1496 }
1497
1498cleanup:
1499 if (ret && diff) {
1500 lyd_free_all(*diff);
1501 *diff = NULL;
1502 }
1503 return ret;
1504}
1505
1506API LY_ERR
1507lyd_new_implicit_module(struct lyd_node **tree, const struct lys_module *module, int implicit_options, struct lyd_node **diff)
1508{
1509 struct lyd_node *root, *d = NULL;
1510 LY_ERR ret = LY_SUCCESS;
1511
1512 LY_CHECK_ARG_RET(NULL, tree, module, LY_EINVAL);
1513 if (diff) {
1514 *diff = NULL;
1515 }
1516
1517 /* add all top-level defaults for this module */
1518 LY_CHECK_GOTO(ret = lyd_new_implicit_r(NULL, tree, NULL, module, NULL, NULL, implicit_options, diff), cleanup);
1519
1520 /* process nested nodes */
1521 LY_LIST_FOR(*tree, root) {
1522 /* skip added default nodes */
1523 if ((root->flags & (LYD_DEFAULT | LYD_NEW)) != (LYD_DEFAULT | LYD_NEW)) {
1524 LY_CHECK_GOTO(ret = lyd_new_implicit_tree(root, implicit_options, diff ? &d : NULL), cleanup);
1525
1526 if (d) {
1527 /* merge into one diff */
1528 lyd_insert_sibling(*diff, d, diff);
1529
1530 d = NULL;
1531 }
1532 }
1533 }
1534
1535cleanup:
1536 if (ret && diff) {
1537 lyd_free_all(*diff);
1538 *diff = NULL;
1539 }
1540 return ret;
1541}
1542
Michal Vasko90932a92020-02-12 14:33:03 +01001543struct lyd_node *
Michal Vaskob104f112020-07-17 09:54:54 +02001544lyd_insert_get_next_anchor(const struct lyd_node *first_sibling, const struct lyd_node *new_node)
Michal Vasko90932a92020-02-12 14:33:03 +01001545{
Michal Vaskob104f112020-07-17 09:54:54 +02001546 const struct lysc_node *schema, *sparent;
Michal Vasko90932a92020-02-12 14:33:03 +01001547 struct lyd_node *match = NULL;
Michal Vaskob104f112020-07-17 09:54:54 +02001548 int found;
Michal Vasko90932a92020-02-12 14:33:03 +01001549
Michal Vaskob104f112020-07-17 09:54:54 +02001550 assert(new_node);
1551
1552 if (!first_sibling || !new_node->schema) {
1553 /* insert at the end, no next anchor */
Michal Vasko90932a92020-02-12 14:33:03 +01001554 return NULL;
1555 }
1556
Michal Vaskob104f112020-07-17 09:54:54 +02001557 if (first_sibling->parent && first_sibling->parent->children_ht) {
1558 /* find the anchor using hashes */
1559 sparent = first_sibling->parent->schema;
1560 schema = lys_getnext(new_node->schema, sparent, NULL, 0);
1561 while (schema) {
1562 /* keep trying to find the first existing instance of the closest following schema sibling,
1563 * otherwise return NULL - inserting at the end */
1564 if (!lyd_find_sibling_schema(first_sibling, schema, &match)) {
1565 break;
1566 }
1567
1568 schema = lys_getnext(schema, sparent, NULL, 0);
1569 }
1570 } else {
1571 /* find the anchor without hashes */
1572 match = (struct lyd_node *)first_sibling;
1573 if (!lysc_data_parent(new_node->schema)) {
1574 /* we are in top-level, skip all the data from preceding modules */
1575 LY_LIST_FOR(match, match) {
1576 if (!match->schema || (strcmp(lyd_owner_module(match)->name, lyd_owner_module(new_node)->name) >= 0)) {
1577 break;
1578 }
1579 }
1580 }
1581
1582 /* get the first schema sibling */
1583 sparent = lysc_data_parent(new_node->schema);
1584 schema = lys_getnext(NULL, sparent, new_node->schema->module->compiled, 0);
1585
1586 found = 0;
1587 LY_LIST_FOR(match, match) {
1588 if (!match->schema || (lyd_owner_module(match) != lyd_owner_module(new_node))) {
1589 /* we have found an opaque node, which must be at the end, so use it OR
1590 * modules do not match, so we must have traversed all the data from new_node module (if any),
1591 * we have found the first node of the next module, that is what we want */
1592 break;
1593 }
1594
1595 /* skip schema nodes until we find the instantiated one */
1596 while (!found) {
1597 if (new_node->schema == schema) {
1598 /* we have found the schema of the new node, continue search to find the first
1599 * data node with a different schema (after our schema) */
1600 found = 1;
1601 break;
1602 }
1603 if (match->schema == schema) {
1604 /* current node (match) is a data node still before the new node, continue search in data */
1605 break;
1606 }
1607 schema = lys_getnext(schema, sparent, new_node->schema->module->compiled, 0);
1608 assert(schema);
1609 }
1610
1611 if (found && (match->schema != new_node->schema)) {
1612 /* find the next node after we have found our node schema data instance */
1613 break;
1614 }
1615 }
Michal Vasko90932a92020-02-12 14:33:03 +01001616 }
1617
1618 return match;
1619}
1620
1621/**
1622 * @brief Insert node after a sibling.
1623 *
Michal Vasko9f96a052020-03-10 09:41:45 +01001624 * Handles inserting into NP containers and key-less lists.
1625 *
Michal Vasko90932a92020-02-12 14:33:03 +01001626 * @param[in] sibling Sibling to insert after.
1627 * @param[in] node Node to insert.
1628 */
1629static void
Michal Vaskof03ed032020-03-04 13:31:44 +01001630lyd_insert_after_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001631{
Michal Vasko0249f7c2020-03-05 16:36:40 +01001632 struct lyd_node_inner *par;
1633
Michal Vasko90932a92020-02-12 14:33:03 +01001634 assert(!node->next && (node->prev == node));
1635
1636 node->next = sibling->next;
1637 node->prev = sibling;
1638 sibling->next = node;
1639 if (node->next) {
1640 /* sibling had a succeeding node */
1641 node->next->prev = node;
1642 } else {
1643 /* sibling was last, find first sibling and change its prev */
1644 if (sibling->parent) {
1645 sibling = sibling->parent->child;
1646 } else {
1647 for (; sibling->prev->next != node; sibling = sibling->prev);
1648 }
1649 sibling->prev = node;
1650 }
1651 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001652
Michal Vasko9f96a052020-03-10 09:41:45 +01001653 for (par = node->parent; par; par = par->parent) {
1654 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
1655 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +01001656 par->flags &= ~LYD_DEFAULT;
1657 }
Michal Vaskob104f112020-07-17 09:54:54 +02001658 if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001659 /* rehash key-less list */
1660 lyd_hash((struct lyd_node *)par);
1661 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001662 }
Michal Vasko90932a92020-02-12 14:33:03 +01001663}
1664
1665/**
1666 * @brief Insert node before a sibling.
1667 *
Michal Vasko9f96a052020-03-10 09:41:45 +01001668 * Handles inserting into NP containers and key-less lists.
1669 *
Michal Vasko90932a92020-02-12 14:33:03 +01001670 * @param[in] sibling Sibling to insert before.
1671 * @param[in] node Node to insert.
1672 */
1673static void
Michal Vaskof03ed032020-03-04 13:31:44 +01001674lyd_insert_before_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001675{
Michal Vasko0249f7c2020-03-05 16:36:40 +01001676 struct lyd_node_inner *par;
1677
Michal Vasko90932a92020-02-12 14:33:03 +01001678 assert(!node->next && (node->prev == node));
1679
1680 node->next = sibling;
1681 /* covers situation of sibling being first */
1682 node->prev = sibling->prev;
1683 sibling->prev = node;
1684 if (node->prev->next) {
1685 /* sibling had a preceding node */
1686 node->prev->next = node;
1687 } else if (sibling->parent) {
1688 /* sibling was first and we must also change parent child pointer */
1689 sibling->parent->child = node;
1690 }
1691 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001692
Michal Vasko9f96a052020-03-10 09:41:45 +01001693 for (par = node->parent; par; par = par->parent) {
1694 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
1695 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +01001696 par->flags &= ~LYD_DEFAULT;
1697 }
Michal Vaskob104f112020-07-17 09:54:54 +02001698 if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001699 /* rehash key-less list */
1700 lyd_hash((struct lyd_node *)par);
1701 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001702 }
Michal Vasko90932a92020-02-12 14:33:03 +01001703}
1704
1705/**
Michal Vaskob104f112020-07-17 09:54:54 +02001706 * @brief Insert node as the first and only child of a parent.
Michal Vasko90932a92020-02-12 14:33:03 +01001707 *
Michal Vasko9f96a052020-03-10 09:41:45 +01001708 * Handles inserting into NP containers and key-less lists.
1709 *
Michal Vasko90932a92020-02-12 14:33:03 +01001710 * @param[in] parent Parent to insert into.
1711 * @param[in] node Node to insert.
1712 */
1713static void
Michal Vaskob104f112020-07-17 09:54:54 +02001714lyd_insert_only_child(struct lyd_node *parent, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001715{
1716 struct lyd_node_inner *par;
1717
Michal Vaskob104f112020-07-17 09:54:54 +02001718 assert(parent && !lyd_node_children(parent, 0) && !node->next && (node->prev == node));
Michal Vasko52927e22020-03-16 17:26:14 +01001719 assert(!parent->schema || (parent->schema->nodetype & LYD_NODE_INNER));
Michal Vasko90932a92020-02-12 14:33:03 +01001720
1721 par = (struct lyd_node_inner *)parent;
1722
Michal Vaskob104f112020-07-17 09:54:54 +02001723 par->child = node;
Michal Vasko90932a92020-02-12 14:33:03 +01001724 node->parent = par;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001725
Michal Vasko9f96a052020-03-10 09:41:45 +01001726 for (; par; par = par->parent) {
1727 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
1728 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +01001729 par->flags &= ~LYD_DEFAULT;
1730 }
Michal Vasko52927e22020-03-16 17:26:14 +01001731 if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001732 /* rehash key-less list */
1733 lyd_hash((struct lyd_node *)par);
1734 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001735 }
Michal Vasko751cb4d2020-07-14 12:25:28 +02001736}
Michal Vasko0249f7c2020-03-05 16:36:40 +01001737
Michal Vasko751cb4d2020-07-14 12:25:28 +02001738/**
1739 * @brief Learn whether a list instance has all the keys.
1740 *
1741 * @param[in] list List instance to check.
1742 * @return non-zero if all the keys were found,
1743 * @return 0 otherwise.
1744 */
1745static int
1746lyd_insert_has_keys(const struct lyd_node *list)
1747{
1748 const struct lyd_node *key;
1749 const struct lysc_node *skey = NULL;
1750
1751 assert(list->schema->nodetype == LYS_LIST);
1752 key = lyd_node_children(list, 0);
1753 while ((skey = lys_getnext(skey, list->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
1754 if (!key || (key->schema != skey)) {
1755 /* key missing */
1756 return 0;
1757 }
1758
1759 key = key->next;
1760 }
1761
1762 /* all keys found */
1763 return 1;
Michal Vasko90932a92020-02-12 14:33:03 +01001764}
1765
1766void
Michal Vaskob104f112020-07-17 09:54:54 +02001767lyd_insert_node(struct lyd_node *parent, struct lyd_node **first_sibling_p, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001768{
Michal Vaskob104f112020-07-17 09:54:54 +02001769 struct lyd_node *anchor, *first_sibling;
Michal Vasko90932a92020-02-12 14:33:03 +01001770
Michal Vaskob104f112020-07-17 09:54:54 +02001771 /* inserting list without its keys is not supported */
1772 assert((parent || first_sibling_p) && node && (node->hash || !node->schema));
Michal Vasko9b368d32020-02-14 13:53:31 +01001773
Michal Vaskob104f112020-07-17 09:54:54 +02001774 if (!parent && first_sibling_p && (*first_sibling_p) && (*first_sibling_p)->parent) {
1775 parent = (struct lyd_node *)(*first_sibling_p)->parent;
Michal Vasko9b368d32020-02-14 13:53:31 +01001776 }
Michal Vasko90932a92020-02-12 14:33:03 +01001777
Michal Vaskob104f112020-07-17 09:54:54 +02001778 /* get first sibling */
1779 first_sibling = parent ? ((struct lyd_node_inner *)parent)->child : *first_sibling_p;
Michal Vasko9f96a052020-03-10 09:41:45 +01001780
Michal Vaskob104f112020-07-17 09:54:54 +02001781 /* find the anchor, our next node, so we can insert before it */
1782 anchor = lyd_insert_get_next_anchor(first_sibling, node);
1783 if (anchor) {
1784 lyd_insert_before_node(anchor, node);
1785 } else if (first_sibling) {
1786 lyd_insert_after_node(first_sibling->prev, node);
1787 } else if (parent) {
1788 lyd_insert_only_child(parent, node);
Michal Vasko90932a92020-02-12 14:33:03 +01001789 } else {
Michal Vaskob104f112020-07-17 09:54:54 +02001790 *first_sibling_p = node;
1791 }
1792
1793 /* insert into parent HT */
1794 lyd_insert_hash(node);
1795
1796 /* finish hashes for our parent, if needed and possible */
1797 if (node->schema && (node->schema->flags & LYS_KEY) && lyd_insert_has_keys(parent)) {
1798 lyd_hash(parent);
1799
1800 /* now we can insert even the list into its parent HT */
1801 lyd_insert_hash(parent);
Michal Vasko90932a92020-02-12 14:33:03 +01001802 }
Michal Vasko90932a92020-02-12 14:33:03 +01001803}
1804
Michal Vaskof03ed032020-03-04 13:31:44 +01001805static LY_ERR
1806lyd_insert_check_schema(const struct lysc_node *parent, const struct lysc_node *schema)
1807{
1808 const struct lysc_node *par2;
1809
1810 assert(schema);
Michal Vasko62ed12d2020-05-21 10:08:25 +02001811 assert(!parent || !(parent->nodetype & (LYS_CASE | LYS_CHOICE)));
Michal Vaskof03ed032020-03-04 13:31:44 +01001812
1813 /* find schema parent */
Michal Vasko62ed12d2020-05-21 10:08:25 +02001814 par2 = lysc_data_parent(schema);
Michal Vaskof03ed032020-03-04 13:31:44 +01001815
1816 if (parent) {
1817 /* inner node */
1818 if (par2 != parent) {
Michal Vaskob104f112020-07-17 09:54:54 +02001819 LOGERR(schema->module->ctx, LY_EINVAL, "Cannot insert, parent of \"%s\" is not \"%s\".", schema->name,
1820 parent->name);
Michal Vaskof03ed032020-03-04 13:31:44 +01001821 return LY_EINVAL;
1822 }
1823 } else {
1824 /* top-level node */
1825 if (par2) {
Radek Krejcif6d14cb2020-07-02 16:11:45 +02001826 LOGERR(schema->module->ctx, LY_EINVAL, "Cannot insert, node \"%s\" is not top-level.", schema->name);
Michal Vaskof03ed032020-03-04 13:31:44 +01001827 return LY_EINVAL;
1828 }
1829 }
1830
1831 return LY_SUCCESS;
1832}
1833
1834API LY_ERR
Michal Vaskob104f112020-07-17 09:54:54 +02001835lyd_insert_child(struct lyd_node *parent, struct lyd_node *node)
Michal Vaskof03ed032020-03-04 13:31:44 +01001836{
1837 struct lyd_node *iter;
1838
Michal Vasko654bc852020-06-23 13:28:06 +02001839 LY_CHECK_ARG_RET(NULL, parent, node, parent->schema->nodetype & LYD_NODE_INNER, LY_EINVAL);
Michal Vaskof03ed032020-03-04 13:31:44 +01001840
1841 LY_CHECK_RET(lyd_insert_check_schema(parent->schema, node->schema));
1842
1843 if (node->schema->flags & LYS_KEY) {
1844 LOGERR(parent->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1845 return LY_EINVAL;
1846 }
1847
1848 if (node->parent || node->prev->next) {
1849 lyd_unlink_tree(node);
1850 }
1851
1852 while (node) {
1853 iter = node->next;
1854 lyd_unlink_tree(node);
1855 lyd_insert_node(parent, NULL, node);
1856 node = iter;
1857 }
1858 return LY_SUCCESS;
1859}
1860
1861API LY_ERR
Michal Vaskob104f112020-07-17 09:54:54 +02001862lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, struct lyd_node **first)
Michal Vaskob1b5c262020-03-05 14:29:47 +01001863{
1864 struct lyd_node *iter;
1865
Michal Vaskob104f112020-07-17 09:54:54 +02001866 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Michal Vaskob1b5c262020-03-05 14:29:47 +01001867
Michal Vaskob104f112020-07-17 09:54:54 +02001868 if (sibling) {
1869 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskob1b5c262020-03-05 14:29:47 +01001870 }
1871
1872 if (node->parent || node->prev->next) {
1873 lyd_unlink_tree(node);
1874 }
1875
1876 while (node) {
Michal Vaskob104f112020-07-17 09:54:54 +02001877 if (node->schema->flags & LYS_KEY) {
1878 LOGERR(LYD_NODE_CTX(node), LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1879 return LY_EINVAL;
1880 }
1881
Michal Vaskob1b5c262020-03-05 14:29:47 +01001882 iter = node->next;
1883 lyd_unlink_tree(node);
1884 lyd_insert_node(NULL, &sibling, node);
1885 node = iter;
1886 }
Michal Vaskob1b5c262020-03-05 14:29:47 +01001887
Michal Vaskob104f112020-07-17 09:54:54 +02001888 if (first) {
1889 /* find the first sibling */
1890 *first = sibling;
1891 while ((*first)->prev->next) {
1892 *first = (*first)->prev;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001893 }
1894 }
1895
1896 return LY_SUCCESS;
1897}
1898
Michal Vaskob1b5c262020-03-05 14:29:47 +01001899API LY_ERR
Michal Vaskof03ed032020-03-04 13:31:44 +01001900lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
1901{
1902 struct lyd_node *iter;
1903
1904 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1905
Michal Vasko62ed12d2020-05-21 10:08:25 +02001906 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskof03ed032020-03-04 13:31:44 +01001907
Michal Vaskob104f112020-07-17 09:54:54 +02001908 if (!(node->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(node->schema->flags & LYS_ORDBY_USER)) {
1909 LOGERR(LYD_NODE_CTX(sibling), LY_EINVAL, "Can be used only for user-ordered nodes.");
Michal Vaskof03ed032020-03-04 13:31:44 +01001910 return LY_EINVAL;
1911 }
1912
1913 if (node->parent || node->prev->next) {
1914 lyd_unlink_tree(node);
1915 }
1916
1917 /* insert in reverse order to get the original order */
1918 node = node->prev;
1919 while (node) {
1920 iter = node->prev;
1921 lyd_unlink_tree(node);
1922
1923 lyd_insert_before_node(sibling, node);
Michal Vasko751cb4d2020-07-14 12:25:28 +02001924 lyd_insert_hash(node);
1925
Michal Vaskof03ed032020-03-04 13:31:44 +01001926 /* move the anchor accordingly */
1927 sibling = node;
1928
1929 node = (iter == node) ? NULL : iter;
1930 }
1931 return LY_SUCCESS;
1932}
1933
1934API LY_ERR
1935lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
1936{
1937 struct lyd_node *iter;
1938
1939 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1940
Michal Vasko62ed12d2020-05-21 10:08:25 +02001941 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskof03ed032020-03-04 13:31:44 +01001942
Michal Vaskob104f112020-07-17 09:54:54 +02001943 if (!(node->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(node->schema->flags & LYS_ORDBY_USER)) {
1944 LOGERR(LYD_NODE_CTX(sibling), LY_EINVAL, "Can be used only for user-ordered nodes.");
Michal Vaskof03ed032020-03-04 13:31:44 +01001945 return LY_EINVAL;
1946 }
1947
1948 if (node->parent || node->prev->next) {
1949 lyd_unlink_tree(node);
1950 }
1951
1952 while (node) {
1953 iter = node->next;
1954 lyd_unlink_tree(node);
1955
1956 lyd_insert_after_node(sibling, node);
Michal Vasko751cb4d2020-07-14 12:25:28 +02001957 lyd_insert_hash(node);
1958
Michal Vaskof03ed032020-03-04 13:31:44 +01001959 /* move the anchor accordingly */
1960 sibling = node;
1961
1962 node = iter;
1963 }
1964 return LY_SUCCESS;
1965}
1966
1967API void
1968lyd_unlink_tree(struct lyd_node *node)
1969{
1970 struct lyd_node *iter;
1971
1972 if (!node) {
1973 return;
1974 }
1975
Michal Vaskob104f112020-07-17 09:54:54 +02001976 /* update hashes while still linked into the tree */
1977 lyd_unlink_hash(node);
1978
Michal Vaskof03ed032020-03-04 13:31:44 +01001979 /* unlink from siblings */
1980 if (node->prev->next) {
1981 node->prev->next = node->next;
1982 }
1983 if (node->next) {
1984 node->next->prev = node->prev;
1985 } else {
1986 /* unlinking the last node */
1987 if (node->parent) {
1988 iter = node->parent->child;
1989 } else {
1990 iter = node->prev;
1991 while (iter->prev != node) {
1992 iter = iter->prev;
1993 }
1994 }
1995 /* update the "last" pointer from the first node */
1996 iter->prev = node->prev;
1997 }
1998
1999 /* unlink from parent */
2000 if (node->parent) {
2001 if (node->parent->child == node) {
2002 /* the node is the first child */
2003 node->parent->child = node->next;
2004 }
2005
Michal Vaskoab49dbe2020-07-17 12:32:47 +02002006 /* check for NP container whether its last non-default node is not being unlinked */
2007 if (node->parent->schema && (node->parent->schema->nodetype == LYS_CONTAINER)
2008 && !(node->parent->flags & LYD_DEFAULT) && !(node->parent->schema->flags & LYS_PRESENCE)) {
2009 LY_LIST_FOR(node->parent->child, iter) {
2010 if ((iter != node) && !(iter->flags & LYD_DEFAULT)) {
2011 break;
2012 }
2013 }
2014 if (!iter) {
2015 node->parent->flags |= LYD_DEFAULT;
2016 }
2017 }
2018
Michal Vaskof03ed032020-03-04 13:31:44 +01002019 /* check for keyless list and update its hash */
2020 for (iter = (struct lyd_node *)node->parent; iter; iter = (struct lyd_node *)iter->parent) {
Michal Vasko413c7f22020-05-05 12:34:06 +02002021 if (iter->schema && (iter->schema->flags & LYS_KEYLESS)) {
Michal Vaskof03ed032020-03-04 13:31:44 +01002022 lyd_hash(iter);
2023 }
2024 }
2025
2026 node->parent = NULL;
2027 }
2028
2029 node->next = NULL;
2030 node->prev = node;
2031}
2032
Michal Vasko90932a92020-02-12 14:33:03 +01002033LY_ERR
Michal Vasko9f96a052020-03-10 09:41:45 +01002034lyd_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 +01002035 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 +01002036 void *prefix_data, LYD_FORMAT format, const struct lysc_node *ctx_snode)
Michal Vasko90932a92020-02-12 14:33:03 +01002037{
2038 LY_ERR ret;
2039 struct lysc_ext_instance *ant = NULL;
Michal Vasko9f96a052020-03-10 09:41:45 +01002040 struct lyd_meta *mt, *last;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002041 LY_ARRAY_COUNT_TYPE u;
Michal Vasko90932a92020-02-12 14:33:03 +01002042
Michal Vasko9f96a052020-03-10 09:41:45 +01002043 assert((parent || meta) && mod);
Michal Vasko6f4cbb62020-02-28 11:15:47 +01002044
Radek Krejci7eb54ba2020-05-18 16:30:04 +02002045 LY_ARRAY_FOR(mod->compiled->exts, u) {
2046 if (mod->compiled->exts[u].def->plugin == lyext_plugins_internal[LYEXT_PLUGIN_INTERNAL_ANNOTATION].plugin &&
2047 !ly_strncmp(mod->compiled->exts[u].argument, name, name_len)) {
Michal Vasko90932a92020-02-12 14:33:03 +01002048 /* we have the annotation definition */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02002049 ant = &mod->compiled->exts[u];
Michal Vasko90932a92020-02-12 14:33:03 +01002050 break;
2051 }
2052 }
2053 if (!ant) {
2054 /* attribute is not defined as a metadata annotation (RFC 7952) */
2055 LOGERR(mod->ctx, LY_EINVAL, "Annotation definition for attribute \"%s:%.*s\" not found.",
2056 mod->name, name_len, name);
2057 return LY_EINVAL;
2058 }
2059
Michal Vasko9f96a052020-03-10 09:41:45 +01002060 mt = calloc(1, sizeof *mt);
2061 LY_CHECK_ERR_RET(!mt, LOGMEM(mod->ctx), LY_EMEM);
2062 mt->parent = parent;
2063 mt->annotation = ant;
Michal Vasko52927e22020-03-16 17:26:14 +01002064 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 +01002065 if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01002066 free(mt);
Michal Vasko90932a92020-02-12 14:33:03 +01002067 return ret;
2068 }
Michal Vasko9f96a052020-03-10 09:41:45 +01002069 mt->name = lydict_insert(mod->ctx, name, name_len);
Michal Vasko90932a92020-02-12 14:33:03 +01002070
Michal Vasko6f4cbb62020-02-28 11:15:47 +01002071 /* insert as the last attribute */
2072 if (parent) {
Michal Vasko9f96a052020-03-10 09:41:45 +01002073 if (parent->meta) {
2074 for (last = parent->meta; last->next; last = last->next);
2075 last->next = mt;
Michal Vasko6f4cbb62020-02-28 11:15:47 +01002076 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +01002077 parent->meta = mt;
Michal Vasko6f4cbb62020-02-28 11:15:47 +01002078 }
Michal Vasko9f96a052020-03-10 09:41:45 +01002079 } else if (*meta) {
2080 for (last = *meta; last->next; last = last->next);
2081 last->next = mt;
Michal Vasko90932a92020-02-12 14:33:03 +01002082 }
2083
2084 /* remove default flags from NP containers */
Michal Vasko4ba6aef2020-07-09 15:44:23 +02002085 while (parent && (parent->schema->nodetype == LYS_CONTAINER) && (parent->flags & LYD_DEFAULT)) {
Michal Vasko90932a92020-02-12 14:33:03 +01002086 parent->flags &= ~LYD_DEFAULT;
2087 parent = (struct lyd_node *)parent->parent;
2088 }
2089
Michal Vasko9f96a052020-03-10 09:41:45 +01002090 if (meta) {
2091 *meta = mt;
Michal Vasko90932a92020-02-12 14:33:03 +01002092 }
2093 return ret;
2094}
2095
Michal Vasko52927e22020-03-16 17:26:14 +01002096LY_ERR
2097ly_create_attr(struct lyd_node *parent, struct ly_attr **attr, const struct ly_ctx *ctx, const char *name,
2098 size_t name_len, const char *value, size_t value_len, int *dynamic, LYD_FORMAT format,
2099 struct ly_prefix *val_prefs, const char *prefix, size_t prefix_len, const char *ns)
2100{
2101 struct ly_attr *at, *last;
2102 struct lyd_node_opaq *opaq;
2103
2104 assert(ctx && (parent || attr) && (!parent || !parent->schema));
2105 assert(name && name_len);
2106 assert((prefix_len && ns) || (!prefix_len && !ns));
2107
2108 if (!value_len) {
2109 value = "";
2110 }
2111
2112 at = calloc(1, sizeof *at);
2113 LY_CHECK_ERR_RET(!at, LOGMEM(ctx), LY_EMEM);
2114 at->parent = (struct lyd_node_opaq *)parent;
2115 at->name = lydict_insert(ctx, name, name_len);
2116 if (dynamic && *dynamic) {
2117 at->value = lydict_insert_zc(ctx, (char *)value);
2118 *dynamic = 0;
2119 } else {
2120 at->value = lydict_insert(ctx, value, value_len);
2121 }
2122
2123 at->format = format;
2124 at->val_prefs = val_prefs;
2125 if (ns) {
2126 at->prefix.pref = lydict_insert(ctx, prefix, prefix_len);
2127 at->prefix.ns = lydict_insert(ctx, ns, 0);
2128 }
2129
2130 /* insert as the last attribute */
2131 if (parent) {
2132 opaq = (struct lyd_node_opaq *)parent;
2133 if (opaq->attr) {
2134 for (last = opaq->attr; last->next; last = last->next);
2135 last->next = at;
2136 } else {
2137 opaq->attr = at;
2138 }
2139 } else if (*attr) {
2140 for (last = *attr; last->next; last = last->next);
2141 last->next = at;
2142 }
2143
2144 if (attr) {
2145 *attr = at;
2146 }
2147 return LY_SUCCESS;
2148}
2149
Radek Krejci084289f2019-07-09 17:35:30 +02002150API const struct lyd_node_term *
Michal Vasko004d3152020-06-11 19:59:22 +02002151lyd_target(const struct ly_path *path, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +02002152{
Michal Vasko004d3152020-06-11 19:59:22 +02002153 struct lyd_node *target;
Radek Krejci084289f2019-07-09 17:35:30 +02002154
Michal Vasko004d3152020-06-11 19:59:22 +02002155 if (ly_path_eval(path, tree, &target)) {
2156 return NULL;
Radek Krejci084289f2019-07-09 17:35:30 +02002157 }
2158
Michal Vasko004d3152020-06-11 19:59:22 +02002159 return (struct lyd_node_term *)target;
Radek Krejci084289f2019-07-09 17:35:30 +02002160}
2161
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002162API LY_ERR
Michal Vasko8f359bf2020-07-28 10:41:15 +02002163lyd_compare_single(const struct lyd_node *node1, const struct lyd_node *node2, int options)
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002164{
2165 const struct lyd_node *iter1, *iter2;
2166 struct lyd_node_term *term1, *term2;
2167 struct lyd_node_any *any1, *any2;
Michal Vasko52927e22020-03-16 17:26:14 +01002168 struct lyd_node_opaq *opaq1, *opaq2;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002169 size_t len1, len2;
Radek Krejci084289f2019-07-09 17:35:30 +02002170
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002171 if (!node1 || !node2) {
2172 if (node1 == node2) {
2173 return LY_SUCCESS;
2174 } else {
2175 return LY_ENOT;
2176 }
2177 }
2178
Michal Vasko52927e22020-03-16 17:26:14 +01002179 if ((LYD_NODE_CTX(node1) != LYD_NODE_CTX(node2)) || (node1->schema != node2->schema)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002180 return LY_ENOT;
2181 }
2182
2183 if (node1->hash != node2->hash) {
2184 return LY_ENOT;
2185 }
Michal Vasko52927e22020-03-16 17:26:14 +01002186 /* 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 +02002187
Michal Vasko52927e22020-03-16 17:26:14 +01002188 if (!node1->schema) {
2189 opaq1 = (struct lyd_node_opaq *)node1;
2190 opaq2 = (struct lyd_node_opaq *)node2;
2191 if ((opaq1->name != opaq2->name) || (opaq1->prefix.ns != opaq2->prefix.ns) || (opaq1->format != opaq2->format)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002192 return LY_ENOT;
2193 }
Michal Vasko52927e22020-03-16 17:26:14 +01002194 switch (opaq1->format) {
2195 case LYD_XML:
2196 if (lyxml_value_compare(opaq1->value, opaq1->val_prefs, opaq2->value, opaq2->val_prefs)) {
2197 return LY_ENOT;
2198 }
2199 break;
2200 case LYD_SCHEMA:
Michal Vasko60ea6352020-06-29 13:39:39 +02002201 case LYD_LYB:
Michal Vasko52927e22020-03-16 17:26:14 +01002202 /* not allowed */
2203 LOGINT(LYD_NODE_CTX(node1));
2204 return LY_EINT;
2205 }
2206 if (options & LYD_COMPARE_FULL_RECURSION) {
2207 iter1 = opaq1->child;
2208 iter2 = opaq2->child;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002209 goto all_children_compare;
Michal Vasko52927e22020-03-16 17:26:14 +01002210 }
2211 return LY_SUCCESS;
2212 } else {
2213 switch (node1->schema->nodetype) {
2214 case LYS_LEAF:
2215 case LYS_LEAFLIST:
2216 if (options & LYD_COMPARE_DEFAULTS) {
2217 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
2218 return LY_ENOT;
2219 }
2220 }
2221
Michal Vasko1a2bf2e2020-06-16 13:07:48 +02002222 term1 = (struct lyd_node_term *)node1;
2223 term2 = (struct lyd_node_term *)node2;
2224 if (term1->value.realtype != term2->value.realtype) {
2225 return LY_ENOT;
2226 }
Michal Vasko52927e22020-03-16 17:26:14 +01002227
Michal Vasko1a2bf2e2020-06-16 13:07:48 +02002228 return term1->value.realtype->plugin->compare(&term1->value, &term2->value);
Michal Vasko52927e22020-03-16 17:26:14 +01002229 case LYS_CONTAINER:
2230 if (options & LYD_COMPARE_DEFAULTS) {
2231 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
2232 return LY_ENOT;
2233 }
2234 }
2235 if (options & LYD_COMPARE_FULL_RECURSION) {
2236 iter1 = ((struct lyd_node_inner*)node1)->child;
2237 iter2 = ((struct lyd_node_inner*)node2)->child;
2238 goto all_children_compare;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002239 }
2240 return LY_SUCCESS;
Michal Vasko1bf09392020-03-27 12:38:10 +01002241 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01002242 case LYS_ACTION:
2243 if (options & LYD_COMPARE_FULL_RECURSION) {
2244 /* TODO action/RPC
2245 goto all_children_compare;
2246 */
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002247 }
2248 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01002249 case LYS_NOTIF:
2250 if (options & LYD_COMPARE_FULL_RECURSION) {
2251 /* TODO Notification
2252 goto all_children_compare;
2253 */
2254 }
2255 return LY_SUCCESS;
2256 case LYS_LIST:
2257 iter1 = ((struct lyd_node_inner*)node1)->child;
2258 iter2 = ((struct lyd_node_inner*)node2)->child;
2259
2260 if (!(node1->schema->flags & LYS_KEYLESS) && !(options & LYD_COMPARE_FULL_RECURSION)) {
2261 /* lists with keys, their equivalence is based on their keys */
2262 for (struct lysc_node *key = ((struct lysc_node_list*)node1->schema)->child;
Michal Vaskoc57d9a92020-06-23 13:28:27 +02002263 key && (key->flags & LYS_KEY);
Michal Vasko52927e22020-03-16 17:26:14 +01002264 key = key->next) {
Michal Vasko8f359bf2020-07-28 10:41:15 +02002265 if (lyd_compare_single(iter1, iter2, options)) {
Michal Vasko52927e22020-03-16 17:26:14 +01002266 return LY_ENOT;
2267 }
2268 iter1 = iter1->next;
2269 iter2 = iter2->next;
2270 }
2271 } else {
2272 /* lists without keys, their equivalence is based on equivalence of all the children (both direct and indirect) */
2273
2274 all_children_compare:
2275 if (!iter1 && !iter2) {
2276 /* no children, nothing to compare */
2277 return LY_SUCCESS;
2278 }
2279
2280 for (; iter1 && iter2; iter1 = iter1->next, iter2 = iter2->next) {
Michal Vasko8f359bf2020-07-28 10:41:15 +02002281 if (lyd_compare_single(iter1, iter2, options | LYD_COMPARE_FULL_RECURSION)) {
Michal Vasko52927e22020-03-16 17:26:14 +01002282 return LY_ENOT;
2283 }
2284 }
2285 if (iter1 || iter2) {
2286 return LY_ENOT;
2287 }
2288 }
2289 return LY_SUCCESS;
2290 case LYS_ANYXML:
2291 case LYS_ANYDATA:
2292 any1 = (struct lyd_node_any*)node1;
2293 any2 = (struct lyd_node_any*)node2;
2294
2295 if (any1->value_type != any2->value_type) {
2296 return LY_ENOT;
2297 }
2298 switch (any1->value_type) {
2299 case LYD_ANYDATA_DATATREE:
2300 iter1 = any1->value.tree;
2301 iter2 = any2->value.tree;
2302 goto all_children_compare;
2303 case LYD_ANYDATA_STRING:
2304 case LYD_ANYDATA_XML:
2305 case LYD_ANYDATA_JSON:
2306 len1 = strlen(any1->value.str);
2307 len2 = strlen(any2->value.str);
2308 if (len1 != len2 || strcmp(any1->value.str, any2->value.str)) {
2309 return LY_ENOT;
2310 }
2311 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01002312 case LYD_ANYDATA_LYB:
Michal Vasko60ea6352020-06-29 13:39:39 +02002313 len1 = lyd_lyb_data_length(any1->value.mem);
2314 len2 = lyd_lyb_data_length(any2->value.mem);
Michal Vasko52927e22020-03-16 17:26:14 +01002315 if (len1 != len2 || memcmp(any1->value.mem, any2->value.mem, len1)) {
2316 return LY_ENOT;
2317 }
2318 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01002319 }
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002320 }
2321 }
2322
Michal Vasko52927e22020-03-16 17:26:14 +01002323 LOGINT(LYD_NODE_CTX(node1));
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002324 return LY_EINT;
2325}
Radek Krejci22ebdba2019-07-25 13:59:43 +02002326
Michal Vasko21725742020-06-29 11:49:25 +02002327API LY_ERR
Michal Vasko8f359bf2020-07-28 10:41:15 +02002328lyd_compare_siblings(const struct lyd_node *node1, const struct lyd_node *node2, int options)
2329{
2330 for (; node1 && node2; node1 = node1->next, node2 = node2->next) {
2331 LY_CHECK_RET(lyd_compare_single(node1, node2, options));
2332 }
2333
Michal Vasko11a81432020-07-28 16:31:29 +02002334 if (node1 == node2) {
2335 return LY_SUCCESS;
Michal Vasko8f359bf2020-07-28 10:41:15 +02002336 }
Michal Vasko11a81432020-07-28 16:31:29 +02002337 return LY_ENOT;
Michal Vasko8f359bf2020-07-28 10:41:15 +02002338}
2339
2340API LY_ERR
Michal Vasko21725742020-06-29 11:49:25 +02002341lyd_compare_meta(const struct lyd_meta *meta1, const struct lyd_meta *meta2)
2342{
2343 if (!meta1 || !meta2) {
2344 if (meta1 == meta2) {
2345 return LY_SUCCESS;
2346 } else {
2347 return LY_ENOT;
2348 }
2349 }
2350
2351 if ((LYD_NODE_CTX(meta1->parent) != LYD_NODE_CTX(meta2->parent)) || (meta1->annotation != meta2->annotation)) {
2352 return LY_ENOT;
2353 }
2354
2355 if (meta1->value.realtype != meta2->value.realtype) {
2356 return LY_ENOT;
2357 }
2358
2359 return meta1->value.realtype->plugin->compare(&meta1->value, &meta2->value);
2360}
2361
Radek Krejci22ebdba2019-07-25 13:59:43 +02002362/**
Michal Vasko52927e22020-03-16 17:26:14 +01002363 * @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 +02002364 *
2365 * 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 +02002366 *
2367 * @param[in] node Original node to duplicate
2368 * @param[in] parent Parent to insert into, NULL for top-level sibling.
2369 * @param[in,out] first First sibling, NULL if no top-level sibling exist yet. Can be also NULL if @p parent is set.
2370 * @param[in] options Bitmask of options flags, see @ref dupoptions.
2371 * @param[out] dup_p Pointer where the created duplicated node is placed (besides connecting it int @p parent / @p first sibling).
2372 * @return LY_ERR value
Radek Krejci22ebdba2019-07-25 13:59:43 +02002373 */
Michal Vasko52927e22020-03-16 17:26:14 +01002374static LY_ERR
Michal Vasko3a41dff2020-07-15 14:30:28 +02002375lyd_dup_r(const struct lyd_node *node, struct lyd_node *parent, struct lyd_node **first, int options,
2376 struct lyd_node **dup_p)
Radek Krejci22ebdba2019-07-25 13:59:43 +02002377{
Michal Vasko52927e22020-03-16 17:26:14 +01002378 LY_ERR ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002379 struct lyd_node *dup = NULL;
Michal Vasko61551fa2020-07-09 15:45:45 +02002380 struct lyd_meta *meta;
2381 struct lyd_node_any *any;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002382 LY_ARRAY_COUNT_TYPE u;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002383
Michal Vasko52927e22020-03-16 17:26:14 +01002384 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002385
Michal Vasko52927e22020-03-16 17:26:14 +01002386 if (!node->schema) {
2387 dup = calloc(1, sizeof(struct lyd_node_opaq));
2388 } else {
2389 switch (node->schema->nodetype) {
Michal Vasko1bf09392020-03-27 12:38:10 +01002390 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01002391 case LYS_ACTION:
2392 case LYS_NOTIF:
2393 case LYS_CONTAINER:
2394 case LYS_LIST:
2395 dup = calloc(1, sizeof(struct lyd_node_inner));
2396 break;
2397 case LYS_LEAF:
2398 case LYS_LEAFLIST:
2399 dup = calloc(1, sizeof(struct lyd_node_term));
2400 break;
2401 case LYS_ANYDATA:
2402 case LYS_ANYXML:
2403 dup = calloc(1, sizeof(struct lyd_node_any));
2404 break;
2405 default:
2406 LOGINT(LYD_NODE_CTX(node));
2407 ret = LY_EINT;
2408 goto error;
2409 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02002410 }
Michal Vasko52927e22020-03-16 17:26:14 +01002411 LY_CHECK_ERR_GOTO(!dup, LOGMEM(LYD_NODE_CTX(node)); ret = LY_EMEM, error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002412
Michal Vaskof6df0a02020-06-16 13:08:34 +02002413 if (options & LYD_DUP_WITH_FLAGS) {
2414 dup->flags = node->flags;
2415 } else {
2416 dup->flags = (node->flags & LYD_DEFAULT) | LYD_NEW;
2417 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02002418 dup->schema = node->schema;
Michal Vasko52927e22020-03-16 17:26:14 +01002419 dup->prev = dup;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002420
Michal Vasko25a32822020-07-09 15:48:22 +02002421 /* duplicate metadata */
2422 if (!(options & LYD_DUP_NO_META)) {
2423 LY_LIST_FOR(node->meta, meta) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002424 LY_CHECK_GOTO(ret = lyd_dup_meta_single(meta, dup, NULL), error);
Michal Vasko25a32822020-07-09 15:48:22 +02002425 }
2426 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02002427
2428 /* nodetype-specific work */
Michal Vasko52927e22020-03-16 17:26:14 +01002429 if (!dup->schema) {
2430 struct lyd_node_opaq *opaq = (struct lyd_node_opaq *)dup;
2431 struct lyd_node_opaq *orig = (struct lyd_node_opaq *)node;
2432 struct lyd_node *child;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002433
2434 if (options & LYD_DUP_RECURSIVE) {
2435 /* duplicate all the children */
2436 LY_LIST_FOR(orig->child, child) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002437 LY_CHECK_GOTO(ret = lyd_dup_r(child, dup, NULL, options, NULL), error);
Michal Vasko52927e22020-03-16 17:26:14 +01002438 }
2439 }
2440 opaq->name = lydict_insert(LYD_NODE_CTX(node), orig->name, 0);
2441 opaq->format = orig->format;
2442 if (orig->prefix.pref) {
2443 opaq->prefix.pref = lydict_insert(LYD_NODE_CTX(node), orig->prefix.pref, 0);
2444 }
2445 if (orig->prefix.ns) {
2446 opaq->prefix.ns = lydict_insert(LYD_NODE_CTX(node), orig->prefix.ns, 0);
2447 }
2448 if (orig->val_prefs) {
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002449 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 +01002450 LY_ARRAY_FOR(orig->val_prefs, u) {
2451 opaq->val_prefs[u].pref = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].pref, 0);
2452 opaq->val_prefs[u].ns = lydict_insert(LYD_NODE_CTX(node), orig->val_prefs[u].ns, 0);
2453 LY_ARRAY_INCREMENT(opaq->val_prefs);
2454 }
2455 }
2456 opaq->value = lydict_insert(LYD_NODE_CTX(node), orig->value, 0);
2457 opaq->ctx = orig->ctx;
2458 } else if (dup->schema->nodetype & LYD_NODE_TERM) {
2459 struct lyd_node_term *term = (struct lyd_node_term *)dup;
2460 struct lyd_node_term *orig = (struct lyd_node_term *)node;
2461
2462 term->hash = orig->hash;
2463 term->value.realtype = orig->value.realtype;
2464 LY_CHECK_ERR_GOTO(term->value.realtype->plugin->duplicate(LYD_NODE_CTX(node), &orig->value, &term->value),
2465 LOGERR(LYD_NODE_CTX(node), LY_EINT, "Value duplication failed."); ret = LY_EINT, error);
2466 } else if (dup->schema->nodetype & LYD_NODE_INNER) {
2467 struct lyd_node_inner *orig = (struct lyd_node_inner *)node;
2468 struct lyd_node *child;
2469
2470 if (options & LYD_DUP_RECURSIVE) {
2471 /* duplicate all the children */
2472 LY_LIST_FOR(orig->child, child) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002473 LY_CHECK_GOTO(ret = lyd_dup_r(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002474 }
Radek Krejci0fe9b512019-07-26 17:51:05 +02002475 } else if (dup->schema->nodetype == LYS_LIST && !(dup->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002476 /* always duplicate keys of a list */
Radek Krejci22ebdba2019-07-25 13:59:43 +02002477 child = orig->child;
Michal Vasko52927e22020-03-16 17:26:14 +01002478 for (struct lysc_node *key = ((struct lysc_node_list *)dup->schema)->child;
Michal Vaskoc57d9a92020-06-23 13:28:27 +02002479 key && (key->flags & LYS_KEY);
Radek Krejci0fe9b512019-07-26 17:51:05 +02002480 key = key->next) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002481 if (!child) {
2482 /* possibly not keys are present in filtered tree */
2483 break;
Radek Krejci0fe9b512019-07-26 17:51:05 +02002484 } else if (child->schema != key) {
2485 /* possibly not all keys are present in filtered tree,
2486 * but there can be also some non-key nodes */
2487 continue;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002488 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002489 LY_CHECK_GOTO(ret = lyd_dup_r(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002490 child = child->next;
2491 }
2492 }
2493 lyd_hash(dup);
2494 } else if (dup->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko61551fa2020-07-09 15:45:45 +02002495 dup->hash = node->hash;
2496 any = (struct lyd_node_any *)node;
2497 LY_CHECK_GOTO(ret = lyd_any_copy_value(dup, &any->value, any->value_type), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002498 }
2499
Michal Vasko52927e22020-03-16 17:26:14 +01002500 /* insert */
2501 lyd_insert_node(parent, first, dup);
Michal Vasko52927e22020-03-16 17:26:14 +01002502
2503 if (dup_p) {
2504 *dup_p = dup;
2505 }
2506 return LY_SUCCESS;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002507
2508error:
Michal Vasko52927e22020-03-16 17:26:14 +01002509 lyd_free_tree(dup);
2510 return ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002511}
2512
Michal Vasko3a41dff2020-07-15 14:30:28 +02002513static LY_ERR
2514lyd_dup_get_local_parent(const struct lyd_node *node, const struct lyd_node_inner *parent, struct lyd_node **dup_parent,
2515 struct lyd_node_inner **local_parent)
Radek Krejci22ebdba2019-07-25 13:59:43 +02002516{
Michal Vasko3a41dff2020-07-15 14:30:28 +02002517 const struct lyd_node_inner *orig_parent, *iter;
2518 int repeat = 1;
2519
2520 *dup_parent = NULL;
2521 *local_parent = NULL;
2522
2523 for (orig_parent = node->parent; repeat && orig_parent; orig_parent = orig_parent->parent) {
2524 if (parent && (parent->schema == orig_parent->schema)) {
2525 /* stop creating parents, connect what we have into the provided parent */
2526 iter = parent;
2527 repeat = 0;
2528 } else {
2529 iter = NULL;
2530 LY_CHECK_RET(lyd_dup_r((struct lyd_node *)orig_parent, NULL, (struct lyd_node **)&iter, 0,
2531 (struct lyd_node **)&iter));
2532 }
2533 if (!*local_parent) {
2534 *local_parent = (struct lyd_node_inner *)iter;
2535 }
2536 if (iter->child) {
2537 /* 1) list - add after keys
2538 * 2) provided parent with some children */
2539 iter->child->prev->next = *dup_parent;
2540 if (*dup_parent) {
2541 (*dup_parent)->prev = iter->child->prev;
2542 iter->child->prev = *dup_parent;
2543 }
2544 } else {
2545 ((struct lyd_node_inner *)iter)->child = *dup_parent;
2546 }
2547 if (*dup_parent) {
2548 (*dup_parent)->parent = (struct lyd_node_inner *)iter;
2549 }
2550 *dup_parent = (struct lyd_node *)iter;
2551 }
2552
2553 if (repeat && parent) {
2554 /* given parent and created parents chain actually do not interconnect */
2555 LOGERR(LYD_NODE_CTX(node), LY_EINVAL,
2556 "Invalid argument parent (%s()) - does not interconnect with the created node's parents chain.", __func__);
2557 return LY_EINVAL;
2558 }
2559
2560 return LY_SUCCESS;
2561}
2562
2563static LY_ERR
2564lyd_dup(const struct lyd_node *node, struct lyd_node_inner *parent, int options, int nosiblings, struct lyd_node **dup)
2565{
2566 LY_ERR rc;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002567 const struct lyd_node *orig; /* original node to be duplicated */
2568 struct lyd_node *first = NULL; /* the first duplicated node, this is returned */
Radek Krejci22ebdba2019-07-25 13:59:43 +02002569 struct lyd_node *top = NULL; /* the most higher created node */
2570 struct lyd_node_inner *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
Radek Krejci22ebdba2019-07-25 13:59:43 +02002571
Michal Vasko3a41dff2020-07-15 14:30:28 +02002572 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002573
2574 if (options & LYD_DUP_WITH_PARENTS) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002575 LY_CHECK_GOTO(rc = lyd_dup_get_local_parent(node, parent, &top, &local_parent), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002576 } else {
2577 local_parent = parent;
2578 }
2579
Radek Krejci22ebdba2019-07-25 13:59:43 +02002580 LY_LIST_FOR(node, orig) {
Michal Vasko52927e22020-03-16 17:26:14 +01002581 /* if there is no local parent, it will be inserted into first */
Michal Vasko3a41dff2020-07-15 14:30:28 +02002582 LY_CHECK_GOTO(rc = lyd_dup_r(orig, (struct lyd_node *)local_parent, &first, options, first ? NULL : &first), error);
2583 if (nosiblings) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002584 break;
2585 }
2586 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002587
2588 /* rehash if needed */
2589 for (; local_parent; local_parent = local_parent->parent) {
2590 if (local_parent->schema->nodetype == LYS_LIST && (local_parent->schema->flags & LYS_KEYLESS)) {
2591 lyd_hash((struct lyd_node *)local_parent);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002592 }
2593 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002594
2595 if (dup) {
2596 *dup = first;
2597 }
2598 return LY_SUCCESS;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002599
2600error:
2601 if (top) {
2602 lyd_free_tree(top);
2603 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +01002604 lyd_free_siblings(first);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002605 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002606 return rc;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002607}
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002608
Michal Vasko3a41dff2020-07-15 14:30:28 +02002609API LY_ERR
2610lyd_dup_single(const struct lyd_node *node, struct lyd_node_inner *parent, int options, struct lyd_node **dup)
2611{
2612 return lyd_dup(node, parent, options, 1, dup);
2613}
2614
2615API LY_ERR
2616lyd_dup_siblings(const struct lyd_node *node, struct lyd_node_inner *parent, int options, struct lyd_node **dup)
2617{
2618 return lyd_dup(node, parent, options, 0, dup);
2619}
2620
2621API LY_ERR
2622lyd_dup_meta_single(const struct lyd_meta *meta, struct lyd_node *node, struct lyd_meta **dup)
Michal Vasko25a32822020-07-09 15:48:22 +02002623{
2624 LY_ERR ret;
2625 struct lyd_meta *mt, *last;
2626
Michal Vasko3a41dff2020-07-15 14:30:28 +02002627 LY_CHECK_ARG_RET(NULL, meta, node, LY_EINVAL);
Michal Vasko25a32822020-07-09 15:48:22 +02002628
2629 /* create a copy */
2630 mt = calloc(1, sizeof *mt);
Michal Vasko3a41dff2020-07-15 14:30:28 +02002631 LY_CHECK_ERR_RET(!mt, LOGMEM(LYD_NODE_CTX(node)), LY_EMEM);
Michal Vasko25a32822020-07-09 15:48:22 +02002632 mt->parent = node;
2633 mt->annotation = meta->annotation;
2634 mt->value.realtype = meta->value.realtype;
2635 ret = mt->value.realtype->plugin->duplicate(LYD_NODE_CTX(node), &meta->value, &mt->value);
Michal Vasko3a41dff2020-07-15 14:30:28 +02002636 LY_CHECK_ERR_RET(ret, LOGERR(LYD_NODE_CTX(node), LY_EINT, "Value duplication failed."), ret);
Michal Vasko25a32822020-07-09 15:48:22 +02002637 mt->name = lydict_insert(LYD_NODE_CTX(node), meta->name, 0);
2638
2639 /* insert as the last attribute */
2640 if (node->meta) {
2641 for (last = node->meta; last->next; last = last->next);
2642 last->next = mt;
2643 } else {
2644 node->meta = mt;
2645 }
2646
Michal Vasko3a41dff2020-07-15 14:30:28 +02002647 if (dup) {
2648 *dup = mt;
2649 }
2650 return LY_SUCCESS;
Michal Vasko25a32822020-07-09 15:48:22 +02002651}
2652
Michal Vasko4490d312020-06-16 13:08:55 +02002653/**
2654 * @brief Merge a source sibling into target siblings.
2655 *
2656 * @param[in,out] first_trg First target sibling, is updated if top-level.
2657 * @param[in] parent_trg Target parent.
2658 * @param[in,out] sibling_src Source sibling to merge, set to NULL if spent.
2659 * @param[in] options Merge options.
2660 * @return LY_ERR value.
2661 */
2662static LY_ERR
2663lyd_merge_sibling_r(struct lyd_node **first_trg, struct lyd_node *parent_trg, const struct lyd_node **sibling_src_p,
2664 int options)
2665{
2666 LY_ERR ret;
2667 const struct lyd_node *child_src, *tmp, *sibling_src;
2668 struct lyd_node *match_trg, *dup_src, *next, *elem;
2669 struct lysc_type *type;
Michal Vasko4490d312020-06-16 13:08:55 +02002670
2671 sibling_src = *sibling_src_p;
2672 if (sibling_src->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
2673 /* try to find the exact instance */
2674 ret = lyd_find_sibling_first(*first_trg, sibling_src, &match_trg);
2675 } else {
2676 /* try to simply find the node, there cannot be more instances */
2677 ret = lyd_find_sibling_val(*first_trg, sibling_src->schema, NULL, 0, &match_trg);
2678 }
2679
2680 if (!ret) {
2681 /* node found, make sure even value matches for all node types */
Michal Vasko8f359bf2020-07-28 10:41:15 +02002682 if ((match_trg->schema->nodetype == LYS_LEAF) && lyd_compare_single(sibling_src, match_trg, LYD_COMPARE_DEFAULTS)) {
Michal Vasko4490d312020-06-16 13:08:55 +02002683 /* since they are different, they cannot both be default */
2684 assert(!(sibling_src->flags & LYD_DEFAULT) || !(match_trg->flags & LYD_DEFAULT));
2685
Michal Vasko3a41dff2020-07-15 14:30:28 +02002686 /* update value (or only LYD_DEFAULT flag) only if flag set or the source node is not default */
2687 if ((options & LYD_MERGE_DEFAULTS) || !(sibling_src->flags & LYD_DEFAULT)) {
Michal Vasko4490d312020-06-16 13:08:55 +02002688 type = ((struct lysc_node_leaf *)match_trg->schema)->type;
2689 type->plugin->free(LYD_NODE_CTX(match_trg), &((struct lyd_node_term *)match_trg)->value);
2690 LY_CHECK_RET(type->plugin->duplicate(LYD_NODE_CTX(match_trg), &((struct lyd_node_term *)sibling_src)->value,
2691 &((struct lyd_node_term *)match_trg)->value));
2692
2693 /* copy flags and add LYD_NEW */
2694 match_trg->flags = sibling_src->flags | LYD_NEW;
2695 }
Michal Vasko8f359bf2020-07-28 10:41:15 +02002696 } else if ((match_trg->schema->nodetype & LYS_ANYDATA) && lyd_compare_single(sibling_src, match_trg, 0)) {
Michal Vasko4c583e82020-07-17 12:16:14 +02002697 /* update value */
2698 LY_CHECK_RET(lyd_any_copy_value(match_trg, &((struct lyd_node_any *)sibling_src)->value,
2699 ((struct lyd_node_any *)sibling_src)->value_type));
Michal Vasko4490d312020-06-16 13:08:55 +02002700
2701 /* copy flags and add LYD_NEW */
2702 match_trg->flags = sibling_src->flags | LYD_NEW;
Michal Vasko4490d312020-06-16 13:08:55 +02002703 } else {
2704 /* check descendants, recursively */
Michal Vasko5bfd4be2020-06-23 13:26:19 +02002705 LY_LIST_FOR_SAFE(LYD_CHILD(sibling_src), tmp, child_src) {
Michal Vasko4490d312020-06-16 13:08:55 +02002706 LY_CHECK_RET(lyd_merge_sibling_r(lyd_node_children_p(match_trg), match_trg, &child_src, options));
2707 }
2708 }
2709 } else {
2710 /* node not found, merge it */
2711 if (options & LYD_MERGE_DESTRUCT) {
2712 dup_src = (struct lyd_node *)sibling_src;
2713 lyd_unlink_tree(dup_src);
2714 /* spend it */
2715 *sibling_src_p = NULL;
2716 } else {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002717 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 +02002718 }
2719
2720 /* set LYD_NEW for all the new nodes, required for validation */
2721 LYD_TREE_DFS_BEGIN(dup_src, next, elem) {
2722 elem->flags |= LYD_NEW;
2723 LYD_TREE_DFS_END(dup_src, next, elem);
2724 }
2725
2726 lyd_insert_node(parent_trg, first_trg, dup_src);
2727 }
2728
2729 return LY_SUCCESS;
2730}
2731
Michal Vasko3a41dff2020-07-15 14:30:28 +02002732static LY_ERR
2733lyd_merge(struct lyd_node **target, const struct lyd_node *source, int options, int nosiblings)
Michal Vasko4490d312020-06-16 13:08:55 +02002734{
2735 const struct lyd_node *sibling_src, *tmp;
2736 int first;
2737
2738 LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
2739
2740 if (!source) {
2741 /* nothing to merge */
2742 return LY_SUCCESS;
2743 }
2744
2745 if (lysc_data_parent((*target)->schema) || lysc_data_parent(source->schema)) {
2746 LOGERR(LYD_NODE_CTX(source), LY_EINVAL, "Invalid arguments - can merge only 2 top-level subtrees (%s()).", __func__);
2747 return LY_EINVAL;
2748 }
2749
2750 LY_LIST_FOR_SAFE(source, tmp, sibling_src) {
2751 first = sibling_src == source ? 1 : 0;
2752 LY_CHECK_RET(lyd_merge_sibling_r(target, NULL, &sibling_src, options));
2753 if (first && !sibling_src) {
2754 /* source was spent (unlinked), move to the next node */
2755 source = tmp;
2756 }
2757
Michal Vasko3a41dff2020-07-15 14:30:28 +02002758 if (nosiblings) {
Michal Vasko4490d312020-06-16 13:08:55 +02002759 break;
2760 }
2761 }
2762
2763 if (options & LYD_MERGE_DESTRUCT) {
2764 /* free any leftover source data that were not merged */
2765 lyd_free_siblings((struct lyd_node *)source);
2766 }
2767
2768 return LY_SUCCESS;
2769}
2770
Michal Vasko3a41dff2020-07-15 14:30:28 +02002771API LY_ERR
2772lyd_merge_tree(struct lyd_node **target, const struct lyd_node *source, int options)
2773{
2774 return lyd_merge(target, source, options, 1);
2775}
2776
2777API LY_ERR
2778lyd_merge_siblings(struct lyd_node **target, const struct lyd_node *source, int options)
2779{
2780 return lyd_merge(target, source, options, 0);
2781}
2782
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002783static LY_ERR
2784lyd_path_str_enlarge(char **buffer, size_t *buflen, size_t reqlen, int is_static)
2785{
Michal Vasko14654712020-02-06 08:35:21 +01002786 /* ending \0 */
2787 ++reqlen;
2788
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002789 if (reqlen > *buflen) {
2790 if (is_static) {
2791 return LY_EINCOMPLETE;
2792 }
2793
2794 *buffer = ly_realloc(*buffer, reqlen * sizeof **buffer);
2795 if (!*buffer) {
2796 return LY_EMEM;
2797 }
2798
2799 *buflen = reqlen;
2800 }
2801
2802 return LY_SUCCESS;
2803}
2804
Michal Vaskod59035b2020-07-08 12:00:06 +02002805LY_ERR
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002806lyd_path_list_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2807{
2808 const struct lyd_node *key;
2809 int dynamic = 0;
2810 size_t len;
2811 const char *val;
2812 char quot;
2813 LY_ERR rc;
2814
Michal Vasko5bfd4be2020-06-23 13:26:19 +02002815 for (key = lyd_node_children(node, 0); key && (key->schema->flags & LYS_KEY); key = key->next) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002816 val = lyd_value2str((struct lyd_node_term *)key, &dynamic);
2817 len = 1 + strlen(key->schema->name) + 2 + strlen(val) + 2;
2818 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2819 if (rc != LY_SUCCESS) {
2820 if (dynamic) {
2821 free((char *)val);
2822 }
2823 return rc;
2824 }
2825
2826 quot = '\'';
2827 if (strchr(val, '\'')) {
2828 quot = '"';
2829 }
2830 *bufused += sprintf(*buffer + *bufused, "[%s=%c%s%c]", key->schema->name, quot, val, quot);
2831
2832 if (dynamic) {
2833 free((char *)val);
2834 }
2835 }
2836
2837 return LY_SUCCESS;
2838}
2839
2840/**
2841 * @brief Append leaf-list value predicate to path.
2842 *
2843 * @param[in] node Node to print.
2844 * @param[in,out] buffer Buffer to print to.
2845 * @param[in,out] buflen Current buffer length.
2846 * @param[in,out] bufused Current number of characters used in @p buffer.
2847 * @param[in] is_static Whether buffer is static or can be reallocated.
2848 * @return LY_ERR
2849 */
2850static LY_ERR
2851lyd_path_leaflist_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2852{
2853 int dynamic = 0;
2854 size_t len;
2855 const char *val;
2856 char quot;
2857 LY_ERR rc;
2858
2859 val = lyd_value2str((struct lyd_node_term *)node, &dynamic);
2860 len = 4 + strlen(val) + 2;
2861 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2862 if (rc != LY_SUCCESS) {
2863 goto cleanup;
2864 }
2865
2866 quot = '\'';
2867 if (strchr(val, '\'')) {
2868 quot = '"';
2869 }
2870 *bufused += sprintf(*buffer + *bufused, "[.=%c%s%c]", quot, val, quot);
2871
2872cleanup:
2873 if (dynamic) {
2874 free((char *)val);
2875 }
2876 return rc;
2877}
2878
2879/**
2880 * @brief Append node position (relative to its other instances) predicate to path.
2881 *
2882 * @param[in] node Node to print.
2883 * @param[in,out] buffer Buffer to print to.
2884 * @param[in,out] buflen Current buffer length.
2885 * @param[in,out] bufused Current number of characters used in @p buffer.
2886 * @param[in] is_static Whether buffer is static or can be reallocated.
2887 * @return LY_ERR
2888 */
2889static LY_ERR
2890lyd_path_position_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, int is_static)
2891{
2892 const struct lyd_node *first, *iter;
2893 size_t len;
2894 int pos;
2895 char *val = NULL;
2896 LY_ERR rc;
2897
2898 if (node->parent) {
2899 first = node->parent->child;
2900 } else {
2901 for (first = node; node->prev->next; node = node->prev);
2902 }
2903 pos = 1;
2904 for (iter = first; iter != node; iter = iter->next) {
2905 if (iter->schema == node->schema) {
2906 ++pos;
2907 }
2908 }
2909 if (asprintf(&val, "%d", pos) == -1) {
2910 return LY_EMEM;
2911 }
2912
2913 len = 1 + strlen(val) + 1;
2914 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
2915 if (rc != LY_SUCCESS) {
2916 goto cleanup;
2917 }
2918
2919 *bufused += sprintf(*buffer + *bufused, "[%s]", val);
2920
2921cleanup:
2922 free(val);
2923 return rc;
2924}
2925
2926API char *
2927lyd_path(const struct lyd_node *node, LYD_PATH_TYPE pathtype, char *buffer, size_t buflen)
2928{
Michal Vasko14654712020-02-06 08:35:21 +01002929 int is_static = 0, i, depth;
2930 size_t bufused = 0, len;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002931 const struct lyd_node *iter;
2932 const struct lys_module *mod;
Michal Vasko790b2bc2020-08-03 13:35:06 +02002933 LY_ERR rc = LY_SUCCESS;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002934
2935 LY_CHECK_ARG_RET(NULL, node, NULL);
2936 if (buffer) {
2937 LY_CHECK_ARG_RET(node->schema->module->ctx, buflen > 1, NULL);
2938 is_static = 1;
Michal Vasko14654712020-02-06 08:35:21 +01002939 } else {
2940 buflen = 0;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002941 }
2942
2943 switch (pathtype) {
Michal Vasko14654712020-02-06 08:35:21 +01002944 case LYD_PATH_LOG:
Michal Vasko790b2bc2020-08-03 13:35:06 +02002945 case LYD_PATH_LOG_NO_LAST_PRED:
Michal Vasko14654712020-02-06 08:35:21 +01002946 depth = 1;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002947 for (iter = node; iter->parent; iter = (const struct lyd_node *)iter->parent) {
2948 ++depth;
2949 }
2950
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002951 goto iter_print;
Michal Vasko14654712020-02-06 08:35:21 +01002952 while (depth) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002953 /* find the right node */
Michal Vasko14654712020-02-06 08:35:21 +01002954 for (iter = node, i = 1; i < depth; iter = (const struct lyd_node *)iter->parent, ++i);
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002955iter_print:
2956 /* print prefix and name */
2957 mod = NULL;
2958 if (!iter->parent || (iter->schema->module != iter->parent->schema->module)) {
2959 mod = iter->schema->module;
2960 }
2961
2962 /* realloc string */
2963 len = 1 + (mod ? strlen(mod->name) + 1 : 0) + strlen(iter->schema->name);
2964 rc = lyd_path_str_enlarge(&buffer, &buflen, bufused + len, is_static);
2965 if (rc != LY_SUCCESS) {
2966 break;
2967 }
2968
2969 /* print next node */
2970 bufused += sprintf(buffer + bufused, "/%s%s%s", mod ? mod->name : "", mod ? ":" : "", iter->schema->name);
2971
Michal Vasko790b2bc2020-08-03 13:35:06 +02002972 /* do not always print the last (first) predicate */
2973 if (bufused || (pathtype == LYD_PATH_LOG)) {
2974 switch (iter->schema->nodetype) {
2975 case LYS_LIST:
2976 if (iter->schema->flags & LYS_KEYLESS) {
2977 /* print its position */
2978 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2979 } else {
2980 /* print all list keys in predicates */
2981 rc = lyd_path_list_predicate(iter, &buffer, &buflen, &bufused, is_static);
2982 }
2983 break;
2984 case LYS_LEAFLIST:
2985 if (iter->schema->flags & LYS_CONFIG_W) {
2986 /* print leaf-list value */
2987 rc = lyd_path_leaflist_predicate(iter, &buffer, &buflen, &bufused, is_static);
2988 } else {
2989 /* print its position */
2990 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
2991 }
2992 break;
2993 default:
2994 /* nothing to print more */
2995 break;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002996 }
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002997 }
2998 if (rc != LY_SUCCESS) {
2999 break;
3000 }
3001
Michal Vasko14654712020-02-06 08:35:21 +01003002 --depth;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003003 }
3004 break;
3005 }
3006
3007 return buffer;
3008}
Michal Vaskoe444f752020-02-10 12:20:06 +01003009
Michal Vasko25a32822020-07-09 15:48:22 +02003010API struct lyd_meta *
3011lyd_find_meta(const struct lyd_meta *first, const struct lys_module *module, const char *name)
3012{
3013 struct lyd_meta *ret = NULL;
3014 const struct ly_ctx *ctx;
3015 const char *prefix, *tmp;
3016 char *str;
3017 size_t pref_len, name_len;
3018
3019 LY_CHECK_ARG_RET(NULL, module || strchr(name, ':'), name, NULL);
3020
3021 if (!first) {
3022 return NULL;
3023 }
3024
3025 ctx = first->annotation->module->ctx;
3026
3027 /* parse the name */
3028 tmp = name;
3029 if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
3030 LOGERR(ctx, LY_EINVAL, "Metadata name \"%s\" is not valid.", name);
3031 return NULL;
3032 }
3033
3034 /* find the module */
3035 if (prefix) {
3036 str = strndup(prefix, pref_len);
3037 module = ly_ctx_get_module_latest(ctx, str);
3038 free(str);
3039 LY_CHECK_ERR_RET(!module, LOGERR(ctx, LY_EINVAL, "Module \"%.*s\" not found.", pref_len, prefix), NULL);
3040 }
3041
3042 /* find the metadata */
3043 LY_LIST_FOR(first, first) {
3044 if ((first->annotation->module == module) && !strcmp(first->name, name)) {
3045 ret = (struct lyd_meta *)first;
3046 break;
3047 }
3048 }
3049
3050 return ret;
3051}
3052
Michal Vasko9b368d32020-02-14 13:53:31 +01003053API LY_ERR
Michal Vaskoe444f752020-02-10 12:20:06 +01003054lyd_find_sibling_first(const struct lyd_node *siblings, const struct lyd_node *target, struct lyd_node **match)
3055{
3056 struct lyd_node **match_p;
3057 struct lyd_node_inner *parent;
3058
Michal Vaskof03ed032020-03-04 13:31:44 +01003059 LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01003060
Michal Vasko62ed12d2020-05-21 10:08:25 +02003061 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(target->schema))) {
3062 /* no data or schema mismatch */
Michal Vasko9b368d32020-02-14 13:53:31 +01003063 if (match) {
3064 *match = NULL;
3065 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003066 return LY_ENOTFOUND;
3067 }
3068
3069 /* find first sibling */
3070 if (siblings->parent) {
3071 siblings = siblings->parent->child;
3072 } else {
3073 while (siblings->prev->next) {
3074 siblings = siblings->prev;
3075 }
3076 }
3077
3078 parent = (struct lyd_node_inner *)siblings->parent;
3079 if (parent && parent->children_ht) {
3080 assert(target->hash);
3081
3082 /* find by hash */
3083 if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
Michal Vaskoda859032020-07-14 12:20:14 +02003084 /* check even value when needed */
Michal Vasko8f359bf2020-07-28 10:41:15 +02003085 if (!(target->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !lyd_compare_single(target, *match_p, 0)) {
Michal Vaskoda859032020-07-14 12:20:14 +02003086 siblings = *match_p;
3087 } else {
3088 siblings = NULL;
3089 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003090 } else {
3091 /* not found */
3092 siblings = NULL;
3093 }
3094 } else {
3095 /* no children hash table */
3096 for (; siblings; siblings = siblings->next) {
Michal Vasko8f359bf2020-07-28 10:41:15 +02003097 if (!lyd_compare_single(siblings, target, 0)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01003098 break;
3099 }
3100 }
3101 }
3102
3103 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01003104 if (match) {
3105 *match = NULL;
3106 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003107 return LY_ENOTFOUND;
3108 }
3109
Michal Vasko9b368d32020-02-14 13:53:31 +01003110 if (match) {
3111 *match = (struct lyd_node *)siblings;
3112 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003113 return LY_SUCCESS;
3114}
3115
Michal Vasko90932a92020-02-12 14:33:03 +01003116static int
3117lyd_hash_table_schema_val_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *UNUSED(cb_data))
3118{
3119 struct lysc_node *val1;
3120 struct lyd_node *val2;
3121
3122 val1 = *((struct lysc_node **)val1_p);
3123 val2 = *((struct lyd_node **)val2_p);
3124
Michal Vasko90932a92020-02-12 14:33:03 +01003125 if (val1 == val2->schema) {
3126 /* schema match is enough */
3127 return 1;
3128 } else {
3129 return 0;
3130 }
3131}
3132
3133static LY_ERR
3134lyd_find_sibling_schema(const struct lyd_node *siblings, const struct lysc_node *schema, struct lyd_node **match)
3135{
3136 struct lyd_node **match_p;
3137 struct lyd_node_inner *parent;
3138 uint32_t hash;
3139 values_equal_cb ht_cb;
3140
Michal Vaskob104f112020-07-17 09:54:54 +02003141 assert(siblings && schema);
Michal Vasko90932a92020-02-12 14:33:03 +01003142
3143 parent = (struct lyd_node_inner *)siblings->parent;
3144 if (parent && parent->children_ht) {
3145 /* calculate our hash */
3146 hash = dict_hash_multi(0, schema->module->name, strlen(schema->module->name));
3147 hash = dict_hash_multi(hash, schema->name, strlen(schema->name));
3148 hash = dict_hash_multi(hash, NULL, 0);
3149
3150 /* use special hash table function */
3151 ht_cb = lyht_set_cb(parent->children_ht, lyd_hash_table_schema_val_equal);
3152
3153 /* find by hash */
3154 if (!lyht_find(parent->children_ht, &schema, hash, (void **)&match_p)) {
3155 siblings = *match_p;
3156 } else {
3157 /* not found */
3158 siblings = NULL;
3159 }
3160
3161 /* set the original hash table compare function back */
3162 lyht_set_cb(parent->children_ht, ht_cb);
3163 } else {
Michal Vaskob104f112020-07-17 09:54:54 +02003164 /* find first sibling */
3165 if (siblings->parent) {
3166 siblings = siblings->parent->child;
3167 } else {
3168 while (siblings->prev->next) {
3169 siblings = siblings->prev;
3170 }
3171 }
3172
3173 /* search manually without hashes */
Michal Vasko90932a92020-02-12 14:33:03 +01003174 for (; siblings; siblings = siblings->next) {
3175 if (siblings->schema == schema) {
3176 /* schema match is enough */
3177 break;
3178 }
3179 }
3180 }
3181
3182 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01003183 if (match) {
3184 *match = NULL;
3185 }
Michal Vasko90932a92020-02-12 14:33:03 +01003186 return LY_ENOTFOUND;
3187 }
3188
Michal Vasko9b368d32020-02-14 13:53:31 +01003189 if (match) {
3190 *match = (struct lyd_node *)siblings;
3191 }
Michal Vasko90932a92020-02-12 14:33:03 +01003192 return LY_SUCCESS;
3193}
3194
Michal Vaskoe444f752020-02-10 12:20:06 +01003195API LY_ERR
3196lyd_find_sibling_val(const struct lyd_node *siblings, const struct lysc_node *schema, const char *key_or_value,
3197 size_t val_len, struct lyd_node **match)
3198{
3199 LY_ERR rc;
3200 struct lyd_node *target = NULL;
3201
Michal Vasko4c583e82020-07-17 12:16:14 +02003202 LY_CHECK_ARG_RET(NULL, schema, !(schema->nodetype & (LYS_CHOICE | LYS_CASE)), LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01003203
Michal Vasko62ed12d2020-05-21 10:08:25 +02003204 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(schema))) {
3205 /* no data or schema mismatch */
Michal Vasko9b368d32020-02-14 13:53:31 +01003206 if (match) {
3207 *match = NULL;
3208 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003209 return LY_ENOTFOUND;
3210 }
3211
Michal Vaskof03ed032020-03-04 13:31:44 +01003212 if (key_or_value && !val_len) {
3213 val_len = strlen(key_or_value);
3214 }
3215
Michal Vaskob104f112020-07-17 09:54:54 +02003216 if ((schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) && key_or_value) {
3217 /* create a data node and find the instance */
3218 if (schema->nodetype == LYS_LEAFLIST) {
3219 /* target used attributes: schema, hash, value */
3220 rc = lyd_create_term(schema, key_or_value, val_len, NULL, lydjson_resolve_prefix, NULL, LYD_JSON, &target);
3221 LY_CHECK_RET(rc && (rc != LY_EINCOMPLETE), rc);
3222 } else {
Michal Vasko90932a92020-02-12 14:33:03 +01003223 /* target used attributes: schema, hash, child (all keys) */
Michal Vasko004d3152020-06-11 19:59:22 +02003224 LY_CHECK_RET(lyd_create_list2(schema, key_or_value, val_len, &target));
Michal Vasko90932a92020-02-12 14:33:03 +01003225 }
3226
3227 /* find it */
3228 rc = lyd_find_sibling_first(siblings, target, match);
Michal Vaskob104f112020-07-17 09:54:54 +02003229 } else {
3230 /* find the first schema node instance */
3231 rc = lyd_find_sibling_schema(siblings, schema, match);
Michal Vaskoe444f752020-02-10 12:20:06 +01003232 }
3233
Michal Vaskoe444f752020-02-10 12:20:06 +01003234 lyd_free_tree(target);
3235 return rc;
3236}
Michal Vaskoccc02342020-05-21 10:09:21 +02003237
3238API LY_ERR
3239lyd_find_xpath(const struct lyd_node *ctx_node, const char *xpath, struct ly_set **set)
3240{
3241 LY_ERR ret = LY_SUCCESS;
3242 struct lyxp_set xp_set;
3243 struct lyxp_expr *exp;
3244 uint32_t i;
3245
3246 LY_CHECK_ARG_RET(NULL, ctx_node, xpath, set, LY_EINVAL);
3247
3248 memset(&xp_set, 0, sizeof xp_set);
3249
3250 /* compile expression */
Michal Vasko004d3152020-06-11 19:59:22 +02003251 exp = lyxp_expr_parse((struct ly_ctx *)LYD_NODE_CTX(ctx_node), xpath, 0, 1);
Michal Vaskoccc02342020-05-21 10:09:21 +02003252 LY_CHECK_ERR_GOTO(!exp, ret = LY_EINVAL, cleanup);
3253
3254 /* evaluate expression */
3255 ret = lyxp_eval(exp, LYD_JSON, ctx_node->schema->module, ctx_node, LYXP_NODE_ELEM, ctx_node, &xp_set, 0);
3256 LY_CHECK_GOTO(ret, cleanup);
3257
3258 /* allocate return set */
3259 *set = ly_set_new();
3260 LY_CHECK_ERR_GOTO(!*set, LOGMEM(LYD_NODE_CTX(ctx_node)); ret = LY_EMEM, cleanup);
3261
3262 /* transform into ly_set */
3263 if (xp_set.type == LYXP_SET_NODE_SET) {
3264 /* allocate memory for all the elements once (even though not all items must be elements but most likely will be) */
3265 (*set)->objs = malloc(xp_set.used * sizeof *(*set)->objs);
3266 LY_CHECK_ERR_GOTO(!(*set)->objs, LOGMEM(LYD_NODE_CTX(ctx_node)); ret = LY_EMEM, cleanup);
3267 (*set)->size = xp_set.used;
3268
3269 for (i = 0; i < xp_set.used; ++i) {
3270 if (xp_set.val.nodes[i].type == LYXP_NODE_ELEM) {
3271 ly_set_add(*set, xp_set.val.nodes[i].node, LY_SET_OPT_USEASLIST);
3272 }
3273 }
3274 }
3275
3276cleanup:
Michal Vasko0691d522020-05-21 13:21:47 +02003277 lyxp_set_free_content(&xp_set);
Michal Vaskoccc02342020-05-21 10:09:21 +02003278 lyxp_expr_free((struct ly_ctx *)LYD_NODE_CTX(ctx_node), exp);
3279 return ret;
3280}