libyang UPDATE optional value validation and context type plugins (#2171)
This patch separates the build-in type validations from store
operations to allow storing a node even if the value doesn't pass the
validations. To do multiple changes were done:
- introduces LY_CTX_BASIC_PLUGINS_ONLY flag, which prevents loading of
any advanced plugins
- introduces LYPLG_TYPE_STORE_ONLY flag, which skip validation and
perform just storing
- introduces LYD_PARSE_STORE_ONLY flag, which implies usage of LYPLG_TYPE_STORE_ONLY
- introduces options for lyd_new_* API
- removes lyd_new_(term|list)_(bin|canon) API
- added sanity checks within lyd_new_(term|list) APIs for proper
combinations of options
- refactored lyd_new_* APIs to use common flags to use common options attributes
diff --git a/src/context.c b/src/context.c
index a7902e9..97ba672 100644
--- a/src/context.c
+++ b/src/context.c
@@ -283,6 +283,7 @@
struct ly_in *in = NULL;
LY_ERR rc = LY_SUCCESS;
struct lys_glob_unres unres = {0};
+ ly_bool builtin_plugins_only;
LY_CHECK_ARG_RET(NULL, new_ctx, LY_EINVAL);
@@ -293,7 +294,8 @@
lydict_init(&ctx->dict);
/* plugins */
- LY_CHECK_ERR_GOTO(lyplg_init(), LOGINT(NULL); rc = LY_EINT, cleanup);
+ builtin_plugins_only = (options & LY_CTX_BUILTIN_PLUGINS_ONLY) ? 1 : 0;
+ LY_CHECK_ERR_GOTO(lyplg_init(builtin_plugins_only), LOGINT(NULL); rc = LY_EINT, cleanup);
if (options & LY_CTX_LEAFREF_LINKING) {
ctx->leafref_links_ht = lyht_new(1, sizeof(struct lyd_leafref_links_rec), ly_ctx_ht_leafref_links_equal_cb, NULL, 1);
@@ -1234,8 +1236,7 @@
LY_CHECK_GOTO(ret = ylib_deviation(cont, mod, 0), error);
/* conformance-type */
- LY_CHECK_GOTO(ret = lyd_new_term(cont, NULL, "conformance-type", mod->implemented ? "implement" : "import", 0,
- NULL), error);
+ LY_CHECK_GOTO(ret = lyd_new_term(cont, NULL, "conformance-type", mod->implemented ? "implement" : "import", 0, NULL), error);
/* submodule list */
LY_CHECK_GOTO(ret = ylib_submodules(cont, mod->parsed, 0), error);
diff --git a/src/context.h b/src/context.h
index 8e8b205..9f1b8e6 100644
--- a/src/context.h
+++ b/src/context.h
@@ -202,6 +202,13 @@
'require-instance false;'. It also enables usage of
[lyd_leafref_get_links](@ref lyd_leafref_get_links) and
[lyd_leafref_link_node_tree](@ref lyd_leafref_link_node_tree) APIs. */
+#define LY_CTX_BUILTIN_PLUGINS_ONLY 0x0800 /**< By default, context loads all available built-in plugins and extensions. This
+ options prohibits loading of built-in non-YANG plugin types and extensions (ipv4-address,
+ ipv6-address, etc.). Instead the value is processed by built-in YANG plugins (usually string)
+ with all its behavioral implications as hex-string comparison becoming case-sensitive.
+ Change of this flag during the lifetime of context is not fully supported. Once the non-YANG
+ plugins or extensions are loaded during context creation, they will be used regardless of this
+ flag. Therefore it is recommended to set this flag during the first context creation. */
/** @} contextoptions */
diff --git a/src/diff.c b/src/diff.c
index 079c898..744f039 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -154,7 +154,7 @@
}
/* create the metadata */
- LY_CHECK_GOTO(rc = lyd_new_meta(NULL, node, NULL, meta_name, meta_val, 0, NULL), cleanup);
+ LY_CHECK_GOTO(rc = lyd_new_meta(NULL, node, NULL, meta_name, meta_val, LYD_NEW_VAL_STORE_ONLY, NULL), cleanup);
cleanup:
free(dyn);
@@ -382,7 +382,7 @@
}
/* set the none operation */
- LY_CHECK_RET(lyd_new_meta(NULL, elem, NULL, "yang:operation", "none", 0, NULL));
+ LY_CHECK_RET(lyd_new_meta(NULL, elem, NULL, "yang:operation", "none", LYD_NEW_VAL_STORE_ONLY, NULL));
}
dup = diff_parent;
@@ -424,12 +424,12 @@
/* add parent operation, if any */
if (diff_parent && (diff_parent != dup)) {
- LY_CHECK_RET(lyd_new_meta(NULL, diff_parent, NULL, "yang:operation", "none", 0, NULL));
+ LY_CHECK_RET(lyd_new_meta(NULL, diff_parent, NULL, "yang:operation", "none", LYD_NEW_VAL_STORE_ONLY, NULL));
}
}
/* add subtree operation */
- LY_CHECK_RET(lyd_new_meta(NULL, dup, NULL, "yang:operation", lyd_diff_op2str(op), 0, NULL));
+ LY_CHECK_RET(lyd_new_meta(NULL, dup, NULL, "yang:operation", lyd_diff_op2str(op), LYD_NEW_VAL_STORE_ONLY, NULL));
if (op == LYD_DIFF_OP_CREATE) {
/* all nested user-ordered (leaf-)lists need special metadata for create op */
@@ -443,37 +443,37 @@
/* orig-default */
if (orig_default) {
- LY_CHECK_RET(lyd_new_meta(NULL, dup, NULL, "yang:orig-default", orig_default, 0, NULL));
+ LY_CHECK_RET(lyd_new_meta(NULL, dup, NULL, "yang:orig-default", orig_default, LYD_NEW_VAL_STORE_ONLY, NULL));
}
/* orig-value */
if (orig_value) {
- LY_CHECK_RET(lyd_new_meta(NULL, dup, NULL, "yang:orig-value", orig_value, 0, NULL));
+ LY_CHECK_RET(lyd_new_meta(NULL, dup, NULL, "yang:orig-value", orig_value, LYD_NEW_VAL_STORE_ONLY, NULL));
}
/* key */
if (key) {
- LY_CHECK_RET(lyd_new_meta(NULL, dup, NULL, "yang:key", key, 0, NULL));
+ LY_CHECK_RET(lyd_new_meta(NULL, dup, NULL, "yang:key", key, LYD_NEW_VAL_STORE_ONLY, NULL));
}
/* value */
if (value) {
- LY_CHECK_RET(lyd_new_meta(NULL, dup, NULL, "yang:value", value, 0, NULL));
+ LY_CHECK_RET(lyd_new_meta(NULL, dup, NULL, "yang:value", value, LYD_NEW_VAL_STORE_ONLY, NULL));
}
/* position */
if (position) {
- LY_CHECK_RET(lyd_new_meta(NULL, dup, NULL, "yang:position", position, 0, NULL));
+ LY_CHECK_RET(lyd_new_meta(NULL, dup, NULL, "yang:position", position, LYD_NEW_VAL_STORE_ONLY, NULL));
}
/* orig-key */
if (orig_key) {
- LY_CHECK_RET(lyd_new_meta(NULL, dup, NULL, "yang:orig-key", orig_key, 0, NULL));
+ LY_CHECK_RET(lyd_new_meta(NULL, dup, NULL, "yang:orig-key", orig_key, LYD_NEW_VAL_STORE_ONLY, NULL));
}
/* orig-position */
if (orig_position) {
- LY_CHECK_RET(lyd_new_meta(NULL, dup, NULL, "yang:orig-position", orig_position, 0, NULL));
+ LY_CHECK_RET(lyd_new_meta(NULL, dup, NULL, "yang:orig-position", orig_position, LYD_NEW_VAL_STORE_ONLY, NULL));
}
return LY_SUCCESS;
@@ -1460,7 +1460,7 @@
lyd_diff_del_meta(node, "operation");
if (node->schema) {
- return lyd_new_meta(LYD_CTX(node), node, NULL, "yang:operation", lyd_diff_op2str(op), 0, NULL);
+ return lyd_new_meta(LYD_CTX(node), node, NULL, "yang:operation", lyd_diff_op2str(op), LYD_NEW_VAL_STORE_ONLY, NULL);
} else {
return lyd_new_attr(node, "yang", "operation", lyd_diff_op2str(op), NULL);
}
@@ -1685,7 +1685,7 @@
/* current value is the previous one (meta) */
LY_CHECK_RET(lyd_new_meta(LYD_CTX(src_diff), *diff_match, NULL, "yang:orig-value",
- lyd_get_value(*diff_match), 0, NULL));
+ lyd_get_value(*diff_match), LYD_NEW_VAL_STORE_ONLY, NULL));
/* update the value itself */
LY_CHECK_RET(lyd_change_term(*diff_match, lyd_get_value(src_diff)));
@@ -1699,10 +1699,10 @@
to_free = *diff_match;
*diff_match = src_dup;
- r = lyd_new_meta(ctx, src_dup, NULL, "yang:orig-value", lyd_get_value(to_free), 0, NULL);
+ r = lyd_new_meta(ctx, src_dup, NULL, "yang:orig-value", lyd_get_value(to_free), LYD_NEW_VAL_STORE_ONLY, NULL);
lyd_free_tree(to_free);
LY_CHECK_RET(r);
- LY_CHECK_RET(lyd_new_meta(ctx, src_dup, NULL, "yang:operation", lyd_diff_op2str(LYD_DIFF_OP_REPLACE), 0, NULL));
+ LY_CHECK_RET(lyd_new_meta(ctx, src_dup, NULL, "yang:operation", lyd_diff_op2str(LYD_DIFF_OP_REPLACE), LYD_NEW_VAL_STORE_ONLY, NULL));
}
} else {
/* deleted + created -> operation NONE */
@@ -1713,7 +1713,7 @@
if ((*diff_match)->schema->nodetype & LYD_NODE_TERM) {
/* add orig-dflt metadata */
LY_CHECK_RET(lyd_new_meta(LYD_CTX(src_diff), *diff_match, NULL, "yang:orig-default",
- trg_flags & LYD_DEFAULT ? "true" : "false", 0, NULL));
+ trg_flags & LYD_DEFAULT ? "true" : "false", LYD_NEW_VAL_STORE_ONLY, NULL));
/* update dflt flag itself */
(*diff_match)->flags &= ~LYD_DEFAULT;
@@ -1763,7 +1763,7 @@
if (diff_match->schema->nodetype & LYD_NODE_TERM) {
/* add orig-default meta because it is expected */
LY_CHECK_RET(lyd_new_meta(LYD_CTX(src_diff), diff_match, NULL, "yang:orig-default",
- src_diff->flags & LYD_DEFAULT ? "true" : "false", 0, NULL));
+ src_diff->flags & LYD_DEFAULT ? "true" : "false", LYD_NEW_VAL_STORE_ONLY, NULL));
}
break;
case LYD_DIFF_OP_REPLACE:
diff --git a/src/parser_common.c b/src/parser_common.c
index dadd1d7..06544f1 100644
--- a/src/parser_common.c
+++ b/src/parser_common.c
@@ -284,8 +284,10 @@
{
LY_ERR r;
ly_bool incomplete;
+ ly_bool store_only = (lydctx->parse_opts & LYD_PARSE_STORE_ONLY) ? 1 : 0;
- if ((r = lyd_create_term(schema, value, value_len, 1, dynamic, format, prefix_data, hints, &incomplete, node))) {
+ if ((r = lyd_create_term(schema, value, value_len, 1, store_only, dynamic, format, prefix_data,
+ hints, &incomplete, node))) {
if (lydctx->data_ctx->ctx != schema->module->ctx) {
/* move errors to the main context */
ly_err_move(schema->module->ctx, (struct ly_ctx *)lydctx->data_ctx->ctx);
@@ -308,6 +310,7 @@
char *dpath = NULL, *path = NULL;
ly_bool incomplete;
struct lyd_meta *first = NULL;
+ ly_bool store_only = (lydctx->parse_opts & LYD_PARSE_STORE_ONLY) ? 1 : 0;
if (meta && *meta) {
/* remember the first metadata */
@@ -323,7 +326,7 @@
}
ly_log_location(NULL, NULL, path, NULL);
- LY_CHECK_GOTO(rc = lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, 1, dynamic, format,
+ LY_CHECK_GOTO(rc = lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, 1, store_only, dynamic, format,
prefix_data, hints, ctx_node, 0, &incomplete), cleanup);
if (incomplete && !(lydctx->parse_opts & LYD_PARSE_ONLY)) {
diff --git a/src/parser_data.h b/src/parser_data.h
index 8b61633..e782b47 100644
--- a/src/parser_data.h
+++ b/src/parser_data.h
@@ -134,6 +134,7 @@
* - when statements on existing nodes are evaluated, if not satisfied, a validation error is raised,
* - invalid multiple data instances/data from several cases cause a validation error,
* - implicit nodes (NP containers and default values) are added.
+ * - Validations based on leaf/leaf-list types restriction is being done regardless of setting LYD_PARSE_ONLY
* @{
*/
/* note: keep the lower 16bits free for use by LYD_VALIDATE_ flags. They are not supposed to be combined together,
@@ -171,6 +172,8 @@
#define LYD_PARSE_NO_NEW 0x1000000 /**< Do not set ::LYD_NEW (non-validated node flag) for any nodes. Use
when parsing validated data to skip some validation tasks and modify
some validation behavior (auto-deletion of cases). */
+#define LYD_PARSE_STORE_ONLY 0x2000000 /**< Perform only storing operation, no validation based on leaf/leaf-list type
+ restrictions will be performed. */
#define LYD_PARSE_OPTS_MASK 0xFFFF0000 /**< Mask for all the LYD_PARSE_ options. */
diff --git a/src/path.c b/src/path.c
index 2214ed0..5fd33e6 100644
--- a/src/path.c
+++ b/src/path.c
@@ -710,8 +710,8 @@
if (key) {
LOG_LOCSET(key, NULL);
}
- ret = lyd_value_store(ctx, &p->value, ((struct lysc_node_leaf *)key)->type, val, val_len, 0, NULL,
- format, prefix_data, LYD_HINT_DATA, key, NULL);
+ ret = lyd_value_store(ctx, &p->value, ((struct lysc_node_leaf *)key)->type, val, val_len, 0, 0,
+ NULL, format, prefix_data, LYD_HINT_DATA, key, NULL);
LOG_LOCBACK(key ? 1 : 0, 0);
LY_CHECK_ERR_GOTO(ret, p->value.realtype = NULL, cleanup);
@@ -776,8 +776,8 @@
if (ctx_node) {
LOG_LOCSET(ctx_node, NULL);
}
- ret = lyd_value_store(ctx, &p->value, ((struct lysc_node_leaflist *)ctx_node)->type, val, val_len, 0, NULL,
- format, prefix_data, LYD_HINT_DATA, ctx_node, NULL);
+ ret = lyd_value_store(ctx, &p->value, ((struct lysc_node_leaflist *)ctx_node)->type, val, val_len, 0, 0,
+ NULL, format, prefix_data, LYD_HINT_DATA, ctx_node, NULL);
LOG_LOCBACK(ctx_node ? 1 : 0, 0);
LY_CHECK_ERR_GOTO(ret, p->value.realtype = NULL, cleanup);
++(*tok_idx);
@@ -1356,7 +1356,7 @@
case LY_PATH_PREDTYPE_LIST_VAR:
case LY_PATH_PREDTYPE_LIST:
/* we will use hashes to find one list instance */
- LY_CHECK_RET(lyd_create_list(path[u].node, path[u].predicates, vars, &target));
+ LY_CHECK_RET(lyd_create_list(path[u].node, path[u].predicates, vars, 1, &target));
lyd_find_sibling_first(start, target, &node);
lyd_free_tree(target);
break;
diff --git a/src/plugins.c b/src/plugins.c
index c1bdad5..1f76049 100644
--- a/src/plugins.c
+++ b/src/plugins.c
@@ -444,7 +444,7 @@
#endif
LY_ERR
-lyplg_init(void)
+lyplg_init(ly_bool builtin_plugins_only)
{
LY_ERR ret;
@@ -470,34 +470,36 @@
LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_string), error);
LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_union), error);
- /* yang */
- LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_instanceid_keys), error);
+ if (!builtin_plugins_only) {
+ /* yang */
+ LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_instanceid_keys), error);
- /* ietf-inet-types */
- LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_ipv4_address), error);
- LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_ipv4_address_no_zone), error);
- LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_ipv6_address), error);
- LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_ipv6_address_no_zone), error);
- LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_ipv4_prefix), error);
- LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_ipv6_prefix), error);
+ /* ietf-inet-types */
+ LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_ipv4_address), error);
+ LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_ipv4_address_no_zone), error);
+ LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_ipv6_address), error);
+ LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_ipv6_address_no_zone), error);
+ LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_ipv4_prefix), error);
+ LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_ipv6_prefix), error);
- /* ietf-yang-types */
- LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_date_and_time), error);
- LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_hex_string), error);
- LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_xpath10), error);
+ /* ietf-yang-types */
+ LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_date_and_time), error);
+ LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_hex_string), error);
+ LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_xpath10), error);
- /* ietf-netconf-acm */
- LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_node_instanceid), error);
+ /* ietf-netconf-acm */
+ LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_node_instanceid), error);
- /* lyds_tree */
- LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_lyds_tree), error);
+ /* lyds_tree */
+ LY_CHECK_GOTO(ret = plugins_insert(LYPLG_TYPE, plugins_lyds_tree), error);
- /* internal extensions */
- LY_CHECK_GOTO(ret = plugins_insert(LYPLG_EXTENSION, plugins_metadata), error);
- LY_CHECK_GOTO(ret = plugins_insert(LYPLG_EXTENSION, plugins_nacm), error);
- LY_CHECK_GOTO(ret = plugins_insert(LYPLG_EXTENSION, plugins_yangdata), error);
- LY_CHECK_GOTO(ret = plugins_insert(LYPLG_EXTENSION, plugins_schema_mount), error);
- LY_CHECK_GOTO(ret = plugins_insert(LYPLG_EXTENSION, plugins_structure), error);
+ /* internal extensions */
+ LY_CHECK_GOTO(ret = plugins_insert(LYPLG_EXTENSION, plugins_metadata), error);
+ LY_CHECK_GOTO(ret = plugins_insert(LYPLG_EXTENSION, plugins_nacm), error);
+ LY_CHECK_GOTO(ret = plugins_insert(LYPLG_EXTENSION, plugins_yangdata), error);
+ LY_CHECK_GOTO(ret = plugins_insert(LYPLG_EXTENSION, plugins_schema_mount), error);
+ LY_CHECK_GOTO(ret = plugins_insert(LYPLG_EXTENSION, plugins_structure), error);
+ }
#ifndef STATIC
/* external types */
diff --git a/src/plugins_internal.h b/src/plugins_internal.h
index d13db16..f624624 100644
--- a/src/plugins_internal.h
+++ b/src/plugins_internal.h
@@ -48,11 +48,12 @@
*
* Covers both the types and extensions plugins.
*
+ * @param[in] builtin_plugins_only Whether to load only built-in YANG plugin types and extensions.
* @return LY_SUCCESS in case of success
* @return LY_EINT in case of internal error
* @return LY_EMEM in case of memory allocation failure.
*/
-LY_ERR lyplg_init(void);
+LY_ERR lyplg_init(ly_bool builtin_plugins_only);
/**
* @brief Remove (unload) all the plugins currently available.
diff --git a/src/plugins_types.h b/src/plugins_types.h
index 4b8b1b9..184393c 100644
--- a/src/plugins_types.h
+++ b/src/plugins_types.h
@@ -475,6 +475,7 @@
#define LYPLG_TYPE_STORE_IMPLEMENT 0x02 /**< If a foreign module is needed to be implemented to successfully instantiate
the value, make the module implemented. */
#define LYPLG_TYPE_STORE_IS_UTF8 0x04 /**< The value is guaranteed to be a valid UTF-8 string, if applicable for the type. */
+#define LYPLG_TYPE_STORE_ONLY 0x08 /**< The value is stored only. The validation must be done using [validate](@ref lyplg_type_validate_clb) */
/** @} plugintypestoreopts */
/**
diff --git a/src/plugins_types/binary.c b/src/plugins_types/binary.c
index a801144..c265511 100644
--- a/src/plugins_types/binary.c
+++ b/src/plugins_types/binary.c
@@ -42,6 +42,8 @@
*/
static const char b64_etable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static LY_ERR lyplg_type_validate_binary(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err);
+
/**
* @brief Encode binary value into a base64 string value.
*
@@ -165,12 +167,11 @@
*
* @param[in] value Value to validate.
* @param[in] value_len Length of @p value.
- * @param[in] type type of the value.
* @param[out] err Error information.
* @return LY_ERR value.
*/
static LY_ERR
-binary_base64_validate(const char *value, size_t value_len, const struct lysc_type_bin *type, struct ly_err_item **err)
+binary_base64_validate(const char *value, size_t value_len, struct ly_err_item **err)
{
uint32_t idx, pad;
@@ -204,13 +205,6 @@
return ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Base64 encoded value length must be divisible by 4.");
}
- /* length restriction of the binary value */
- if (type->length) {
- const uint32_t octet_count = ((idx + pad) / 4) * 3 - pad;
-
- LY_CHECK_RET(lyplg_type_validate_range(LY_TYPE_BINARY, type->length, octet_count, value, value_len, err));
- }
-
return LY_SUCCESS;
}
@@ -266,7 +260,6 @@
struct ly_err_item **err)
{
LY_ERR ret = LY_SUCCESS;
- struct lysc_type_bin *type_bin = (struct lysc_type_bin *)type;
struct lyd_value_binary *val;
/* init storage */
@@ -306,7 +299,7 @@
LY_CHECK_GOTO(ret, cleanup);
/* validate */
- ret = binary_base64_validate(value, value_len, type_bin, err);
+ ret = binary_base64_validate(value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
}
@@ -324,6 +317,12 @@
LY_CHECK_GOTO(ret, cleanup);
}
+ if (!(options & LYPLG_TYPE_STORE_ONLY)) {
+ /* validate value */
+ ret = lyplg_type_validate_binary(ctx, type, NULL, NULL, storage, err);
+ LY_CHECK_GOTO(ret, cleanup);
+ }
+
cleanup:
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
free((void *)value);
@@ -335,6 +334,33 @@
return ret;
}
+/**
+ * @brief Implementation of ::lyplg_type_validate_clb for the binary type.
+ */
+static LY_ERR
+lyplg_type_validate_binary(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node),
+ const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
+{
+ struct lysc_type_bin *type_bin = (struct lysc_type_bin *)type;
+ struct lyd_value_binary *val;
+ const void *value;
+ size_t value_len;
+
+ LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL);
+
+ val = LYPLG_TYPE_VAL_IS_DYN(val) ? (struct lyd_value_binary *)(storage->dyn_mem) : (struct lyd_value_binary *)(storage->fixed_mem);
+ value = storage->_canonical;
+ value_len = strlen(storage->_canonical);
+ *err = NULL;
+
+ /* length restriction of the binary value */
+ if (type_bin->length) {
+ LY_CHECK_RET(lyplg_type_validate_range(LY_TYPE_BINARY, type_bin->length, val->size, value, value_len, err));
+ }
+
+ return LY_SUCCESS;
+}
+
LIBYANG_API_DEF LY_ERR
lyplg_type_compare_binary(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1, const struct lyd_value *val2)
{
@@ -470,7 +496,7 @@
.plugin.id = "libyang 2 - binary, version 1",
.plugin.store = lyplg_type_store_binary,
- .plugin.validate = NULL,
+ .plugin.validate = lyplg_type_validate_binary,
.plugin.compare = lyplg_type_compare_binary,
.plugin.sort = lyplg_type_sort_binary,
.plugin.print = lyplg_type_print_binary,
diff --git a/src/plugins_types/decimal64.c b/src/plugins_types/decimal64.c
index 9edc968..0eb01a0 100644
--- a/src/plugins_types/decimal64.c
+++ b/src/plugins_types/decimal64.c
@@ -33,6 +33,8 @@
* | 8 | yes | `int64_t *` | little-endian value represented without floating point |
*/
+static LY_ERR lyplg_type_validate_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err);
+
/**
* @brief Convert decimal64 number to canonical string.
*
@@ -140,10 +142,9 @@
LY_CHECK_GOTO(ret, cleanup);
}
- if (type_dec->range) {
- /* check range of the number */
- ret = lyplg_type_validate_range(type->basetype, type_dec->range, num, storage->_canonical,
- strlen(storage->_canonical), err);
+ if (!(options & LYPLG_TYPE_STORE_ONLY)) {
+ /* validate value */
+ ret = lyplg_type_validate_decimal64(ctx, type, NULL, NULL, storage, err);
LY_CHECK_GOTO(ret, cleanup);
}
@@ -158,6 +159,31 @@
return ret;
}
+/**
+ * @brief Implementation of ::lyplg_type_validate_clb for the built-in decimal64 type.
+ */
+static LY_ERR
+lyplg_type_validate_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node),
+ const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
+{
+ LY_ERR ret;
+ struct lysc_type_dec *type_dec = (struct lysc_type_dec *)type;
+ int64_t num;
+
+ LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL);
+ *err = NULL;
+ num = storage->dec64;
+
+ if (type_dec->range) {
+ /* check range of the number */
+ ret = lyplg_type_validate_range(type->basetype, type_dec->range, num, storage->_canonical,
+ strlen(storage->_canonical), err);
+ LY_CHECK_RET(ret);
+ }
+
+ return LY_SUCCESS;
+}
+
LIBYANG_API_DEF LY_ERR
lyplg_type_compare_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1,
const struct lyd_value *val2)
@@ -236,7 +262,7 @@
.plugin.id = "libyang 2 - decimal64, version 1",
.plugin.store = lyplg_type_store_decimal64,
- .plugin.validate = NULL,
+ .plugin.validate = lyplg_type_validate_decimal64,
.plugin.compare = lyplg_type_compare_decimal64,
.plugin.sort = lyplg_type_sort_decimal64,
.plugin.print = lyplg_type_print_decimal64,
diff --git a/src/plugins_types/integer.c b/src/plugins_types/integer.c
index 73c4533..eb66499 100644
--- a/src/plugins_types/integer.c
+++ b/src/plugins_types/integer.c
@@ -36,6 +36,9 @@
* | 1/2/4/8 | yes | pointer to the specific integer type | little-endian integer value |
*/
+static LY_ERR lyplg_type_validate_int(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err);
+static LY_ERR lyplg_type_validate_uint(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err);
+
/**
* @brief LYB value size of each integer type.
*/
@@ -54,7 +57,6 @@
int64_t num = 0;
int base = 1;
char *canon = NULL;
- struct lysc_type_num *type_num = (struct lysc_type_num *)type;
/* init storage */
memset(storage, 0, sizeof *storage);
@@ -154,10 +156,9 @@
LY_CHECK_GOTO(ret, cleanup);
}
- /* validate range of the number */
- if (type_num->range) {
- ret = lyplg_type_validate_range(type->basetype, type_num->range, num, storage->_canonical,
- strlen(storage->_canonical), err);
+ if (!(options & LYPLG_TYPE_STORE_ONLY)) {
+ /* validate value */
+ ret = lyplg_type_validate_int(ctx, type, NULL, NULL, storage, err);
LY_CHECK_GOTO(ret, cleanup);
}
@@ -172,6 +173,48 @@
return ret;
}
+/**
+ * @brief Implementation of ::lyplg_type_validate_clb for the signed interger types.
+ */
+static LY_ERR
+lyplg_type_validate_int(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node),
+ const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
+{
+ LY_ERR ret;
+ struct lysc_type_num *type_num = (struct lysc_type_num *)type;
+ int64_t num;
+
+ LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL);
+ *err = NULL;
+
+ /* set the value (matters for big-endian) and get the correct int64 number */
+ switch (type->basetype) {
+ case LY_TYPE_INT8:
+ num = storage->int8;
+ break;
+ case LY_TYPE_INT16:
+ num = storage->int16;
+ break;
+ case LY_TYPE_INT32:
+ num = storage->int32;
+ break;
+ case LY_TYPE_INT64:
+ num = storage->int64;
+ break;
+ default:
+ return LY_EINVAL;
+ }
+
+ /* validate range of the number */
+ if (type_num->range) {
+ ret = lyplg_type_validate_range(type->basetype, type_num->range, num, storage->_canonical,
+ strlen(storage->_canonical), err);
+ LY_CHECK_RET(ret);
+ }
+
+ return LY_SUCCESS;
+}
+
LIBYANG_API_DEF LY_ERR
lyplg_type_compare_int(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1, const struct lyd_value *val2)
{
@@ -318,7 +361,6 @@
uint64_t num = 0;
int base = 0;
char *canon;
- struct lysc_type_num *type_num = (struct lysc_type_num *)type;
/* init storage */
memset(storage, 0, sizeof *storage);
@@ -398,10 +440,9 @@
LY_CHECK_GOTO(ret, cleanup);
}
- /* validate range of the number */
- if (type_num->range) {
- ret = lyplg_type_validate_range(type->basetype, type_num->range, num, storage->_canonical,
- strlen(storage->_canonical), err);
+ if (!(options & LYPLG_TYPE_STORE_ONLY)) {
+ /* validate value */
+ ret = lyplg_type_validate_uint(ctx, type, NULL, NULL, storage, err);
LY_CHECK_GOTO(ret, cleanup);
}
@@ -416,6 +457,48 @@
return ret;
}
+/**
+ * @brief Implementation of ::lyplg_type_validate_clb for the unsigned interger types.
+ */
+static LY_ERR
+lyplg_type_validate_uint(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node),
+ const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
+{
+ LY_ERR ret;
+ struct lysc_type_num *type_num = (struct lysc_type_num *)type;
+ uint64_t num;
+
+ LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL);
+ *err = NULL;
+
+ /* set the value (matters for big-endian) and get the correct int64 number */
+ switch (type->basetype) {
+ case LY_TYPE_UINT8:
+ num = storage->uint8;
+ break;
+ case LY_TYPE_UINT16:
+ num = storage->uint16;
+ break;
+ case LY_TYPE_UINT32:
+ num = storage->uint32;
+ break;
+ case LY_TYPE_UINT64:
+ num = storage->uint64;
+ break;
+ default:
+ return LY_EINVAL;
+ }
+
+ /* validate range of the number */
+ if (type_num->range) {
+ ret = lyplg_type_validate_range(type->basetype, type_num->range, num, storage->_canonical,
+ strlen(storage->_canonical), err);
+ LY_CHECK_RET(ret);
+ }
+
+ return LY_SUCCESS;
+}
+
LIBYANG_API_DEF LY_ERR
lyplg_type_compare_uint(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1, const struct lyd_value *val2)
{
@@ -563,7 +646,7 @@
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_uint,
- .plugin.validate = NULL,
+ .plugin.validate = lyplg_type_validate_uint,
.plugin.compare = lyplg_type_compare_uint,
.plugin.sort = lyplg_type_sort_uint,
.plugin.print = lyplg_type_print_uint,
@@ -577,7 +660,7 @@
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_uint,
- .plugin.validate = NULL,
+ .plugin.validate = lyplg_type_validate_uint,
.plugin.compare = lyplg_type_compare_uint,
.plugin.sort = lyplg_type_sort_uint,
.plugin.print = lyplg_type_print_uint,
@@ -591,7 +674,7 @@
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_uint,
- .plugin.validate = NULL,
+ .plugin.validate = lyplg_type_validate_uint,
.plugin.compare = lyplg_type_compare_uint,
.plugin.sort = lyplg_type_sort_uint,
.plugin.print = lyplg_type_print_uint,
@@ -605,7 +688,7 @@
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_uint,
- .plugin.validate = NULL,
+ .plugin.validate = lyplg_type_validate_uint,
.plugin.compare = lyplg_type_compare_uint,
.plugin.sort = lyplg_type_sort_uint,
.plugin.print = lyplg_type_print_uint,
@@ -619,7 +702,7 @@
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_int,
- .plugin.validate = NULL,
+ .plugin.validate = lyplg_type_validate_int,
.plugin.compare = lyplg_type_compare_int,
.plugin.sort = lyplg_type_sort_int,
.plugin.print = lyplg_type_print_int,
@@ -633,7 +716,7 @@
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_int,
- .plugin.validate = NULL,
+ .plugin.validate = lyplg_type_validate_int,
.plugin.compare = lyplg_type_compare_int,
.plugin.sort = lyplg_type_sort_int,
.plugin.print = lyplg_type_print_int,
@@ -647,7 +730,7 @@
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_int,
- .plugin.validate = NULL,
+ .plugin.validate = lyplg_type_validate_int,
.plugin.compare = lyplg_type_compare_int,
.plugin.sort = lyplg_type_sort_int,
.plugin.print = lyplg_type_print_int,
@@ -661,7 +744,7 @@
.plugin.id = "libyang 2 - integers, version 1",
.plugin.store = lyplg_type_store_int,
- .plugin.validate = NULL,
+ .plugin.validate = lyplg_type_validate_int,
.plugin.compare = lyplg_type_compare_int,
.plugin.sort = lyplg_type_sort_int,
.plugin.print = lyplg_type_print_int,
diff --git a/src/plugins_types/string.c b/src/plugins_types/string.c
index 5ae5204..e4c1cb9 100644
--- a/src/plugins_types/string.c
+++ b/src/plugins_types/string.c
@@ -34,6 +34,8 @@
* | string length | yes | `char *` | string itself |
*/
+static LY_ERR lyplg_type_validate_string(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err);
+
/**
* @brief Check string value for invalid characters.
*
@@ -64,7 +66,6 @@
struct ly_err_item **err)
{
LY_ERR ret = LY_SUCCESS;
- struct lysc_type_str *type_str = (struct lysc_type_str *)type;
/* init storage */
memset(storage, 0, sizeof *storage);
@@ -80,17 +81,6 @@
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
- /* length restriction of the string */
- if (type_str->length) {
- /* value_len is in bytes, but we need number of characters here */
- ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err);
- LY_CHECK_GOTO(ret, cleanup);
- }
-
- /* pattern restrictions */
- ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
- LY_CHECK_GOTO(ret, cleanup);
-
/* store canonical value */
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
@@ -101,6 +91,12 @@
LY_CHECK_GOTO(ret, cleanup);
}
+ if (!(options & LYPLG_TYPE_STORE_ONLY)) {
+ /* validate value */
+ ret = lyplg_type_validate_string(ctx, type, NULL, NULL, storage, err);
+ LY_CHECK_GOTO(ret, cleanup);
+ }
+
cleanup:
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
free((void *)value);
@@ -113,6 +109,37 @@
}
/**
+ * @brief Implementation of ::lyplg_type_validate_clb for the string type.
+ */
+static LY_ERR
+lyplg_type_validate_string(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node),
+ const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
+{
+ LY_ERR ret;
+ struct lysc_type_str *type_str = (struct lysc_type_str *)type;
+ const void *value;
+ size_t value_len;
+
+ LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL);
+ value = storage->_canonical;
+ value_len = strlen(storage->_canonical);
+ *err = NULL;
+
+ /* length restriction of the string */
+ if (type_str->length) {
+ /* value_len is in bytes, but we need number of characters here */
+ ret = lyplg_type_validate_range(LY_TYPE_STRING, type_str->length, ly_utf8len(value, value_len), value, value_len, err);
+ LY_CHECK_RET(ret);
+ }
+
+ /* pattern restrictions */
+ ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
+ LY_CHECK_RET(ret);
+
+ return LY_SUCCESS;
+}
+
+/**
* @brief Plugin information for string type implementation.
*
* Note that external plugins are supposed to use:
@@ -127,7 +154,7 @@
.plugin.id = "libyang 2 - string, version 1",
.plugin.store = lyplg_type_store_string,
- .plugin.validate = NULL,
+ .plugin.validate = lyplg_type_validate_string,
.plugin.compare = lyplg_type_compare_simple,
.plugin.sort = lyplg_type_sort_simple,
.plugin.print = lyplg_type_print_simple,
diff --git a/src/plugins_types/union.c b/src/plugins_types/union.c
index 32c682c..8dbc68b 100644
--- a/src/plugins_types/union.c
+++ b/src/plugins_types/union.c
@@ -156,6 +156,7 @@
* @param[in] ctx libyang context.
* @param[in] type Specific union type to use for storing.
* @param[in] subvalue Union subvalue structure.
+ * @param[in] options The store options.
* @param[in] resolve Whether the value needs to be resolved (validated by a callback).
* @param[in] ctx_node Context node for prefix resolution.
* @param[in] tree Data tree for resolving (validation).
@@ -164,13 +165,14 @@
* @return LY_ERR value.
*/
static LY_ERR
-union_store_type(const struct ly_ctx *ctx, struct lysc_type *type, struct lyd_value_union *subvalue,
+union_store_type(const struct ly_ctx *ctx, struct lysc_type *type, struct lyd_value_union *subvalue, uint32_t options,
ly_bool resolve, const struct lyd_node *ctx_node, const struct lyd_node *tree, struct lys_glob_unres *unres,
struct ly_err_item **err)
{
LY_ERR ret;
const void *value = NULL;
size_t value_len = 0;
+ uint32_t opts;
*err = NULL;
@@ -181,7 +183,8 @@
value_len = subvalue->orig_len;
}
- ret = type->plugin->store(ctx, type, value, value_len, 0, subvalue->format, subvalue->prefix_data, subvalue->hints,
+ opts = (options & LYPLG_TYPE_STORE_ONLY) ? LYPLG_TYPE_STORE_ONLY : 0;
+ ret = type->plugin->store(ctx, type, value, value_len, opts, subvalue->format, subvalue->prefix_data, subvalue->hints,
subvalue->ctx_node, &subvalue->value, unres, err);
if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
/* clear any leftover/freed garbage */
@@ -207,6 +210,7 @@
* @param[in] ctx libyang context.
* @param[in] types Sized array of union types.
* @param[in] subvalue Union subvalue structure.
+ * @param[in] options The store options.
* @param[in] resolve Whether the value needs to be resolved (validated by a callback).
* @param[in] ctx_node Context node for prefix resolution.
* @param[in] tree Data tree for resolving (validation).
@@ -217,8 +221,8 @@
*/
static LY_ERR
union_find_type(const struct ly_ctx *ctx, struct lysc_type **types, struct lyd_value_union *subvalue,
- ly_bool resolve, const struct lyd_node *ctx_node, const struct lyd_node *tree, uint32_t *type_idx,
- struct lys_glob_unres *unres, struct ly_err_item **err)
+ uint32_t options, ly_bool resolve, const struct lyd_node *ctx_node, const struct lyd_node *tree,
+ uint32_t *type_idx, struct lys_glob_unres *unres, struct ly_err_item **err)
{
LY_ERR ret = LY_SUCCESS;
LY_ARRAY_COUNT_TYPE u;
@@ -242,7 +246,7 @@
/* use the first usable subtype to store the value */
for (u = 0; u < LY_ARRAY_COUNT(types); ++u) {
- ret = union_store_type(ctx, types[u], subvalue, resolve, ctx_node, tree, unres, &e);
+ ret = union_store_type(ctx, types[u], subvalue, options, resolve, ctx_node, tree, unres, &e);
if ((ret == LY_SUCCESS) || (ret == LY_EINCOMPLETE)) {
break;
}
@@ -330,7 +334,7 @@
}
/* use the specific type to store the value */
- ret = union_store_type(ctx, type_u->types[type_idx], subvalue, 0, NULL, NULL, unres, err);
+ ret = union_store_type(ctx, type_u->types[type_idx], subvalue, *options, 0, NULL, NULL, unres, err);
return ret;
}
@@ -368,7 +372,7 @@
LY_CHECK_GOTO(ret, cleanup);
/* use the first usable subtype to store the value */
- ret = union_find_type(ctx, type_u->types, subvalue, 0, NULL, NULL, NULL, unres, err);
+ ret = union_find_type(ctx, type_u->types, subvalue, options, 0, NULL, NULL, NULL, unres, err);
LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup);
}
@@ -406,11 +410,11 @@
if (subvalue->format == LY_VALUE_LYB) {
/* use the specific type to store the value */
lyb_parse_union(subvalue->original, 0, &type_idx, NULL, NULL);
- ret = union_store_type(ctx, type_u->types[type_idx], subvalue, 1, ctx_node, tree, NULL, err);
+ ret = union_store_type(ctx, type_u->types[type_idx], subvalue, 0, 1, ctx_node, tree, NULL, err);
LY_CHECK_RET(ret);
} else {
/* use the first usable subtype to store the value */
- ret = union_find_type(ctx, type_u->types, subvalue, 1, ctx_node, tree, NULL, NULL, err);
+ ret = union_find_type(ctx, type_u->types, subvalue, 0, 1, ctx_node, tree, NULL, NULL, err);
LY_CHECK_RET(ret);
}
@@ -491,7 +495,7 @@
ctx = subvalue->ctx_node->module->ctx;
}
subvalue->value.realtype->plugin->free(ctx, &subvalue->value);
- r = union_find_type(ctx, type_u->types, subvalue, 0, NULL, NULL, &type_idx, NULL, &err);
+ r = union_find_type(ctx, type_u->types, subvalue, 0, 0, NULL, NULL, &type_idx, NULL, &err);
ly_err_free(err);
LY_CHECK_RET((r != LY_SUCCESS) && (r != LY_EINCOMPLETE), NULL);
diff --git a/src/tree_data.c b/src/tree_data.c
index a5f27a3..a9146d4 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -1344,8 +1344,9 @@
LY_ERR
lyd_create_meta(struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod, const char *name,
- size_t name_len, const char *value, size_t value_len, ly_bool is_utf8, ly_bool *dynamic, LY_VALUE_FORMAT format,
- void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node, ly_bool clear_dflt, ly_bool *incomplete)
+ size_t name_len, const char *value, size_t value_len, ly_bool is_utf8, ly_bool store_only, ly_bool *dynamic,
+ LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node, ly_bool clear_dflt,
+ ly_bool *incomplete)
{
LY_ERR ret = LY_SUCCESS;
struct lysc_ext_instance *ant = NULL;
@@ -1368,7 +1369,7 @@
mt->parent = parent;
mt->annotation = ant;
lyplg_ext_get_storage(ant, LY_STMT_TYPE, sizeof ant_type, (const void **)&ant_type);
- ret = lyd_value_store(mod->ctx, &mt->value, ant_type, value, value_len, is_utf8, dynamic, format, prefix_data, hints,
+ ret = lyd_value_store(mod->ctx, &mt->value, ant_type, value, value_len, is_utf8, store_only, dynamic, format, prefix_data, hints,
ctx_node, incomplete);
LY_CHECK_ERR_GOTO(ret, free(mt), cleanup);
ret = lydict_insert(mod->ctx, name, name_len, &mt->name);
@@ -2138,7 +2139,7 @@
/* store canonical value in the target context */
val_can = lyd_get_value(node);
type = ((struct lysc_node_leaf *)term->schema)->type;
- ret = lyd_value_store(trg_ctx, &term->value, type, val_can, strlen(val_can), 1, NULL, LY_VALUE_CANON, NULL,
+ ret = lyd_value_store(trg_ctx, &term->value, type, val_can, strlen(val_can), 1, 1, NULL, LY_VALUE_CANON, NULL,
LYD_HINT_DATA, term->schema, NULL);
LY_CHECK_GOTO(ret, error);
}
@@ -2467,7 +2468,7 @@
/* duplicate callback expect only the same contexts, so use the store callback */
val_can = lyd_value_get_canonical(meta->annotation->module->ctx, &meta->value);
- ret = lyd_value_store(parent_ctx, &mt->value, ant_type, val_can, strlen(val_can), 1, NULL,
+ ret = lyd_value_store(parent_ctx, &mt->value, ant_type, val_can, strlen(val_can), 1, 1, NULL,
LY_VALUE_CANON, NULL, LYD_HINT_DATA, parent->schema, NULL);
} else {
/* annotation */
@@ -3201,11 +3202,11 @@
/* create a data node and find the instance */
if (schema->nodetype == LYS_LEAFLIST) {
/* target used attributes: schema, hash, value */
- rc = lyd_create_term(schema, key_or_value, val_len, 0, NULL, LY_VALUE_JSON, NULL, LYD_HINT_DATA, NULL, &target);
+ rc = lyd_create_term(schema, key_or_value, val_len, 0, 1, NULL, LY_VALUE_JSON, NULL, LYD_HINT_DATA, NULL, &target);
LY_CHECK_RET(rc);
} else {
/* target used attributes: schema, hash, child (all keys) */
- LY_CHECK_RET(lyd_create_list2(schema, key_or_value, val_len, &target));
+ LY_CHECK_RET(lyd_create_list2(schema, key_or_value, val_len, 1, &target));
}
/* find it */
diff --git a/src/tree_data.h b/src/tree_data.h
index a7ce4bf..9084f8e 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -282,11 +282,10 @@
* - ::lyd_new_inner()
* - ::lyd_new_term()
* - ::lyd_new_term_bin()
- * - ::lyd_new_term_canon()
* - ::lyd_new_list()
- * - ::lyd_new_list_bin()
- * - ::lyd_new_list_canon()
* - ::lyd_new_list2()
+ * - ::lyd_new_list3()
+ * - ::lyd_new_list3_bin()
* - ::lyd_new_any()
* - ::lyd_new_opaq()
* - ::lyd_new_opaq2()
@@ -1248,53 +1247,60 @@
LIBYANG_API_DECL LY_ERR lyd_new_ext_inner(const struct lysc_ext_instance *ext, const char *name, struct lyd_node **node);
/**
+ * @ingroup datatree
+ * @defgroup newvalueoptions New value creation options
+ *
+ * Various options to change lyd_new_*() behavior. The LYD_NEW_VAL* can be used within any API, others
+ * are API specific
+ *
+ * Default behavior:
+ * - the input data nodes or RPC/Action is taken into account
+ * - the value is being validated with all possible validations, which doesn't require existence of any other data nodes
+ * - the input value is expected to be in JSON format
+ * - if the target node already exists (and is not default), an error is returned.
+ * - the whole path to the target node is created (with any missing parents) if necessary.
+ * - RPC output schema children are completely ignored in all modules. Input is searched and nodes created normally.
+ * - during creation of new metadata, the nodes will have default flag set
+ * - value is copied and stored internally during any node creation
+ * @{
+ */
+
+#define LYD_NEW_VAL_OUTPUT 0x01 /**< Flag in case the @p parent is RPC/Action. If value is 0, the input's data nodes of the RPC/Action are
+ taken into consideration. Otherwise, the output's data node is going to be created. */
+#define LYD_NEW_VAL_STORE_ONLY 0x02 /**< Whether to perform only storing operation with no or minimum valitions */
+#define LYD_NEW_VAL_BIN_VALUE 0x04 /**< Interpret the provided leaf/leaf-list @p value as being in the binary
+ ::LY_VALUE_LYB format, to learn what exactly is expected see @ref howtoDataLYB. */
+#define LYD_NEW_VAL_CANON_VALUE 0x08 /**< Interpret the provided leaf/leaf-list @p value as being in the canonical
+ (or JSON if no defined) ::LY_VALUE_CANON format. If it is not, it may lead
+ to unexpected behavior. */
+#define LYD_NEW_META_CLEAR_DFLT 0x10 /**< Whether to clear the default flag starting from @p parent, recursively all NP containers. */
+#define LYD_NEW_PATH_UPDATE 0x20 /**< If the target node exists, is a leaf, and it is updated with a new value or its
+ default flag is changed, it is returned. If the target node exists and is not
+ a leaf or generally no change occurs in the @p parent tree, NULL is returned and
+ no error set. */
+#define LYD_NEW_PATH_OPAQ 0x40 /**< Enables the creation of opaque nodes with some specific rules. If the __last node__
+ in the path is not uniquely defined ((leaf-)list without a predicate) or has an
+ invalid value (leaf/leaf-list), it is created as opaque. */
+#define LYD_NEW_PATH_WITH_OPAQ 0x80 /**< Consider opaque nodes normally when searching for existing nodes. */
+#define LYD_NEW_ANY_USE_VALUE 0x100 /**< Whether to use dynamic @p value or make a copy. */
+
+/** @} newvalueoptions */
+
+/**
* @brief Create a new list node in the data tree.
*
* @param[in] parent Parent node for the node being created. NULL in case of creating a top level element.
* @param[in] module Module of the node being created. If NULL, @p parent module will be used.
* @param[in] name Schema node name of the new data node. The node must be #LYS_LIST.
- * @param[in] output Flag in case the @p parent is RPC/Action. If value is 0, the input's data nodes of the RPC/Action are
- * taken into consideration. Otherwise, the output's data node is going to be created.
+ * @param[in] options Bitmask of options, see @ref newvalueoptions.
* @param[out] node Optional created node.
* @param[in] ... Ordered key values of the new list instance, all must be set. In case of an instance-identifier
- * or identityref value, the JSON format is expected (module names instead of prefixes). No keys are expected for
- * key-less lists.
+ * or identityref value, the JSON format is expected (module names instead of prefixes). No keys are expected for key-less lists.
+ * In case of format set to LY_FORMAT_LYB, every key value must be followed by its length.
* @return LY_ERR value.
*/
LIBYANG_API_DECL LY_ERR lyd_new_list(struct lyd_node *parent, const struct lys_module *module, const char *name,
- ly_bool output, struct lyd_node **node, ...);
-
-/**
- * @brief Create a new list node in the data tree.
- *
- * @param[in] parent Parent node for the node being created. NULL in case of creating a top level element.
- * @param[in] module Module of the node being created. If NULL, @p parent module will be used.
- * @param[in] name Schema node name of the new data node. The node must be #LYS_LIST.
- * @param[in] output Flag in case the @p parent is RPC/Action. If value is 0, the input's data nodes of the RPC/Action are
- * taken into consideration. Otherwise, the output's data node is going to be created.
- * @param[out] node Optional created node.
- * @param[in] ... Ordered binary key values of the new list instance, all must be set. Every key value must be followed
- * by its length. No keys are expected for key-less lists.
- * @return LY_ERR value.
- */
-LIBYANG_API_DECL LY_ERR lyd_new_list_bin(struct lyd_node *parent, const struct lys_module *module, const char *name,
- ly_bool output, struct lyd_node **node, ...);
-
-/**
- * @brief Create a new list node in the data tree.
- *
- * @param[in] parent Parent node for the node being created. NULL in case of creating a top level element.
- * @param[in] module Module of the node being created. If NULL, @p parent module will be used.
- * @param[in] name Schema node name of the new data node. The node must be #LYS_LIST.
- * @param[in] output Flag in case the @p parent is RPC/Action. If value is 0, the input's data nodes of the RPC/Action are
- * taken into consideration. Otherwise, the output's data node is going to be created.
- * @param[out] node Optional created node.
- * @param[in] ... Ordered canonical key values of the new list instance, all must be set. No keys are expected for
- * key-less lists.
- * @return LY_ERR value.
- */
-LIBYANG_API_DECL LY_ERR lyd_new_list_canon(struct lyd_node *parent, const struct lys_module *module, const char *name,
- ly_bool output, struct lyd_node **node, ...);
+ uint32_t options, struct lyd_node **node, ...);
/**
* @brief Create a new top-level list node defined in the given extension instance.
@@ -1304,13 +1310,15 @@
*
* @param[in] ext Extension instance where the list node being created is defined.
* @param[in] name Schema node name of the new data node. The node must be #LYS_LIST.
+ * @param[in] options Bitmask of options, see @ref newvalueoptions.
* @param[out] node The created node.
* @param[in] ... Ordered key values of the new list instance, all must be set. In case of an instance-identifier
- * or identityref value, the JSON format is expected (module names instead of prefixes). No keys are expected for
- * key-less lists.
+ * or identityref value, the JSON format is expected (module names instead of prefixes). No keys are expected for key-less lists.
+ * In case of format set to LY_FORMAT_LYB, every key value must be followed by its length.
* @return LY_ERR value.
*/
-LIBYANG_API_DECL LY_ERR lyd_new_ext_list(const struct lysc_ext_instance *ext, const char *name, struct lyd_node **node, ...);
+LIBYANG_API_DECL LY_ERR lyd_new_ext_list(const struct lysc_ext_instance *ext, const char *name, uint32_t options,
+ struct lyd_node **node, ...);
/**
* @brief Create a new list node in the data tree.
@@ -1321,109 +1329,77 @@
* @param[in] keys All key values predicate in the form of "[key1='val1'][key2='val2']...", they do not have to be ordered.
* In case of an instance-identifier or identityref value, the JSON format is expected (module names instead of prefixes).
* Use NULL or string of length 0 in case of key-less list.
- * @param[in] output Flag in case the @p parent is RPC/Action. If value is 0, the input's data nodes of the RPC/Action are
- * taken into consideration. Otherwise, the output's data node is going to be created.
+ * @param[in] options Bitmask of options, see @ref newvalueoptions.
* @param[out] node Optional created node.
* @return LY_ERR value.
*/
LIBYANG_API_DECL LY_ERR lyd_new_list2(struct lyd_node *parent, const struct lys_module *module, const char *name,
- const char *keys, ly_bool output, struct lyd_node **node);
+ const char *keys, uint32_t options, struct lyd_node **node);
/**
* @brief Create a new list node in the data tree.
*
+ * To create a term node based on binary value, use ::lyd_new_list3_bin().
+ *
* @param[in] parent Parent node for the node being created. NULL in case of creating a top level element.
* @param[in] module Module of the node being created. If NULL, @p parent module will be used.
* @param[in] name Schema node name of the new data node. The node must be #LYS_LIST.
* @param[in] key_values Ordered key string values of the new list instance, all must be set.
* @param[in] value_lengths Array of lengths of each @p key_values, may be NULL if @p key_values are 0-terminated strings.
- * @param[in] output Flag in case the @p parent is RPC/Action. If value is 0, the input's data nodes of the RPC/Action are
- * taken into consideration. Otherwise, the output's data node is going to be created.
+ * @param[in] options Bitmask of options, see @ref newvalueoptions.
* @param[out] node Optional created node.
* @return LY_ERR value.
*/
LIBYANG_API_DECL LY_ERR lyd_new_list3(struct lyd_node *parent, const struct lys_module *module, const char *name,
- const char **key_values, uint32_t *value_lengths, ly_bool output, struct lyd_node **node);
+ const char **key_values, uint32_t *value_lengths, uint32_t options, struct lyd_node **node);
/**
- * @brief Create a new list node in the data tree.
+ * @brief Create a new list node in the data tree based on binary value.
*
* @param[in] parent Parent node for the node being created. NULL in case of creating a top level element.
* @param[in] module Module of the node being created. If NULL, @p parent module will be used.
* @param[in] name Schema node name of the new data node. The node must be #LYS_LIST.
- * @param[in] key_values Ordered key binary (LYB) values of the new list instance, all must be set.
- * @param[in] value_lengths Array of lengths of each @p key_values.
- * @param[in] output Flag in case the @p parent is RPC/Action. If value is 0, the input's data nodes of the RPC/Action are
- * taken into consideration. Otherwise, the output's data node is going to be created.
+ * @param[in] key_values Ordered key string values of the new list instance, all must be set.
+ * @param[in] value_lengths Array of lengths of each @p key_values, may be NULL if @p key_values are 0-terminated strings.
+ * @param[in] options Bitmask of options, see @ref newvalueoptions.
* @param[out] node Optional created node.
* @return LY_ERR value.
*/
LIBYANG_API_DECL LY_ERR lyd_new_list3_bin(struct lyd_node *parent, const struct lys_module *module, const char *name,
- const void **key_values, uint32_t *value_lengths, ly_bool output, struct lyd_node **node);
-
-/**
- * @brief Create a new list node in the data tree.
- *
- * @param[in] parent Parent node for the node being created. NULL in case of creating a top level element.
- * @param[in] module Module of the node being created. If NULL, @p parent module will be used.
- * @param[in] name Schema node name of the new data node. The node must be #LYS_LIST.
- * @param[in] key_values Ordered key canonical values of the new list instance, all must be set.
- * @param[in] value_lengths Array of lengths of each @p key_values, may be NULL if @p key_values are 0-terminated strings.
- * @param[in] output Flag in case the @p parent is RPC/Action. If value is 0, the input's data nodes of the RPC/Action are
- * taken into consideration. Otherwise, the output's data node is going to be created.
- * @param[out] node Optional created node.
- * @return LY_ERR value.
- */
-LIBYANG_API_DECL LY_ERR lyd_new_list3_canon(struct lyd_node *parent, const struct lys_module *module, const char *name,
- const char **key_values, uint32_t *value_lengths, ly_bool output, struct lyd_node **node);
+ const void **key_values, uint32_t *value_lengths, uint32_t options, struct lyd_node **node);
/**
* @brief Create a new term node in the data tree.
*
* To create a top-level term node defined in an extension instance, use ::lyd_new_ext_term().
+ * To create a term node based on binary value, use ::lyd_new_term_bin().
*
* @param[in] parent Parent node for the node being created. NULL in case of creating a top level element.
* @param[in] module Module of the node being created. If NULL, @p parent module will be used.
* @param[in] name Schema node name of the new data node. The node can be #LYS_LEAF or #LYS_LEAFLIST.
- * @param[in] val_str String value of the node. If it varies based on the format, ::LY_VALUE_JSON is expected.
- * @param[in] output Flag in case the @p parent is RPC/Action. If value is 0, the input's data nodes of the RPC/Action are
- * taken into consideration. Otherwise, the output's data node is going to be created.
+ * @param[in] value The value of the node in @p format.
+ * @param[in] options Bitmask of options, see @ref newvalueoptions.
* @param[out] node Optional created node.
* @return LY_ERR value.
*/
LIBYANG_API_DECL LY_ERR lyd_new_term(struct lyd_node *parent, const struct lys_module *module, const char *name,
- const char *val_str, ly_bool output, struct lyd_node **node);
+ const char *value, uint32_t options, struct lyd_node **node);
/**
- * @brief Create a new term node in the data tree.
+ * @brief Create a new term node in the data tree based on binary value.
*
* @param[in] parent Parent node for the node being created. NULL in case of creating a top level element.
* @param[in] module Module of the node being created. If NULL, @p parent module will be used.
* @param[in] name Schema node name of the new data node. The node can be #LYS_LEAF or #LYS_LEAFLIST.
* @param[in] value Binary value of the node. To learn what exactly is expected see @ref howtoDataLYB.
+ * @param[in] value The value of the node in @p format.
* @param[in] value_len Length of @p value.
- * @param[in] output Flag in case the @p parent is RPC/Action. If value is 0, the input's data nodes of the RPC/Action are
- * taken into consideration. Otherwise, the output's data node is going to be created.
+ * @param[in] options Bitmask of options, see @ref newvalueoptions.
* @param[out] node Optional created node.
* @return LY_ERR value.
*/
LIBYANG_API_DECL LY_ERR lyd_new_term_bin(struct lyd_node *parent, const struct lys_module *module, const char *name,
- const void *value, size_t value_len, ly_bool output, struct lyd_node **node);
-
-/**
- * @brief Create a new term node in the data tree.
- *
- * @param[in] parent Parent node for the node being created. NULL in case of creating a top level element.
- * @param[in] module Module of the node being created. If NULL, @p parent module will be used.
- * @param[in] name Schema node name of the new data node. The node can be #LYS_LEAF or #LYS_LEAFLIST.
- * @param[in] val_str Canonical string value of the node. If it is not, it may lead to unexpected behavior.
- * @param[in] output Flag in case the @p parent is RPC/Action. If value is 0, the input's data nodes of the RPC/Action are
- * taken into consideration. Otherwise, the output's data node is going to be created.
- * @param[out] node Optional created node.
- * @return LY_ERR value.
- */
-LIBYANG_API_DECL LY_ERR lyd_new_term_canon(struct lyd_node *parent, const struct lys_module *module, const char *name,
- const char *val_str, ly_bool output, struct lyd_node **node);
+ const void *value, size_t value_len, uint32_t options, struct lyd_node **node);
/**
* @brief Create a new top-level term node defined in the given extension instance.
@@ -1434,12 +1410,14 @@
* @param[in] ext Extension instance where the term node being created is defined.
* @param[in] name Schema node name of the new data node. The node can be #LYS_LEAF or #LYS_LEAFLIST.
* @param[in] val_str String form of the value of the node being created. In case of an instance-identifier or identityref
- * value, the JSON format is expected (module names instead of prefixes).
+ * @param[in] value The value of the node in @p format. In case of an instance-identifier or identityref value,
+ * the JSON format is expected (module names instead of prefixes).
+ * @param[in] options Bitmask of options, see @ref newvalueoptions.
* @param[out] node The created node.
* @return LY_ERR value.
*/
-LIBYANG_API_DECL LY_ERR lyd_new_ext_term(const struct lysc_ext_instance *ext, const char *name, const char *val_str,
- struct lyd_node **node);
+LIBYANG_API_DECL LY_ERR lyd_new_ext_term(const struct lysc_ext_instance *ext, const char *name, const void *value,
+ size_t value_len, uint32_t options, struct lyd_node **node);
/**
* @brief Create a new any node in the data tree.
@@ -1450,15 +1428,13 @@
* @param[in] module Module of the node being created. If NULL, @p parent module will be used.
* @param[in] name Schema node name of the new data node. The node can be #LYS_ANYDATA or #LYS_ANYXML.
* @param[in] value Value for the node. Expected type is determined by @p value_type.
- * @param[in] use_value Whether to use dynamic @p value or make a copy.
+ * @param[in] options Bitmask of options, see @ref newvalueoptions.
* @param[in] value_type Type of the provided value in @p value.
- * @param[in] output Flag in case the @p parent is RPC/Action. If value is 0, the input's data nodes of the RPC/Action are
- * taken into consideration. Otherwise, the output's data node is going to be created.
* @param[out] node Optional created node.
* @return LY_ERR value.
*/
LIBYANG_API_DECL LY_ERR lyd_new_any(struct lyd_node *parent, const struct lys_module *module, const char *name,
- const void *value, ly_bool use_value, LYD_ANYDATA_VALUETYPE value_type, ly_bool output, struct lyd_node **node);
+ const void *value, uint32_t options, LYD_ANYDATA_VALUETYPE value_type, struct lyd_node **node);
/**
* @brief Create a new top-level any node defined in the given extension instance.
@@ -1469,13 +1445,13 @@
* @param[in] ext Extension instance where the any node being created is defined.
* @param[in] name Schema node name of the new data node. The node can be #LYS_ANYDATA or #LYS_ANYXML.
* @param[in] value Value for the node. Expected type is determined by @p value_type.
- * @param[in] use_value Whether to use dynamic @p value or make a copy.
+ * @param[in] options Bitmask of options, see @ref newvalueoptions.
* @param[in] value_type Type of the provided value in @p value.
* @param[out] node The created node.
* @return LY_ERR value.
*/
LIBYANG_API_DECL LY_ERR lyd_new_ext_any(const struct lysc_ext_instance *ext, const char *name, const void *value,
- ly_bool use_value, LYD_ANYDATA_VALUETYPE value_type, struct lyd_node **node);
+ uint32_t options, LYD_ANYDATA_VALUETYPE value_type, struct lyd_node **node);
/**
* @brief Create new metadata.
@@ -1487,26 +1463,26 @@
* If the prefix is specified it is always used but if not specified, @p module must be set.
* @param[in] val_str String form of the value of the metadata. In case of an instance-identifier or identityref
* value, the JSON format is expected (module names instead of prefixes).
- * @param[in] clear_dflt Whether to clear the default flag starting from @p parent, recursively all NP containers.
+ * @param[in] options Bitmask of options, see @ref newvalueoptions.
* @param[out] meta Optional created metadata. Must be set if @p parent is NULL.
* @return LY_ERR value.
*/
LIBYANG_API_DECL LY_ERR lyd_new_meta(const struct ly_ctx *ctx, struct lyd_node *parent, const struct lys_module *module,
- const char *name, const char *val_str, ly_bool clear_dflt, struct lyd_meta **meta);
+ const char *name, const char *val_str, uint32_t options, struct lyd_meta **meta);
/**
* @brief Create new metadata from an opaque node attribute if possible.
*
* @param[in] ctx libyang context.
* @param[in] parent Optional parent node for the metadata being created. Must be set if @p meta is NULL.
- * @param[in] clear_dflt Whether to clear the default flag starting from @p parent, recursively all NP containers.
+ * @param[in] options Bitmask of options, see @ref newvalueoptions.
* @param[in] attr Opaque node attribute to parse into metadata.
* @param[out] meta Optional created metadata. Must be set if @p parent is NULL.
* @return LY_SUCCESS on success.
* @return LY_ENOT if the attribute could not be parsed into any metadata.
* @return LY_ERR on error.
*/
-LIBYANG_API_DECL LY_ERR lyd_new_meta2(const struct ly_ctx *ctx, struct lyd_node *parent, ly_bool clear_dflt,
+LIBYANG_API_DECL LY_ERR lyd_new_meta2(const struct ly_ctx *ctx, struct lyd_node *parent, uint32_t options,
const struct lyd_attr *attr, struct lyd_meta **meta);
/**
@@ -1571,37 +1547,6 @@
struct lyd_attr **attr);
/**
- * @ingroup datatree
- * @defgroup pathoptions Data path creation options
- *
- * Various options to change lyd_new_path*() behavior.
- *
- * Default behavior:
- * - if the target node already exists (and is not default), an error is returned.
- * - the whole path to the target node is created (with any missing parents) if necessary.
- * - RPC output schema children are completely ignored in all modules. Input is searched and nodes created normally.
- * @{
- */
-
-#define LYD_NEW_PATH_UPDATE 0x01 /**< If the target node exists, is a leaf, and it is updated with a new value or its
- default flag is changed, it is returned. If the target node exists and is not
- a leaf or generally no change occurs in the @p parent tree, NULL is returned and
- no error set. */
-#define LYD_NEW_PATH_OUTPUT 0x02 /**< Changes the behavior to ignoring RPC/action input schema nodes and using only
- output ones. */
-#define LYD_NEW_PATH_OPAQ 0x04 /**< Enables the creation of opaque nodes with some specific rules. If the __last node__
- in the path is not uniquely defined ((leaf-)list without a predicate) or has an
- invalid value (leaf/leaf-list), it is created as opaque. */
-#define LYD_NEW_PATH_BIN_VALUE 0x08 /**< Interpret the provided leaf/leaf-list @p value as being in the binary
- ::LY_VALUE_LYB format, to learn what exactly is expected see @ref howtoDataLYB. */
-#define LYD_NEW_PATH_CANON_VALUE 0x10 /**< Interpret the provided leaf/leaf-list @p value as being in the canonical
- (or JSON if no defined) ::LY_VALUE_CANON format. If it is not, it may lead
- to unexpected behavior. */
-#define LYD_NEW_PATH_WITH_OPAQ 0x20 /**< Consider opaque nodes normally when searching for existing nodes. */
-
-/** @} pathoptions */
-
-/**
* @brief Create a new node in the data tree based on a path. If creating anyxml/anydata nodes, ::lyd_new_path2
* should be used instead, this function expects the value as string.
*
@@ -1622,7 +1567,7 @@
* @param[in] path [Path](@ref howtoXPath) to create.
* @param[in] value String value of the new leaf/leaf-list. If it varies based on the format, ::LY_VALUE_JSON is expected.
* For other node types, it should be NULL.
- * @param[in] options Bitmask of options, see @ref pathoptions.
+ * @param[in] options Bitmask of options, see @ref newvaloptions.
* @param[out] node Optional first created node.
* @return LY_SUCCESS on success.
* @return LY_EEXIST if the final node to create exists (unless ::LYD_NEW_PATH_UPDATE is used).
@@ -1648,7 +1593,7 @@
* @param[in] value_len Length of @p value in bytes. May be 0 if @p value is a zero-terminated string. Ignored when
* creating anyxml/anydata nodes.
* @param[in] value_type Anyxml/anydata node @p value type.
- * @param[in] options Bitmask of options, see @ref pathoptions.
+ * @param[in] options Bitmask of options, see @ref newvaloptions.
* @param[out] new_parent Optional first parent node created. If only one node was created, equals to @p new_node.
* @param[out] new_node Optional last node created.
* @return LY_SUCCESS on success.
@@ -1675,7 +1620,7 @@
* @param[in] ext Extension instance where the node being created is defined.
* @param[in] path [Path](@ref howtoXPath) to create.
* @param[in] value Value of the new leaf/leaf-list. For other node types, it should be NULL.
- * @param[in] options Bitmask of options, see @ref pathoptions.
+ * @param[in] options Bitmask of options, see @ref nevaloptions.
* @param[out] node Optional first created node.
* @return LY_SUCCESS on success.
* @return LY_EEXIST if the final node to create exists (unless ::LYD_NEW_PATH_UPDATE is used).
diff --git a/src/tree_data_common.c b/src/tree_data_common.c
index eb14433..9746faa 100644
--- a/src/tree_data_common.c
+++ b/src/tree_data_common.c
@@ -505,8 +505,8 @@
LY_ERR
lyd_value_store(const struct ly_ctx *ctx, struct lyd_value *val, const struct lysc_type *type, const void *value,
- size_t value_len, ly_bool is_utf8, ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints,
- const struct lysc_node *ctx_node, ly_bool *incomplete)
+ size_t value_len, ly_bool is_utf8, ly_bool store_only, ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data,
+ uint32_t hints, const struct lysc_node *ctx_node, ly_bool *incomplete)
{
LY_ERR ret;
struct ly_err_item *err = NULL;
@@ -525,6 +525,9 @@
if (is_utf8) {
options |= LYPLG_TYPE_STORE_IS_UTF8;
}
+ if (store_only) {
+ options |= LYPLG_TYPE_STORE_ONLY;
+ }
ret = type->plugin->store(ctx, type, value, value_len, options, format, prefix_data, hints, ctx_node, val, NULL, &err);
if (dynamic) {
@@ -688,7 +691,7 @@
/* store the value */
LOG_LOCSET(NULL, &node->node);
- ret = lyd_value_store(ctx, &val, type, value, value_len, 0, NULL, LY_VALUE_JSON, NULL, LYD_HINT_DATA, node->schema, NULL);
+ ret = lyd_value_store(ctx, &val, type, value, value_len, 0, 0, NULL, LY_VALUE_JSON, NULL, LYD_HINT_DATA, node->schema, NULL);
LOG_LOCBACK(0, 1);
LY_CHECK_RET(ret);
diff --git a/src/tree_data_internal.h b/src/tree_data_internal.h
index 57ec2c4..2bfa66d 100644
--- a/src/tree_data_internal.h
+++ b/src/tree_data_internal.h
@@ -225,6 +225,7 @@
* @param[in] value String value to be parsed.
* @param[in] value_len Length of @p value, must be set correctly.
* @param[in] is_utf8 Whether @p value is a valid UTF-8 string, if applicable.
+ * @param[in] store_only Whether to perform storing operation only.
* @param[in,out] dynamic Flag if @p value is dynamically allocated, is adjusted when @p value is consumed.
* @param[in] format Input format of @p value.
* @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
@@ -236,8 +237,8 @@
* @return LY_ERR value if an error occurred.
*/
LY_ERR lyd_create_term(const struct lysc_node *schema, const char *value, size_t value_len, ly_bool is_utf8,
- ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, ly_bool *incomplete,
- struct lyd_node **node);
+ ly_bool store_only, ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints,
+ ly_bool *incomplete, struct lyd_node **node);
/**
* @brief Create a term (leaf/leaf-list) node from a parsed value by duplicating it.
@@ -274,12 +275,13 @@
* @param[in] schema Schema node of the new data node.
* @param[in] predicates Compiled key list predicates.
* @param[in] vars Array of defined variables to use in predicates, may be NULL.
+ * @param[in] store_only Whether to perform storing operation only.
* @param[out] node Created node.
* @return LY_SUCCESS on success.
* @return LY_ERR value if an error occurred.
*/
LY_ERR lyd_create_list(const struct lysc_node *schema, const struct ly_path_predicate *predicates,
- const struct lyxp_var *vars, struct lyd_node **node);
+ const struct lyxp_var *vars, ly_bool store_only, struct lyd_node **node);
/**
* @brief Create a list with all its keys (cannot be used for key-less list).
@@ -289,11 +291,13 @@
* @param[in] schema Schema node of the new data node.
* @param[in] keys Key list predicates.
* @param[in] keys_len Length of @p keys.
+ * @param[in] store_only Whether to perform storing operation only.
* @param[out] node Created node.
* @return LY_SUCCESS on success.
* @return LY_ERR value if an error occurred.
*/
-LY_ERR lyd_create_list2(const struct lysc_node *schema, const char *keys, size_t keys_len, struct lyd_node **node);
+LY_ERR lyd_create_list2(const struct lysc_node *schema, const char *keys, size_t keys_len, ly_bool store_only,
+ struct lyd_node **node);
/**
* @brief Create an anyxml/anydata node.
@@ -464,6 +468,7 @@
* @param[in] value String value to be parsed.
* @param[in] value_len Length of @p value, must be set correctly.
* @param[in] is_utf8 Whether @p value is a valid UTF-8 string, if applicable.
+ * @param[in] store_only Whether to perform storing operation only.
* @param[in,out] dynamic Flag if @p value is dynamically allocated, is adjusted when @p value is consumed.
* @param[in] format Input format of @p value.
* @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
@@ -476,8 +481,9 @@
* @return LY_ERR value if an error occurred.
*/
LY_ERR lyd_create_meta(struct lyd_node *parent, struct lyd_meta **meta, const struct lys_module *mod, const char *name,
- size_t name_len, const char *value, size_t value_len, ly_bool is_utf8, ly_bool *dynamic, LY_VALUE_FORMAT format,
- void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node, ly_bool clear_dflt, ly_bool *incomplete);
+ size_t name_len, const char *value, size_t value_len, ly_bool is_utf8, ly_bool store_only, ly_bool *dynamic,
+ LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node, ly_bool clear_dflt,
+ ly_bool *incomplete);
/**
* @brief Create a copy of the metadata.
@@ -533,6 +539,7 @@
* @param[in] value Value to be parsed, must not be NULL.
* @param[in] value_len Length of the give @p value, must be set correctly.
* @param[in] is_utf8 Whether @p value is a valid UTF-8 string, if applicable.
+ * @param[in] store_only Whether to perform storing operation only.
* @param[in,out] dynamic Flag if @p value is dynamically allocated, is adjusted when @p value is consumed.
* @param[in] format Input format of @p value.
* @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
@@ -543,8 +550,8 @@
* @return LY_ERR value on error.
*/
LY_ERR lyd_value_store(const struct ly_ctx *ctx, struct lyd_value *val, const struct lysc_type *type, const void *value,
- size_t value_len, ly_bool is_utf8, ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints,
- const struct lysc_node *ctx_node, ly_bool *incomplete);
+ size_t value_len, ly_bool is_utf8, ly_bool store_only, ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data,
+ uint32_t hints, const struct lysc_node *ctx_node, ly_bool *incomplete);
/**
* @brief Validate previously incompletely stored value.
diff --git a/src/tree_data_new.c b/src/tree_data_new.c
index bbe59f2..7a965a3 100644
--- a/src/tree_data_new.c
+++ b/src/tree_data_new.c
@@ -52,8 +52,8 @@
#include "xpath.h"
LY_ERR
-lyd_create_term(const struct lysc_node *schema, const char *value, size_t value_len, ly_bool is_utf8, ly_bool *dynamic,
- LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, ly_bool *incomplete, struct lyd_node **node)
+lyd_create_term(const struct lysc_node *schema, const char *value, size_t value_len, ly_bool is_utf8, ly_bool store_only,
+ ly_bool *dynamic, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, ly_bool *incomplete, struct lyd_node **node)
{
LY_ERR ret;
struct lyd_node_term *term;
@@ -69,7 +69,7 @@
LOG_LOCSET(schema, NULL);
ret = lyd_value_store(schema->module->ctx, &term->value, ((struct lysc_node_leaf *)term->schema)->type, value,
- value_len, is_utf8, dynamic, format, prefix_data, hints, schema, incomplete);
+ value_len, is_utf8, store_only, dynamic, format, prefix_data, hints, schema, incomplete);
LOG_LOCBACK(1, 0);
LY_CHECK_ERR_RET(ret, free(term), ret);
lyd_hash(&term->node);
@@ -136,7 +136,7 @@
LY_ERR
lyd_create_list(const struct lysc_node *schema, const struct ly_path_predicate *predicates, const struct lyxp_var *vars,
- struct lyd_node **node)
+ ly_bool store_only, struct lyd_node **node)
{
LY_ERR ret = LY_SUCCESS;
struct lyd_node *list = NULL, *key;
@@ -163,7 +163,7 @@
/* store the value */
LOG_LOCSET(predicates[u].key, NULL);
ret = lyd_value_store(schema->module->ctx, &val, ((struct lysc_node_leaf *)predicates[u].key)->type,
- var->value, strlen(var->value), 0, NULL, LY_VALUE_JSON, NULL, LYD_HINT_DATA, predicates[u].key, NULL);
+ var->value, strlen(var->value), 0, store_only, NULL, LY_VALUE_JSON, NULL, LYD_HINT_DATA, predicates[u].key, NULL);
LOG_LOCBACK(1, 0);
LY_CHECK_GOTO(ret, cleanup);
@@ -196,7 +196,7 @@
}
LY_ERR
-lyd_create_list2(const struct lysc_node *schema, const char *keys, size_t keys_len, struct lyd_node **node)
+lyd_create_list2(const struct lysc_node *schema, const char *keys, size_t keys_len, ly_bool store_only, struct lyd_node **node)
{
LY_ERR ret = LY_SUCCESS;
struct lyxp_expr *expr = NULL;
@@ -214,7 +214,7 @@
NULL, &predicates), cleanup);
/* create the list node */
- LY_CHECK_GOTO(ret = lyd_create_list(schema, predicates, NULL, node), cleanup);
+ LY_CHECK_GOTO(ret = lyd_create_list(schema, predicates, NULL, store_only, node), cleanup);
cleanup:
LOG_LOCBACK(1, 0);
@@ -471,6 +471,29 @@
return ret;
}
+/**
+ * @brief Gets format from lyd_new_* options
+ *
+ * @param[in] options Bitmask of options, see @ref newvalueoptions.
+ * @param[out] format The output format.
+ * @return LY_ERR value.
+ */
+static LY_ERR
+_lyd_new_val_format(const uint32_t options, LY_VALUE_FORMAT *format)
+{
+ LY_CHECK_ARG_RET(NULL, format, !((options & LYD_NEW_VAL_BIN_VALUE) && (options & LYD_NEW_VAL_CANON_VALUE)), LY_EVALID);
+
+ if (options & LYD_NEW_VAL_BIN_VALUE) {
+ *format = LY_VALUE_LYB;
+ } else if (options & LYD_NEW_VAL_CANON_VALUE) {
+ *format = LY_VALUE_CANON;
+ } else {
+ *format = LY_VALUE_JSON;
+ }
+
+ return LY_SUCCESS;
+}
+
LIBYANG_API_DEF LY_ERR
lyd_new_inner(struct lyd_node *parent, const struct lys_module *module, const char *name, ly_bool output,
struct lyd_node **node)
@@ -546,25 +569,25 @@
* @param[in] parent Parent node for the node being created. NULL in case of creating a top level element.
* @param[in] module Module of the node being created. If NULL, @p parent module will be used.
* @param[in] name Schema node name of the new data node. The node must be #LYS_LIST.
- * @param[in] output Flag in case the @p parent is RPC/Action. If value is 0, the input's data nodes of the RPC/Action are
- * taken into consideration. Otherwise, the output's data node is going to be created.
+ * @param[in] options Bitmask of options, see @ref newvalueoptions.
* @param[out] node Created node.
* @return LY_ERR value.
*/
static LY_ERR
_lyd_new_list_node(const struct ly_ctx *ctx, const struct lyd_node *parent, const struct lys_module *module,
- const char *name, ly_bool output, struct lyd_node **node)
+ const char *name, uint32_t options, struct lyd_node **node)
{
struct lyd_node *ret = NULL;
const struct lysc_node *schema;
struct lysc_ext_instance *ext = NULL;
+ uint32_t getnext_opts = (options & LYD_NEW_VAL_OUTPUT) ? LYS_GETNEXT_OUTPUT : 0;
LY_ERR r;
if (!module) {
module = parent->schema->module;
}
- schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, output ? LYS_GETNEXT_OUTPUT : 0);
+ schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, getnext_opts);
if (!schema && parent) {
r = ly_nested_ext_schema(parent, NULL, module->name, strlen(module->name), LY_VALUE_JSON, NULL, name,
strlen(name), &schema, &ext);
@@ -583,23 +606,9 @@
return LY_SUCCESS;
}
-/**
- * @brief Create a new list node in the data tree.
- *
- * @param[in] parent Parent node for the node being created. NULL in case of creating a top level element.
- * @param[in] module Module of the node being created. If NULL, @p parent module will be used.
- * @param[in] name Schema node name of the new data node. The node must be #LYS_LIST.
- * @param[in] format Format of key values.
- * @param[in] output Flag in case the @p parent is RPC/Action. If value is 0, the input's data nodes of the RPC/Action are
- * taken into consideration. Otherwise, the output's data node is going to be created.
- * @param[out] node Optional created node.
- * @param[in] ap Ordered key values of the new list instance, all must be set. For ::LY_VALUE_LYB, every value must
- * be followed by the value length.
- * @return LY_ERR value.
- */
-static LY_ERR
-_lyd_new_list(struct lyd_node *parent, const struct lys_module *module, const char *name, LY_VALUE_FORMAT format,
- ly_bool output, struct lyd_node **node, va_list ap)
+LIBYANG_API_DEF LY_ERR
+lyd_new_list(struct lyd_node *parent, const struct lys_module *module, const char *name, uint32_t options,
+ struct lyd_node **node, ...)
{
struct lyd_node *ret = NULL, *key;
const struct lysc_node *key_s;
@@ -607,13 +616,19 @@
const void *key_val;
uint32_t key_len;
LY_ERR rc = LY_SUCCESS;
+ ly_bool store_only = (options & LYD_NEW_VAL_STORE_ONLY) ? 1 : 0;
+ LY_VALUE_FORMAT format;
+ va_list ap;
LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
+ LY_CHECK_RET(_lyd_new_val_format(options, &format));
+ LY_CHECK_ARG_RET(ctx, !(store_only && (format == LY_VALUE_CANON || format == LY_VALUE_LYB)), LY_EINVAL);
/* create the list node */
- LY_CHECK_RET(_lyd_new_list_node(ctx, parent, module, name, output, &ret));
+ LY_CHECK_RET(_lyd_new_list_node(ctx, parent, module, name, options, &ret));
+ va_start(ap, node);
/* create and insert all the keys */
for (key_s = lysc_node_child(ret->schema); key_s && (key_s->flags & LYS_KEY); key_s = key_s->next) {
if (format == LY_VALUE_LYB) {
@@ -623,8 +638,7 @@
key_val = va_arg(ap, const char *);
key_len = key_val ? strlen((char *)key_val) : 0;
}
-
- rc = lyd_create_term(key_s, key_val, key_len, 0, NULL, format, NULL, LYD_HINT_DATA, NULL, &key);
+ rc = lyd_create_term(key_s, key_val, key_len, 0, store_only, NULL, format, NULL, LYD_HINT_DATA, NULL, &key);
LY_CHECK_GOTO(rc, cleanup);
lyd_insert_node(ret, NULL, key, LYD_INSERT_NODE_LAST);
}
@@ -634,6 +648,7 @@
}
cleanup:
+ va_end(ap);
if (rc) {
lyd_free_tree(ret);
ret = NULL;
@@ -644,61 +659,21 @@
}
LIBYANG_API_DEF LY_ERR
-lyd_new_list(struct lyd_node *parent, const struct lys_module *module, const char *name, ly_bool output,
- struct lyd_node **node, ...)
-{
- LY_ERR rc;
- va_list ap;
-
- va_start(ap, node);
-
- rc = _lyd_new_list(parent, module, name, LY_VALUE_JSON, output, node, ap);
-
- va_end(ap);
- return rc;
-}
-
-LIBYANG_API_DEF LY_ERR
-lyd_new_list_bin(struct lyd_node *parent, const struct lys_module *module, const char *name, ly_bool output,
- struct lyd_node **node, ...)
-{
- LY_ERR rc;
- va_list ap;
-
- va_start(ap, node);
-
- rc = _lyd_new_list(parent, module, name, LY_VALUE_LYB, output, node, ap);
-
- va_end(ap);
- return rc;
-}
-
-LIBYANG_API_DEF LY_ERR
-lyd_new_list_canon(struct lyd_node *parent, const struct lys_module *module, const char *name, ly_bool output,
- struct lyd_node **node, ...)
-{
- LY_ERR rc;
- va_list ap;
-
- va_start(ap, node);
-
- rc = _lyd_new_list(parent, module, name, LY_VALUE_CANON, output, node, ap);
-
- va_end(ap);
- return rc;
-}
-
-LIBYANG_API_DEF LY_ERR
-lyd_new_ext_list(const struct lysc_ext_instance *ext, const char *name, struct lyd_node **node, ...)
+lyd_new_ext_list(const struct lysc_ext_instance *ext, const char *name, uint32_t options, struct lyd_node **node, ...)
{
struct lyd_node *ret = NULL, *key;
const struct lysc_node *schema, *key_s;
struct ly_ctx *ctx = ext ? ext->module->ctx : NULL;
va_list ap;
const char *key_val;
+ size_t key_len;
LY_ERR rc = LY_SUCCESS;
+ ly_bool store_only = (options & LYD_NEW_VAL_STORE_ONLY) ? 1 : 0;
+ LY_VALUE_FORMAT format;
LY_CHECK_ARG_RET(ctx, ext, node, name, LY_EINVAL);
+ LY_CHECK_RET(_lyd_new_val_format(options, &format));
+ LY_CHECK_ARG_RET(ctx, !(store_only && (format == LY_VALUE_CANON || format == LY_VALUE_LYB)), LY_EINVAL);
schema = lysc_ext_find_node(ext, NULL, name, 0, LYS_LIST, 0);
if (!schema) {
@@ -717,10 +692,14 @@
/* create and insert all the keys */
for (key_s = lysc_node_child(schema); key_s && (key_s->flags & LYS_KEY); key_s = key_s->next) {
- key_val = va_arg(ap, const char *);
-
- rc = lyd_create_term(key_s, key_val, key_val ? strlen(key_val) : 0, 0, NULL, LY_VALUE_JSON, NULL, LYD_HINT_DATA,
- NULL, &key);
+ if (format == LY_VALUE_LYB) {
+ key_val = va_arg(ap, const void *);
+ key_len = va_arg(ap, uint32_t);
+ } else {
+ key_val = va_arg(ap, const char *);
+ key_len = key_val ? strlen((char *)key_val) : 0;
+ }
+ rc = lyd_create_term(key_s, key_val, key_len, 0, store_only, NULL, format, NULL, LYD_HINT_DATA, NULL, &key);
LY_CHECK_GOTO(rc, cleanup);
lyd_insert_node(ret, NULL, key, LYD_INSERT_NODE_LAST);
}
@@ -737,13 +716,14 @@
LIBYANG_API_DEF LY_ERR
lyd_new_list2(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *keys,
- ly_bool output, struct lyd_node **node)
+ uint32_t options, struct lyd_node **node)
{
LY_ERR r;
struct lyd_node *ret = NULL;
const struct lysc_node *schema;
struct lysc_ext_instance *ext = NULL;
const struct ly_ctx *ctx = parent ? LYD_CTX(parent) : (module ? module->ctx : NULL);
+ uint32_t getnext_opts = (options & LYD_NEW_VAL_OUTPUT) ? LYS_GETNEXT_OUTPUT : 0;
LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
@@ -756,7 +736,7 @@
}
/* find schema node */
- schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, output ? LYS_GETNEXT_OUTPUT : 0);
+ schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYS_LIST, getnext_opts);
if (!schema && parent) {
r = ly_nested_ext_schema(parent, NULL, module->name, strlen(module->name), LY_VALUE_JSON, NULL, name, strlen(name),
&schema, &ext);
@@ -769,7 +749,9 @@
LY_CHECK_RET(lyd_create_inner(schema, &ret));
} else {
/* create the list node */
- LY_CHECK_RET(lyd_create_list2(schema, keys, strlen(keys), &ret));
+ ly_bool store_only = (options & LYD_NEW_VAL_STORE_ONLY) ? 1 : 0;
+
+ LY_CHECK_RET(lyd_create_list2(schema, keys, strlen(keys), store_only, &ret));
}
if (ext) {
ret->flags |= LYD_EXT;
@@ -790,17 +772,15 @@
* @param[in] parent Parent node for the node being created. NULL in case of creating a top level element.
* @param[in] module Module of the node being created. If NULL, @p parent module will be used.
* @param[in] name Schema node name of the new data node. The node must be #LYS_LIST.
- * @param[in] format Format of key values.
- * @param[in] key_values Ordered key values of the new list instance, all must be set.
- * @param[in] value_lengths Lengths of @p key_values, required for ::LY_VALUE_LYB, optional otherwise.
- * @param[in] output Flag in case the @p parent is RPC/Action. If value is 0, the input's data nodes of the RPC/Action are
- * taken into consideration. Otherwise, the output's data node is going to be created.
+ * @param[in] key_values Ordered key string values of the new list instance, all must be set.
+ * @param[in] value_lengths Array of lengths of each @p key_values, may be NULL if @p key_values are 0-terminated strings.
+ * @param[in] options Bitmask of options, see @ref newvalueoptions.
* @param[out] node Optional created node.
* @return LY_ERR value.
*/
static LY_ERR
-_lyd_new_list3(struct lyd_node *parent, const struct lys_module *module, const char *name, LY_VALUE_FORMAT format,
- const void **key_values, uint32_t *value_lengths, ly_bool output, struct lyd_node **node)
+_lyd_new_list3(struct lyd_node *parent, const struct lys_module *module, const char *name, const void **key_values,
+ uint32_t *value_lengths, uint32_t options, struct lyd_node **node)
{
struct lyd_node *ret = NULL, *key;
const struct lysc_node *key_s;
@@ -808,12 +788,16 @@
const void *key_val;
uint32_t key_len, i;
LY_ERR rc = LY_SUCCESS;
+ ly_bool store_only = (options & LYD_NEW_VAL_STORE_ONLY) ? 1 : 0;
+ LY_VALUE_FORMAT format;
+ LY_CHECK_RET(_lyd_new_val_format(options, &format));
LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, (format != LY_VALUE_LYB) || value_lengths, LY_EINVAL);
LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
+ LY_CHECK_ARG_RET(ctx, !(store_only && (format == LY_VALUE_CANON || format == LY_VALUE_LYB)), LY_EINVAL);
/* create the list node */
- LY_CHECK_RET(_lyd_new_list_node(ctx, parent, module, name, output, &ret));
+ LY_CHECK_RET(_lyd_new_list_node(ctx, parent, module, name, options, &ret));
if (!(ret->schema->flags & LYS_KEYLESS) && !key_values) {
LOGERR(ctx, LY_EINVAL, "Missing list \"%s\" keys.", LYD_NAME(ret));
@@ -827,7 +811,7 @@
key_val = key_values[i] ? key_values[i] : "";
key_len = value_lengths ? value_lengths[i] : strlen(key_val);
- rc = lyd_create_term(key_s, key_val, key_len, 0, NULL, format, NULL, LYD_HINT_DATA, NULL, &key);
+ rc = lyd_create_term(key_s, key_val, key_len, 0, store_only, NULL, format, NULL, LYD_HINT_DATA, NULL, &key);
LY_CHECK_GOTO(rc, cleanup);
lyd_insert_node(ret, NULL, key, LYD_INSERT_NODE_LAST);
}
@@ -848,23 +832,21 @@
LIBYANG_API_DEF LY_ERR
lyd_new_list3(struct lyd_node *parent, const struct lys_module *module, const char *name, const char **key_values,
- uint32_t *value_lengths, ly_bool output, struct lyd_node **node)
+ uint32_t *value_lengths, uint32_t options, struct lyd_node **node)
{
- return _lyd_new_list3(parent, module, name, LY_VALUE_JSON, (const void **)key_values, value_lengths, output, node);
+ const struct ly_ctx *ctx = parent ? LYD_CTX(parent) : (module ? module->ctx : NULL);
+
+ LY_CHECK_ARG_RET(ctx, !(options & LYD_NEW_VAL_BIN_VALUE), LY_EINVAL);
+
+ return _lyd_new_list3(parent, module, name, (const void **)key_values, value_lengths, options, node);
}
-LIBYANG_API_DEF LY_ERR
+LIBYANG_API_DECL LY_ERR
lyd_new_list3_bin(struct lyd_node *parent, const struct lys_module *module, const char *name, const void **key_values,
- uint32_t *value_lengths, ly_bool output, struct lyd_node **node)
+ uint32_t *value_lengths, uint32_t options, struct lyd_node **node)
{
- return _lyd_new_list3(parent, module, name, LY_VALUE_LYB, key_values, value_lengths, output, node);
-}
-
-LIBYANG_API_DEF LY_ERR
-lyd_new_list3_canon(struct lyd_node *parent, const struct lys_module *module, const char *name, const char **key_values,
- uint32_t *value_lengths, ly_bool output, struct lyd_node **node)
-{
- return _lyd_new_list3(parent, module, name, LY_VALUE_CANON, (const void **)key_values, value_lengths, output, node);
+ options |= LYD_NEW_VAL_BIN_VALUE;
+ return _lyd_new_list3(parent, module, name, key_values, value_lengths, options, node);
}
/**
@@ -872,33 +854,36 @@
*
* @param[in] parent Parent node for the node being created. NULL in case of creating a top level element.
* @param[in] module Module of the node being created. If NULL, @p parent module will be used.
- * @param[in] name Schema node name of the new data node. The node can be ::LYS_LEAF or ::LYS_LEAFLIST.
- * @param[in] value Value of the node being created.
+ * @param[in] name Schema node name of the new data node. The node can be #LYS_LEAF or #LYS_LEAFLIST.
+ * @param[in] value The value of the node in @p format.
* @param[in] value_len Length of @p value.
- * @param[in] format Format of @p value.
- * @param[in] output Flag in case the @p parent is RPC/Action. If value is 0, the input's data nodes of the RPC/Action are
- * taken into consideration. Otherwise, the output's data node is going to be created.
+ * @param[in] options Bitmask of options, see @ref newvalueoptions.
* @param[out] node Optional created node.
* @return LY_ERR value.
*/
static LY_ERR
_lyd_new_term(struct lyd_node *parent, const struct lys_module *module, const char *name, const void *value,
- size_t value_len, LY_VALUE_FORMAT format, ly_bool output, struct lyd_node **node)
+ size_t value_len, uint32_t options, struct lyd_node **node)
{
LY_ERR r;
struct lyd_node *ret = NULL;
const struct lysc_node *schema;
struct lysc_ext_instance *ext = NULL;
const struct ly_ctx *ctx = parent ? LYD_CTX(parent) : (module ? module->ctx : NULL);
+ uint32_t getnext_opts = (options & LYD_NEW_VAL_OUTPUT) ? LYS_GETNEXT_OUTPUT : 0;
+ ly_bool store_only = (options & LYD_NEW_VAL_STORE_ONLY) ? 1 : 0;
+ LY_VALUE_FORMAT format;
LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name, LY_EINVAL);
LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
+ LY_CHECK_RET(_lyd_new_val_format(options, &format));
+ LY_CHECK_ARG_RET(ctx, !(store_only && (format == LY_VALUE_CANON || format == LY_VALUE_LYB)), LY_EINVAL);
if (!module) {
module = parent->schema->module;
}
- schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_TERM, output ? LYS_GETNEXT_OUTPUT : 0);
+ schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_TERM, getnext_opts);
if (!schema && parent) {
r = ly_nested_ext_schema(parent, NULL, module->name, strlen(module->name), LY_VALUE_JSON, NULL, name,
strlen(name), &schema, &ext);
@@ -906,7 +891,7 @@
}
LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Term node \"%s\" not found.", name), LY_ENOTFOUND);
- LY_CHECK_RET(lyd_create_term(schema, value, value_len, 0, NULL, format, NULL, LYD_HINT_DATA, NULL, &ret));
+ LY_CHECK_RET(lyd_create_term(schema, value, value_len, 0, store_only, NULL, format, NULL, LYD_HINT_DATA, NULL, &ret));
if (ext) {
ret->flags |= LYD_EXT;
}
@@ -921,35 +906,37 @@
}
LIBYANG_API_DEF LY_ERR
-lyd_new_term(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str,
- ly_bool output, struct lyd_node **node)
+lyd_new_term(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *value,
+ uint32_t options, struct lyd_node **node)
{
- return _lyd_new_term(parent, module, name, val_str, val_str ? strlen(val_str) : 0, LY_VALUE_JSON, output, node);
+ const struct ly_ctx *ctx = parent ? LYD_CTX(parent) : (module ? module->ctx : NULL);
+
+ LY_CHECK_ARG_RET(ctx, !(options & LYD_NEW_VAL_BIN_VALUE), LY_EINVAL);
+ return _lyd_new_term(parent, module, name, value, value ? strlen(value) : 0, options, node);
+}
+
+LIBYANG_API_DECL LY_ERR
+lyd_new_term_bin(struct lyd_node *parent, const struct lys_module *module, const char *name,
+ const void *value, size_t value_len, uint32_t options, struct lyd_node **node)
+{
+ options |= LYD_NEW_VAL_BIN_VALUE;
+ return _lyd_new_term(parent, module, name, value, value_len, options, node);
}
LIBYANG_API_DEF LY_ERR
-lyd_new_term_bin(struct lyd_node *parent, const struct lys_module *module, const char *name, const void *value,
- size_t value_len, ly_bool output, struct lyd_node **node)
-{
- return _lyd_new_term(parent, module, name, value, value_len, LY_VALUE_LYB, output, node);
-}
-
-LIBYANG_API_DEF LY_ERR
-lyd_new_term_canon(struct lyd_node *parent, const struct lys_module *module, const char *name, const char *val_str,
- ly_bool output, struct lyd_node **node)
-{
- return _lyd_new_term(parent, module, name, val_str, val_str ? strlen(val_str) : 0, LY_VALUE_CANON, output, node);
-}
-
-LIBYANG_API_DEF LY_ERR
-lyd_new_ext_term(const struct lysc_ext_instance *ext, const char *name, const char *val_str, struct lyd_node **node)
+lyd_new_ext_term(const struct lysc_ext_instance *ext, const char *name, const void *value, size_t value_len,
+ uint32_t options, struct lyd_node **node)
{
LY_ERR rc;
struct lyd_node *ret = NULL;
const struct lysc_node *schema;
struct ly_ctx *ctx = ext ? ext->module->ctx : NULL;
+ ly_bool store_only = (options & LYD_NEW_VAL_STORE_ONLY) ? 1 : 0;
+ LY_VALUE_FORMAT format;
LY_CHECK_ARG_RET(ctx, ext, node, name, LY_EINVAL);
+ LY_CHECK_RET(_lyd_new_val_format(options, &format));
+ LY_CHECK_ARG_RET(ctx, !(store_only && (format == LY_VALUE_CANON || format == LY_VALUE_LYB)), LY_EINVAL);
schema = lysc_ext_find_node(ext, NULL, name, 0, LYD_NODE_TERM, 0);
if (!schema) {
@@ -961,8 +948,7 @@
}
return LY_ENOTFOUND;
}
- rc = lyd_create_term(schema, val_str, val_str ? strlen(val_str) : 0, 0, NULL, LY_VALUE_JSON, NULL, LYD_HINT_DATA,
- NULL, &ret);
+ rc = lyd_create_term(schema, value, value_len, 0, store_only, NULL, format, NULL, LYD_HINT_DATA, NULL, &ret);
LY_CHECK_RET(rc);
*node = ret;
@@ -972,13 +958,15 @@
LIBYANG_API_DEF LY_ERR
lyd_new_any(struct lyd_node *parent, const struct lys_module *module, const char *name, const void *value,
- ly_bool use_value, LYD_ANYDATA_VALUETYPE value_type, ly_bool output, struct lyd_node **node)
+ uint32_t options, LYD_ANYDATA_VALUETYPE value_type, struct lyd_node **node)
{
LY_ERR r;
struct lyd_node *ret = NULL;
const struct lysc_node *schema;
struct lysc_ext_instance *ext = NULL;
const struct ly_ctx *ctx = parent ? LYD_CTX(parent) : (module ? module->ctx : NULL);
+ uint32_t getnext_opts = (options & LYS_GETNEXT_OUTPUT) ? LYS_GETNEXT_OUTPUT : 0;
+ ly_bool use_value = (options & LYD_NEW_ANY_USE_VALUE) ? 1 : 0;
LY_CHECK_ARG_RET(ctx, parent || module, parent || node, name,
(value_type == LYD_ANYDATA_DATATREE) || (value_type == LYD_ANYDATA_STRING) || value, LY_EINVAL);
@@ -988,7 +976,7 @@
module = parent->schema->module;
}
- schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_ANY, output ? LYS_GETNEXT_OUTPUT : 0);
+ schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_ANY, getnext_opts);
if (!schema && parent) {
r = ly_nested_ext_schema(parent, NULL, module->name, strlen(module->name), LY_VALUE_JSON, NULL, name,
strlen(name), &schema, &ext);
@@ -1011,12 +999,13 @@
}
LIBYANG_API_DEF LY_ERR
-lyd_new_ext_any(const struct lysc_ext_instance *ext, const char *name, const void *value, ly_bool use_value,
+lyd_new_ext_any(const struct lysc_ext_instance *ext, const char *name, const void *value, uint32_t options,
LYD_ANYDATA_VALUETYPE value_type, struct lyd_node **node)
{
struct lyd_node *ret = NULL;
const struct lysc_node *schema;
struct ly_ctx *ctx = ext ? ext->module->ctx : NULL;
+ ly_bool use_value = (options & LYD_NEW_ANY_USE_VALUE) ? 1 : 0;
LY_CHECK_ARG_RET(ctx, ext, node, name, LY_EINVAL);
@@ -1039,10 +1028,12 @@
LIBYANG_API_DEF LY_ERR
lyd_new_meta(const struct ly_ctx *ctx, struct lyd_node *parent, const struct lys_module *module, const char *name,
- const char *val_str, ly_bool clear_dflt, struct lyd_meta **meta)
+ const char *val_str, uint32_t options, struct lyd_meta **meta)
{
const char *prefix, *tmp;
size_t pref_len, name_len;
+ ly_bool clear_dflt = options & LYD_NEW_META_CLEAR_DFLT;
+ ly_bool store_only = options & LYD_NEW_VAL_STORE_ONLY;
LY_CHECK_ARG_RET(ctx, ctx || parent, name, module || strchr(name, ':'), parent || meta, LY_EINVAL);
LY_CHECK_CTX_EQUAL_RET(ctx, parent ? LYD_CTX(parent) : NULL, module ? module->ctx : NULL, LY_EINVAL);
@@ -1076,15 +1067,16 @@
val_str = "";
}
- return lyd_create_meta(parent, meta, module, name, name_len, val_str, strlen(val_str), 0, NULL, LY_VALUE_JSON,
+ return lyd_create_meta(parent, meta, module, name, name_len, val_str, strlen(val_str), 0, store_only, NULL, LY_VALUE_JSON,
NULL, LYD_HINT_DATA, parent ? parent->schema : NULL, clear_dflt, NULL);
}
LIBYANG_API_DEF LY_ERR
-lyd_new_meta2(const struct ly_ctx *ctx, struct lyd_node *parent, ly_bool clear_dflt, const struct lyd_attr *attr,
- struct lyd_meta **meta)
+lyd_new_meta2(const struct ly_ctx *ctx, struct lyd_node *parent, uint32_t options, const struct lyd_attr *attr, struct lyd_meta **meta)
{
const struct lys_module *mod;
+ ly_bool clear_dflt = options & LYD_NEW_META_CLEAR_DFLT;
+ ly_bool store_only = options & LYD_NEW_VAL_STORE_ONLY;
LY_CHECK_ARG_RET(NULL, ctx, attr, parent || meta, LY_EINVAL);
LY_CHECK_CTX_EQUAL_RET(ctx, parent ? LYD_CTX(parent) : NULL, LY_EINVAL);
@@ -1118,7 +1110,7 @@
}
return lyd_create_meta(parent, meta, mod, attr->name.name, strlen(attr->name.name), attr->value, strlen(attr->value),
- 0, NULL, attr->format, attr->val_prefix_data, attr->hints, parent ? parent->schema : NULL, clear_dflt, NULL);
+ 0, store_only, NULL, attr->format, attr->val_prefix_data, attr->hints, parent ? parent->schema : NULL, clear_dflt, NULL);
}
LIBYANG_API_DEF LY_ERR
@@ -1355,7 +1347,7 @@
/* parse the new value */
LOG_LOCSET(term->schema, term);
- ret = lyd_value_store(LYD_CTX(term), &val, type, value, value_len, 0, NULL, format, NULL, LYD_HINT_DATA,
+ ret = lyd_value_store(LYD_CTX(term), &val, type, value, value_len, 0, 0, NULL, format, NULL, LYD_HINT_DATA,
term->schema, NULL);
LOG_LOCBACK(1, 1);
LY_CHECK_GOTO(ret, cleanup);
@@ -1445,7 +1437,7 @@
/* parse the new value into a new meta structure */
ret = lyd_create_meta(NULL, &m2, meta->annotation->module, meta->name, strlen(meta->name), val_str, strlen(val_str),
- 0, NULL, LY_VALUE_JSON, NULL, LYD_HINT_DATA, meta->parent ? meta->parent->schema : NULL, 0, NULL);
+ 0, 0, NULL, LY_VALUE_JSON, NULL, LYD_HINT_DATA, meta->parent ? meta->parent->schema : NULL, 0, NULL);
LY_CHECK_GOTO(ret, cleanup);
/* compare original and new value */
@@ -1600,7 +1592,7 @@
if (!r) {
/* try to store the value */
LY_CHECK_RET(lyd_value_store(schema->module->ctx, &val, ((struct lysc_node_leaflist *)schema)->type,
- value, value_len, 0, NULL, format, NULL, LYD_HINT_DATA, schema, NULL));
+ value, value_len, 0, 0, NULL, format, NULL, LYD_HINT_DATA, schema, NULL));
++((struct lysc_type *)val.realtype)->refcount;
/* store the new predicate so that it is used when searching for this instance */
@@ -1660,12 +1652,13 @@
struct lyd_node *nparent = NULL, *nnode = NULL, *node = NULL, *cur_parent;
const struct lysc_node *schema;
const struct lyd_value *val = NULL;
+ ly_bool store_only = (options & LYD_NEW_VAL_STORE_ONLY) ? 1 : 0;
LY_ARRAY_COUNT_TYPE path_idx = 0, orig_count = 0;
LY_VALUE_FORMAT format;
assert(parent || ctx);
assert(path && ((path[0] == '/') || parent));
- assert(!(options & LYD_NEW_PATH_BIN_VALUE) || !(options & LYD_NEW_PATH_CANON_VALUE));
+ assert(!(options & LYD_NEW_VAL_BIN_VALUE) || !(options & LYD_NEW_VAL_CANON_VALUE));
if (!ctx) {
ctx = LYD_CTX(parent);
@@ -1673,9 +1666,9 @@
if (value && !value_len) {
value_len = strlen(value);
}
- if (options & LYD_NEW_PATH_BIN_VALUE) {
+ if (options & LYD_NEW_VAL_BIN_VALUE) {
format = LY_VALUE_LYB;
- } else if (options & LYD_NEW_PATH_CANON_VALUE) {
+ } else if (options & LYD_NEW_VAL_CANON_VALUE) {
format = LY_VALUE_CANON;
} else {
format = LY_VALUE_JSON;
@@ -1686,7 +1679,7 @@
LY_PATH_PRED_SIMPLE, &exp), cleanup);
/* compile path */
- LY_CHECK_GOTO(ret = ly_path_compile(ctx, NULL, lyd_node_schema(parent), ext, exp, options & LYD_NEW_PATH_OUTPUT ?
+ LY_CHECK_GOTO(ret = ly_path_compile(ctx, NULL, lyd_node_schema(parent), ext, exp, options & LYD_NEW_VAL_OUTPUT ?
LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY, 0, LY_VALUE_JSON, NULL, &p), cleanup);
/* check the compiled path before searching existing nodes, it may be shortened */
@@ -1751,7 +1744,7 @@
LYD_NODEHINT_LIST, &node), cleanup);
} else {
/* create standard list instance */
- LY_CHECK_GOTO(ret = lyd_create_list(schema, p[path_idx].predicates, NULL, &node), cleanup);
+ LY_CHECK_GOTO(ret = lyd_create_list(schema, p[path_idx].predicates, NULL, store_only, &node), cleanup);
}
break;
case LYS_CONTAINER:
@@ -1787,8 +1780,7 @@
if (val) {
LY_CHECK_GOTO(ret = lyd_create_term2(schema, val, &node), cleanup);
} else {
- LY_CHECK_GOTO(ret = lyd_create_term(schema, value, value_len, 0, NULL, format, NULL, LYD_HINT_DATA,
- NULL, &node), cleanup);
+ LY_CHECK_GOTO(ret = lyd_create_term(schema, value, value_len, 0, store_only, NULL, format, NULL, LYD_HINT_DATA, NULL, &node), cleanup);
}
break;
case LYS_LEAF:
@@ -1817,8 +1809,7 @@
}
/* create a leaf instance */
- LY_CHECK_GOTO(ret = lyd_create_term(schema, value, value_len, 0, NULL, format, NULL, LYD_HINT_DATA, NULL,
- &node), cleanup);
+ LY_CHECK_GOTO(ret = lyd_create_term(schema, value, value_len, 0, store_only, NULL, format, NULL, LYD_HINT_DATA, NULL, &node), cleanup);
break;
case LYS_ANYDATA:
case LYS_ANYXML:
@@ -1876,7 +1867,7 @@
struct lyd_node **node)
{
LY_CHECK_ARG_RET(ctx, parent || ctx, path, (path[0] == '/') || parent,
- !(options & LYD_NEW_PATH_BIN_VALUE) || !(options & LYD_NEW_PATH_CANON_VALUE), LY_EINVAL);
+ !(options & LYD_NEW_VAL_BIN_VALUE) || !(options & LYD_NEW_VAL_CANON_VALUE), LY_EINVAL);
LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, ctx, LY_EINVAL);
return lyd_new_path_(parent, ctx, NULL, path, value, 0, LYD_ANYDATA_STRING, options, node, NULL);
@@ -1888,7 +1879,7 @@
struct lyd_node **new_node)
{
LY_CHECK_ARG_RET(ctx, parent || ctx, path, (path[0] == '/') || parent,
- !(options & LYD_NEW_PATH_BIN_VALUE) || !(options & LYD_NEW_PATH_CANON_VALUE), LY_EINVAL);
+ !(options & LYD_NEW_VAL_BIN_VALUE) || !(options & LYD_NEW_VAL_CANON_VALUE), LY_EINVAL);
LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, ctx, LY_EINVAL);
return lyd_new_path_(parent, ctx, NULL, path, value, value_len, value_type, options, new_parent, new_node);
@@ -1901,7 +1892,7 @@
const struct ly_ctx *ctx = ext ? ext->module->ctx : NULL;
LY_CHECK_ARG_RET(ctx, ext, path, (path[0] == '/') || parent,
- !(options & LYD_NEW_PATH_BIN_VALUE) || !(options & LYD_NEW_PATH_CANON_VALUE), LY_EINVAL);
+ !(options & LYD_NEW_VAL_BIN_VALUE) || !(options & LYD_NEW_VAL_CANON_VALUE), LY_EINVAL);
LY_CHECK_CTX_EQUAL_RET(parent ? LYD_CTX(parent) : NULL, ctx, LY_EINVAL);
return lyd_new_path_(parent, ctx, ext, path, value, 0, LYD_ANYDATA_STRING, options, node, NULL);
diff --git a/src/tree_data_sorted.c b/src/tree_data_sorted.c
index 54ad2ff..182e9c5 100644
--- a/src/tree_data_sorted.c
+++ b/src/tree_data_sorted.c
@@ -1170,7 +1170,7 @@
LY_CHECK_ERR_RET(!modyang, LOGERR(LYD_CTX(leader), LY_EINT, "The yang module is not installed."), LY_EINT);
/* create new metadata, its rbt is NULL */
- ret = lyd_create_meta(leader, &meta, modyang, RB_NAME, RB_NAME_LEN, NULL, 0, 0, NULL,
+ ret = lyd_create_meta(leader, &meta, modyang, RB_NAME, RB_NAME_LEN, NULL, 0, 0, 1, NULL,
LY_VALUE_CANON, NULL, LYD_HINT_DATA, NULL, 0, NULL);
LY_CHECK_RET(ret);
diff --git a/src/xpath.c b/src/xpath.c
index bfadbb9..57ba64d 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -6224,7 +6224,7 @@
/* create specific data instance if needed */
if (scnode->nodetype == LYS_LIST) {
- LY_CHECK_GOTO(ret = lyd_create_list(scnode, predicates, NULL, &inst), cleanup);
+ LY_CHECK_GOTO(ret = lyd_create_list(scnode, predicates, NULL, 1, &inst), cleanup);
} else if (scnode->nodetype == LYS_LEAFLIST) {
LY_CHECK_GOTO(ret = lyd_create_term2(scnode, &predicates[0].value, &inst), cleanup);
}