blob: 9380fe635d67beee380d7a19b682de166965b80c [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>
Radek Krejci47fab892020-11-05 17:02:41 +010021#include <inttypes.h>
Radek Krejcie7b95092019-05-15 11:03:07 +020022#include <stdarg.h>
23#include <stdint.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020024#include <stdio.h>
25#include <stdlib.h>
Radek Krejcie7b95092019-05-15 11:03:07 +020026#include <string.h>
Radek Krejcie7b95092019-05-15 11:03:07 +020027
Radek Krejci535ea9f2020-05-29 16:01:05 +020028#include "common.h"
Michal Vasko5aa44c02020-06-29 11:47:02 +020029#include "compat.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020030#include "context.h"
31#include "dict.h"
Michal Vaskoa6669ba2020-08-06 16:14:26 +020032#include "diff.h"
Michal Vasko90932a92020-02-12 14:33:03 +010033#include "hash_table.h"
Radek Krejci47fab892020-11-05 17:02:41 +010034#include "in.h"
Michal Vaskoafac7822020-10-20 14:22:26 +020035#include "in_internal.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020036#include "log.h"
Radek Krejci7931b192020-06-25 17:05:03 +020037#include "parser_data.h"
38#include "parser_internal.h"
Michal Vasko004d3152020-06-11 19:59:22 +020039#include "path.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020040#include "plugins_exts.h"
Michal Vasko90932a92020-02-12 14:33:03 +010041#include "plugins_exts_internal.h"
Michal Vasko69730152020-10-09 16:30:07 +020042#include "plugins_exts_metadata.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020043#include "plugins_types.h"
44#include "set.h"
45#include "tree.h"
46#include "tree_data_internal.h"
47#include "tree_schema.h"
48#include "tree_schema_internal.h"
Michal Vaskoa6669ba2020-08-06 16:14:26 +020049#include "validation.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020050#include "xml.h"
51#include "xpath.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020052
Michal Vaskob104f112020-07-17 09:54:54 +020053static LY_ERR lyd_find_sibling_schema(const struct lyd_node *siblings, const struct lysc_node *schema,
Radek Krejci0f969882020-08-21 16:56:47 +020054 struct lyd_node **match);
Michal Vaskob104f112020-07-17 09:54:54 +020055
Radek Krejci084289f2019-07-09 17:35:30 +020056LY_ERR
Michal Vaskofeca4fb2020-10-05 08:58:40 +020057lyd_value_store(const struct ly_ctx *ctx, struct lyd_value *val, const struct lysc_type *type, const char *value,
58 size_t value_len, ly_bool *dynamic, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints,
59 const struct lysc_node *ctx_node, ly_bool *incomplete, enum LY_VLOG_ELEM log_elem_type, const void *log_elem)
Radek Krejci084289f2019-07-09 17:35:30 +020060{
Michal Vaskofeca4fb2020-10-05 08:58:40 +020061 LY_ERR ret;
Radek Krejci084289f2019-07-09 17:35:30 +020062 struct ly_err_item *err = NULL;
Michal Vasko25d6ad02020-10-22 12:20:22 +020063 uint32_t options = (dynamic && *dynamic ? LY_TYPE_STORE_DYNAMIC : 0);
Radek Krejci084289f2019-07-09 17:35:30 +020064
Michal Vaskofeca4fb2020-10-05 08:58:40 +020065 if (incomplete) {
66 *incomplete = 0;
Radek Krejci084289f2019-07-09 17:35:30 +020067 }
68
Michal Vaskofeca4fb2020-10-05 08:58:40 +020069 ret = type->plugin->store(ctx, type, value, value_len, options, format, prefix_data, hints, ctx_node, val, &err);
Michal Vasko90932a92020-02-12 14:33:03 +010070 if (ret == LY_EINCOMPLETE) {
Michal Vaskofeca4fb2020-10-05 08:58:40 +020071 if (incomplete) {
72 *incomplete = 1;
73 }
74 } else if (ret) {
75 if (err) {
76 LOGVAL(ctx, log_elem_type, log_elem, err->vecode, err->msg);
77 ly_err_free(err);
78 } else {
79 LOGVAL(ctx, log_elem_type, log_elem, LYVE_OTHER, "Storing value \"%.*s\" failed.", (int)value_len, value);
80 }
81 return ret;
Michal Vasko90932a92020-02-12 14:33:03 +010082 }
83
Michal Vaskofeca4fb2020-10-05 08:58:40 +020084 if (dynamic) {
85 *dynamic = 0;
86 }
87 return LY_SUCCESS;
Michal Vasko90932a92020-02-12 14:33:03 +010088}
89
Radek Krejci38d85362019-09-05 16:26:38 +020090LY_ERR
Michal Vaskofeca4fb2020-10-05 08:58:40 +020091lyd_value_validate_incomplete(const struct ly_ctx *ctx, const struct lysc_type *type, struct lyd_value *val,
92 const struct lyd_node *ctx_node, const struct lyd_node *tree, enum LY_VLOG_ELEM log_elem_type, const void *log_elem)
Radek Krejci38d85362019-09-05 16:26:38 +020093{
Michal Vaskofeca4fb2020-10-05 08:58:40 +020094 LY_ERR ret;
Radek Krejci38d85362019-09-05 16:26:38 +020095 struct ly_err_item *err = NULL;
Radek Krejci38d85362019-09-05 16:26:38 +020096
Michal Vaskofeca4fb2020-10-05 08:58:40 +020097 assert(type->plugin->validate);
Michal Vasko8d544252020-03-02 10:19:52 +010098
Michal Vaskofeca4fb2020-10-05 08:58:40 +020099 ret = type->plugin->validate(ctx, type, ctx_node, tree, val, &err);
100 if (ret) {
Radek Krejci38d85362019-09-05 16:26:38 +0200101 if (err) {
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200102 LOGVAL(ctx, log_elem_type, log_elem, err->vecode, err->msg);
Radek Krejci38d85362019-09-05 16:26:38 +0200103 ly_err_free(err);
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200104 } else {
105 LOGVAL(ctx, log_elem_type, log_elem, LYVE_OTHER, "Resolving value \"%s\" failed.", val->canonical);
Radek Krejci38d85362019-09-05 16:26:38 +0200106 }
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200107 return ret;
Radek Krejci38d85362019-09-05 16:26:38 +0200108 }
109
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200110 return LY_SUCCESS;
Radek Krejci38d85362019-09-05 16:26:38 +0200111}
112
Michal Vaskof937cfe2020-08-03 16:07:12 +0200113LY_ERR
114_lys_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const char *value, size_t value_len,
Radek Krejci0f969882020-08-21 16:56:47 +0200115 LY_PREFIX_FORMAT format, void *prefix_data)
Radek Krejci084289f2019-07-09 17:35:30 +0200116{
117 LY_ERR rc = LY_SUCCESS;
118 struct ly_err_item *err = NULL;
Michal Vaskoba99a3e2020-08-18 15:50:05 +0200119 struct lyd_value storage;
Radek Krejci084289f2019-07-09 17:35:30 +0200120 struct lysc_type *type;
Radek Krejci084289f2019-07-09 17:35:30 +0200121
122 LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
123
124 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
125 LOGARG(ctx, node);
126 return LY_EINVAL;
127 }
128
Michal Vasko22df3f02020-08-24 13:29:22 +0200129 type = ((struct lysc_node_leaf *)node)->type;
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200130 rc = type->plugin->store(ctx ? ctx : node->module->ctx, type, value, value_len, 0, format, prefix_data,
131 LYD_HINT_SCHEMA, node, &storage, &err);
Radek Krejci73dead22019-07-11 16:46:16 +0200132 if (rc == LY_EINCOMPLETE) {
133 /* actually success since we do not provide the context tree and call validation with
134 * LY_TYPE_OPTS_INCOMPLETE_DATA */
135 rc = LY_SUCCESS;
136 } else if (rc && err) {
137 if (ctx) {
138 /* log only in case the ctx was provided as input parameter */
Radek Krejci73dead22019-07-11 16:46:16 +0200139 LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
Radek Krejci084289f2019-07-09 17:35:30 +0200140 }
Radek Krejci73dead22019-07-11 16:46:16 +0200141 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200142 }
143
Michal Vaskoba99a3e2020-08-18 15:50:05 +0200144 if (!rc) {
145 type->plugin->free(ctx ? ctx : node->module->ctx, &storage);
146 }
Radek Krejci084289f2019-07-09 17:35:30 +0200147 return rc;
148}
149
150API LY_ERR
Michal Vaskof937cfe2020-08-03 16:07:12 +0200151lys_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const char *value, size_t value_len)
152{
Michal Vaskoc8a230d2020-08-14 12:17:10 +0200153 return _lys_value_validate(ctx, node, value, value_len, LY_PREF_JSON, NULL);
Michal Vaskof937cfe2020-08-03 16:07:12 +0200154}
155
156API LY_ERR
Michal Vasko44685da2020-03-17 15:38:06 +0100157lyd_value_validate(const struct ly_ctx *ctx, const struct lyd_node_term *node, const char *value, size_t value_len,
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200158 const struct lyd_node *tree, const struct lysc_type **realtype)
Radek Krejci084289f2019-07-09 17:35:30 +0200159{
160 LY_ERR rc;
161 struct ly_err_item *err = NULL;
162 struct lysc_type *type;
Michal Vasko3701af52020-08-03 14:29:38 +0200163 struct lyd_value val = {0};
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200164 ly_bool stored = 0;
Radek Krejci084289f2019-07-09 17:35:30 +0200165
166 LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
167
Michal Vasko22df3f02020-08-24 13:29:22 +0200168 type = ((struct lysc_node_leaf *)node->schema)->type;
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200169 /* store */
170 rc = type->plugin->store(ctx ? ctx : LYD_CTX(node), type, value, value_len, 0, LY_PREF_JSON, NULL,
171 LYD_HINT_DATA, node->schema, &val, &err);
Radek Krejci73dead22019-07-11 16:46:16 +0200172 if (rc == LY_EINCOMPLETE) {
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200173 stored = 1;
174
175 /* resolve */
176 rc = type->plugin->validate(ctx ? ctx : LYD_CTX(node), type, (struct lyd_node *)node, tree, &val, &err);
177 }
178
179 if (rc) {
Radek Krejci73dead22019-07-11 16:46:16 +0200180 if (err) {
181 if (ctx) {
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200182 LOGVAL(ctx, LY_VLOG_LYD, node, err->vecode, err->msg);
Radek Krejci084289f2019-07-09 17:35:30 +0200183 }
Radek Krejci73dead22019-07-11 16:46:16 +0200184 ly_err_free(err);
Radek Krejci084289f2019-07-09 17:35:30 +0200185 }
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200186 if (stored) {
187 type->plugin->free(ctx ? ctx : LYD_CTX(node), &val);
188 }
Radek Krejci73dead22019-07-11 16:46:16 +0200189 return rc;
Radek Krejci084289f2019-07-09 17:35:30 +0200190 }
191
Michal Vasko3701af52020-08-03 14:29:38 +0200192 if (realtype) {
193 *realtype = val.realtype;
194 }
195
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200196 type->plugin->free(ctx ? ctx : LYD_CTX(node), &val);
Radek Krejci084289f2019-07-09 17:35:30 +0200197 return LY_SUCCESS;
198}
199
200API LY_ERR
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200201lyd_value_compare(const struct lyd_node_term *node, const char *value, size_t value_len)
Radek Krejci084289f2019-07-09 17:35:30 +0200202{
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200203 LY_ERR ret = LY_SUCCESS;
Radek Krejci084289f2019-07-09 17:35:30 +0200204 struct ly_ctx *ctx;
205 struct lysc_type *type;
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200206 struct lyd_value val = {0};
Radek Krejci084289f2019-07-09 17:35:30 +0200207
208 LY_CHECK_ARG_RET(node ? node->schema->module->ctx : NULL, node, value, LY_EINVAL);
209
210 ctx = node->schema->module->ctx;
Michal Vasko22df3f02020-08-24 13:29:22 +0200211 type = ((struct lysc_node_leaf *)node->schema)->type;
Radek Krejci084289f2019-07-09 17:35:30 +0200212
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200213 /* store the value */
214 ret = lyd_value_store(ctx, &val, type, value, value_len, NULL, LY_PREF_JSON, NULL, LYD_HINT_DATA, node->schema,
215 NULL, LY_VLOG_LYSC, node->schema);
216 LY_CHECK_RET(ret);
Radek Krejci084289f2019-07-09 17:35:30 +0200217
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200218 /* compare values */
219 ret = type->plugin->compare(&node->value, &val);
Radek Krejci084289f2019-07-09 17:35:30 +0200220
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200221 type->plugin->free(ctx, &val);
Radek Krejci084289f2019-07-09 17:35:30 +0200222 return ret;
223}
224
Radek Krejci19611252020-10-04 13:54:53 +0200225API ly_bool
226lyd_is_default(const struct lyd_node *node)
227{
228 const struct lysc_node_leaf *leaf;
229 const struct lysc_node_leaflist *llist;
230 const struct lyd_node_term *term;
231 LY_ARRAY_COUNT_TYPE u;
232
233 assert(node->schema->nodetype & LYD_NODE_TERM);
234 term = (const struct lyd_node_term *)node;
235
236 if (node->schema->nodetype == LYS_LEAF) {
237 leaf = (const struct lysc_node_leaf *)node->schema;
238 if (!leaf->dflt) {
239 return 0;
240 }
241
242 /* compare with the default value */
243 if (leaf->type->plugin->compare(&term->value, leaf->dflt)) {
244 return 0;
245 }
246 } else {
247 llist = (const struct lysc_node_leaflist *)node->schema;
248 if (!llist->dflts) {
249 return 0;
250 }
251
252 LY_ARRAY_FOR(llist->dflts, u) {
253 /* compare with each possible default value */
254 if (llist->type->plugin->compare(&term->value, llist->dflts[u])) {
255 return 0;
256 }
257 }
258 }
259
260 return 1;
261}
262
Radek Krejci7931b192020-06-25 17:05:03 +0200263static LYD_FORMAT
Michal Vasko63f3d842020-07-08 10:10:14 +0200264lyd_parse_get_format(const struct ly_in *in, LYD_FORMAT format)
Radek Krejcie7b95092019-05-15 11:03:07 +0200265{
Michal Vasko69730152020-10-09 16:30:07 +0200266 if (!format && (in->type == LY_IN_FILEPATH)) {
Radek Krejcie7b95092019-05-15 11:03:07 +0200267 /* unknown format - try to detect it from filename's suffix */
Radek Krejci7931b192020-06-25 17:05:03 +0200268 const char *path = in->method.fpath.filepath;
269 size_t len = strlen(path);
Radek Krejcie7b95092019-05-15 11:03:07 +0200270
271 /* ignore trailing whitespaces */
Michal Vaskod989ba02020-08-24 10:59:24 +0200272 for ( ; len > 0 && isspace(path[len - 1]); len--) {}
Radek Krejcie7b95092019-05-15 11:03:07 +0200273
Michal Vasko69730152020-10-09 16:30:07 +0200274 if ((len >= 5) && !strncmp(&path[len - 4], ".xml", 4)) {
Radek Krejcie7b95092019-05-15 11:03:07 +0200275 format = LYD_XML;
Michal Vasko69730152020-10-09 16:30:07 +0200276 } else if ((len >= 6) && !strncmp(&path[len - 5], ".json", 5)) {
Radek Krejcie7b95092019-05-15 11:03:07 +0200277 format = LYD_JSON;
Michal Vasko69730152020-10-09 16:30:07 +0200278 } else if ((len >= 5) && !strncmp(&path[len - 4], ".lyb", 4)) {
Radek Krejcie7b95092019-05-15 11:03:07 +0200279 format = LYD_LYB;
Radek Krejci7931b192020-06-25 17:05:03 +0200280 } /* else still unknown */
Radek Krejcie7b95092019-05-15 11:03:07 +0200281 }
282
Radek Krejci7931b192020-06-25 17:05:03 +0200283 return format;
284}
Radek Krejcie7b95092019-05-15 11:03:07 +0200285
Radek Krejci7931b192020-06-25 17:05:03 +0200286API LY_ERR
Radek Krejci1deb5be2020-08-26 16:43:36 +0200287lyd_parse_data(const struct ly_ctx *ctx, struct ly_in *in, LYD_FORMAT format, uint32_t parse_options, uint32_t validate_options,
Radek Krejci0f969882020-08-21 16:56:47 +0200288 struct lyd_node **tree)
Radek Krejci7931b192020-06-25 17:05:03 +0200289{
Radek Krejci1798aae2020-07-14 13:26:06 +0200290 LY_ERR ret = LY_SUCCESS;
291 struct lyd_ctx *lydctx = NULL;
292
Radek Krejci7931b192020-06-25 17:05:03 +0200293 LY_CHECK_ARG_RET(ctx, ctx, in, tree, LY_EINVAL);
294 LY_CHECK_ARG_RET(ctx, !(parse_options & ~LYD_PARSE_OPTS_MASK), LY_EINVAL);
295 LY_CHECK_ARG_RET(ctx, !(validate_options & ~LYD_VALIDATE_OPTS_MASK), LY_EINVAL);
296
297 format = lyd_parse_get_format(in, format);
298 LY_CHECK_ARG_RET(ctx, format, LY_EINVAL);
299
Radek Krejci1798aae2020-07-14 13:26:06 +0200300 /* init */
301 *tree = NULL;
302
Michal Vasko63f3d842020-07-08 10:10:14 +0200303 /* remember input position */
304 in->func_start = in->current;
Radek Krejci7931b192020-06-25 17:05:03 +0200305
306 switch (format) {
307 case LYD_XML:
Radek Krejci1798aae2020-07-14 13:26:06 +0200308 LY_CHECK_RET(lyd_parse_xml_data(ctx, in, parse_options, validate_options, tree, &lydctx));
309 break;
Radek Krejci7931b192020-06-25 17:05:03 +0200310 case LYD_JSON:
Radek Krejci1798aae2020-07-14 13:26:06 +0200311 LY_CHECK_RET(lyd_parse_json_data(ctx, in, parse_options, validate_options, tree, &lydctx));
312 break;
Radek Krejci7931b192020-06-25 17:05:03 +0200313 case LYD_LYB:
Radek Krejci1798aae2020-07-14 13:26:06 +0200314 LY_CHECK_RET(lyd_parse_lyb_data(ctx, in, parse_options, validate_options, tree, &lydctx));
315 break;
Michal Vaskoc8a230d2020-08-14 12:17:10 +0200316 case LYD_UNKNOWN:
Radek Krejci7931b192020-06-25 17:05:03 +0200317 LOGINT_RET(ctx);
318 }
319
Radek Krejci1798aae2020-07-14 13:26:06 +0200320 if (!(parse_options & LYD_PARSE_ONLY)) {
321 uint32_t i = 0;
322 const struct lys_module *mod;
323 struct lyd_node *first, *next, **first2;
Radek Krejci7931b192020-06-25 17:05:03 +0200324
Radek Krejci1798aae2020-07-14 13:26:06 +0200325 next = *tree;
326 while (1) {
327 if (validate_options & LYD_VALIDATE_PRESENT) {
328 mod = lyd_data_next_module(&next, &first);
329 } else {
330 mod = lyd_mod_next_module(next, NULL, ctx, &i, &first);
331 }
332 if (!mod) {
333 break;
334 }
335 if (first == *tree) {
336 /* make sure first2 changes are carried to tree */
337 first2 = tree;
338 } else {
339 first2 = &first;
340 }
341
342 /* validate new top-level nodes, autodelete CANNOT occur, all nodes are new */
343 LY_CHECK_GOTO(ret = lyd_validate_new(first2, NULL, mod, NULL), cleanup);
344
345 /* add all top-level defaults for this module */
346 ret = lyd_new_implicit_r(NULL, first2, NULL, mod, &lydctx->unres_node_type, &lydctx->when_check,
Michal Vasko69730152020-10-09 16:30:07 +0200347 (validate_options & LYD_VALIDATE_NO_STATE) ? LYD_IMPLICIT_NO_STATE : 0, NULL);
Radek Krejci1798aae2020-07-14 13:26:06 +0200348 LY_CHECK_GOTO(ret, cleanup);
349
350 /* finish incompletely validated terminal values/attributes and when conditions */
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200351 ret = lyd_validate_unres(tree, &lydctx->when_check, &lydctx->unres_node_type, &lydctx->unres_meta_type, NULL);
Radek Krejci1798aae2020-07-14 13:26:06 +0200352 LY_CHECK_GOTO(ret, cleanup);
353
354 /* perform final validation that assumes the data tree is final */
355 LY_CHECK_GOTO(ret = lyd_validate_final_r(*first2, NULL, mod, validate_options, 0), cleanup);
356 }
357 }
358
359cleanup:
Michal Vaskoafac7822020-10-20 14:22:26 +0200360 lydctx->free(lydctx);
Radek Krejci1798aae2020-07-14 13:26:06 +0200361 if (ret) {
362 lyd_free_all(*tree);
363 *tree = NULL;
364 }
365 return ret;
Radek Krejci7931b192020-06-25 17:05:03 +0200366}
367
368API LY_ERR
Radek Krejci1deb5be2020-08-26 16:43:36 +0200369lyd_parse_data_mem(const struct ly_ctx *ctx, const char *data, LYD_FORMAT format, uint32_t parse_options, uint32_t validate_options,
Radek Krejci0f969882020-08-21 16:56:47 +0200370 struct lyd_node **tree)
Radek Krejci7931b192020-06-25 17:05:03 +0200371{
372 LY_ERR ret;
373 struct ly_in *in;
374
375 LY_CHECK_RET(ly_in_new_memory(data, &in));
376 ret = lyd_parse_data(ctx, in, format, parse_options, validate_options, tree);
377
378 ly_in_free(in, 0);
379 return ret;
380}
381
382API LY_ERR
Radek Krejci1deb5be2020-08-26 16:43:36 +0200383lyd_parse_data_fd(const struct ly_ctx *ctx, int fd, LYD_FORMAT format, uint32_t parse_options, uint32_t validate_options,
Radek Krejci0f969882020-08-21 16:56:47 +0200384 struct lyd_node **tree)
Radek Krejci7931b192020-06-25 17:05:03 +0200385{
386 LY_ERR ret;
387 struct ly_in *in;
388
389 LY_CHECK_RET(ly_in_new_fd(fd, &in));
390 ret = lyd_parse_data(ctx, in, format, parse_options, validate_options, tree);
391
392 ly_in_free(in, 0);
393 return ret;
394}
395
396API LY_ERR
Radek Krejci1deb5be2020-08-26 16:43:36 +0200397lyd_parse_data_path(const struct ly_ctx *ctx, const char *path, LYD_FORMAT format, uint32_t parse_options,
398 uint32_t validate_options, struct lyd_node **tree)
Radek Krejci7931b192020-06-25 17:05:03 +0200399{
400 LY_ERR ret;
401 struct ly_in *in;
402
403 LY_CHECK_RET(ly_in_new_filepath(path, 0, &in));
404 ret = lyd_parse_data(ctx, in, format, parse_options, validate_options, tree);
405
406 ly_in_free(in, 0);
407 return ret;
408}
409
Radek Krejci7931b192020-06-25 17:05:03 +0200410API LY_ERR
411lyd_parse_rpc(const struct ly_ctx *ctx, struct ly_in *in, LYD_FORMAT format, struct lyd_node **tree, struct lyd_node **op)
412{
413 LY_CHECK_ARG_RET(ctx, ctx, in, tree, LY_EINVAL);
414
415 format = lyd_parse_get_format(in, format);
416 LY_CHECK_ARG_RET(ctx, format, LY_EINVAL);
417
Radek Krejci1798aae2020-07-14 13:26:06 +0200418 /* init */
419 *tree = NULL;
420 if (op) {
421 *op = NULL;
422 }
423
Michal Vasko63f3d842020-07-08 10:10:14 +0200424 /* remember input position */
425 in->func_start = in->current;
426
Radek Krejci7931b192020-06-25 17:05:03 +0200427 switch (format) {
428 case LYD_XML:
Michal Vasko63f3d842020-07-08 10:10:14 +0200429 return lyd_parse_xml_rpc(ctx, in, tree, op);
Radek Krejci7931b192020-06-25 17:05:03 +0200430 case LYD_JSON:
Michal Vasko63f3d842020-07-08 10:10:14 +0200431 return lyd_parse_json_rpc(ctx, in, tree, op);
Radek Krejci7931b192020-06-25 17:05:03 +0200432 case LYD_LYB:
Michal Vasko63f3d842020-07-08 10:10:14 +0200433 return lyd_parse_lyb_rpc(ctx, in, tree, op);
Michal Vaskoc8a230d2020-08-14 12:17:10 +0200434 case LYD_UNKNOWN:
435 break;
Radek Krejci7931b192020-06-25 17:05:03 +0200436 }
437
438 LOGINT_RET(ctx);
439}
440
441API LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +0200442lyd_parse_reply(const struct lyd_node *request, struct ly_in *in, LYD_FORMAT format, struct lyd_node **tree,
Radek Krejci0f969882020-08-21 16:56:47 +0200443 struct lyd_node **op)
Radek Krejci7931b192020-06-25 17:05:03 +0200444{
445 LY_CHECK_ARG_RET(NULL, request, LY_EINVAL);
Michal Vaskob7be7a82020-08-20 09:09:04 +0200446 LY_CHECK_ARG_RET(LYD_CTX(request), in, tree || op, LY_EINVAL);
Radek Krejci7931b192020-06-25 17:05:03 +0200447
448 format = lyd_parse_get_format(in, format);
Michal Vaskob7be7a82020-08-20 09:09:04 +0200449 LY_CHECK_ARG_RET(LYD_CTX(request), format, LY_EINVAL);
Radek Krejci7931b192020-06-25 17:05:03 +0200450
Radek Krejci1798aae2020-07-14 13:26:06 +0200451 /* init */
452 if (tree) {
453 *tree = NULL;
454 }
455 if (op) {
456 *op = NULL;
457 }
458
Michal Vasko63f3d842020-07-08 10:10:14 +0200459 /* remember input position */
460 in->func_start = in->current;
461
Radek Krejci7931b192020-06-25 17:05:03 +0200462 switch (format) {
463 case LYD_XML:
Michal Vasko63f3d842020-07-08 10:10:14 +0200464 return lyd_parse_xml_reply(request, in, tree, op);
Radek Krejci7931b192020-06-25 17:05:03 +0200465 case LYD_JSON:
Michal Vasko63f3d842020-07-08 10:10:14 +0200466 return lyd_parse_json_reply(request, in, tree, op);
Radek Krejci7931b192020-06-25 17:05:03 +0200467 case LYD_LYB:
Michal Vasko63f3d842020-07-08 10:10:14 +0200468 return lyd_parse_lyb_reply(request, in, tree, op);
Michal Vaskoc8a230d2020-08-14 12:17:10 +0200469 case LYD_UNKNOWN:
470 break;
Radek Krejci7931b192020-06-25 17:05:03 +0200471 }
472
Michal Vaskob7be7a82020-08-20 09:09:04 +0200473 LOGINT_RET(LYD_CTX(request));
Radek Krejci7931b192020-06-25 17:05:03 +0200474}
475
476API LY_ERR
477lyd_parse_notif(const struct ly_ctx *ctx, struct ly_in *in, LYD_FORMAT format, struct lyd_node **tree, struct lyd_node **ntf)
478{
Radek Krejci1798aae2020-07-14 13:26:06 +0200479 LY_CHECK_ARG_RET(ctx, ctx, in, tree || ntf, LY_EINVAL);
Radek Krejci7931b192020-06-25 17:05:03 +0200480
481 format = lyd_parse_get_format(in, format);
482 LY_CHECK_ARG_RET(ctx, format, LY_EINVAL);
483
Radek Krejci1798aae2020-07-14 13:26:06 +0200484 /* init */
485 if (tree) {
486 *tree = NULL;
487 }
488 if (ntf) {
489 *ntf = NULL;
490 }
491
Michal Vasko63f3d842020-07-08 10:10:14 +0200492 /* remember input position */
493 in->func_start = in->current;
494
Radek Krejci7931b192020-06-25 17:05:03 +0200495 switch (format) {
496 case LYD_XML:
Michal Vasko63f3d842020-07-08 10:10:14 +0200497 return lyd_parse_xml_notif(ctx, in, tree, ntf);
Radek Krejci7931b192020-06-25 17:05:03 +0200498 case LYD_JSON:
Michal Vasko63f3d842020-07-08 10:10:14 +0200499 return lyd_parse_json_notif(ctx, in, tree, ntf);
Radek Krejci7931b192020-06-25 17:05:03 +0200500 case LYD_LYB:
Michal Vasko63f3d842020-07-08 10:10:14 +0200501 return lyd_parse_lyb_notif(ctx, in, tree, ntf);
Michal Vaskoc8a230d2020-08-14 12:17:10 +0200502 case LYD_UNKNOWN:
503 break;
Radek Krejci7931b192020-06-25 17:05:03 +0200504 }
505
506 LOGINT_RET(ctx);
Radek Krejcie7b95092019-05-15 11:03:07 +0200507}
Radek Krejci084289f2019-07-09 17:35:30 +0200508
Michal Vasko90932a92020-02-12 14:33:03 +0100509LY_ERR
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200510lyd_create_term(const struct lysc_node *schema, const char *value, size_t value_len, ly_bool *dynamic,
511 LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints, ly_bool *incomplete, struct lyd_node **node)
Michal Vasko90932a92020-02-12 14:33:03 +0100512{
513 LY_ERR ret;
514 struct lyd_node_term *term;
515
Michal Vasko9b368d32020-02-14 13:53:31 +0100516 assert(schema->nodetype & LYD_NODE_TERM);
517
Michal Vasko90932a92020-02-12 14:33:03 +0100518 term = calloc(1, sizeof *term);
519 LY_CHECK_ERR_RET(!term, LOGMEM(schema->module->ctx), LY_EMEM);
520
521 term->schema = schema;
522 term->prev = (struct lyd_node *)term;
Michal Vasko9b368d32020-02-14 13:53:31 +0100523 term->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100524
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200525 ret = lyd_value_store(schema->module->ctx, &term->value, ((struct lysc_node_leaf *)term->schema)->type, value,
526 value_len, dynamic, format, prefix_data, hints, schema, incomplete, LY_VLOG_LYSC, schema);
527 LY_CHECK_ERR_RET(ret, free(term), ret);
Michal Vasko9b368d32020-02-14 13:53:31 +0100528 lyd_hash((struct lyd_node *)term);
529
530 *node = (struct lyd_node *)term;
531 return ret;
532}
533
534LY_ERR
535lyd_create_term2(const struct lysc_node *schema, const struct lyd_value *val, struct lyd_node **node)
536{
537 LY_ERR ret;
538 struct lyd_node_term *term;
539 struct lysc_type *type;
540
541 assert(schema->nodetype & LYD_NODE_TERM);
Michal Vaskoba99a3e2020-08-18 15:50:05 +0200542 assert(val && val->canonical && val->realtype);
Michal Vasko9b368d32020-02-14 13:53:31 +0100543
544 term = calloc(1, sizeof *term);
545 LY_CHECK_ERR_RET(!term, LOGMEM(schema->module->ctx), LY_EMEM);
546
547 term->schema = schema;
548 term->prev = (struct lyd_node *)term;
549 term->flags = LYD_NEW;
550
551 type = ((struct lysc_node_leaf *)schema)->type;
552 ret = type->plugin->duplicate(schema->module->ctx, val, &term->value);
553 if (ret) {
554 LOGERR(schema->module->ctx, ret, "Value duplication failed.");
555 free(term);
556 return ret;
557 }
558 lyd_hash((struct lyd_node *)term);
Michal Vasko90932a92020-02-12 14:33:03 +0100559
560 *node = (struct lyd_node *)term;
561 return ret;
562}
563
564LY_ERR
565lyd_create_inner(const struct lysc_node *schema, struct lyd_node **node)
566{
567 struct lyd_node_inner *in;
568
Michal Vasko9b368d32020-02-14 13:53:31 +0100569 assert(schema->nodetype & LYD_NODE_INNER);
570
Michal Vasko90932a92020-02-12 14:33:03 +0100571 in = calloc(1, sizeof *in);
572 LY_CHECK_ERR_RET(!in, LOGMEM(schema->module->ctx), LY_EMEM);
573
574 in->schema = schema;
575 in->prev = (struct lyd_node *)in;
Michal Vasko9b368d32020-02-14 13:53:31 +0100576 in->flags = LYD_NEW;
Michal Vasko3383be72020-11-03 17:15:31 +0100577 if ((schema->nodetype == LYS_CONTAINER) && !(schema->flags & LYS_PRESENCE)) {
578 in->flags |= LYD_DEFAULT;
579 }
Michal Vasko90932a92020-02-12 14:33:03 +0100580
Michal Vasko9b368d32020-02-14 13:53:31 +0100581 /* do not hash list with keys, we need them for the hash */
582 if ((schema->nodetype != LYS_LIST) || (schema->flags & LYS_KEYLESS)) {
583 lyd_hash((struct lyd_node *)in);
584 }
Michal Vasko90932a92020-02-12 14:33:03 +0100585
586 *node = (struct lyd_node *)in;
587 return LY_SUCCESS;
588}
589
Michal Vasko90932a92020-02-12 14:33:03 +0100590LY_ERR
Michal Vasko004d3152020-06-11 19:59:22 +0200591lyd_create_list(const struct lysc_node *schema, const struct ly_path_predicate *predicates, struct lyd_node **node)
Michal Vasko90932a92020-02-12 14:33:03 +0100592{
593 LY_ERR ret = LY_SUCCESS;
Michal Vasko90932a92020-02-12 14:33:03 +0100594 struct lyd_node *list = NULL, *key;
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200595 LY_ARRAY_COUNT_TYPE u;
Michal Vasko90932a92020-02-12 14:33:03 +0100596
Michal Vasko004d3152020-06-11 19:59:22 +0200597 assert((schema->nodetype == LYS_LIST) && !(schema->flags & LYS_KEYLESS));
Michal Vasko90932a92020-02-12 14:33:03 +0100598
599 /* create list */
600 LY_CHECK_GOTO(ret = lyd_create_inner(schema, &list), cleanup);
601
Michal Vasko90932a92020-02-12 14:33:03 +0100602 /* create and insert all the keys */
Michal Vasko004d3152020-06-11 19:59:22 +0200603 LY_ARRAY_FOR(predicates, u) {
604 LY_CHECK_GOTO(ret = lyd_create_term2(predicates[u].key, &predicates[u].value, &key), cleanup);
Michal Vasko90932a92020-02-12 14:33:03 +0100605 lyd_insert_node(list, NULL, key);
606 }
607
Michal Vasko9b368d32020-02-14 13:53:31 +0100608 /* hash having all the keys */
609 lyd_hash(list);
610
Michal Vasko90932a92020-02-12 14:33:03 +0100611 /* success */
612 *node = list;
613 list = NULL;
614
615cleanup:
616 lyd_free_tree(list);
Michal Vasko004d3152020-06-11 19:59:22 +0200617 return ret;
618}
619
620static LY_ERR
621lyd_create_list2(const struct lysc_node *schema, const char *keys, size_t keys_len, struct lyd_node **node)
622{
623 LY_ERR ret = LY_SUCCESS;
624 struct lyxp_expr *expr = NULL;
625 uint16_t exp_idx = 0;
626 enum ly_path_pred_type pred_type = 0;
627 struct ly_path_predicate *predicates = NULL;
628
629 /* parse keys */
Michal Vasko6b26e742020-07-17 15:02:10 +0200630 LY_CHECK_GOTO(ret = ly_path_parse_predicate(schema->module->ctx, NULL, keys, keys_len, LY_PATH_PREFIX_OPTIONAL,
Michal Vasko69730152020-10-09 16:30:07 +0200631 LY_PATH_PRED_KEYS, &expr), cleanup);
Michal Vasko004d3152020-06-11 19:59:22 +0200632
633 /* compile them */
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200634 LY_CHECK_GOTO(ret = ly_path_compile_predicate(schema->module->ctx, NULL, NULL, schema, expr, &exp_idx, LY_PREF_JSON,
635 NULL, &predicates, &pred_type), cleanup);
Michal Vasko004d3152020-06-11 19:59:22 +0200636
637 /* create the list node */
638 LY_CHECK_GOTO(ret = lyd_create_list(schema, predicates, node), cleanup);
639
640cleanup:
641 lyxp_expr_free(schema->module->ctx, expr);
Michal Vaskof7e16e22020-10-21 09:24:39 +0200642 ly_path_predicates_free(schema->module->ctx, pred_type, predicates);
Michal Vasko90932a92020-02-12 14:33:03 +0100643 return ret;
644}
645
646LY_ERR
647lyd_create_any(const struct lysc_node *schema, const void *value, LYD_ANYDATA_VALUETYPE value_type, struct lyd_node **node)
648{
649 struct lyd_node_any *any;
650
Michal Vasko9b368d32020-02-14 13:53:31 +0100651 assert(schema->nodetype & LYD_NODE_ANY);
652
Michal Vasko90932a92020-02-12 14:33:03 +0100653 any = calloc(1, sizeof *any);
654 LY_CHECK_ERR_RET(!any, LOGMEM(schema->module->ctx), LY_EMEM);
655
656 any->schema = schema;
657 any->prev = (struct lyd_node *)any;
Michal Vasko9b368d32020-02-14 13:53:31 +0100658 any->flags = LYD_NEW;
Michal Vasko90932a92020-02-12 14:33:03 +0100659
Radek Krejci1798aae2020-07-14 13:26:06 +0200660 /* TODO: convert XML/JSON strings into a opaq data tree */
661 any->value.str = value;
Michal Vasko90932a92020-02-12 14:33:03 +0100662 any->value_type = value_type;
Michal Vasko9b368d32020-02-14 13:53:31 +0100663 lyd_hash((struct lyd_node *)any);
Michal Vasko90932a92020-02-12 14:33:03 +0100664
665 *node = (struct lyd_node *)any;
666 return LY_SUCCESS;
667}
668
Michal Vasko52927e22020-03-16 17:26:14 +0100669LY_ERR
Michal Vasko501af032020-11-11 20:27:44 +0100670lyd_create_opaq(const struct ly_ctx *ctx, const char *name, size_t name_len, const char *prefix, size_t pref_len,
671 const char *module_key, size_t module_key_len, const char *value, size_t value_len, ly_bool *dynamic,
672 LY_PREFIX_FORMAT format, void *val_prefix_data, uint32_t hints, struct lyd_node **node)
Michal Vasko52927e22020-03-16 17:26:14 +0100673{
Radek Krejci011e4aa2020-09-04 15:22:31 +0200674 LY_ERR ret = LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +0100675 struct lyd_node_opaq *opaq;
676
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200677 assert(ctx && name && name_len && format);
Michal Vasko52927e22020-03-16 17:26:14 +0100678
679 if (!value_len) {
680 value = "";
681 }
682
683 opaq = calloc(1, sizeof *opaq);
Michal Vasko501af032020-11-11 20:27:44 +0100684 LY_CHECK_ERR_GOTO(!opaq, LOGMEM(ctx); ret = LY_EMEM, finish);
Michal Vasko52927e22020-03-16 17:26:14 +0100685
686 opaq->prev = (struct lyd_node *)opaq;
Michal Vaskoad92b672020-11-12 13:11:31 +0100687 LY_CHECK_GOTO(ret = lydict_insert(ctx, name, name_len, &opaq->name.name), finish);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200688
Michal Vasko52927e22020-03-16 17:26:14 +0100689 if (pref_len) {
Michal Vaskoad92b672020-11-12 13:11:31 +0100690 LY_CHECK_GOTO(ret = lydict_insert(ctx, prefix, pref_len, &opaq->name.prefix), finish);
Michal Vasko52927e22020-03-16 17:26:14 +0100691 }
Radek Krejci1798aae2020-07-14 13:26:06 +0200692 if (module_key_len) {
Michal Vaskoad92b672020-11-12 13:11:31 +0100693 LY_CHECK_GOTO(ret = lydict_insert(ctx, module_key, module_key_len, &opaq->name.module_ns), finish);
Radek Krejci1798aae2020-07-14 13:26:06 +0200694 }
Michal Vasko52927e22020-03-16 17:26:14 +0100695 if (dynamic && *dynamic) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200696 LY_CHECK_GOTO(ret = lydict_insert_zc(ctx, (char *)value, &opaq->value), finish);
Michal Vasko52927e22020-03-16 17:26:14 +0100697 *dynamic = 0;
698 } else {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200699 LY_CHECK_GOTO(ret = lydict_insert(ctx, value, value_len, &opaq->value), finish);
Michal Vasko52927e22020-03-16 17:26:14 +0100700 }
Michal Vasko501af032020-11-11 20:27:44 +0100701
702 opaq->format = format;
703 opaq->val_prefix_data = val_prefix_data;
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200704 opaq->hints = hints;
Michal Vasko52927e22020-03-16 17:26:14 +0100705 opaq->ctx = ctx;
706
Radek Krejci011e4aa2020-09-04 15:22:31 +0200707finish:
708 if (ret) {
709 lyd_free_tree((struct lyd_node *)opaq);
Michal Vasko501af032020-11-11 20:27:44 +0100710 ly_free_prefix_data(format, val_prefix_data);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200711 } else {
712 *node = (struct lyd_node *)opaq;
713 }
714 return ret;
Michal Vasko52927e22020-03-16 17:26:14 +0100715}
716
Michal Vasko3a41dff2020-07-15 14:30:28 +0200717API LY_ERR
Radek Krejci41ac9942020-11-02 14:47:56 +0100718lyd_new_inner(struct lyd_node *parent, const struct lys_module *module, const char *name, ly_bool output, struct lyd_node **node)
Michal Vasko013a8182020-03-03 10:46:53 +0100719{
720 struct lyd_node *ret = NULL;
721 const struct lysc_node *schema;
722 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
723
Michal Vasko6027eb92020-07-15 16:37:30 +0200724 LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
Michal Vasko013a8182020-03-03 10:46:53 +0100725
Michal Vaskof03ed032020-03-04 13:31:44 +0100726 if (!module) {
727 module = parent->schema->module;
728 }
729
Michal Vasko3a41dff2020-07-15 14:30:28 +0200730 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0,
Radek Krejci41ac9942020-11-02 14:47:56 +0100731 LYS_CONTAINER | LYS_NOTIF | LYS_RPC | LYS_ACTION, output ? LYS_GETNEXT_OUTPUT : 0);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200732 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 +0100733
Michal Vasko3a41dff2020-07-15 14:30:28 +0200734 LY_CHECK_RET(lyd_create_inner(schema, &ret));
735 if (parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100736 lyd_insert_node(parent, NULL, ret);
737 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200738
739 if (node) {
740 *node = ret;
741 }
742 return LY_SUCCESS;
Michal Vasko013a8182020-03-03 10:46:53 +0100743}
744
Michal Vasko3a41dff2020-07-15 14:30:28 +0200745API LY_ERR
Radek Krejci41ac9942020-11-02 14:47:56 +0100746lyd_new_list(struct lyd_node *parent, const struct lys_module *module, const char *name, ly_bool output, struct lyd_node **node, ...)
Michal Vasko013a8182020-03-03 10:46:53 +0100747{
748 struct lyd_node *ret = NULL, *key;
749 const struct lysc_node *schema, *key_s;
750 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
751 va_list ap;
752 const char *key_val;
753 LY_ERR rc = LY_SUCCESS;
754
Michal Vasko6027eb92020-07-15 16:37:30 +0200755 LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
Michal Vasko013a8182020-03-03 10:46:53 +0100756
Michal Vaskof03ed032020-03-04 13:31:44 +0100757 if (!module) {
758 module = parent->schema->module;
759 }
760
Radek Krejci41ac9942020-11-02 14:47:56 +0100761 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, output ? LYS_GETNEXT_OUTPUT : 0);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200762 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), LY_ENOTFOUND);
Michal Vasko013a8182020-03-03 10:46:53 +0100763
764 /* create list inner node */
Michal Vasko3a41dff2020-07-15 14:30:28 +0200765 LY_CHECK_RET(lyd_create_inner(schema, &ret));
Michal Vasko013a8182020-03-03 10:46:53 +0100766
Michal Vasko3a41dff2020-07-15 14:30:28 +0200767 va_start(ap, node);
Michal Vasko013a8182020-03-03 10:46:53 +0100768
769 /* create and insert all the keys */
770 for (key_s = lysc_node_children(schema, 0); key_s && (key_s->flags & LYS_KEY); key_s = key_s->next) {
771 key_val = va_arg(ap, const char *);
772
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200773 rc = lyd_create_term(key_s, key_val, key_val ? strlen(key_val) : 0, NULL, LY_PREF_JSON, NULL, LYD_HINT_DATA,
774 NULL, &key);
775 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko013a8182020-03-03 10:46:53 +0100776 lyd_insert_node(ret, NULL, key);
777 }
778
Michal Vasko013a8182020-03-03 10:46:53 +0100779 if (parent) {
780 lyd_insert_node(parent, NULL, ret);
781 }
782
783cleanup:
Michal Vasko3a41dff2020-07-15 14:30:28 +0200784 va_end(ap);
Michal Vasko013a8182020-03-03 10:46:53 +0100785 if (rc) {
786 lyd_free_tree(ret);
787 ret = NULL;
Michal Vasko3a41dff2020-07-15 14:30:28 +0200788 } else if (node) {
789 *node = ret;
Michal Vasko013a8182020-03-03 10:46:53 +0100790 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200791 return rc;
Michal Vasko013a8182020-03-03 10:46:53 +0100792}
793
Michal Vasko3a41dff2020-07-15 14:30:28 +0200794API LY_ERR
795lyd_new_list2(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *keys,
Radek Krejci41ac9942020-11-02 14:47:56 +0100796 ly_bool output, struct lyd_node **node)
Michal Vasko013a8182020-03-03 10:46:53 +0100797{
798 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 }
Michal Vasko004d3152020-06-11 19:59:22 +0200807 if (!keys) {
808 keys = "";
809 }
Michal Vaskof03ed032020-03-04 13:31:44 +0100810
Michal Vasko004d3152020-06-11 19:59:22 +0200811 /* find schema node */
Radek Krejci41ac9942020-11-02 14:47:56 +0100812 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, output ? LYS_GETNEXT_OUTPUT : 0);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200813 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "List node \"%s\" not found.", name), LY_ENOTFOUND);
Michal Vasko013a8182020-03-03 10:46:53 +0100814
Michal Vasko004d3152020-06-11 19:59:22 +0200815 if ((schema->flags & LYS_KEYLESS) && !keys[0]) {
816 /* key-less list */
Michal Vasko3a41dff2020-07-15 14:30:28 +0200817 LY_CHECK_RET(lyd_create_inner(schema, &ret));
Michal Vasko004d3152020-06-11 19:59:22 +0200818 } else {
819 /* create the list node */
Michal Vasko3a41dff2020-07-15 14:30:28 +0200820 LY_CHECK_RET(lyd_create_list2(schema, keys, strlen(keys), &ret));
Michal Vasko004d3152020-06-11 19:59:22 +0200821 }
Michal Vasko004d3152020-06-11 19:59:22 +0200822 if (parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100823 lyd_insert_node(parent, NULL, ret);
824 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200825
826 if (node) {
827 *node = ret;
828 }
829 return LY_SUCCESS;
Michal Vasko013a8182020-03-03 10:46:53 +0100830}
831
Michal Vasko3a41dff2020-07-15 14:30:28 +0200832API LY_ERR
833lyd_new_term(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str,
Radek Krejci41ac9942020-11-02 14:47:56 +0100834 ly_bool output, struct lyd_node **node)
Michal Vasko013a8182020-03-03 10:46:53 +0100835{
Michal Vaskocbff3e92020-05-27 12:56:41 +0200836 LY_ERR rc;
Michal Vasko013a8182020-03-03 10:46:53 +0100837 struct lyd_node *ret = NULL;
838 const struct lysc_node *schema;
839 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
840
Michal Vasko6027eb92020-07-15 16:37:30 +0200841 LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
Michal Vasko013a8182020-03-03 10:46:53 +0100842
Michal Vaskof03ed032020-03-04 13:31:44 +0100843 if (!module) {
844 module = parent->schema->module;
845 }
846
Radek Krejci41ac9942020-11-02 14:47:56 +0100847 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_TERM, output ? LYS_GETNEXT_OUTPUT : 0);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200848 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Term node \"%s\" not found.", name), LY_ENOTFOUND);
Michal Vasko013a8182020-03-03 10:46:53 +0100849
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200850 rc = lyd_create_term(schema, val_str, val_str ? strlen(val_str) : 0, NULL, LY_PREF_JSON, NULL, LYD_HINT_DATA, NULL,
851 &ret);
852 LY_CHECK_RET(rc);
Michal Vaskocbff3e92020-05-27 12:56:41 +0200853 if (parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100854 lyd_insert_node(parent, NULL, ret);
855 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200856
857 if (node) {
858 *node = ret;
859 }
860 return LY_SUCCESS;
Michal Vasko013a8182020-03-03 10:46:53 +0100861}
862
Michal Vasko3a41dff2020-07-15 14:30:28 +0200863API LY_ERR
Michal Vasko013a8182020-03-03 10:46:53 +0100864lyd_new_any(struct lyd_node *parent, const struct lys_module *module, const char *name, const void *value,
Radek Krejci41ac9942020-11-02 14:47:56 +0100865 LYD_ANYDATA_VALUETYPE value_type, ly_bool output, struct lyd_node **node)
Michal Vasko013a8182020-03-03 10:46:53 +0100866{
867 struct lyd_node *ret = NULL;
868 const struct lysc_node *schema;
869 struct ly_ctx *ctx = parent ? parent->schema->module->ctx : (module ? module->ctx : NULL);
870
Michal Vasko6027eb92020-07-15 16:37:30 +0200871 LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
Michal Vasko013a8182020-03-03 10:46:53 +0100872
Michal Vaskof03ed032020-03-04 13:31:44 +0100873 if (!module) {
874 module = parent->schema->module;
875 }
876
Radek Krejci41ac9942020-11-02 14:47:56 +0100877 schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_ANY, output ? LYS_GETNEXT_OUTPUT : 0);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200878 LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Any node \"%s\" not found.", name), LY_ENOTFOUND);
Michal Vasko013a8182020-03-03 10:46:53 +0100879
Michal Vasko3a41dff2020-07-15 14:30:28 +0200880 LY_CHECK_RET(lyd_create_any(schema, value, value_type, &ret));
881 if (parent) {
Michal Vasko013a8182020-03-03 10:46:53 +0100882 lyd_insert_node(parent, NULL, ret);
883 }
Michal Vasko3a41dff2020-07-15 14:30:28 +0200884
885 if (node) {
886 *node = ret;
887 }
888 return LY_SUCCESS;
Michal Vasko013a8182020-03-03 10:46:53 +0100889}
890
Michal Vasko4490d312020-06-16 13:08:55 +0200891/**
892 * @brief Update node value.
893 *
894 * @param[in] node Node to update.
895 * @param[in] value New value to set.
896 * @param[in] value_type Type of @p value for any node.
897 * @param[out] new_parent Set to @p node if the value was updated, otherwise set to NULL.
898 * @param[out] new_node Set to @p node if the value was updated, otherwise set to NULL.
899 * @return LY_ERR value.
900 */
Michal Vasko00cbf532020-06-15 13:58:47 +0200901static LY_ERR
902lyd_new_path_update(struct lyd_node *node, const void *value, LYD_ANYDATA_VALUETYPE value_type,
Radek Krejci0f969882020-08-21 16:56:47 +0200903 struct lyd_node **new_parent, struct lyd_node **new_node)
Michal Vasko00cbf532020-06-15 13:58:47 +0200904{
905 LY_ERR ret = LY_SUCCESS;
906 struct lyd_node *new_any;
907
908 switch (node->schema->nodetype) {
909 case LYS_CONTAINER:
910 case LYS_NOTIF:
911 case LYS_RPC:
912 case LYS_ACTION:
913 case LYS_LIST:
914 case LYS_LEAFLIST:
915 /* if it exists, there is nothing to update */
916 *new_parent = NULL;
917 *new_node = NULL;
918 break;
919 case LYS_LEAF:
920 ret = lyd_change_term(node, value);
921 if ((ret == LY_SUCCESS) || (ret == LY_EEXIST)) {
922 /* there was an actual change (at least of the default flag) */
923 *new_parent = node;
924 *new_node = node;
925 ret = LY_SUCCESS;
926 } else if (ret == LY_ENOT) {
927 /* no change */
928 *new_parent = NULL;
929 *new_node = NULL;
930 ret = LY_SUCCESS;
931 } /* else error */
932 break;
933 case LYS_ANYDATA:
934 case LYS_ANYXML:
935 /* create a new any node */
936 LY_CHECK_RET(lyd_create_any(node->schema, value, value_type, &new_any));
937
938 /* compare with the existing one */
Michal Vasko8f359bf2020-07-28 10:41:15 +0200939 if (lyd_compare_single(node, new_any, 0)) {
Michal Vasko00cbf532020-06-15 13:58:47 +0200940 /* not equal, switch values (so that we can use generic node free) */
941 ((struct lyd_node_any *)new_any)->value = ((struct lyd_node_any *)node)->value;
942 ((struct lyd_node_any *)new_any)->value_type = ((struct lyd_node_any *)node)->value_type;
943 ((struct lyd_node_any *)node)->value.str = value;
944 ((struct lyd_node_any *)node)->value_type = value_type;
945
946 *new_parent = node;
947 *new_node = node;
948 } else {
949 /* they are equal */
950 *new_parent = NULL;
951 *new_node = NULL;
952 }
953 lyd_free_tree(new_any);
954 break;
955 default:
Michal Vaskob7be7a82020-08-20 09:09:04 +0200956 LOGINT(LYD_CTX(node));
Michal Vasko00cbf532020-06-15 13:58:47 +0200957 ret = LY_EINT;
958 break;
959 }
960
961 return ret;
962}
963
Michal Vasko3a41dff2020-07-15 14:30:28 +0200964API LY_ERR
Michal Vasko871a0252020-11-11 18:35:24 +0100965lyd_new_meta(const struct ly_ctx *ctx, struct lyd_node *parent, const struct lys_module *module, const char *name,
966 const char *val_str, ly_bool clear_dflt, struct lyd_meta **meta)
Michal Vaskod86997b2020-05-26 15:19:54 +0200967{
Michal Vaskod86997b2020-05-26 15:19:54 +0200968 const char *prefix, *tmp;
Michal Vaskod86997b2020-05-26 15:19:54 +0200969 size_t pref_len, name_len;
970
Michal Vasko871a0252020-11-11 18:35:24 +0100971 LY_CHECK_ARG_RET(NULL, ctx, name, module || strchr(name, ':'), parent || meta, LY_EINVAL);
Michal Vasko00cbf532020-06-15 13:58:47 +0200972
Michal Vasko871a0252020-11-11 18:35:24 +0100973 if (parent && !parent->schema) {
974 LOGERR(ctx, LY_EINVAL, "Cannot add metadata to an opaque node \"%s\".", ((struct lyd_node_opaq *)parent)->name);
975 return LY_EINVAL;
976 }
Michal Vaskod86997b2020-05-26 15:19:54 +0200977
978 /* parse the name */
979 tmp = name;
980 if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
981 LOGERR(ctx, LY_EINVAL, "Metadata name \"%s\" is not valid.", name);
Michal Vasko871a0252020-11-11 18:35:24 +0100982 return LY_EINVAL;
Michal Vaskod86997b2020-05-26 15:19:54 +0200983 }
984
985 /* find the module */
986 if (prefix) {
Radek Krejci0ad51f12020-07-16 12:08:12 +0200987 module = ly_ctx_get_module_implemented2(ctx, prefix, pref_len);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200988 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 +0200989 }
990
991 /* set value if none */
992 if (!val_str) {
993 val_str = "";
994 }
995
Michal Vasko871a0252020-11-11 18:35:24 +0100996 return lyd_create_meta(parent, meta, module, name, name_len, val_str, strlen(val_str), NULL, LY_PREF_JSON,
997 NULL, LYD_HINT_DATA, clear_dflt, NULL);
998}
Michal Vasko3a41dff2020-07-15 14:30:28 +0200999
Michal Vaskoba696702020-11-11 19:12:45 +01001000API LY_ERR
1001lyd_new_meta2(const struct ly_ctx *ctx, struct lyd_node *parent, ly_bool clear_dflt, const struct lyd_attr *attr,
1002 struct lyd_meta **meta)
1003{
1004 const struct lys_module *mod;
1005
1006 LY_CHECK_ARG_RET(NULL, ctx, attr, parent || meta, LY_EINVAL);
1007
1008 if (parent && !parent->schema) {
1009 LOGERR(ctx, LY_EINVAL, "Cannot add metadata to an opaque node \"%s\".", ((struct lyd_node_opaq *)parent)->name);
1010 return LY_EINVAL;
Michal Vasko3a41dff2020-07-15 14:30:28 +02001011 }
Michal Vaskoba696702020-11-11 19:12:45 +01001012
1013 switch (attr->format) {
1014 case LY_PREF_XML:
Michal Vaskoad92b672020-11-12 13:11:31 +01001015 mod = ly_ctx_get_module_implemented_ns(ctx, attr->name.module_ns);
Michal Vaskoba696702020-11-11 19:12:45 +01001016 if (!mod) {
Michal Vaskoad92b672020-11-12 13:11:31 +01001017 LOGERR(ctx, LY_EINVAL, "Module with namespace \"%s\" not found.", attr->name.module_ns);
Michal Vaskoba696702020-11-11 19:12:45 +01001018 return LY_ENOTFOUND;
1019 }
1020 break;
1021 case LY_PREF_JSON:
Michal Vaskoad92b672020-11-12 13:11:31 +01001022 mod = ly_ctx_get_module_implemented(ctx, attr->name.module_name);
Michal Vaskoba696702020-11-11 19:12:45 +01001023 if (!mod) {
Michal Vaskoad92b672020-11-12 13:11:31 +01001024 LOGERR(ctx, LY_EINVAL, "Module \"%s\" not found.", attr->name.module_name);
Michal Vaskoba696702020-11-11 19:12:45 +01001025 return LY_ENOTFOUND;
1026 }
1027 break;
1028 default:
1029 LOGINT_RET(ctx);
1030 }
1031
Michal Vaskoad92b672020-11-12 13:11:31 +01001032 return lyd_create_meta(parent, meta, mod, attr->name.name, strlen(attr->name.name), attr->value, strlen(attr->value),
Michal Vaskoba696702020-11-11 19:12:45 +01001033 NULL, attr->format, attr->val_prefix_data, attr->hints, clear_dflt, NULL);
Michal Vaskod86997b2020-05-26 15:19:54 +02001034}
1035
Michal Vasko3a41dff2020-07-15 14:30:28 +02001036API LY_ERR
Michal Vasko00cbf532020-06-15 13:58:47 +02001037lyd_new_opaq(struct lyd_node *parent, const struct ly_ctx *ctx, const char *name, const char *value,
Radek Krejci0f969882020-08-21 16:56:47 +02001038 const char *module_name, struct lyd_node **node)
Michal Vasko00cbf532020-06-15 13:58:47 +02001039{
1040 struct lyd_node *ret = NULL;
1041
Michal Vasko6027eb92020-07-15 16:37:30 +02001042 LY_CHECK_ARG_RET(ctx, parent || ctx, parent || node, name, module_name, LY_EINVAL);
Michal Vasko00cbf532020-06-15 13:58:47 +02001043
1044 if (!ctx) {
Michal Vaskob7be7a82020-08-20 09:09:04 +02001045 ctx = LYD_CTX(parent);
Michal Vasko00cbf532020-06-15 13:58:47 +02001046 }
1047 if (!value) {
1048 value = "";
1049 }
1050
Michal Vasko501af032020-11-11 20:27:44 +01001051 LY_CHECK_RET(lyd_create_opaq(ctx, name, strlen(name), NULL, 0, module_name, strlen(module_name), value,
1052 strlen(value), NULL, LY_PREF_JSON, NULL, 0, &ret));
Michal Vasko3a41dff2020-07-15 14:30:28 +02001053 if (parent) {
Michal Vasko00cbf532020-06-15 13:58:47 +02001054 lyd_insert_node(parent, NULL, ret);
1055 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02001056
1057 if (node) {
1058 *node = ret;
1059 }
1060 return LY_SUCCESS;
Michal Vasko00cbf532020-06-15 13:58:47 +02001061}
1062
Michal Vasko3a41dff2020-07-15 14:30:28 +02001063API LY_ERR
1064lyd_new_attr(struct lyd_node *parent, const char *module_name, const char *name, const char *val_str,
Radek Krejci0f969882020-08-21 16:56:47 +02001065 struct lyd_attr **attr)
Michal Vasko00cbf532020-06-15 13:58:47 +02001066{
Radek Krejci1798aae2020-07-14 13:26:06 +02001067 struct lyd_attr *ret = NULL;
Michal Vasko00cbf532020-06-15 13:58:47 +02001068 const struct ly_ctx *ctx;
1069 const char *prefix, *tmp;
1070 size_t pref_len, name_len;
1071
Michal Vasko3a41dff2020-07-15 14:30:28 +02001072 LY_CHECK_ARG_RET(NULL, parent, !parent->schema, name, LY_EINVAL);
Michal Vasko00cbf532020-06-15 13:58:47 +02001073
Michal Vaskob7be7a82020-08-20 09:09:04 +02001074 ctx = LYD_CTX(parent);
Michal Vasko00cbf532020-06-15 13:58:47 +02001075
1076 /* parse the name */
1077 tmp = name;
1078 if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
1079 LOGERR(ctx, LY_EINVAL, "Metadata name \"%s\" is not valid.", name);
Michal Vasko3a41dff2020-07-15 14:30:28 +02001080 return LY_EVALID;
Michal Vasko00cbf532020-06-15 13:58:47 +02001081 }
1082
1083 /* set value if none */
1084 if (!val_str) {
1085 val_str = "";
1086 }
1087
Michal Vasko501af032020-11-11 20:27:44 +01001088 LY_CHECK_RET(lyd_create_attr(parent, &ret, ctx, name, name_len, prefix, pref_len, module_name,
1089 module_name ? strlen(module_name) : 0, val_str, strlen(val_str), NULL, LY_PREF_JSON, NULL, 0));
Michal Vasko3a41dff2020-07-15 14:30:28 +02001090
1091 if (attr) {
1092 *attr = ret;
1093 }
1094 return LY_SUCCESS;
Michal Vasko00cbf532020-06-15 13:58:47 +02001095}
1096
1097API LY_ERR
1098lyd_change_term(struct lyd_node *term, const char *val_str)
1099{
1100 LY_ERR ret = LY_SUCCESS;
1101 struct lysc_type *type;
1102 struct lyd_node_term *t;
1103 struct lyd_node *parent;
1104 struct lyd_value val = {0};
Radek Krejci857189e2020-09-01 13:26:36 +02001105 ly_bool dflt_change, val_change;
Michal Vasko00cbf532020-06-15 13:58:47 +02001106
1107 LY_CHECK_ARG_RET(NULL, term, term->schema, term->schema->nodetype & LYD_NODE_TERM, LY_EINVAL);
1108
1109 if (!val_str) {
1110 val_str = "";
1111 }
1112 t = (struct lyd_node_term *)term;
1113 type = ((struct lysc_node_leaf *)term->schema)->type;
1114
1115 /* parse the new value */
Michal Vaskofeca4fb2020-10-05 08:58:40 +02001116 ret = lyd_value_store(LYD_CTX(term), &val, type, val_str, strlen(val_str), NULL, LY_PREF_JSON, NULL, LYD_HINT_DATA,
1117 term->schema, NULL, LY_VLOG_LYD, term);
1118 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko00cbf532020-06-15 13:58:47 +02001119
1120 /* compare original and new value */
1121 if (type->plugin->compare(&t->value, &val)) {
1122 /* values differ, switch them */
Michal Vaskob7be7a82020-08-20 09:09:04 +02001123 type->plugin->free(LYD_CTX(term), &t->value);
Michal Vasko00cbf532020-06-15 13:58:47 +02001124 t->value = val;
1125 memset(&val, 0, sizeof val);
1126 val_change = 1;
1127 } else {
1128 val_change = 0;
1129 }
1130
1131 /* always clear the default flag */
1132 if (term->flags & LYD_DEFAULT) {
1133 for (parent = term; parent; parent = (struct lyd_node *)parent->parent) {
1134 parent->flags &= ~LYD_DEFAULT;
1135 }
1136 dflt_change = 1;
1137 } else {
1138 dflt_change = 0;
1139 }
1140
1141 if (val_change || dflt_change) {
1142 /* make the node non-validated */
1143 term->flags &= LYD_NEW;
1144 }
1145
1146 if (val_change) {
1147 if (term->schema->nodetype == LYS_LEAFLIST) {
1148 /* leaf-list needs to be hashed again and re-inserted into parent */
1149 lyd_unlink_hash(term);
1150 lyd_hash(term);
1151 LY_CHECK_GOTO(ret = lyd_insert_hash(term), cleanup);
1152 } else if ((term->schema->flags & LYS_KEY) && term->parent) {
1153 /* list needs to be updated if its key was changed */
1154 assert(term->parent->schema->nodetype == LYS_LIST);
1155 lyd_unlink_hash((struct lyd_node *)term->parent);
1156 lyd_hash((struct lyd_node *)term->parent);
1157 LY_CHECK_GOTO(ret = lyd_insert_hash((struct lyd_node *)term->parent), cleanup);
1158 } /* else leaf that is not a key, its value is not used for its hash so it does not change */
1159 }
1160
1161 /* retrun value */
1162 if (!val_change) {
1163 if (dflt_change) {
1164 /* only default flag change */
1165 ret = LY_EEXIST;
1166 } else {
1167 /* no change */
1168 ret = LY_ENOT;
1169 }
1170 } /* else value changed, LY_SUCCESS */
1171
1172cleanup:
Michal Vaskob7be7a82020-08-20 09:09:04 +02001173 type->plugin->free(LYD_CTX(term), &val);
Michal Vasko00cbf532020-06-15 13:58:47 +02001174 return ret;
1175}
1176
Michal Vasko41586352020-07-13 13:54:25 +02001177API LY_ERR
1178lyd_change_meta(struct lyd_meta *meta, const char *val_str)
1179{
1180 LY_ERR ret = LY_SUCCESS;
Radek Krejci2b18bf12020-11-06 11:20:20 +01001181 struct lyd_meta *m2 = NULL;
Michal Vasko41586352020-07-13 13:54:25 +02001182 struct lyd_value val;
Radek Krejci857189e2020-09-01 13:26:36 +02001183 ly_bool val_change;
Michal Vasko41586352020-07-13 13:54:25 +02001184
1185 LY_CHECK_ARG_RET(NULL, meta, LY_EINVAL);
1186
1187 if (!val_str) {
1188 val_str = "";
1189 }
1190
1191 /* parse the new value into a new meta structure */
1192 LY_CHECK_GOTO(ret = lyd_create_meta(NULL, &m2, meta->annotation->module, meta->name, strlen(meta->name), val_str,
Michal Vasko871a0252020-11-11 18:35:24 +01001193 strlen(val_str), NULL, LY_PREF_JSON, NULL, LYD_HINT_DATA, 0, NULL), cleanup);
Michal Vasko41586352020-07-13 13:54:25 +02001194
1195 /* compare original and new value */
1196 if (lyd_compare_meta(meta, m2)) {
1197 /* values differ, switch them */
1198 val = meta->value;
1199 meta->value = m2->value;
1200 m2->value = val;
1201 val_change = 1;
1202 } else {
1203 val_change = 0;
1204 }
1205
1206 /* retrun value */
1207 if (!val_change) {
1208 /* no change */
1209 ret = LY_ENOT;
1210 } /* else value changed, LY_SUCCESS */
1211
1212cleanup:
1213 return ret;
1214}
1215
Michal Vasko3a41dff2020-07-15 14:30:28 +02001216API LY_ERR
Radek Krejci1deb5be2020-08-26 16:43:36 +02001217lyd_new_path(struct lyd_node *parent, const struct ly_ctx *ctx, const char *path, const char *value, uint32_t options,
Radek Krejci0f969882020-08-21 16:56:47 +02001218 struct lyd_node **node)
Michal Vasko00cbf532020-06-15 13:58:47 +02001219{
Michal Vasko3a41dff2020-07-15 14:30:28 +02001220 return lyd_new_path2(parent, ctx, path, value, 0, options, node, NULL);
Michal Vasko00cbf532020-06-15 13:58:47 +02001221}
1222
1223API LY_ERR
1224lyd_new_path2(struct lyd_node *parent, const struct ly_ctx *ctx, const char *path, const void *value,
Radek Krejci1deb5be2020-08-26 16:43:36 +02001225 LYD_ANYDATA_VALUETYPE value_type, uint32_t options, struct lyd_node **new_parent, struct lyd_node **new_node)
Michal Vasko00cbf532020-06-15 13:58:47 +02001226{
1227 LY_ERR ret = LY_SUCCESS, r;
1228 struct lyxp_expr *exp = NULL;
1229 struct ly_path *p = NULL;
1230 struct lyd_node *nparent = NULL, *nnode = NULL, *node = NULL, *cur_parent;
1231 const struct lysc_node *schema;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001232 LY_ARRAY_COUNT_TYPE path_idx = 0;
Michal Vasko00cbf532020-06-15 13:58:47 +02001233 struct ly_path_predicate *pred;
1234
1235 LY_CHECK_ARG_RET(ctx, parent || ctx, path, (path[0] == '/') || parent, LY_EINVAL);
1236
1237 if (!ctx) {
Michal Vaskob7be7a82020-08-20 09:09:04 +02001238 ctx = LYD_CTX(parent);
Michal Vasko00cbf532020-06-15 13:58:47 +02001239 }
1240
1241 /* parse path */
Michal Vasko6b26e742020-07-17 15:02:10 +02001242 LY_CHECK_GOTO(ret = ly_path_parse(ctx, NULL, path, strlen(path), LY_PATH_BEGIN_EITHER, LY_PATH_LREF_FALSE,
Michal Vasko69730152020-10-09 16:30:07 +02001243 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_SIMPLE, &exp), cleanup);
Michal Vasko00cbf532020-06-15 13:58:47 +02001244
1245 /* compile path */
1246 LY_CHECK_GOTO(ret = ly_path_compile(ctx, NULL, parent ? parent->schema : NULL, exp, LY_PATH_LREF_FALSE,
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001247 options & LYD_NEW_PATH_OUTPUT ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY, LY_PREF_JSON,
1248 NULL, &p), cleanup);
Michal Vasko00cbf532020-06-15 13:58:47 +02001249
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001250 schema = p[LY_ARRAY_COUNT(p) - 1].node;
Michal Vasko69730152020-10-09 16:30:07 +02001251 if ((schema->nodetype == LYS_LIST) && (p[LY_ARRAY_COUNT(p) - 1].pred_type == LY_PATH_PREDTYPE_NONE) &&
Radek Krejci092e33c2020-10-12 15:33:10 +02001252 !(options & LYD_NEW_PATH_OPAQ)) {
Michal Vasko00cbf532020-06-15 13:58:47 +02001253 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_XPATH, "Predicate missing for %s \"%s\" in path.",
Michal Vasko69730152020-10-09 16:30:07 +02001254 lys_nodetype2str(schema->nodetype), schema->name);
Michal Vasko00cbf532020-06-15 13:58:47 +02001255 ret = LY_EINVAL;
1256 goto cleanup;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001257 } 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 +02001258 /* parse leafref value into a predicate, if not defined in the path */
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001259 p[LY_ARRAY_COUNT(p) - 1].pred_type = LY_PATH_PREDTYPE_LEAFLIST;
1260 LY_ARRAY_NEW_GOTO(ctx, p[LY_ARRAY_COUNT(p) - 1].predicates, pred, ret, cleanup);
Michal Vasko00cbf532020-06-15 13:58:47 +02001261
1262 if (!value) {
1263 value = "";
1264 }
1265
1266 r = LY_SUCCESS;
Radek Krejci092e33c2020-10-12 15:33:10 +02001267 if (options & LYD_NEW_PATH_OPAQ) {
Michal Vaskof937cfe2020-08-03 16:07:12 +02001268 r = lys_value_validate(NULL, schema, value, strlen(value));
Michal Vasko00cbf532020-06-15 13:58:47 +02001269 }
1270 if (!r) {
Michal Vaskofeca4fb2020-10-05 08:58:40 +02001271 ret = lyd_value_store(ctx, &pred->value, ((struct lysc_node_leaflist *)schema)->type, value, strlen(value),
1272 NULL, LY_PREF_JSON, NULL, LYD_HINT_DATA, schema, NULL, LY_VLOG_LYSC, schema);
1273 LY_CHECK_GOTO(ret, cleanup);
Michal Vaskoae875662020-10-21 10:33:17 +02001274 ++((struct lysc_type *)pred->value.realtype)->refcount;
Michal Vasko00cbf532020-06-15 13:58:47 +02001275 } /* else we have opaq flag and the value is not valid, leavne no predicate and then create an opaque node */
1276 }
1277
1278 /* try to find any existing nodes in the path */
1279 if (parent) {
1280 ret = ly_path_eval_partial(p, parent, &path_idx, &node);
1281 if (ret == LY_SUCCESS) {
1282 /* the node exists, are we supposed to update it or is it just a default? */
Radek Krejci092e33c2020-10-12 15:33:10 +02001283 if (!(options & LYD_NEW_PATH_UPDATE) && !(node->flags & LYD_DEFAULT)) {
Michal Vasko00cbf532020-06-15 13:58:47 +02001284 LOGERR(ctx, LY_EEXIST, "Path \"%s\" already exists", path);
1285 ret = LY_EEXIST;
1286 goto cleanup;
1287 }
1288
1289 /* update the existing node */
1290 ret = lyd_new_path_update(node, value, value_type, &nparent, &nnode);
1291 goto cleanup;
1292 } else if (ret == LY_EINCOMPLETE) {
1293 /* some nodes were found, adjust the iterator to the next segment */
1294 ++path_idx;
1295 } else if (ret == LY_ENOTFOUND) {
1296 /* we will create the nodes from top-level, default behavior (absolute path), or from the parent (relative path) */
Michal Vasko45b0d202020-11-06 17:20:46 +01001297 if (lysc_data_parent(p[0].node)) {
Michal Vasko00cbf532020-06-15 13:58:47 +02001298 node = parent;
1299 }
1300 } else {
1301 /* error */
1302 goto cleanup;
1303 }
1304 }
1305
1306 /* create all the non-existing nodes in a loop */
Michal Vaskod989ba02020-08-24 10:59:24 +02001307 for ( ; path_idx < LY_ARRAY_COUNT(p); ++path_idx) {
Michal Vasko00cbf532020-06-15 13:58:47 +02001308 cur_parent = node;
1309 schema = p[path_idx].node;
1310
1311 switch (schema->nodetype) {
1312 case LYS_LIST:
1313 if (!(schema->flags & LYS_KEYLESS)) {
Radek Krejci092e33c2020-10-12 15:33:10 +02001314 if ((options & LYD_NEW_PATH_OPAQ) && (p[path_idx].pred_type == LY_PATH_PREDTYPE_NONE)) {
Michal Vasko00cbf532020-06-15 13:58:47 +02001315 /* creating opaque list without keys */
Michal Vasko501af032020-11-11 20:27:44 +01001316 LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0,
1317 schema->module->name, strlen(schema->module->name), NULL, 0, NULL, LY_PREF_JSON, NULL,
1318 LYD_NODEHINT_LIST, &node), cleanup);
Michal Vasko00cbf532020-06-15 13:58:47 +02001319 } else {
1320 assert(p[path_idx].pred_type == LY_PATH_PREDTYPE_LIST);
1321 LY_CHECK_GOTO(ret = lyd_create_list(schema, p[path_idx].predicates, &node), cleanup);
1322 }
1323 break;
1324 }
Radek Krejci0f969882020-08-21 16:56:47 +02001325 /* fallthrough */
Michal Vasko00cbf532020-06-15 13:58:47 +02001326 case LYS_CONTAINER:
1327 case LYS_NOTIF:
1328 case LYS_RPC:
1329 case LYS_ACTION:
1330 LY_CHECK_GOTO(ret = lyd_create_inner(schema, &node), cleanup);
1331 break;
1332 case LYS_LEAFLIST:
Radek Krejci092e33c2020-10-12 15:33:10 +02001333 if ((options & LYD_NEW_PATH_OPAQ) && (p[path_idx].pred_type == LY_PATH_PREDTYPE_NONE)) {
Michal Vasko00cbf532020-06-15 13:58:47 +02001334 /* creating opaque leaf-list without value */
Michal Vasko501af032020-11-11 20:27:44 +01001335 LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0,
1336 schema->module->name, strlen(schema->module->name), NULL, 0, NULL, LY_PREF_JSON, NULL,
1337 LYD_NODEHINT_LEAFLIST, &node), cleanup);
Michal Vasko00cbf532020-06-15 13:58:47 +02001338 } else {
1339 assert(p[path_idx].pred_type == LY_PATH_PREDTYPE_LEAFLIST);
1340 LY_CHECK_GOTO(ret = lyd_create_term2(schema, &p[path_idx].predicates[0].value, &node), cleanup);
1341 }
1342 break;
1343 case LYS_LEAF:
1344 /* make there is some value */
1345 if (!value) {
1346 value = "";
1347 }
1348
1349 r = LY_SUCCESS;
Radek Krejci092e33c2020-10-12 15:33:10 +02001350 if (options & LYD_NEW_PATH_OPAQ) {
Michal Vaskof937cfe2020-08-03 16:07:12 +02001351 r = lys_value_validate(NULL, schema, value, strlen(value));
Michal Vasko00cbf532020-06-15 13:58:47 +02001352 }
1353 if (!r) {
Michal Vaskofeca4fb2020-10-05 08:58:40 +02001354 ret = lyd_create_term(schema, value, strlen(value), NULL, LY_PREF_JSON, NULL, LYD_HINT_DATA, NULL, &node);
1355 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko00cbf532020-06-15 13:58:47 +02001356 } else {
1357 /* creating opaque leaf without value */
Michal Vasko501af032020-11-11 20:27:44 +01001358 LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, schema->module->name,
1359 strlen(schema->module->name), NULL, 0, NULL, LY_PREF_JSON, NULL, 0, &node), cleanup);
Michal Vasko00cbf532020-06-15 13:58:47 +02001360 }
1361 break;
1362 case LYS_ANYDATA:
1363 case LYS_ANYXML:
1364 LY_CHECK_GOTO(ret = lyd_create_any(schema, value, value_type, &node), cleanup);
1365 break;
1366 default:
1367 LOGINT(ctx);
1368 ret = LY_EINT;
1369 goto cleanup;
1370 }
1371
1372 if (cur_parent) {
1373 /* connect to the parent */
1374 lyd_insert_node(cur_parent, NULL, node);
1375 } else if (parent) {
1376 /* connect to top-level siblings */
1377 lyd_insert_node(NULL, &parent, node);
1378 }
1379
1380 /* update remembered nodes */
1381 if (!nparent) {
1382 nparent = node;
1383 }
1384 nnode = node;
1385 }
1386
1387cleanup:
1388 lyxp_expr_free(ctx, exp);
1389 ly_path_free(ctx, p);
1390 if (!ret) {
1391 /* set out params only on success */
1392 if (new_parent) {
1393 *new_parent = nparent;
1394 }
1395 if (new_node) {
1396 *new_node = nnode;
1397 }
1398 }
1399 return ret;
1400}
1401
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001402LY_ERR
1403lyd_new_implicit_r(struct lyd_node *parent, struct lyd_node **first, const struct lysc_node *sparent,
Radek Krejci1deb5be2020-08-26 16:43:36 +02001404 const struct lys_module *mod, struct ly_set *node_types, struct ly_set *node_when, uint32_t impl_opts,
Radek Krejci0f969882020-08-21 16:56:47 +02001405 struct lyd_node **diff)
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001406{
1407 LY_ERR ret;
1408 const struct lysc_node *iter = NULL;
Radek Krejci2b18bf12020-11-06 11:20:20 +01001409 struct lyd_node *node = NULL;
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001410 struct lyd_value **dflts;
1411 LY_ARRAY_COUNT_TYPE u;
1412
1413 assert(first && (parent || sparent || mod));
1414
1415 if (!sparent && parent) {
1416 sparent = parent->schema;
1417 }
1418
1419 while ((iter = lys_getnext(iter, sparent, mod ? mod->compiled : NULL, LYS_GETNEXT_WITHCHOICE))) {
1420 if ((impl_opts & LYD_IMPLICIT_NO_STATE) && (iter->flags & LYS_CONFIG_R)) {
1421 continue;
Michal Vasko44b19a12020-08-07 09:21:30 +02001422 } else if ((impl_opts & LYD_IMPLICIT_NO_CONFIG) && (iter->flags & LYS_CONFIG_W)) {
1423 continue;
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001424 }
1425
1426 switch (iter->nodetype) {
1427 case LYS_CHOICE:
1428 if (((struct lysc_node_choice *)iter)->dflt && !lys_getnext_data(NULL, *first, NULL, iter, NULL)) {
1429 /* create default case data */
1430 LY_CHECK_RET(lyd_new_implicit_r(parent, first, (struct lysc_node *)((struct lysc_node_choice *)iter)->dflt,
Michal Vasko69730152020-10-09 16:30:07 +02001431 NULL, node_types, node_when, impl_opts, diff));
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001432 }
1433 break;
1434 case LYS_CONTAINER:
1435 if (!(iter->flags & LYS_PRESENCE) && lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
1436 /* create default NP container */
1437 LY_CHECK_RET(lyd_create_inner(iter, &node));
Michal Vasko0cadfcb2020-11-04 17:17:05 +01001438 node->flags = LYD_DEFAULT | (node->schema->when ? LYD_WHEN_TRUE : 0);
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001439 lyd_insert_node(parent, first, node);
1440
1441 /* cannot be a NP container with when */
1442 assert(!iter->when);
1443
Michal Vaskoe49b6322020-11-05 17:38:36 +01001444 if (diff) {
1445 /* add into diff */
1446 LY_CHECK_RET(lyd_val_diff_add(node, LYD_DIFF_OP_CREATE, diff));
1447 }
1448
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001449 /* create any default children */
1450 LY_CHECK_RET(lyd_new_implicit_r(node, lyd_node_children_p(node), NULL, NULL, node_types, node_when,
Michal Vasko69730152020-10-09 16:30:07 +02001451 impl_opts, diff));
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001452 }
1453 break;
1454 case LYS_LEAF:
Michal Vasko69730152020-10-09 16:30:07 +02001455 if (!(impl_opts & LYD_IMPLICIT_NO_DEFAULTS) && ((struct lysc_node_leaf *)iter)->dflt &&
1456 lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001457 /* create default leaf */
1458 ret = lyd_create_term2(iter, ((struct lysc_node_leaf *)iter)->dflt, &node);
1459 if (ret == LY_EINCOMPLETE) {
1460 if (node_types) {
1461 /* remember to resolve type */
Radek Krejci3d92e442020-10-12 12:48:13 +02001462 LY_CHECK_RET(ly_set_add(node_types, node, 1, NULL));
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001463 }
1464 } else if (ret) {
1465 return ret;
1466 }
Michal Vasko0cadfcb2020-11-04 17:17:05 +01001467 node->flags = LYD_DEFAULT | (node->schema->when ? LYD_WHEN_TRUE : 0);
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001468 lyd_insert_node(parent, first, node);
1469
1470 if (iter->when && node_when) {
1471 /* remember to resolve when */
Radek Krejci3d92e442020-10-12 12:48:13 +02001472 LY_CHECK_RET(ly_set_add(node_when, node, 1, NULL));
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001473 }
1474 if (diff) {
1475 /* add into diff */
1476 LY_CHECK_RET(lyd_val_diff_add(node, LYD_DIFF_OP_CREATE, diff));
1477 }
1478 }
1479 break;
1480 case LYS_LEAFLIST:
Michal Vasko69730152020-10-09 16:30:07 +02001481 if (!(impl_opts & LYD_IMPLICIT_NO_DEFAULTS) && ((struct lysc_node_leaflist *)iter)->dflts &&
1482 lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001483 /* create all default leaf-lists */
1484 dflts = ((struct lysc_node_leaflist *)iter)->dflts;
1485 LY_ARRAY_FOR(dflts, u) {
1486 ret = lyd_create_term2(iter, dflts[u], &node);
1487 if (ret == LY_EINCOMPLETE) {
1488 if (node_types) {
1489 /* remember to resolve type */
Radek Krejci3d92e442020-10-12 12:48:13 +02001490 LY_CHECK_RET(ly_set_add(node_types, node, 1, NULL));
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001491 }
1492 } else if (ret) {
1493 return ret;
1494 }
Radek Krejcic5b54a02020-11-05 17:13:18 +01001495 node->flags = LYD_DEFAULT | (node->schema->when ? LYD_WHEN_TRUE : 0);
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001496 lyd_insert_node(parent, first, node);
1497
1498 if (iter->when && node_when) {
1499 /* remember to resolve when */
Radek Krejci3d92e442020-10-12 12:48:13 +02001500 LY_CHECK_RET(ly_set_add(node_when, node, 1, NULL));
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001501 }
1502 if (diff) {
1503 /* add into diff */
1504 LY_CHECK_RET(lyd_val_diff_add(node, LYD_DIFF_OP_CREATE, diff));
1505 }
1506 }
1507 }
1508 break;
1509 default:
1510 /* without defaults */
1511 break;
1512 }
1513 }
1514
1515 return LY_SUCCESS;
1516}
1517
1518API LY_ERR
Radek Krejci1deb5be2020-08-26 16:43:36 +02001519lyd_new_implicit_tree(struct lyd_node *tree, uint32_t implicit_options, struct lyd_node **diff)
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001520{
Michal Vasko56daf732020-08-10 10:57:18 +02001521 struct lyd_node *node;
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001522 LY_ERR ret = LY_SUCCESS;
1523
1524 LY_CHECK_ARG_RET(NULL, tree, LY_EINVAL);
1525 if (diff) {
1526 *diff = NULL;
1527 }
1528
Michal Vasko56daf732020-08-10 10:57:18 +02001529 LYD_TREE_DFS_BEGIN(tree, node) {
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001530 /* skip added default nodes */
Michal Vasko69730152020-10-09 16:30:07 +02001531 if (((node->flags & (LYD_DEFAULT | LYD_NEW)) != (LYD_DEFAULT | LYD_NEW)) &&
1532 (node->schema->nodetype & LYD_NODE_INNER)) {
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001533 LY_CHECK_GOTO(ret = lyd_new_implicit_r(node, lyd_node_children_p((struct lyd_node *)node), NULL, NULL, NULL,
Michal Vasko69730152020-10-09 16:30:07 +02001534 NULL, implicit_options, diff), cleanup);
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001535 }
1536
Michal Vasko56daf732020-08-10 10:57:18 +02001537 LYD_TREE_DFS_END(tree, node);
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001538 }
1539
1540cleanup:
1541 if (ret && diff) {
1542 lyd_free_all(*diff);
1543 *diff = NULL;
1544 }
1545 return ret;
1546}
1547
1548API LY_ERR
Radek Krejci1deb5be2020-08-26 16:43:36 +02001549lyd_new_implicit_all(struct lyd_node **tree, const struct ly_ctx *ctx, uint32_t implicit_options, struct lyd_node **diff)
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001550{
1551 const struct lys_module *mod;
1552 struct lyd_node *d = NULL;
1553 uint32_t i = 0;
1554 LY_ERR ret = LY_SUCCESS;
1555
1556 LY_CHECK_ARG_RET(ctx, tree, *tree || ctx, LY_EINVAL);
1557 if (diff) {
1558 *diff = NULL;
1559 }
1560 if (!ctx) {
Michal Vaskob7be7a82020-08-20 09:09:04 +02001561 ctx = LYD_CTX(*tree);
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001562 }
1563
1564 /* add nodes for each module one-by-one */
1565 while ((mod = ly_ctx_get_module_iter(ctx, &i))) {
1566 if (!mod->implemented) {
1567 continue;
1568 }
1569
1570 LY_CHECK_GOTO(ret = lyd_new_implicit_module(tree, mod, implicit_options, diff ? &d : NULL), cleanup);
1571 if (d) {
1572 /* merge into one diff */
1573 lyd_insert_sibling(*diff, d, diff);
1574
1575 d = NULL;
1576 }
1577 }
1578
1579cleanup:
1580 if (ret && diff) {
1581 lyd_free_all(*diff);
1582 *diff = NULL;
1583 }
1584 return ret;
1585}
1586
1587API LY_ERR
Radek Krejci1deb5be2020-08-26 16:43:36 +02001588lyd_new_implicit_module(struct lyd_node **tree, const struct lys_module *module, uint32_t implicit_options, struct lyd_node **diff)
Michal Vaskoa6669ba2020-08-06 16:14:26 +02001589{
1590 struct lyd_node *root, *d = NULL;
1591 LY_ERR ret = LY_SUCCESS;
1592
1593 LY_CHECK_ARG_RET(NULL, tree, module, LY_EINVAL);
1594 if (diff) {
1595 *diff = NULL;
1596 }
1597
1598 /* add all top-level defaults for this module */
1599 LY_CHECK_GOTO(ret = lyd_new_implicit_r(NULL, tree, NULL, module, NULL, NULL, implicit_options, diff), cleanup);
1600
1601 /* process nested nodes */
1602 LY_LIST_FOR(*tree, root) {
1603 /* skip added default nodes */
1604 if ((root->flags & (LYD_DEFAULT | LYD_NEW)) != (LYD_DEFAULT | LYD_NEW)) {
1605 LY_CHECK_GOTO(ret = lyd_new_implicit_tree(root, implicit_options, diff ? &d : NULL), cleanup);
1606
1607 if (d) {
1608 /* merge into one diff */
1609 lyd_insert_sibling(*diff, d, diff);
1610
1611 d = NULL;
1612 }
1613 }
1614 }
1615
1616cleanup:
1617 if (ret && diff) {
1618 lyd_free_all(*diff);
1619 *diff = NULL;
1620 }
1621 return ret;
1622}
1623
Michal Vasko90932a92020-02-12 14:33:03 +01001624struct lyd_node *
Michal Vaskob104f112020-07-17 09:54:54 +02001625lyd_insert_get_next_anchor(const struct lyd_node *first_sibling, const struct lyd_node *new_node)
Michal Vasko90932a92020-02-12 14:33:03 +01001626{
Michal Vaskob104f112020-07-17 09:54:54 +02001627 const struct lysc_node *schema, *sparent;
Michal Vasko90932a92020-02-12 14:33:03 +01001628 struct lyd_node *match = NULL;
Radek Krejci857189e2020-09-01 13:26:36 +02001629 ly_bool found;
Michal Vasko90932a92020-02-12 14:33:03 +01001630
Michal Vaskob104f112020-07-17 09:54:54 +02001631 assert(new_node);
1632
1633 if (!first_sibling || !new_node->schema) {
1634 /* insert at the end, no next anchor */
Michal Vasko90932a92020-02-12 14:33:03 +01001635 return NULL;
1636 }
1637
Michal Vaskob104f112020-07-17 09:54:54 +02001638 if (first_sibling->parent && first_sibling->parent->children_ht) {
1639 /* find the anchor using hashes */
1640 sparent = first_sibling->parent->schema;
1641 schema = lys_getnext(new_node->schema, sparent, NULL, 0);
1642 while (schema) {
1643 /* keep trying to find the first existing instance of the closest following schema sibling,
1644 * otherwise return NULL - inserting at the end */
1645 if (!lyd_find_sibling_schema(first_sibling, schema, &match)) {
1646 break;
1647 }
1648
1649 schema = lys_getnext(schema, sparent, NULL, 0);
1650 }
1651 } else {
1652 /* find the anchor without hashes */
1653 match = (struct lyd_node *)first_sibling;
1654 if (!lysc_data_parent(new_node->schema)) {
1655 /* we are in top-level, skip all the data from preceding modules */
1656 LY_LIST_FOR(match, match) {
1657 if (!match->schema || (strcmp(lyd_owner_module(match)->name, lyd_owner_module(new_node)->name) >= 0)) {
1658 break;
1659 }
1660 }
1661 }
1662
1663 /* get the first schema sibling */
1664 sparent = lysc_data_parent(new_node->schema);
1665 schema = lys_getnext(NULL, sparent, new_node->schema->module->compiled, 0);
1666
1667 found = 0;
1668 LY_LIST_FOR(match, match) {
1669 if (!match->schema || (lyd_owner_module(match) != lyd_owner_module(new_node))) {
1670 /* we have found an opaque node, which must be at the end, so use it OR
1671 * modules do not match, so we must have traversed all the data from new_node module (if any),
1672 * we have found the first node of the next module, that is what we want */
1673 break;
1674 }
1675
1676 /* skip schema nodes until we find the instantiated one */
1677 while (!found) {
1678 if (new_node->schema == schema) {
1679 /* we have found the schema of the new node, continue search to find the first
1680 * data node with a different schema (after our schema) */
1681 found = 1;
1682 break;
1683 }
1684 if (match->schema == schema) {
1685 /* current node (match) is a data node still before the new node, continue search in data */
1686 break;
1687 }
1688 schema = lys_getnext(schema, sparent, new_node->schema->module->compiled, 0);
1689 assert(schema);
1690 }
1691
1692 if (found && (match->schema != new_node->schema)) {
1693 /* find the next node after we have found our node schema data instance */
1694 break;
1695 }
1696 }
Michal Vasko90932a92020-02-12 14:33:03 +01001697 }
1698
1699 return match;
1700}
1701
1702/**
1703 * @brief Insert node after a sibling.
1704 *
Michal Vasko9f96a052020-03-10 09:41:45 +01001705 * Handles inserting into NP containers and key-less lists.
1706 *
Michal Vasko90932a92020-02-12 14:33:03 +01001707 * @param[in] sibling Sibling to insert after.
1708 * @param[in] node Node to insert.
1709 */
1710static void
Michal Vaskof03ed032020-03-04 13:31:44 +01001711lyd_insert_after_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001712{
Michal Vasko0249f7c2020-03-05 16:36:40 +01001713 struct lyd_node_inner *par;
1714
Michal Vasko90932a92020-02-12 14:33:03 +01001715 assert(!node->next && (node->prev == node));
1716
1717 node->next = sibling->next;
1718 node->prev = sibling;
1719 sibling->next = node;
1720 if (node->next) {
1721 /* sibling had a succeeding node */
1722 node->next->prev = node;
1723 } else {
1724 /* sibling was last, find first sibling and change its prev */
1725 if (sibling->parent) {
1726 sibling = sibling->parent->child;
1727 } else {
Michal Vaskod989ba02020-08-24 10:59:24 +02001728 for ( ; sibling->prev->next != node; sibling = sibling->prev) {}
Michal Vasko90932a92020-02-12 14:33:03 +01001729 }
1730 sibling->prev = node;
1731 }
1732 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001733
Michal Vasko9f96a052020-03-10 09:41:45 +01001734 for (par = node->parent; par; par = par->parent) {
1735 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
1736 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +01001737 par->flags &= ~LYD_DEFAULT;
1738 }
Michal Vaskob104f112020-07-17 09:54:54 +02001739 if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001740 /* rehash key-less list */
1741 lyd_hash((struct lyd_node *)par);
1742 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001743 }
Michal Vasko90932a92020-02-12 14:33:03 +01001744}
1745
1746/**
1747 * @brief Insert node before a sibling.
1748 *
Michal Vasko9f96a052020-03-10 09:41:45 +01001749 * Handles inserting into NP containers and key-less lists.
1750 *
Michal Vasko90932a92020-02-12 14:33:03 +01001751 * @param[in] sibling Sibling to insert before.
1752 * @param[in] node Node to insert.
1753 */
1754static void
Michal Vaskof03ed032020-03-04 13:31:44 +01001755lyd_insert_before_node(struct lyd_node *sibling, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001756{
Michal Vasko0249f7c2020-03-05 16:36:40 +01001757 struct lyd_node_inner *par;
1758
Michal Vasko90932a92020-02-12 14:33:03 +01001759 assert(!node->next && (node->prev == node));
1760
1761 node->next = sibling;
1762 /* covers situation of sibling being first */
1763 node->prev = sibling->prev;
1764 sibling->prev = node;
1765 if (node->prev->next) {
1766 /* sibling had a preceding node */
1767 node->prev->next = node;
1768 } else if (sibling->parent) {
1769 /* sibling was first and we must also change parent child pointer */
1770 sibling->parent->child = node;
1771 }
1772 node->parent = sibling->parent;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001773
Michal Vasko9f96a052020-03-10 09:41:45 +01001774 for (par = node->parent; par; par = par->parent) {
1775 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
1776 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +01001777 par->flags &= ~LYD_DEFAULT;
1778 }
Michal Vaskob104f112020-07-17 09:54:54 +02001779 if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001780 /* rehash key-less list */
1781 lyd_hash((struct lyd_node *)par);
1782 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001783 }
Michal Vasko90932a92020-02-12 14:33:03 +01001784}
1785
1786/**
Michal Vaskob104f112020-07-17 09:54:54 +02001787 * @brief Insert node as the first and only child of a parent.
Michal Vasko90932a92020-02-12 14:33:03 +01001788 *
Michal Vasko9f96a052020-03-10 09:41:45 +01001789 * Handles inserting into NP containers and key-less lists.
1790 *
Michal Vasko90932a92020-02-12 14:33:03 +01001791 * @param[in] parent Parent to insert into.
1792 * @param[in] node Node to insert.
1793 */
1794static void
Michal Vaskob104f112020-07-17 09:54:54 +02001795lyd_insert_only_child(struct lyd_node *parent, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001796{
1797 struct lyd_node_inner *par;
1798
Radek Krejcia1c1e542020-09-29 16:06:52 +02001799 assert(parent && !lyd_child(parent) && !node->next && (node->prev == node));
Michal Vasko52927e22020-03-16 17:26:14 +01001800 assert(!parent->schema || (parent->schema->nodetype & LYD_NODE_INNER));
Michal Vasko90932a92020-02-12 14:33:03 +01001801
1802 par = (struct lyd_node_inner *)parent;
1803
Michal Vaskob104f112020-07-17 09:54:54 +02001804 par->child = node;
Michal Vasko90932a92020-02-12 14:33:03 +01001805 node->parent = par;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001806
Michal Vaskod989ba02020-08-24 10:59:24 +02001807 for ( ; par; par = par->parent) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001808 if ((par->flags & LYD_DEFAULT) && !(node->flags & LYD_DEFAULT)) {
1809 /* remove default flags from NP containers */
Michal Vasko0249f7c2020-03-05 16:36:40 +01001810 par->flags &= ~LYD_DEFAULT;
1811 }
Michal Vasko52927e22020-03-16 17:26:14 +01001812 if (par->schema && (par->schema->nodetype == LYS_LIST) && (par->schema->flags & LYS_KEYLESS)) {
Michal Vasko9f96a052020-03-10 09:41:45 +01001813 /* rehash key-less list */
1814 lyd_hash((struct lyd_node *)par);
1815 }
Michal Vasko0249f7c2020-03-05 16:36:40 +01001816 }
Michal Vasko751cb4d2020-07-14 12:25:28 +02001817}
Michal Vasko0249f7c2020-03-05 16:36:40 +01001818
Michal Vasko751cb4d2020-07-14 12:25:28 +02001819/**
1820 * @brief Learn whether a list instance has all the keys.
1821 *
1822 * @param[in] list List instance to check.
1823 * @return non-zero if all the keys were found,
1824 * @return 0 otherwise.
1825 */
1826static int
1827lyd_insert_has_keys(const struct lyd_node *list)
1828{
1829 const struct lyd_node *key;
1830 const struct lysc_node *skey = NULL;
1831
1832 assert(list->schema->nodetype == LYS_LIST);
Radek Krejcia1c1e542020-09-29 16:06:52 +02001833 key = lyd_child(list);
Michal Vasko751cb4d2020-07-14 12:25:28 +02001834 while ((skey = lys_getnext(skey, list->schema, NULL, 0)) && (skey->flags & LYS_KEY)) {
1835 if (!key || (key->schema != skey)) {
1836 /* key missing */
1837 return 0;
1838 }
1839
1840 key = key->next;
1841 }
1842
1843 /* all keys found */
1844 return 1;
Michal Vasko90932a92020-02-12 14:33:03 +01001845}
1846
1847void
Michal Vaskob104f112020-07-17 09:54:54 +02001848lyd_insert_node(struct lyd_node *parent, struct lyd_node **first_sibling_p, struct lyd_node *node)
Michal Vasko90932a92020-02-12 14:33:03 +01001849{
Michal Vaskob104f112020-07-17 09:54:54 +02001850 struct lyd_node *anchor, *first_sibling;
Michal Vasko90932a92020-02-12 14:33:03 +01001851
Michal Vaskob104f112020-07-17 09:54:54 +02001852 /* inserting list without its keys is not supported */
1853 assert((parent || first_sibling_p) && node && (node->hash || !node->schema));
Michal Vaskof756c942020-11-06 17:21:37 +01001854 assert(!parent || !parent->schema ||
1855 (parent->schema->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_ACTION | LYS_NOTIF)));
Michal Vasko9b368d32020-02-14 13:53:31 +01001856
Michal Vaskob104f112020-07-17 09:54:54 +02001857 if (!parent && first_sibling_p && (*first_sibling_p) && (*first_sibling_p)->parent) {
1858 parent = (struct lyd_node *)(*first_sibling_p)->parent;
Michal Vasko9b368d32020-02-14 13:53:31 +01001859 }
Michal Vasko90932a92020-02-12 14:33:03 +01001860
Michal Vaskob104f112020-07-17 09:54:54 +02001861 /* get first sibling */
1862 first_sibling = parent ? ((struct lyd_node_inner *)parent)->child : *first_sibling_p;
Michal Vasko9f96a052020-03-10 09:41:45 +01001863
Michal Vaskob104f112020-07-17 09:54:54 +02001864 /* find the anchor, our next node, so we can insert before it */
1865 anchor = lyd_insert_get_next_anchor(first_sibling, node);
1866 if (anchor) {
1867 lyd_insert_before_node(anchor, node);
Michal Vasko26123192020-11-09 21:02:34 +01001868 if (!parent && (*first_sibling_p == anchor)) {
1869 /* move first sibling */
1870 *first_sibling_p = node;
1871 }
Michal Vaskob104f112020-07-17 09:54:54 +02001872 } else if (first_sibling) {
1873 lyd_insert_after_node(first_sibling->prev, node);
1874 } else if (parent) {
1875 lyd_insert_only_child(parent, node);
Michal Vasko90932a92020-02-12 14:33:03 +01001876 } else {
Michal Vaskob104f112020-07-17 09:54:54 +02001877 *first_sibling_p = node;
1878 }
1879
1880 /* insert into parent HT */
1881 lyd_insert_hash(node);
1882
1883 /* finish hashes for our parent, if needed and possible */
Michal Vasko9e8de2d2020-09-01 08:17:10 +02001884 if (node->schema && (node->schema->flags & LYS_KEY) && parent && lyd_insert_has_keys(parent)) {
Michal Vaskob104f112020-07-17 09:54:54 +02001885 lyd_hash(parent);
1886
1887 /* now we can insert even the list into its parent HT */
1888 lyd_insert_hash(parent);
Michal Vasko90932a92020-02-12 14:33:03 +01001889 }
Michal Vasko90932a92020-02-12 14:33:03 +01001890}
1891
Michal Vaskof03ed032020-03-04 13:31:44 +01001892static LY_ERR
1893lyd_insert_check_schema(const struct lysc_node *parent, const struct lysc_node *schema)
1894{
1895 const struct lysc_node *par2;
1896
1897 assert(schema);
Michal Vasko62ed12d2020-05-21 10:08:25 +02001898 assert(!parent || !(parent->nodetype & (LYS_CASE | LYS_CHOICE)));
Michal Vaskof03ed032020-03-04 13:31:44 +01001899
1900 /* find schema parent */
Michal Vasko62ed12d2020-05-21 10:08:25 +02001901 par2 = lysc_data_parent(schema);
Michal Vaskof03ed032020-03-04 13:31:44 +01001902
1903 if (parent) {
1904 /* inner node */
1905 if (par2 != parent) {
Michal Vaskob104f112020-07-17 09:54:54 +02001906 LOGERR(schema->module->ctx, LY_EINVAL, "Cannot insert, parent of \"%s\" is not \"%s\".", schema->name,
Michal Vasko69730152020-10-09 16:30:07 +02001907 parent->name);
Michal Vaskof03ed032020-03-04 13:31:44 +01001908 return LY_EINVAL;
1909 }
1910 } else {
1911 /* top-level node */
1912 if (par2) {
Radek Krejcif6d14cb2020-07-02 16:11:45 +02001913 LOGERR(schema->module->ctx, LY_EINVAL, "Cannot insert, node \"%s\" is not top-level.", schema->name);
Michal Vaskof03ed032020-03-04 13:31:44 +01001914 return LY_EINVAL;
1915 }
1916 }
1917
1918 return LY_SUCCESS;
1919}
1920
1921API LY_ERR
Michal Vaskob104f112020-07-17 09:54:54 +02001922lyd_insert_child(struct lyd_node *parent, struct lyd_node *node)
Michal Vaskof03ed032020-03-04 13:31:44 +01001923{
1924 struct lyd_node *iter;
1925
Michal Vasko654bc852020-06-23 13:28:06 +02001926 LY_CHECK_ARG_RET(NULL, parent, node, parent->schema->nodetype & LYD_NODE_INNER, LY_EINVAL);
Michal Vaskof03ed032020-03-04 13:31:44 +01001927
1928 LY_CHECK_RET(lyd_insert_check_schema(parent->schema, node->schema));
1929
1930 if (node->schema->flags & LYS_KEY) {
1931 LOGERR(parent->schema->module->ctx, LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
1932 return LY_EINVAL;
1933 }
1934
1935 if (node->parent || node->prev->next) {
1936 lyd_unlink_tree(node);
1937 }
1938
1939 while (node) {
1940 iter = node->next;
1941 lyd_unlink_tree(node);
1942 lyd_insert_node(parent, NULL, node);
1943 node = iter;
1944 }
1945 return LY_SUCCESS;
1946}
1947
1948API LY_ERR
Michal Vaskob104f112020-07-17 09:54:54 +02001949lyd_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, struct lyd_node **first)
Michal Vaskob1b5c262020-03-05 14:29:47 +01001950{
1951 struct lyd_node *iter;
1952
Michal Vaskob104f112020-07-17 09:54:54 +02001953 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Michal Vaskob1b5c262020-03-05 14:29:47 +01001954
Michal Vaskob104f112020-07-17 09:54:54 +02001955 if (sibling) {
1956 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskob1b5c262020-03-05 14:29:47 +01001957 }
1958
1959 if (node->parent || node->prev->next) {
1960 lyd_unlink_tree(node);
1961 }
1962
1963 while (node) {
Michal Vaskob104f112020-07-17 09:54:54 +02001964 if (node->schema->flags & LYS_KEY) {
Michal Vaskob7be7a82020-08-20 09:09:04 +02001965 LOGERR(LYD_CTX(node), LY_EINVAL, "Cannot insert key \"%s\".", node->schema->name);
Michal Vaskob104f112020-07-17 09:54:54 +02001966 return LY_EINVAL;
1967 }
1968
Michal Vaskob1b5c262020-03-05 14:29:47 +01001969 iter = node->next;
1970 lyd_unlink_tree(node);
1971 lyd_insert_node(NULL, &sibling, node);
1972 node = iter;
1973 }
Michal Vaskob1b5c262020-03-05 14:29:47 +01001974
Michal Vaskob104f112020-07-17 09:54:54 +02001975 if (first) {
1976 /* find the first sibling */
1977 *first = sibling;
1978 while ((*first)->prev->next) {
1979 *first = (*first)->prev;
Michal Vasko0249f7c2020-03-05 16:36:40 +01001980 }
1981 }
1982
1983 return LY_SUCCESS;
1984}
1985
Michal Vaskob1b5c262020-03-05 14:29:47 +01001986API LY_ERR
Michal Vaskof03ed032020-03-04 13:31:44 +01001987lyd_insert_before(struct lyd_node *sibling, struct lyd_node *node)
1988{
1989 struct lyd_node *iter;
1990
1991 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
1992
Michal Vasko62ed12d2020-05-21 10:08:25 +02001993 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskof03ed032020-03-04 13:31:44 +01001994
Michal Vaskob104f112020-07-17 09:54:54 +02001995 if (!(node->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(node->schema->flags & LYS_ORDBY_USER)) {
Michal Vaskob7be7a82020-08-20 09:09:04 +02001996 LOGERR(LYD_CTX(sibling), LY_EINVAL, "Can be used only for user-ordered nodes.");
Michal Vaskof03ed032020-03-04 13:31:44 +01001997 return LY_EINVAL;
1998 }
1999
2000 if (node->parent || node->prev->next) {
2001 lyd_unlink_tree(node);
2002 }
2003
2004 /* insert in reverse order to get the original order */
2005 node = node->prev;
2006 while (node) {
2007 iter = node->prev;
2008 lyd_unlink_tree(node);
2009
2010 lyd_insert_before_node(sibling, node);
Michal Vasko751cb4d2020-07-14 12:25:28 +02002011 lyd_insert_hash(node);
2012
Michal Vaskof03ed032020-03-04 13:31:44 +01002013 /* move the anchor accordingly */
2014 sibling = node;
2015
2016 node = (iter == node) ? NULL : iter;
2017 }
2018 return LY_SUCCESS;
2019}
2020
2021API LY_ERR
2022lyd_insert_after(struct lyd_node *sibling, struct lyd_node *node)
2023{
2024 struct lyd_node *iter;
2025
2026 LY_CHECK_ARG_RET(NULL, sibling, node, LY_EINVAL);
2027
Michal Vasko62ed12d2020-05-21 10:08:25 +02002028 LY_CHECK_RET(lyd_insert_check_schema(lysc_data_parent(sibling->schema), node->schema));
Michal Vaskof03ed032020-03-04 13:31:44 +01002029
Michal Vaskob104f112020-07-17 09:54:54 +02002030 if (!(node->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(node->schema->flags & LYS_ORDBY_USER)) {
Michal Vaskob7be7a82020-08-20 09:09:04 +02002031 LOGERR(LYD_CTX(sibling), LY_EINVAL, "Can be used only for user-ordered nodes.");
Michal Vaskof03ed032020-03-04 13:31:44 +01002032 return LY_EINVAL;
2033 }
2034
2035 if (node->parent || node->prev->next) {
2036 lyd_unlink_tree(node);
2037 }
2038
2039 while (node) {
2040 iter = node->next;
2041 lyd_unlink_tree(node);
2042
2043 lyd_insert_after_node(sibling, node);
Michal Vasko751cb4d2020-07-14 12:25:28 +02002044 lyd_insert_hash(node);
2045
Michal Vaskof03ed032020-03-04 13:31:44 +01002046 /* move the anchor accordingly */
2047 sibling = node;
2048
2049 node = iter;
2050 }
2051 return LY_SUCCESS;
2052}
2053
2054API void
2055lyd_unlink_tree(struct lyd_node *node)
2056{
2057 struct lyd_node *iter;
2058
2059 if (!node) {
2060 return;
2061 }
2062
Michal Vaskob104f112020-07-17 09:54:54 +02002063 /* update hashes while still linked into the tree */
2064 lyd_unlink_hash(node);
2065
Michal Vaskof03ed032020-03-04 13:31:44 +01002066 /* unlink from siblings */
2067 if (node->prev->next) {
2068 node->prev->next = node->next;
2069 }
2070 if (node->next) {
2071 node->next->prev = node->prev;
2072 } else {
2073 /* unlinking the last node */
2074 if (node->parent) {
2075 iter = node->parent->child;
2076 } else {
2077 iter = node->prev;
2078 while (iter->prev != node) {
2079 iter = iter->prev;
2080 }
2081 }
2082 /* update the "last" pointer from the first node */
2083 iter->prev = node->prev;
2084 }
2085
2086 /* unlink from parent */
2087 if (node->parent) {
2088 if (node->parent->child == node) {
2089 /* the node is the first child */
2090 node->parent->child = node->next;
2091 }
2092
Michal Vaskoab49dbe2020-07-17 12:32:47 +02002093 /* check for NP container whether its last non-default node is not being unlinked */
Michal Vasko69730152020-10-09 16:30:07 +02002094 if (node->parent->schema && (node->parent->schema->nodetype == LYS_CONTAINER) &&
2095 !(node->parent->flags & LYD_DEFAULT) && !(node->parent->schema->flags & LYS_PRESENCE)) {
Michal Vaskoab49dbe2020-07-17 12:32:47 +02002096 LY_LIST_FOR(node->parent->child, iter) {
2097 if ((iter != node) && !(iter->flags & LYD_DEFAULT)) {
2098 break;
2099 }
2100 }
2101 if (!iter) {
2102 node->parent->flags |= LYD_DEFAULT;
2103 }
2104 }
2105
Michal Vaskof03ed032020-03-04 13:31:44 +01002106 /* check for keyless list and update its hash */
2107 for (iter = (struct lyd_node *)node->parent; iter; iter = (struct lyd_node *)iter->parent) {
Michal Vasko413c7f22020-05-05 12:34:06 +02002108 if (iter->schema && (iter->schema->flags & LYS_KEYLESS)) {
Michal Vaskof03ed032020-03-04 13:31:44 +01002109 lyd_hash(iter);
2110 }
2111 }
2112
2113 node->parent = NULL;
2114 }
2115
2116 node->next = NULL;
2117 node->prev = node;
2118}
2119
Michal Vaskoa5da3292020-08-12 13:10:50 +02002120void
Michal Vasko871a0252020-11-11 18:35:24 +01002121lyd_insert_meta(struct lyd_node *parent, struct lyd_meta *meta, ly_bool clear_dflt)
Radek Krejci1798aae2020-07-14 13:26:06 +02002122{
2123 struct lyd_meta *last, *iter;
2124
2125 assert(parent);
Michal Vaskoa5da3292020-08-12 13:10:50 +02002126
2127 if (!meta) {
2128 return;
2129 }
Radek Krejci1798aae2020-07-14 13:26:06 +02002130
2131 for (iter = meta; iter; iter = iter->next) {
2132 iter->parent = parent;
2133 }
2134
2135 /* insert as the last attribute */
2136 if (parent->meta) {
Radek Krejci1e008d22020-08-17 11:37:37 +02002137 for (last = parent->meta; last->next; last = last->next) {}
Radek Krejci1798aae2020-07-14 13:26:06 +02002138 last->next = meta;
2139 } else {
2140 parent->meta = meta;
2141 }
2142
2143 /* remove default flags from NP containers */
Michal Vasko871a0252020-11-11 18:35:24 +01002144 while (clear_dflt && parent && (parent->schema->nodetype == LYS_CONTAINER) && (parent->flags & LYD_DEFAULT)) {
Radek Krejci1798aae2020-07-14 13:26:06 +02002145 parent->flags &= ~LYD_DEFAULT;
2146 parent = (struct lyd_node *)parent->parent;
2147 }
Radek Krejci1798aae2020-07-14 13:26:06 +02002148}
2149
2150LY_ERR
Michal Vasko9f96a052020-03-10 09:41:45 +01002151lyd_create_meta(struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod, const char *name,
Michal Vaskofeca4fb2020-10-05 08:58:40 +02002152 size_t name_len, const char *value, size_t value_len, ly_bool *dynamic, LY_PREFIX_FORMAT format,
Michal Vasko871a0252020-11-11 18:35:24 +01002153 void *prefix_data, uint32_t hints, ly_bool clear_dflt, ly_bool *incomplete)
Michal Vasko90932a92020-02-12 14:33:03 +01002154{
Michal Vaskofeca4fb2020-10-05 08:58:40 +02002155 LY_ERR rc;
Michal Vasko90932a92020-02-12 14:33:03 +01002156 struct lysc_ext_instance *ant = NULL;
Michal Vasko9f96a052020-03-10 09:41:45 +01002157 struct lyd_meta *mt, *last;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002158 LY_ARRAY_COUNT_TYPE u;
Michal Vasko90932a92020-02-12 14:33:03 +01002159
Michal Vasko9f96a052020-03-10 09:41:45 +01002160 assert((parent || meta) && mod);
Michal Vasko6f4cbb62020-02-28 11:15:47 +01002161
Radek Krejci7eb54ba2020-05-18 16:30:04 +02002162 LY_ARRAY_FOR(mod->compiled->exts, u) {
Michal Vasko69730152020-10-09 16:30:07 +02002163 if ((mod->compiled->exts[u].def->plugin == lyext_plugins_internal[LYEXT_PLUGIN_INTERNAL_ANNOTATION].plugin) &&
Radek Krejci7eb54ba2020-05-18 16:30:04 +02002164 !ly_strncmp(mod->compiled->exts[u].argument, name, name_len)) {
Michal Vasko90932a92020-02-12 14:33:03 +01002165 /* we have the annotation definition */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02002166 ant = &mod->compiled->exts[u];
Michal Vasko90932a92020-02-12 14:33:03 +01002167 break;
2168 }
2169 }
2170 if (!ant) {
2171 /* attribute is not defined as a metadata annotation (RFC 7952) */
2172 LOGERR(mod->ctx, LY_EINVAL, "Annotation definition for attribute \"%s:%.*s\" not found.",
2173 mod->name, name_len, name);
2174 return LY_EINVAL;
2175 }
2176
Michal Vasko9f96a052020-03-10 09:41:45 +01002177 mt = calloc(1, sizeof *mt);
2178 LY_CHECK_ERR_RET(!mt, LOGMEM(mod->ctx), LY_EMEM);
2179 mt->parent = parent;
2180 mt->annotation = ant;
Michal Vaskofeca4fb2020-10-05 08:58:40 +02002181 rc = lyd_value_store(mod->ctx, &mt->value, ((struct lyext_metadata *)ant->data)->type, value, value_len, dynamic,
2182 format, prefix_data, hints, parent ? parent->schema : NULL, incomplete, LY_VLOG_NONE, NULL);
2183 LY_CHECK_ERR_RET(rc, free(mt), rc);
Radek Krejci011e4aa2020-09-04 15:22:31 +02002184 rc = lydict_insert(mod->ctx, name, name_len, &mt->name);
2185 LY_CHECK_ERR_RET(rc, free(mt), rc);
Michal Vasko90932a92020-02-12 14:33:03 +01002186
Michal Vasko6f4cbb62020-02-28 11:15:47 +01002187 /* insert as the last attribute */
2188 if (parent) {
Michal Vasko871a0252020-11-11 18:35:24 +01002189 lyd_insert_meta(parent, mt, clear_dflt);
Michal Vasko9f96a052020-03-10 09:41:45 +01002190 } else if (*meta) {
Radek Krejci1e008d22020-08-17 11:37:37 +02002191 for (last = *meta; last->next; last = last->next) {}
Michal Vasko9f96a052020-03-10 09:41:45 +01002192 last->next = mt;
Michal Vasko90932a92020-02-12 14:33:03 +01002193 }
2194
Michal Vasko9f96a052020-03-10 09:41:45 +01002195 if (meta) {
2196 *meta = mt;
Michal Vasko90932a92020-02-12 14:33:03 +01002197 }
Michal Vaskofeca4fb2020-10-05 08:58:40 +02002198 return LY_SUCCESS;
Michal Vasko90932a92020-02-12 14:33:03 +01002199}
2200
Michal Vaskoa5da3292020-08-12 13:10:50 +02002201void
2202lyd_insert_attr(struct lyd_node *parent, struct lyd_attr *attr)
2203{
2204 struct lyd_attr *last, *iter;
2205 struct lyd_node_opaq *opaq;
2206
2207 assert(parent && !parent->schema);
2208
2209 if (!attr) {
2210 return;
2211 }
2212
2213 opaq = (struct lyd_node_opaq *)parent;
2214 for (iter = attr; iter; iter = iter->next) {
2215 iter->parent = opaq;
2216 }
2217
2218 /* insert as the last attribute */
2219 if (opaq->attr) {
Radek Krejci1e008d22020-08-17 11:37:37 +02002220 for (last = opaq->attr; last->next; last = last->next) {}
Michal Vaskoa5da3292020-08-12 13:10:50 +02002221 last->next = attr;
2222 } else {
2223 opaq->attr = attr;
2224 }
2225}
2226
Michal Vasko52927e22020-03-16 17:26:14 +01002227LY_ERR
Michal Vaskofeca4fb2020-10-05 08:58:40 +02002228lyd_create_attr(struct lyd_node *parent, struct lyd_attr **attr, const struct ly_ctx *ctx, const char *name, size_t name_len,
Michal Vasko501af032020-11-11 20:27:44 +01002229 const char *prefix, size_t prefix_len, const char *module_key, size_t module_key_len, const char *value,
2230 size_t value_len, ly_bool *dynamic, LY_PREFIX_FORMAT format, void *val_prefix_data, uint32_t hints)
Michal Vasko52927e22020-03-16 17:26:14 +01002231{
Radek Krejci011e4aa2020-09-04 15:22:31 +02002232 LY_ERR ret = LY_SUCCESS;
Radek Krejci1798aae2020-07-14 13:26:06 +02002233 struct lyd_attr *at, *last;
Michal Vasko52927e22020-03-16 17:26:14 +01002234
2235 assert(ctx && (parent || attr) && (!parent || !parent->schema));
Michal Vaskofeca4fb2020-10-05 08:58:40 +02002236 assert(name && name_len && format);
Michal Vasko52927e22020-03-16 17:26:14 +01002237
2238 if (!value_len) {
2239 value = "";
2240 }
2241
2242 at = calloc(1, sizeof *at);
Michal Vasko6b5cb2a2020-11-11 19:11:21 +01002243 LY_CHECK_ERR_RET(!at, LOGMEM(ctx); ly_free_prefix_data(format, val_prefix_data), LY_EMEM);
Radek Krejcid46e46a2020-09-15 14:22:42 +02002244
Michal Vaskoad92b672020-11-12 13:11:31 +01002245 LY_CHECK_GOTO(ret = lydict_insert(ctx, name, name_len, &at->name.name), finish);
Michal Vasko501af032020-11-11 20:27:44 +01002246 if (prefix_len) {
Michal Vaskoad92b672020-11-12 13:11:31 +01002247 LY_CHECK_GOTO(ret = lydict_insert(ctx, prefix, prefix_len, &at->name.prefix), finish);
Michal Vasko501af032020-11-11 20:27:44 +01002248 }
2249 if (module_key_len) {
Michal Vaskoad92b672020-11-12 13:11:31 +01002250 LY_CHECK_GOTO(ret = lydict_insert(ctx, module_key, module_key_len, &at->name.module_ns), finish);
Michal Vasko501af032020-11-11 20:27:44 +01002251 }
2252
Michal Vasko52927e22020-03-16 17:26:14 +01002253 if (dynamic && *dynamic) {
Radek Krejci011e4aa2020-09-04 15:22:31 +02002254 ret = lydict_insert_zc(ctx, (char *)value, &at->value);
2255 LY_CHECK_GOTO(ret, finish);
Michal Vasko52927e22020-03-16 17:26:14 +01002256 *dynamic = 0;
2257 } else {
Radek Krejci011e4aa2020-09-04 15:22:31 +02002258 LY_CHECK_GOTO(ret = lydict_insert(ctx, value, value_len, &at->value), finish);
Michal Vasko52927e22020-03-16 17:26:14 +01002259 }
Michal Vasko501af032020-11-11 20:27:44 +01002260 at->format = format;
2261 at->val_prefix_data = val_prefix_data;
2262 at->hints = hints;
Michal Vasko52927e22020-03-16 17:26:14 +01002263
2264 /* insert as the last attribute */
2265 if (parent) {
Michal Vaskoa5da3292020-08-12 13:10:50 +02002266 lyd_insert_attr(parent, at);
Michal Vasko52927e22020-03-16 17:26:14 +01002267 } else if (*attr) {
Radek Krejci1e008d22020-08-17 11:37:37 +02002268 for (last = *attr; last->next; last = last->next) {}
Michal Vasko52927e22020-03-16 17:26:14 +01002269 last->next = at;
2270 }
2271
Radek Krejci011e4aa2020-09-04 15:22:31 +02002272finish:
2273 if (ret) {
2274 lyd_free_attr_single(ctx, at);
2275 } else if (attr) {
Michal Vasko52927e22020-03-16 17:26:14 +01002276 *attr = at;
2277 }
2278 return LY_SUCCESS;
2279}
2280
Radek Krejci084289f2019-07-09 17:35:30 +02002281API const struct lyd_node_term *
Michal Vasko004d3152020-06-11 19:59:22 +02002282lyd_target(const struct ly_path *path, const struct lyd_node *tree)
Radek Krejci084289f2019-07-09 17:35:30 +02002283{
Michal Vasko004d3152020-06-11 19:59:22 +02002284 struct lyd_node *target;
Radek Krejci084289f2019-07-09 17:35:30 +02002285
Michal Vasko004d3152020-06-11 19:59:22 +02002286 if (ly_path_eval(path, tree, &target)) {
2287 return NULL;
Radek Krejci084289f2019-07-09 17:35:30 +02002288 }
2289
Michal Vasko004d3152020-06-11 19:59:22 +02002290 return (struct lyd_node_term *)target;
Radek Krejci084289f2019-07-09 17:35:30 +02002291}
2292
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002293API LY_ERR
Radek Krejci1deb5be2020-08-26 16:43:36 +02002294lyd_compare_single(const struct lyd_node *node1, const struct lyd_node *node2, uint32_t options)
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002295{
2296 const struct lyd_node *iter1, *iter2;
2297 struct lyd_node_term *term1, *term2;
2298 struct lyd_node_any *any1, *any2;
Michal Vasko52927e22020-03-16 17:26:14 +01002299 struct lyd_node_opaq *opaq1, *opaq2;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002300 size_t len1, len2;
Radek Krejci084289f2019-07-09 17:35:30 +02002301
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002302 if (!node1 || !node2) {
2303 if (node1 == node2) {
2304 return LY_SUCCESS;
2305 } else {
2306 return LY_ENOT;
2307 }
2308 }
2309
Michal Vaskob7be7a82020-08-20 09:09:04 +02002310 if ((LYD_CTX(node1) != LYD_CTX(node2)) || (node1->schema != node2->schema)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002311 return LY_ENOT;
2312 }
2313
2314 if (node1->hash != node2->hash) {
2315 return LY_ENOT;
2316 }
Michal Vasko52927e22020-03-16 17:26:14 +01002317 /* 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 +02002318
Michal Vasko52927e22020-03-16 17:26:14 +01002319 if (!node1->schema) {
2320 opaq1 = (struct lyd_node_opaq *)node1;
2321 opaq2 = (struct lyd_node_opaq *)node2;
Michal Vaskoad92b672020-11-12 13:11:31 +01002322 if ((opaq1->name.name != opaq2->name.name) || (opaq1->format != opaq2->format) ||
2323 (opaq1->name.module_ns != opaq2->name.module_ns)) {
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002324 return LY_ENOT;
2325 }
Michal Vasko52927e22020-03-16 17:26:14 +01002326 switch (opaq1->format) {
Michal Vasko6b5cb2a2020-11-11 19:11:21 +01002327 case LY_PREF_XML:
2328 if (lyxml_value_compare(LYD_CTX(node1), opaq1->value, opaq1->val_prefix_data, opaq2->value, opaq2->val_prefix_data)) {
Michal Vasko52927e22020-03-16 17:26:14 +01002329 return LY_ENOT;
2330 }
2331 break;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +01002332 case LY_PREF_JSON:
Radek Krejci1798aae2020-07-14 13:26:06 +02002333 /* prefixes in JSON are unique, so it is not necessary to canonize the values */
2334 if (strcmp(opaq1->value, opaq2->value)) {
2335 return LY_ENOT;
2336 }
2337 break;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +01002338 default:
Michal Vasko52927e22020-03-16 17:26:14 +01002339 /* not allowed */
Michal Vaskob7be7a82020-08-20 09:09:04 +02002340 LOGINT(LYD_CTX(node1));
Michal Vasko52927e22020-03-16 17:26:14 +01002341 return LY_EINT;
2342 }
2343 if (options & LYD_COMPARE_FULL_RECURSION) {
2344 iter1 = opaq1->child;
2345 iter2 = opaq2->child;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002346 goto all_children_compare;
Michal Vasko52927e22020-03-16 17:26:14 +01002347 }
2348 return LY_SUCCESS;
2349 } else {
2350 switch (node1->schema->nodetype) {
2351 case LYS_LEAF:
2352 case LYS_LEAFLIST:
2353 if (options & LYD_COMPARE_DEFAULTS) {
2354 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
2355 return LY_ENOT;
2356 }
2357 }
2358
Michal Vasko1a2bf2e2020-06-16 13:07:48 +02002359 term1 = (struct lyd_node_term *)node1;
2360 term2 = (struct lyd_node_term *)node2;
2361 if (term1->value.realtype != term2->value.realtype) {
2362 return LY_ENOT;
2363 }
Michal Vasko52927e22020-03-16 17:26:14 +01002364
Michal Vasko1a2bf2e2020-06-16 13:07:48 +02002365 return term1->value.realtype->plugin->compare(&term1->value, &term2->value);
Michal Vasko52927e22020-03-16 17:26:14 +01002366 case LYS_CONTAINER:
2367 if (options & LYD_COMPARE_DEFAULTS) {
2368 if ((node1->flags & LYD_DEFAULT) != (node2->flags & LYD_DEFAULT)) {
2369 return LY_ENOT;
2370 }
2371 }
2372 if (options & LYD_COMPARE_FULL_RECURSION) {
Michal Vasko22df3f02020-08-24 13:29:22 +02002373 iter1 = ((struct lyd_node_inner *)node1)->child;
2374 iter2 = ((struct lyd_node_inner *)node2)->child;
Michal Vasko52927e22020-03-16 17:26:14 +01002375 goto all_children_compare;
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002376 }
2377 return LY_SUCCESS;
Michal Vasko1bf09392020-03-27 12:38:10 +01002378 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01002379 case LYS_ACTION:
2380 if (options & LYD_COMPARE_FULL_RECURSION) {
2381 /* TODO action/RPC
2382 goto all_children_compare;
2383 */
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002384 }
2385 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01002386 case LYS_NOTIF:
2387 if (options & LYD_COMPARE_FULL_RECURSION) {
2388 /* TODO Notification
2389 goto all_children_compare;
2390 */
2391 }
2392 return LY_SUCCESS;
2393 case LYS_LIST:
Michal Vasko22df3f02020-08-24 13:29:22 +02002394 iter1 = ((struct lyd_node_inner *)node1)->child;
2395 iter2 = ((struct lyd_node_inner *)node2)->child;
Michal Vasko52927e22020-03-16 17:26:14 +01002396
2397 if (!(node1->schema->flags & LYS_KEYLESS) && !(options & LYD_COMPARE_FULL_RECURSION)) {
2398 /* lists with keys, their equivalence is based on their keys */
Michal Vasko22df3f02020-08-24 13:29:22 +02002399 for (struct lysc_node *key = ((struct lysc_node_list *)node1->schema)->child;
Michal Vaskoc57d9a92020-06-23 13:28:27 +02002400 key && (key->flags & LYS_KEY);
Michal Vasko52927e22020-03-16 17:26:14 +01002401 key = key->next) {
Michal Vasko8f359bf2020-07-28 10:41:15 +02002402 if (lyd_compare_single(iter1, iter2, options)) {
Michal Vasko52927e22020-03-16 17:26:14 +01002403 return LY_ENOT;
2404 }
2405 iter1 = iter1->next;
2406 iter2 = iter2->next;
2407 }
2408 } else {
2409 /* lists without keys, their equivalence is based on equivalence of all the children (both direct and indirect) */
2410
Radek Krejci0f969882020-08-21 16:56:47 +02002411all_children_compare:
Michal Vasko52927e22020-03-16 17:26:14 +01002412 if (!iter1 && !iter2) {
2413 /* no children, nothing to compare */
2414 return LY_SUCCESS;
2415 }
2416
Michal Vaskod989ba02020-08-24 10:59:24 +02002417 for ( ; iter1 && iter2; iter1 = iter1->next, iter2 = iter2->next) {
Michal Vasko8f359bf2020-07-28 10:41:15 +02002418 if (lyd_compare_single(iter1, iter2, options | LYD_COMPARE_FULL_RECURSION)) {
Michal Vasko52927e22020-03-16 17:26:14 +01002419 return LY_ENOT;
2420 }
2421 }
2422 if (iter1 || iter2) {
2423 return LY_ENOT;
2424 }
2425 }
2426 return LY_SUCCESS;
2427 case LYS_ANYXML:
2428 case LYS_ANYDATA:
Michal Vasko22df3f02020-08-24 13:29:22 +02002429 any1 = (struct lyd_node_any *)node1;
2430 any2 = (struct lyd_node_any *)node2;
Michal Vasko52927e22020-03-16 17:26:14 +01002431
2432 if (any1->value_type != any2->value_type) {
2433 return LY_ENOT;
2434 }
2435 switch (any1->value_type) {
2436 case LYD_ANYDATA_DATATREE:
2437 iter1 = any1->value.tree;
2438 iter2 = any2->value.tree;
2439 goto all_children_compare;
2440 case LYD_ANYDATA_STRING:
2441 case LYD_ANYDATA_XML:
2442 case LYD_ANYDATA_JSON:
2443 len1 = strlen(any1->value.str);
2444 len2 = strlen(any2->value.str);
Michal Vasko69730152020-10-09 16:30:07 +02002445 if ((len1 != len2) || strcmp(any1->value.str, any2->value.str)) {
Michal Vasko52927e22020-03-16 17:26:14 +01002446 return LY_ENOT;
2447 }
2448 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01002449 case LYD_ANYDATA_LYB:
Michal Vasko60ea6352020-06-29 13:39:39 +02002450 len1 = lyd_lyb_data_length(any1->value.mem);
2451 len2 = lyd_lyb_data_length(any2->value.mem);
Michal Vasko69730152020-10-09 16:30:07 +02002452 if ((len1 != len2) || memcmp(any1->value.mem, any2->value.mem, len1)) {
Michal Vasko52927e22020-03-16 17:26:14 +01002453 return LY_ENOT;
2454 }
2455 return LY_SUCCESS;
Michal Vasko52927e22020-03-16 17:26:14 +01002456 }
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002457 }
2458 }
2459
Michal Vaskob7be7a82020-08-20 09:09:04 +02002460 LOGINT(LYD_CTX(node1));
Radek Krejci1f05b6a2019-07-18 16:15:06 +02002461 return LY_EINT;
2462}
Radek Krejci22ebdba2019-07-25 13:59:43 +02002463
Michal Vasko21725742020-06-29 11:49:25 +02002464API LY_ERR
Radek Krejci1deb5be2020-08-26 16:43:36 +02002465lyd_compare_siblings(const struct lyd_node *node1, const struct lyd_node *node2, uint32_t options)
Michal Vasko8f359bf2020-07-28 10:41:15 +02002466{
Michal Vaskod989ba02020-08-24 10:59:24 +02002467 for ( ; node1 && node2; node1 = node1->next, node2 = node2->next) {
Michal Vasko8f359bf2020-07-28 10:41:15 +02002468 LY_CHECK_RET(lyd_compare_single(node1, node2, options));
2469 }
2470
Michal Vasko11a81432020-07-28 16:31:29 +02002471 if (node1 == node2) {
2472 return LY_SUCCESS;
Michal Vasko8f359bf2020-07-28 10:41:15 +02002473 }
Michal Vasko11a81432020-07-28 16:31:29 +02002474 return LY_ENOT;
Michal Vasko8f359bf2020-07-28 10:41:15 +02002475}
2476
2477API LY_ERR
Michal Vasko21725742020-06-29 11:49:25 +02002478lyd_compare_meta(const struct lyd_meta *meta1, const struct lyd_meta *meta2)
2479{
2480 if (!meta1 || !meta2) {
2481 if (meta1 == meta2) {
2482 return LY_SUCCESS;
2483 } else {
2484 return LY_ENOT;
2485 }
2486 }
2487
Michal Vaskoa8083062020-11-06 17:22:10 +01002488 if ((meta1->annotation->module->ctx != meta2->annotation->module->ctx) || (meta1->annotation != meta2->annotation)) {
Michal Vasko21725742020-06-29 11:49:25 +02002489 return LY_ENOT;
2490 }
2491
2492 if (meta1->value.realtype != meta2->value.realtype) {
2493 return LY_ENOT;
2494 }
2495
2496 return meta1->value.realtype->plugin->compare(&meta1->value, &meta2->value);
2497}
2498
Radek Krejci22ebdba2019-07-25 13:59:43 +02002499/**
Michal Vasko52927e22020-03-16 17:26:14 +01002500 * @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 +02002501 *
2502 * 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 +02002503 *
2504 * @param[in] node Original node to duplicate
2505 * @param[in] parent Parent to insert into, NULL for top-level sibling.
2506 * @param[in,out] first First sibling, NULL if no top-level sibling exist yet. Can be also NULL if @p parent is set.
2507 * @param[in] options Bitmask of options flags, see @ref dupoptions.
2508 * @param[out] dup_p Pointer where the created duplicated node is placed (besides connecting it int @p parent / @p first sibling).
2509 * @return LY_ERR value
Radek Krejci22ebdba2019-07-25 13:59:43 +02002510 */
Michal Vasko52927e22020-03-16 17:26:14 +01002511static LY_ERR
Radek Krejci1deb5be2020-08-26 16:43:36 +02002512lyd_dup_r(const struct lyd_node *node, struct lyd_node *parent, struct lyd_node **first, uint32_t options,
Radek Krejci0f969882020-08-21 16:56:47 +02002513 struct lyd_node **dup_p)
Radek Krejci22ebdba2019-07-25 13:59:43 +02002514{
Michal Vasko52927e22020-03-16 17:26:14 +01002515 LY_ERR ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002516 struct lyd_node *dup = NULL;
Michal Vasko61551fa2020-07-09 15:45:45 +02002517 struct lyd_meta *meta;
2518 struct lyd_node_any *any;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002519
Michal Vasko52927e22020-03-16 17:26:14 +01002520 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002521
Michal Vasko52927e22020-03-16 17:26:14 +01002522 if (!node->schema) {
2523 dup = calloc(1, sizeof(struct lyd_node_opaq));
2524 } else {
2525 switch (node->schema->nodetype) {
Michal Vasko1bf09392020-03-27 12:38:10 +01002526 case LYS_RPC:
Michal Vasko52927e22020-03-16 17:26:14 +01002527 case LYS_ACTION:
2528 case LYS_NOTIF:
2529 case LYS_CONTAINER:
2530 case LYS_LIST:
2531 dup = calloc(1, sizeof(struct lyd_node_inner));
2532 break;
2533 case LYS_LEAF:
2534 case LYS_LEAFLIST:
2535 dup = calloc(1, sizeof(struct lyd_node_term));
2536 break;
2537 case LYS_ANYDATA:
2538 case LYS_ANYXML:
2539 dup = calloc(1, sizeof(struct lyd_node_any));
2540 break;
2541 default:
Michal Vaskob7be7a82020-08-20 09:09:04 +02002542 LOGINT(LYD_CTX(node));
Michal Vasko52927e22020-03-16 17:26:14 +01002543 ret = LY_EINT;
2544 goto error;
2545 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02002546 }
Michal Vaskob7be7a82020-08-20 09:09:04 +02002547 LY_CHECK_ERR_GOTO(!dup, LOGMEM(LYD_CTX(node)); ret = LY_EMEM, error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002548
Michal Vaskof6df0a02020-06-16 13:08:34 +02002549 if (options & LYD_DUP_WITH_FLAGS) {
2550 dup->flags = node->flags;
2551 } else {
2552 dup->flags = (node->flags & LYD_DEFAULT) | LYD_NEW;
2553 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02002554 dup->schema = node->schema;
Michal Vasko52927e22020-03-16 17:26:14 +01002555 dup->prev = dup;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002556
Michal Vasko25a32822020-07-09 15:48:22 +02002557 /* duplicate metadata */
2558 if (!(options & LYD_DUP_NO_META)) {
2559 LY_LIST_FOR(node->meta, meta) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002560 LY_CHECK_GOTO(ret = lyd_dup_meta_single(meta, dup, NULL), error);
Michal Vasko25a32822020-07-09 15:48:22 +02002561 }
2562 }
Radek Krejci22ebdba2019-07-25 13:59:43 +02002563
2564 /* nodetype-specific work */
Michal Vasko52927e22020-03-16 17:26:14 +01002565 if (!dup->schema) {
2566 struct lyd_node_opaq *opaq = (struct lyd_node_opaq *)dup;
2567 struct lyd_node_opaq *orig = (struct lyd_node_opaq *)node;
2568 struct lyd_node *child;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002569
2570 if (options & LYD_DUP_RECURSIVE) {
2571 /* duplicate all the children */
2572 LY_LIST_FOR(orig->child, child) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002573 LY_CHECK_GOTO(ret = lyd_dup_r(child, dup, NULL, options, NULL), error);
Michal Vasko52927e22020-03-16 17:26:14 +01002574 }
2575 }
Michal Vaskoad92b672020-11-12 13:11:31 +01002576 LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), orig->name.name, 0, &opaq->name.name), error);
Michal Vasko52927e22020-03-16 17:26:14 +01002577 opaq->format = orig->format;
Michal Vaskoad92b672020-11-12 13:11:31 +01002578 if (orig->name.prefix) {
2579 LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), orig->name.prefix, 0, &opaq->name.prefix), error);
Michal Vasko52927e22020-03-16 17:26:14 +01002580 }
Michal Vaskoad92b672020-11-12 13:11:31 +01002581 LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), orig->name.module_ns, 0, &opaq->name.module_ns), error);
Michal Vasko6b5cb2a2020-11-11 19:11:21 +01002582 if (orig->val_prefix_data) {
2583 ret = ly_dup_prefix_data(LYD_CTX(node), opaq->format, orig->val_prefix_data, &opaq->val_prefix_data);
2584 LY_CHECK_GOTO(ret, error);
Michal Vasko52927e22020-03-16 17:26:14 +01002585 }
Radek Krejci011e4aa2020-09-04 15:22:31 +02002586 LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), orig->value, 0, &opaq->value), error);
Michal Vasko52927e22020-03-16 17:26:14 +01002587 opaq->ctx = orig->ctx;
2588 } else if (dup->schema->nodetype & LYD_NODE_TERM) {
2589 struct lyd_node_term *term = (struct lyd_node_term *)dup;
2590 struct lyd_node_term *orig = (struct lyd_node_term *)node;
2591
2592 term->hash = orig->hash;
Michal Vaskob7be7a82020-08-20 09:09:04 +02002593 LY_CHECK_ERR_GOTO(orig->value.realtype->plugin->duplicate(LYD_CTX(node), &orig->value, &term->value),
Michal Vasko69730152020-10-09 16:30:07 +02002594 LOGERR(LYD_CTX(node), LY_EINT, "Value duplication failed."); ret = LY_EINT, error);
Michal Vasko52927e22020-03-16 17:26:14 +01002595 } else if (dup->schema->nodetype & LYD_NODE_INNER) {
2596 struct lyd_node_inner *orig = (struct lyd_node_inner *)node;
2597 struct lyd_node *child;
2598
2599 if (options & LYD_DUP_RECURSIVE) {
2600 /* duplicate all the children */
2601 LY_LIST_FOR(orig->child, child) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002602 LY_CHECK_GOTO(ret = lyd_dup_r(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002603 }
Michal Vasko69730152020-10-09 16:30:07 +02002604 } else if ((dup->schema->nodetype == LYS_LIST) && !(dup->schema->flags & LYS_KEYLESS)) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002605 /* always duplicate keys of a list */
Radek Krejci22ebdba2019-07-25 13:59:43 +02002606 child = orig->child;
Michal Vasko52927e22020-03-16 17:26:14 +01002607 for (struct lysc_node *key = ((struct lysc_node_list *)dup->schema)->child;
Michal Vaskoc57d9a92020-06-23 13:28:27 +02002608 key && (key->flags & LYS_KEY);
Radek Krejci0fe9b512019-07-26 17:51:05 +02002609 key = key->next) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002610 if (!child) {
2611 /* possibly not keys are present in filtered tree */
2612 break;
Radek Krejci0fe9b512019-07-26 17:51:05 +02002613 } else if (child->schema != key) {
2614 /* possibly not all keys are present in filtered tree,
2615 * but there can be also some non-key nodes */
2616 continue;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002617 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002618 LY_CHECK_GOTO(ret = lyd_dup_r(child, dup, NULL, options, NULL), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002619 child = child->next;
2620 }
2621 }
2622 lyd_hash(dup);
2623 } else if (dup->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko61551fa2020-07-09 15:45:45 +02002624 dup->hash = node->hash;
2625 any = (struct lyd_node_any *)node;
2626 LY_CHECK_GOTO(ret = lyd_any_copy_value(dup, &any->value, any->value_type), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002627 }
2628
Michal Vasko52927e22020-03-16 17:26:14 +01002629 /* insert */
2630 lyd_insert_node(parent, first, dup);
Michal Vasko52927e22020-03-16 17:26:14 +01002631
2632 if (dup_p) {
2633 *dup_p = dup;
2634 }
2635 return LY_SUCCESS;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002636
2637error:
Michal Vasko52927e22020-03-16 17:26:14 +01002638 lyd_free_tree(dup);
2639 return ret;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002640}
2641
Michal Vasko3a41dff2020-07-15 14:30:28 +02002642static LY_ERR
2643lyd_dup_get_local_parent(const struct lyd_node *node, const struct lyd_node_inner *parent, struct lyd_node **dup_parent,
Radek Krejci0f969882020-08-21 16:56:47 +02002644 struct lyd_node_inner **local_parent)
Radek Krejci22ebdba2019-07-25 13:59:43 +02002645{
Michal Vasko3a41dff2020-07-15 14:30:28 +02002646 const struct lyd_node_inner *orig_parent, *iter;
Radek Krejci857189e2020-09-01 13:26:36 +02002647 ly_bool repeat = 1;
Michal Vasko3a41dff2020-07-15 14:30:28 +02002648
2649 *dup_parent = NULL;
2650 *local_parent = NULL;
2651
2652 for (orig_parent = node->parent; repeat && orig_parent; orig_parent = orig_parent->parent) {
2653 if (parent && (parent->schema == orig_parent->schema)) {
2654 /* stop creating parents, connect what we have into the provided parent */
2655 iter = parent;
2656 repeat = 0;
2657 } else {
2658 iter = NULL;
2659 LY_CHECK_RET(lyd_dup_r((struct lyd_node *)orig_parent, NULL, (struct lyd_node **)&iter, 0,
Radek Krejci0f969882020-08-21 16:56:47 +02002660 (struct lyd_node **)&iter));
Michal Vasko3a41dff2020-07-15 14:30:28 +02002661 }
2662 if (!*local_parent) {
2663 *local_parent = (struct lyd_node_inner *)iter;
2664 }
2665 if (iter->child) {
2666 /* 1) list - add after keys
2667 * 2) provided parent with some children */
2668 iter->child->prev->next = *dup_parent;
2669 if (*dup_parent) {
2670 (*dup_parent)->prev = iter->child->prev;
2671 iter->child->prev = *dup_parent;
2672 }
2673 } else {
2674 ((struct lyd_node_inner *)iter)->child = *dup_parent;
2675 }
2676 if (*dup_parent) {
2677 (*dup_parent)->parent = (struct lyd_node_inner *)iter;
2678 }
2679 *dup_parent = (struct lyd_node *)iter;
2680 }
2681
2682 if (repeat && parent) {
2683 /* given parent and created parents chain actually do not interconnect */
Michal Vaskob7be7a82020-08-20 09:09:04 +02002684 LOGERR(LYD_CTX(node), LY_EINVAL,
Michal Vasko69730152020-10-09 16:30:07 +02002685 "Invalid argument parent (%s()) - does not interconnect with the created node's parents chain.", __func__);
Michal Vasko3a41dff2020-07-15 14:30:28 +02002686 return LY_EINVAL;
2687 }
2688
2689 return LY_SUCCESS;
2690}
2691
2692static LY_ERR
Radek Krejci857189e2020-09-01 13:26:36 +02002693lyd_dup(const struct lyd_node *node, struct lyd_node_inner *parent, uint32_t options, ly_bool nosiblings, struct lyd_node **dup)
Michal Vasko3a41dff2020-07-15 14:30:28 +02002694{
2695 LY_ERR rc;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002696 const struct lyd_node *orig; /* original node to be duplicated */
2697 struct lyd_node *first = NULL; /* the first duplicated node, this is returned */
Radek Krejci22ebdba2019-07-25 13:59:43 +02002698 struct lyd_node *top = NULL; /* the most higher created node */
2699 struct lyd_node_inner *local_parent = NULL; /* the direct parent node for the duplicated node(s) */
Radek Krejci22ebdba2019-07-25 13:59:43 +02002700
Michal Vasko3a41dff2020-07-15 14:30:28 +02002701 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002702
2703 if (options & LYD_DUP_WITH_PARENTS) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002704 LY_CHECK_GOTO(rc = lyd_dup_get_local_parent(node, parent, &top, &local_parent), error);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002705 } else {
2706 local_parent = parent;
2707 }
2708
Radek Krejci22ebdba2019-07-25 13:59:43 +02002709 LY_LIST_FOR(node, orig) {
Michal Vasko52927e22020-03-16 17:26:14 +01002710 /* if there is no local parent, it will be inserted into first */
Michal Vasko3a41dff2020-07-15 14:30:28 +02002711 LY_CHECK_GOTO(rc = lyd_dup_r(orig, (struct lyd_node *)local_parent, &first, options, first ? NULL : &first), error);
2712 if (nosiblings) {
Radek Krejci22ebdba2019-07-25 13:59:43 +02002713 break;
2714 }
2715 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002716
2717 /* rehash if needed */
Michal Vaskod989ba02020-08-24 10:59:24 +02002718 for ( ; local_parent; local_parent = local_parent->parent) {
Michal Vasko69730152020-10-09 16:30:07 +02002719 if ((local_parent->schema->nodetype == LYS_LIST) && (local_parent->schema->flags & LYS_KEYLESS)) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002720 lyd_hash((struct lyd_node *)local_parent);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002721 }
2722 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002723
2724 if (dup) {
2725 *dup = first;
2726 }
2727 return LY_SUCCESS;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002728
2729error:
2730 if (top) {
2731 lyd_free_tree(top);
2732 } else {
Michal Vaskof03ed032020-03-04 13:31:44 +01002733 lyd_free_siblings(first);
Radek Krejci22ebdba2019-07-25 13:59:43 +02002734 }
Michal Vasko3a41dff2020-07-15 14:30:28 +02002735 return rc;
Radek Krejci22ebdba2019-07-25 13:59:43 +02002736}
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002737
Michal Vasko3a41dff2020-07-15 14:30:28 +02002738API LY_ERR
Radek Krejci1deb5be2020-08-26 16:43:36 +02002739lyd_dup_single(const struct lyd_node *node, struct lyd_node_inner *parent, uint32_t options, struct lyd_node **dup)
Michal Vasko3a41dff2020-07-15 14:30:28 +02002740{
2741 return lyd_dup(node, parent, options, 1, dup);
2742}
2743
2744API LY_ERR
Radek Krejci1deb5be2020-08-26 16:43:36 +02002745lyd_dup_siblings(const struct lyd_node *node, struct lyd_node_inner *parent, uint32_t options, struct lyd_node **dup)
Michal Vasko3a41dff2020-07-15 14:30:28 +02002746{
2747 return lyd_dup(node, parent, options, 0, dup);
2748}
2749
2750API LY_ERR
2751lyd_dup_meta_single(const struct lyd_meta *meta, struct lyd_node *node, struct lyd_meta **dup)
Michal Vasko25a32822020-07-09 15:48:22 +02002752{
Radek Krejci011e4aa2020-09-04 15:22:31 +02002753 LY_ERR ret = LY_SUCCESS;
Michal Vasko25a32822020-07-09 15:48:22 +02002754 struct lyd_meta *mt, *last;
2755
Michal Vasko3a41dff2020-07-15 14:30:28 +02002756 LY_CHECK_ARG_RET(NULL, meta, node, LY_EINVAL);
Michal Vasko25a32822020-07-09 15:48:22 +02002757
2758 /* create a copy */
2759 mt = calloc(1, sizeof *mt);
Michal Vaskob7be7a82020-08-20 09:09:04 +02002760 LY_CHECK_ERR_RET(!mt, LOGMEM(LYD_CTX(node)), LY_EMEM);
Michal Vasko25a32822020-07-09 15:48:22 +02002761 mt->annotation = meta->annotation;
Michal Vaskob7be7a82020-08-20 09:09:04 +02002762 ret = meta->value.realtype->plugin->duplicate(LYD_CTX(node), &meta->value, &mt->value);
Radek Krejci011e4aa2020-09-04 15:22:31 +02002763 LY_CHECK_ERR_GOTO(ret, LOGERR(LYD_CTX(node), LY_EINT, "Value duplication failed."), finish);
2764 LY_CHECK_GOTO(ret = lydict_insert(LYD_CTX(node), meta->name, 0, &mt->name), finish);
Michal Vasko25a32822020-07-09 15:48:22 +02002765
2766 /* insert as the last attribute */
Radek Krejci011e4aa2020-09-04 15:22:31 +02002767 mt->parent = node;
Michal Vasko25a32822020-07-09 15:48:22 +02002768 if (node->meta) {
Radek Krejci1e008d22020-08-17 11:37:37 +02002769 for (last = node->meta; last->next; last = last->next) {}
Michal Vasko25a32822020-07-09 15:48:22 +02002770 last->next = mt;
2771 } else {
2772 node->meta = mt;
2773 }
2774
Radek Krejci011e4aa2020-09-04 15:22:31 +02002775finish:
2776 if (ret) {
2777 lyd_free_meta_single(mt);
2778 } else if (dup) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002779 *dup = mt;
2780 }
2781 return LY_SUCCESS;
Michal Vasko25a32822020-07-09 15:48:22 +02002782}
2783
Michal Vasko4490d312020-06-16 13:08:55 +02002784/**
2785 * @brief Merge a source sibling into target siblings.
2786 *
2787 * @param[in,out] first_trg First target sibling, is updated if top-level.
2788 * @param[in] parent_trg Target parent.
2789 * @param[in,out] sibling_src Source sibling to merge, set to NULL if spent.
2790 * @param[in] options Merge options.
2791 * @return LY_ERR value.
2792 */
2793static LY_ERR
2794lyd_merge_sibling_r(struct lyd_node **first_trg, struct lyd_node *parent_trg, const struct lyd_node **sibling_src_p,
Radek Krejci1deb5be2020-08-26 16:43:36 +02002795 uint16_t options)
Michal Vasko4490d312020-06-16 13:08:55 +02002796{
2797 LY_ERR ret;
2798 const struct lyd_node *child_src, *tmp, *sibling_src;
Michal Vasko56daf732020-08-10 10:57:18 +02002799 struct lyd_node *match_trg, *dup_src, *elem;
Michal Vasko4490d312020-06-16 13:08:55 +02002800 struct lysc_type *type;
Michal Vasko4490d312020-06-16 13:08:55 +02002801
2802 sibling_src = *sibling_src_p;
2803 if (sibling_src->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
2804 /* try to find the exact instance */
2805 ret = lyd_find_sibling_first(*first_trg, sibling_src, &match_trg);
2806 } else {
2807 /* try to simply find the node, there cannot be more instances */
2808 ret = lyd_find_sibling_val(*first_trg, sibling_src->schema, NULL, 0, &match_trg);
2809 }
2810
2811 if (!ret) {
2812 /* node found, make sure even value matches for all node types */
Michal Vasko8f359bf2020-07-28 10:41:15 +02002813 if ((match_trg->schema->nodetype == LYS_LEAF) && lyd_compare_single(sibling_src, match_trg, LYD_COMPARE_DEFAULTS)) {
Michal Vasko4490d312020-06-16 13:08:55 +02002814 /* since they are different, they cannot both be default */
2815 assert(!(sibling_src->flags & LYD_DEFAULT) || !(match_trg->flags & LYD_DEFAULT));
2816
Michal Vasko3a41dff2020-07-15 14:30:28 +02002817 /* update value (or only LYD_DEFAULT flag) only if flag set or the source node is not default */
2818 if ((options & LYD_MERGE_DEFAULTS) || !(sibling_src->flags & LYD_DEFAULT)) {
Michal Vasko4490d312020-06-16 13:08:55 +02002819 type = ((struct lysc_node_leaf *)match_trg->schema)->type;
Michal Vaskob7be7a82020-08-20 09:09:04 +02002820 type->plugin->free(LYD_CTX(match_trg), &((struct lyd_node_term *)match_trg)->value);
2821 LY_CHECK_RET(type->plugin->duplicate(LYD_CTX(match_trg), &((struct lyd_node_term *)sibling_src)->value,
Michal Vasko69730152020-10-09 16:30:07 +02002822 &((struct lyd_node_term *)match_trg)->value));
Michal Vasko4490d312020-06-16 13:08:55 +02002823
2824 /* copy flags and add LYD_NEW */
2825 match_trg->flags = sibling_src->flags | LYD_NEW;
2826 }
Michal Vasko8f359bf2020-07-28 10:41:15 +02002827 } else if ((match_trg->schema->nodetype & LYS_ANYDATA) && lyd_compare_single(sibling_src, match_trg, 0)) {
Michal Vasko4c583e82020-07-17 12:16:14 +02002828 /* update value */
2829 LY_CHECK_RET(lyd_any_copy_value(match_trg, &((struct lyd_node_any *)sibling_src)->value,
Radek Krejci0f969882020-08-21 16:56:47 +02002830 ((struct lyd_node_any *)sibling_src)->value_type));
Michal Vasko4490d312020-06-16 13:08:55 +02002831
2832 /* copy flags and add LYD_NEW */
2833 match_trg->flags = sibling_src->flags | LYD_NEW;
Michal Vasko4490d312020-06-16 13:08:55 +02002834 } else {
2835 /* check descendants, recursively */
Radek Krejcia1c1e542020-09-29 16:06:52 +02002836 LY_LIST_FOR_SAFE(lyd_child_no_keys(sibling_src), tmp, child_src) {
Michal Vasko4490d312020-06-16 13:08:55 +02002837 LY_CHECK_RET(lyd_merge_sibling_r(lyd_node_children_p(match_trg), match_trg, &child_src, options));
2838 }
2839 }
2840 } else {
2841 /* node not found, merge it */
2842 if (options & LYD_MERGE_DESTRUCT) {
2843 dup_src = (struct lyd_node *)sibling_src;
2844 lyd_unlink_tree(dup_src);
2845 /* spend it */
2846 *sibling_src_p = NULL;
2847 } else {
Michal Vasko3a41dff2020-07-15 14:30:28 +02002848 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 +02002849 }
2850
2851 /* set LYD_NEW for all the new nodes, required for validation */
Michal Vasko56daf732020-08-10 10:57:18 +02002852 LYD_TREE_DFS_BEGIN(dup_src, elem) {
Michal Vasko4490d312020-06-16 13:08:55 +02002853 elem->flags |= LYD_NEW;
Michal Vasko56daf732020-08-10 10:57:18 +02002854 LYD_TREE_DFS_END(dup_src, elem);
Michal Vasko4490d312020-06-16 13:08:55 +02002855 }
2856
2857 lyd_insert_node(parent_trg, first_trg, dup_src);
2858 }
2859
2860 return LY_SUCCESS;
2861}
2862
Michal Vasko3a41dff2020-07-15 14:30:28 +02002863static LY_ERR
Radek Krejci857189e2020-09-01 13:26:36 +02002864lyd_merge(struct lyd_node **target, const struct lyd_node *source, uint16_t options, ly_bool nosiblings)
Michal Vasko4490d312020-06-16 13:08:55 +02002865{
2866 const struct lyd_node *sibling_src, *tmp;
Radek Krejci857189e2020-09-01 13:26:36 +02002867 ly_bool first;
Michal Vasko4490d312020-06-16 13:08:55 +02002868
2869 LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
2870
2871 if (!source) {
2872 /* nothing to merge */
2873 return LY_SUCCESS;
2874 }
2875
2876 if (lysc_data_parent((*target)->schema) || lysc_data_parent(source->schema)) {
Michal Vaskob7be7a82020-08-20 09:09:04 +02002877 LOGERR(LYD_CTX(source), LY_EINVAL, "Invalid arguments - can merge only 2 top-level subtrees (%s()).", __func__);
Michal Vasko4490d312020-06-16 13:08:55 +02002878 return LY_EINVAL;
2879 }
2880
2881 LY_LIST_FOR_SAFE(source, tmp, sibling_src) {
Radek Krejci857189e2020-09-01 13:26:36 +02002882 first = (sibling_src == source) ? 1 : 0;
Michal Vasko4490d312020-06-16 13:08:55 +02002883 LY_CHECK_RET(lyd_merge_sibling_r(target, NULL, &sibling_src, options));
2884 if (first && !sibling_src) {
2885 /* source was spent (unlinked), move to the next node */
2886 source = tmp;
2887 }
2888
Michal Vasko3a41dff2020-07-15 14:30:28 +02002889 if (nosiblings) {
Michal Vasko4490d312020-06-16 13:08:55 +02002890 break;
2891 }
2892 }
2893
2894 if (options & LYD_MERGE_DESTRUCT) {
2895 /* free any leftover source data that were not merged */
2896 lyd_free_siblings((struct lyd_node *)source);
2897 }
2898
2899 return LY_SUCCESS;
2900}
2901
Michal Vasko3a41dff2020-07-15 14:30:28 +02002902API LY_ERR
Radek Krejci1deb5be2020-08-26 16:43:36 +02002903lyd_merge_tree(struct lyd_node **target, const struct lyd_node *source, uint16_t options)
Michal Vasko3a41dff2020-07-15 14:30:28 +02002904{
2905 return lyd_merge(target, source, options, 1);
2906}
2907
2908API LY_ERR
Radek Krejci1deb5be2020-08-26 16:43:36 +02002909lyd_merge_siblings(struct lyd_node **target, const struct lyd_node *source, uint16_t options)
Michal Vasko3a41dff2020-07-15 14:30:28 +02002910{
2911 return lyd_merge(target, source, options, 0);
2912}
2913
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002914static LY_ERR
Radek Krejci857189e2020-09-01 13:26:36 +02002915lyd_path_str_enlarge(char **buffer, size_t *buflen, size_t reqlen, ly_bool is_static)
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002916{
Michal Vasko14654712020-02-06 08:35:21 +01002917 /* ending \0 */
2918 ++reqlen;
2919
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002920 if (reqlen > *buflen) {
2921 if (is_static) {
2922 return LY_EINCOMPLETE;
2923 }
2924
2925 *buffer = ly_realloc(*buffer, reqlen * sizeof **buffer);
2926 if (!*buffer) {
2927 return LY_EMEM;
2928 }
2929
2930 *buflen = reqlen;
2931 }
2932
2933 return LY_SUCCESS;
2934}
2935
Michal Vaskod59035b2020-07-08 12:00:06 +02002936LY_ERR
Radek Krejci857189e2020-09-01 13:26:36 +02002937lyd_path_list_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, ly_bool is_static)
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002938{
2939 const struct lyd_node *key;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002940 size_t len;
2941 const char *val;
2942 char quot;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002943
Radek Krejcia1c1e542020-09-29 16:06:52 +02002944 for (key = lyd_child(node); key && (key->schema->flags & LYS_KEY); key = key->next) {
Michal Vaskob7be7a82020-08-20 09:09:04 +02002945 val = LYD_CANON_VALUE(key);
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002946 len = 1 + strlen(key->schema->name) + 2 + strlen(val) + 2;
Michal Vaskoba99a3e2020-08-18 15:50:05 +02002947 LY_CHECK_RET(lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static));
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002948
2949 quot = '\'';
2950 if (strchr(val, '\'')) {
2951 quot = '"';
2952 }
2953 *bufused += sprintf(*buffer + *bufused, "[%s=%c%s%c]", key->schema->name, quot, val, quot);
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002954 }
2955
2956 return LY_SUCCESS;
2957}
2958
2959/**
2960 * @brief Append leaf-list value predicate to path.
2961 *
2962 * @param[in] node Node to print.
2963 * @param[in,out] buffer Buffer to print to.
2964 * @param[in,out] buflen Current buffer length.
2965 * @param[in,out] bufused Current number of characters used in @p buffer.
2966 * @param[in] is_static Whether buffer is static or can be reallocated.
2967 * @return LY_ERR
2968 */
2969static LY_ERR
Radek Krejci857189e2020-09-01 13:26:36 +02002970lyd_path_leaflist_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, ly_bool is_static)
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002971{
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002972 size_t len;
2973 const char *val;
2974 char quot;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002975
Michal Vaskob7be7a82020-08-20 09:09:04 +02002976 val = LYD_CANON_VALUE(node);
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002977 len = 4 + strlen(val) + 2;
Michal Vaskoba99a3e2020-08-18 15:50:05 +02002978 LY_CHECK_RET(lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static));
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002979
2980 quot = '\'';
2981 if (strchr(val, '\'')) {
2982 quot = '"';
2983 }
2984 *bufused += sprintf(*buffer + *bufused, "[.=%c%s%c]", quot, val, quot);
2985
Michal Vaskoba99a3e2020-08-18 15:50:05 +02002986 return LY_SUCCESS;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02002987}
2988
2989/**
2990 * @brief Append node position (relative to its other instances) predicate to path.
2991 *
2992 * @param[in] node Node to print.
2993 * @param[in,out] buffer Buffer to print to.
2994 * @param[in,out] buflen Current buffer length.
2995 * @param[in,out] bufused Current number of characters used in @p buffer.
2996 * @param[in] is_static Whether buffer is static or can be reallocated.
2997 * @return LY_ERR
2998 */
2999static LY_ERR
Radek Krejci857189e2020-09-01 13:26:36 +02003000lyd_path_position_predicate(const struct lyd_node *node, char **buffer, size_t *buflen, size_t *bufused, ly_bool is_static)
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003001{
3002 const struct lyd_node *first, *iter;
3003 size_t len;
Radek Krejci1deb5be2020-08-26 16:43:36 +02003004 uint64_t pos;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003005 char *val = NULL;
3006 LY_ERR rc;
3007
3008 if (node->parent) {
3009 first = node->parent->child;
3010 } else {
Michal Vaskoe070bfe2020-08-31 12:27:25 +02003011 for (first = node; first->prev->next; first = first->prev) {}
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003012 }
3013 pos = 1;
3014 for (iter = first; iter != node; iter = iter->next) {
3015 if (iter->schema == node->schema) {
3016 ++pos;
3017 }
3018 }
Radek Krejci1deb5be2020-08-26 16:43:36 +02003019 if (asprintf(&val, "%" PRIu64, pos) == -1) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003020 return LY_EMEM;
3021 }
3022
3023 len = 1 + strlen(val) + 1;
3024 rc = lyd_path_str_enlarge(buffer, buflen, *bufused + len, is_static);
3025 if (rc != LY_SUCCESS) {
3026 goto cleanup;
3027 }
3028
3029 *bufused += sprintf(*buffer + *bufused, "[%s]", val);
3030
3031cleanup:
3032 free(val);
3033 return rc;
3034}
3035
3036API char *
3037lyd_path(const struct lyd_node *node, LYD_PATH_TYPE pathtype, char *buffer, size_t buflen)
3038{
Radek Krejci857189e2020-09-01 13:26:36 +02003039 ly_bool is_static = 0;
Radek Krejci1deb5be2020-08-26 16:43:36 +02003040 uint32_t i, depth;
Michal Vasko14654712020-02-06 08:35:21 +01003041 size_t bufused = 0, len;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003042 const struct lyd_node *iter;
3043 const struct lys_module *mod;
Michal Vasko790b2bc2020-08-03 13:35:06 +02003044 LY_ERR rc = LY_SUCCESS;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003045
3046 LY_CHECK_ARG_RET(NULL, node, NULL);
3047 if (buffer) {
3048 LY_CHECK_ARG_RET(node->schema->module->ctx, buflen > 1, NULL);
3049 is_static = 1;
Michal Vasko14654712020-02-06 08:35:21 +01003050 } else {
3051 buflen = 0;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003052 }
3053
3054 switch (pathtype) {
Michal Vasko14654712020-02-06 08:35:21 +01003055 case LYD_PATH_LOG:
Michal Vasko790b2bc2020-08-03 13:35:06 +02003056 case LYD_PATH_LOG_NO_LAST_PRED:
Michal Vasko14654712020-02-06 08:35:21 +01003057 depth = 1;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003058 for (iter = node; iter->parent; iter = (const struct lyd_node *)iter->parent) {
3059 ++depth;
3060 }
3061
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003062 goto iter_print;
Michal Vasko14654712020-02-06 08:35:21 +01003063 while (depth) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003064 /* find the right node */
Radek Krejci1e008d22020-08-17 11:37:37 +02003065 for (iter = node, i = 1; i < depth; iter = (const struct lyd_node *)iter->parent, ++i) {}
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003066iter_print:
3067 /* print prefix and name */
3068 mod = NULL;
Michal Vasko69730152020-10-09 16:30:07 +02003069 if (iter->schema && (!iter->parent || (iter->schema->module != iter->parent->schema->module))) {
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003070 mod = iter->schema->module;
3071 }
3072
3073 /* realloc string */
Michal Vaskoad92b672020-11-12 13:11:31 +01003074 len = 1 + (mod ? strlen(mod->name) + 1 : 0) + (iter->schema ? strlen(iter->schema->name) :
3075 strlen(((struct lyd_node_opaq *)iter)->name.name));
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003076 rc = lyd_path_str_enlarge(&buffer, &buflen, bufused + len, is_static);
3077 if (rc != LY_SUCCESS) {
3078 break;
3079 }
3080
3081 /* print next node */
Radek Krejci1798aae2020-07-14 13:26:06 +02003082 bufused += sprintf(buffer + bufused, "/%s%s%s", mod ? mod->name : "", mod ? ":" : "",
Michal Vaskoad92b672020-11-12 13:11:31 +01003083 iter->schema ? iter->schema->name : ((struct lyd_node_opaq *)iter)->name.name);
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003084
Michal Vasko790b2bc2020-08-03 13:35:06 +02003085 /* do not always print the last (first) predicate */
Michal Vasko552e1122020-11-06 17:22:44 +01003086 if (iter->schema && ((depth > 1) || (pathtype == LYD_PATH_LOG))) {
Michal Vasko790b2bc2020-08-03 13:35:06 +02003087 switch (iter->schema->nodetype) {
3088 case LYS_LIST:
3089 if (iter->schema->flags & LYS_KEYLESS) {
3090 /* print its position */
3091 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
3092 } else {
3093 /* print all list keys in predicates */
3094 rc = lyd_path_list_predicate(iter, &buffer, &buflen, &bufused, is_static);
3095 }
3096 break;
3097 case LYS_LEAFLIST:
3098 if (iter->schema->flags & LYS_CONFIG_W) {
3099 /* print leaf-list value */
3100 rc = lyd_path_leaflist_predicate(iter, &buffer, &buflen, &bufused, is_static);
3101 } else {
3102 /* print its position */
3103 rc = lyd_path_position_predicate(iter, &buffer, &buflen, &bufused, is_static);
3104 }
3105 break;
3106 default:
3107 /* nothing to print more */
3108 break;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003109 }
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003110 }
3111 if (rc != LY_SUCCESS) {
3112 break;
3113 }
3114
Michal Vasko14654712020-02-06 08:35:21 +01003115 --depth;
Michal Vasko5ec7cda2019-09-11 13:43:08 +02003116 }
3117 break;
3118 }
3119
3120 return buffer;
3121}
Michal Vaskoe444f752020-02-10 12:20:06 +01003122
Michal Vasko25a32822020-07-09 15:48:22 +02003123API struct lyd_meta *
3124lyd_find_meta(const struct lyd_meta *first, const struct lys_module *module, const char *name)
3125{
3126 struct lyd_meta *ret = NULL;
3127 const struct ly_ctx *ctx;
3128 const char *prefix, *tmp;
3129 char *str;
3130 size_t pref_len, name_len;
3131
3132 LY_CHECK_ARG_RET(NULL, module || strchr(name, ':'), name, NULL);
3133
3134 if (!first) {
3135 return NULL;
3136 }
3137
3138 ctx = first->annotation->module->ctx;
3139
3140 /* parse the name */
3141 tmp = name;
3142 if (ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len) || tmp[0]) {
3143 LOGERR(ctx, LY_EINVAL, "Metadata name \"%s\" is not valid.", name);
3144 return NULL;
3145 }
3146
3147 /* find the module */
3148 if (prefix) {
3149 str = strndup(prefix, pref_len);
3150 module = ly_ctx_get_module_latest(ctx, str);
3151 free(str);
3152 LY_CHECK_ERR_RET(!module, LOGERR(ctx, LY_EINVAL, "Module \"%.*s\" not found.", pref_len, prefix), NULL);
3153 }
3154
3155 /* find the metadata */
3156 LY_LIST_FOR(first, first) {
3157 if ((first->annotation->module == module) && !strcmp(first->name, name)) {
3158 ret = (struct lyd_meta *)first;
3159 break;
3160 }
3161 }
3162
3163 return ret;
3164}
3165
Michal Vasko9b368d32020-02-14 13:53:31 +01003166API LY_ERR
Michal Vaskoe444f752020-02-10 12:20:06 +01003167lyd_find_sibling_first(const struct lyd_node *siblings, const struct lyd_node *target, struct lyd_node **match)
3168{
3169 struct lyd_node **match_p;
3170 struct lyd_node_inner *parent;
3171
Michal Vaskof03ed032020-03-04 13:31:44 +01003172 LY_CHECK_ARG_RET(NULL, target, LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01003173
Michal Vasko62ed12d2020-05-21 10:08:25 +02003174 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(target->schema))) {
3175 /* no data or schema mismatch */
Michal Vasko9b368d32020-02-14 13:53:31 +01003176 if (match) {
3177 *match = NULL;
3178 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003179 return LY_ENOTFOUND;
3180 }
3181
3182 /* find first sibling */
3183 if (siblings->parent) {
3184 siblings = siblings->parent->child;
3185 } else {
3186 while (siblings->prev->next) {
3187 siblings = siblings->prev;
3188 }
3189 }
3190
3191 parent = (struct lyd_node_inner *)siblings->parent;
3192 if (parent && parent->children_ht) {
3193 assert(target->hash);
3194
3195 /* find by hash */
3196 if (!lyht_find(parent->children_ht, &target, target->hash, (void **)&match_p)) {
Michal Vaskoda859032020-07-14 12:20:14 +02003197 /* check even value when needed */
Michal Vasko8f359bf2020-07-28 10:41:15 +02003198 if (!(target->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !lyd_compare_single(target, *match_p, 0)) {
Michal Vaskoda859032020-07-14 12:20:14 +02003199 siblings = *match_p;
3200 } else {
3201 siblings = NULL;
3202 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003203 } else {
3204 /* not found */
3205 siblings = NULL;
3206 }
3207 } else {
3208 /* no children hash table */
Michal Vaskod989ba02020-08-24 10:59:24 +02003209 for ( ; siblings; siblings = siblings->next) {
Michal Vasko8f359bf2020-07-28 10:41:15 +02003210 if (!lyd_compare_single(siblings, target, 0)) {
Michal Vaskoe444f752020-02-10 12:20:06 +01003211 break;
3212 }
3213 }
3214 }
3215
3216 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01003217 if (match) {
3218 *match = NULL;
3219 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003220 return LY_ENOTFOUND;
3221 }
3222
Michal Vasko9b368d32020-02-14 13:53:31 +01003223 if (match) {
3224 *match = (struct lyd_node *)siblings;
3225 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003226 return LY_SUCCESS;
3227}
3228
Radek Krejci857189e2020-09-01 13:26:36 +02003229/**
3230 * @brief Comparison callback to match schema node with a schema of a data node.
3231 *
3232 * @param[in] val1_p Pointer to the schema node
3233 * @param[in] val2_p Pointer to the data node
3234 * Implementation of ::values_equal_cb.
3235 */
3236static ly_bool
3237lyd_hash_table_schema_val_equal(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *UNUSED(cb_data))
Michal Vasko90932a92020-02-12 14:33:03 +01003238{
3239 struct lysc_node *val1;
3240 struct lyd_node *val2;
3241
3242 val1 = *((struct lysc_node **)val1_p);
3243 val2 = *((struct lyd_node **)val2_p);
3244
Michal Vasko90932a92020-02-12 14:33:03 +01003245 if (val1 == val2->schema) {
3246 /* schema match is enough */
3247 return 1;
3248 } else {
3249 return 0;
3250 }
3251}
3252
3253static LY_ERR
3254lyd_find_sibling_schema(const struct lyd_node *siblings, const struct lysc_node *schema, struct lyd_node **match)
3255{
3256 struct lyd_node **match_p;
3257 struct lyd_node_inner *parent;
3258 uint32_t hash;
3259 values_equal_cb ht_cb;
3260
Michal Vaskob104f112020-07-17 09:54:54 +02003261 assert(siblings && schema);
Michal Vasko90932a92020-02-12 14:33:03 +01003262
3263 parent = (struct lyd_node_inner *)siblings->parent;
3264 if (parent && parent->children_ht) {
3265 /* calculate our hash */
3266 hash = dict_hash_multi(0, schema->module->name, strlen(schema->module->name));
3267 hash = dict_hash_multi(hash, schema->name, strlen(schema->name));
3268 hash = dict_hash_multi(hash, NULL, 0);
3269
3270 /* use special hash table function */
3271 ht_cb = lyht_set_cb(parent->children_ht, lyd_hash_table_schema_val_equal);
3272
3273 /* find by hash */
3274 if (!lyht_find(parent->children_ht, &schema, hash, (void **)&match_p)) {
3275 siblings = *match_p;
3276 } else {
3277 /* not found */
3278 siblings = NULL;
3279 }
3280
3281 /* set the original hash table compare function back */
3282 lyht_set_cb(parent->children_ht, ht_cb);
3283 } else {
Michal Vaskob104f112020-07-17 09:54:54 +02003284 /* find first sibling */
3285 if (siblings->parent) {
3286 siblings = siblings->parent->child;
3287 } else {
3288 while (siblings->prev->next) {
3289 siblings = siblings->prev;
3290 }
3291 }
3292
3293 /* search manually without hashes */
Michal Vaskod989ba02020-08-24 10:59:24 +02003294 for ( ; siblings; siblings = siblings->next) {
Michal Vasko90932a92020-02-12 14:33:03 +01003295 if (siblings->schema == schema) {
3296 /* schema match is enough */
3297 break;
3298 }
3299 }
3300 }
3301
3302 if (!siblings) {
Michal Vasko9b368d32020-02-14 13:53:31 +01003303 if (match) {
3304 *match = NULL;
3305 }
Michal Vasko90932a92020-02-12 14:33:03 +01003306 return LY_ENOTFOUND;
3307 }
3308
Michal Vasko9b368d32020-02-14 13:53:31 +01003309 if (match) {
3310 *match = (struct lyd_node *)siblings;
3311 }
Michal Vasko90932a92020-02-12 14:33:03 +01003312 return LY_SUCCESS;
3313}
3314
Michal Vaskoe444f752020-02-10 12:20:06 +01003315API LY_ERR
3316lyd_find_sibling_val(const struct lyd_node *siblings, const struct lysc_node *schema, const char *key_or_value,
Radek Krejci0f969882020-08-21 16:56:47 +02003317 size_t val_len, struct lyd_node **match)
Michal Vaskoe444f752020-02-10 12:20:06 +01003318{
3319 LY_ERR rc;
3320 struct lyd_node *target = NULL;
3321
Michal Vasko4c583e82020-07-17 12:16:14 +02003322 LY_CHECK_ARG_RET(NULL, schema, !(schema->nodetype & (LYS_CHOICE | LYS_CASE)), LY_EINVAL);
Michal Vaskoe444f752020-02-10 12:20:06 +01003323
Michal Vasko62ed12d2020-05-21 10:08:25 +02003324 if (!siblings || (lysc_data_parent(siblings->schema) != lysc_data_parent(schema))) {
3325 /* no data or schema mismatch */
Michal Vasko9b368d32020-02-14 13:53:31 +01003326 if (match) {
3327 *match = NULL;
3328 }
Michal Vaskoe444f752020-02-10 12:20:06 +01003329 return LY_ENOTFOUND;
3330 }
3331
Michal Vaskof03ed032020-03-04 13:31:44 +01003332 if (key_or_value && !val_len) {
3333 val_len = strlen(key_or_value);
3334 }
3335
Michal Vaskob104f112020-07-17 09:54:54 +02003336 if ((schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) && key_or_value) {
3337 /* create a data node and find the instance */
3338 if (schema->nodetype == LYS_LEAFLIST) {
3339 /* target used attributes: schema, hash, value */
Michal Vaskofeca4fb2020-10-05 08:58:40 +02003340 rc = lyd_create_term(schema, key_or_value, val_len, NULL, LY_PREF_JSON, NULL, LYD_HINT_DATA, NULL, &target);
3341 LY_CHECK_RET(rc);
Michal Vaskob104f112020-07-17 09:54:54 +02003342 } else {
Michal Vasko90932a92020-02-12 14:33:03 +01003343 /* target used attributes: schema, hash, child (all keys) */
Michal Vasko004d3152020-06-11 19:59:22 +02003344 LY_CHECK_RET(lyd_create_list2(schema, key_or_value, val_len, &target));
Michal Vasko90932a92020-02-12 14:33:03 +01003345 }
3346
3347 /* find it */
3348 rc = lyd_find_sibling_first(siblings, target, match);
Michal Vaskob104f112020-07-17 09:54:54 +02003349 } else {
3350 /* find the first schema node instance */
3351 rc = lyd_find_sibling_schema(siblings, schema, match);
Michal Vaskoe444f752020-02-10 12:20:06 +01003352 }
3353
Michal Vaskoe444f752020-02-10 12:20:06 +01003354 lyd_free_tree(target);
3355 return rc;
3356}
Michal Vaskoccc02342020-05-21 10:09:21 +02003357
3358API LY_ERR
3359lyd_find_xpath(const struct lyd_node *ctx_node, const char *xpath, struct ly_set **set)
3360{
3361 LY_ERR ret = LY_SUCCESS;
3362 struct lyxp_set xp_set;
Radek Krejcif03a9e22020-09-18 20:09:31 +02003363 struct lyxp_expr *exp = NULL;
Michal Vaskoccc02342020-05-21 10:09:21 +02003364 uint32_t i;
3365
3366 LY_CHECK_ARG_RET(NULL, ctx_node, xpath, set, LY_EINVAL);
3367
3368 memset(&xp_set, 0, sizeof xp_set);
3369
3370 /* compile expression */
Radek Krejcif03a9e22020-09-18 20:09:31 +02003371 ret = lyxp_expr_parse((struct ly_ctx *)LYD_CTX(ctx_node), xpath, 0, 1, &exp);
3372 LY_CHECK_GOTO(ret, cleanup);
Michal Vaskoccc02342020-05-21 10:09:21 +02003373
3374 /* evaluate expression */
Michal Vaskocdad7122020-11-09 21:04:44 +01003375 ret = lyxp_eval(exp, NULL, LY_PREF_JSON, NULL, ctx_node, ctx_node, &xp_set, LYXP_IGNORE_WHEN);
Michal Vaskoccc02342020-05-21 10:09:21 +02003376 LY_CHECK_GOTO(ret, cleanup);
3377
3378 /* allocate return set */
Radek Krejciba03a5a2020-08-27 14:40:41 +02003379 ret = ly_set_new(set);
3380 LY_CHECK_GOTO(ret, cleanup);
Michal Vaskoccc02342020-05-21 10:09:21 +02003381
3382 /* transform into ly_set */
3383 if (xp_set.type == LYXP_SET_NODE_SET) {
3384 /* allocate memory for all the elements once (even though not all items must be elements but most likely will be) */
3385 (*set)->objs = malloc(xp_set.used * sizeof *(*set)->objs);
Michal Vaskob7be7a82020-08-20 09:09:04 +02003386 LY_CHECK_ERR_GOTO(!(*set)->objs, LOGMEM(LYD_CTX(ctx_node)); ret = LY_EMEM, cleanup);
Michal Vaskoccc02342020-05-21 10:09:21 +02003387 (*set)->size = xp_set.used;
3388
3389 for (i = 0; i < xp_set.used; ++i) {
3390 if (xp_set.val.nodes[i].type == LYXP_NODE_ELEM) {
Radek Krejci3d92e442020-10-12 12:48:13 +02003391 ret = ly_set_add(*set, xp_set.val.nodes[i].node, 1, NULL);
Radek Krejciba03a5a2020-08-27 14:40:41 +02003392 LY_CHECK_GOTO(ret, cleanup);
Michal Vaskoccc02342020-05-21 10:09:21 +02003393 }
3394 }
3395 }
3396
3397cleanup:
Michal Vasko0691d522020-05-21 13:21:47 +02003398 lyxp_set_free_content(&xp_set);
Michal Vaskob7be7a82020-08-20 09:09:04 +02003399 lyxp_expr_free((struct ly_ctx *)LYD_CTX(ctx_node), exp);
Michal Vaskoccc02342020-05-21 10:09:21 +02003400 return ret;
3401}
Radek Krejcica989142020-11-05 11:32:22 +01003402
3403API uint32_t
3404lyd_list_pos(const struct lyd_node *instance)
3405{
3406 const struct lyd_node *iter = NULL;
3407 uint32_t pos = 0;
3408
3409 if (!instance || !(instance->schema->nodetype & (LYS_LIST | LYS_LEAFLIST))) {
3410 return 0;
3411 }
3412
3413 /* data instances are ordered, so we can stop when we found instance of other schema node */
3414 for (iter = instance; iter->schema == instance->schema; iter = iter->prev) {
Radek Krejcibb27df32020-11-13 15:39:16 +01003415 if (pos && (iter->next == NULL)) {
Radek Krejcica989142020-11-05 11:32:22 +01003416 /* overrun to the end of the siblings list */
3417 break;
3418 }
3419 ++pos;
3420 }
3421
3422 return pos;
3423}
Radek Krejci4233f9b2020-11-05 12:38:35 +01003424
3425API struct lyd_node *
3426lyd_first_sibling(const struct lyd_node *node)
3427{
3428 struct lyd_node *start;
3429
3430 if (!node) {
3431 return NULL;
3432 }
3433
3434 /* get the first sibling */
3435 if (node->parent) {
3436 start = node->parent->child;
3437 } else {
Radek Krejcibb27df32020-11-13 15:39:16 +01003438 for (start = (struct lyd_node *)node; start->prev->next; start = start->prev) {}
Radek Krejci4233f9b2020-11-05 12:38:35 +01003439 }
3440
3441 return start;
3442}