plugins types REFACTOR split store callback into store and resolve cb (#1220)
Refs #1161
Co-authored-by: Radek Krejci <rkrejci@cesnet.cz>
diff --git a/src/diff.c b/src/diff.c
index 0c28bf4..dff6acb 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -1127,7 +1127,7 @@
meta = lyd_find_meta(diff_match->meta, mod, "orig-value");
LY_CHECK_ERR_RET(!meta, LOGINT(LYD_CTX(diff_match)), LY_EINT);
str_val = meta->value.canonical;
- ret = lyd_value_compare((struct lyd_node_term *)diff_match, str_val, strlen(str_val), NULL);
+ ret = lyd_value_compare((struct lyd_node_term *)diff_match, str_val, strlen(str_val));
if (!ret) {
/* values are the same, remove orig-value meta and set oper to NONE */
lyd_free_meta_single(meta);
diff --git a/src/parser.c b/src/parser.c
index 6b6ab74..c915fc1 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -407,31 +407,30 @@
LY_ERR
lyd_parser_create_term(struct lyd_ctx *lydctx, const struct lysc_node *schema, const char *value, size_t value_len,
- ly_bool *dynamic, uint32_t value_hints, LY_PREFIX_FORMAT format, void *prefix_data, struct lyd_node **node)
+ ly_bool *dynamic, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints, struct lyd_node **node)
{
- LY_ERR ret;
+ ly_bool incomplete;
- ret = lyd_create_term(schema, value, value_len, dynamic, value_hints, format, prefix_data, node);
- if (ret == LY_EINCOMPLETE) {
- if (!(lydctx->parse_options & LYD_PARSE_ONLY)) {
- LY_CHECK_RET(ly_set_add(&lydctx->unres_node_type, *node, LY_SET_OPT_USEASLIST, NULL));
- }
- ret = LY_SUCCESS;
+ LY_CHECK_RET(lyd_create_term(schema, value, value_len, dynamic, format, prefix_data, hints, &incomplete, node));
+
+ if (incomplete && !(lydctx->parse_options & LYD_PARSE_ONLY)) {
+ LY_CHECK_RET(ly_set_add(&lydctx->unres_node_type, *node, LY_SET_OPT_USEASLIST, NULL));
}
- return ret;
+ return LY_SUCCESS;
}
LY_ERR
lyd_parser_create_meta(struct lyd_ctx *lydctx, 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 *dynamic, uint32_t value_hints,
- LY_PREFIX_FORMAT format, void *prefix_data, const struct lysc_node *ctx_snode)
+ const char *name, size_t name_len, const char *value, size_t value_len, ly_bool *dynamic, LY_PREFIX_FORMAT format,
+ void *prefix_data, uint32_t hints)
{
- LY_ERR ret;
- ret = lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, dynamic, value_hints, format, prefix_data,
- ctx_snode);
- if (ret == LY_EINCOMPLETE) {
+ ly_bool incomplete;
+
+ LY_CHECK_RET(lyd_create_meta(parent, meta, mod, name, name_len, value, value_len, dynamic, format, prefix_data,
+ hints, &incomplete));
+
+ if (incomplete && !(lydctx->parse_options & LYD_PARSE_ONLY)) {
LY_CHECK_RET(ly_set_add(&lydctx->unres_meta_type, *meta, LY_SET_OPT_USEASLIST, NULL));
- ret = LY_SUCCESS;
}
- return ret;
+ return LY_SUCCESS;
}
diff --git a/src/parser_internal.h b/src/parser_internal.h
index 87553f9..79496c7 100644
--- a/src/parser_internal.h
+++ b/src/parser_internal.h
@@ -168,20 +168,19 @@
* @brief Wrapper around lyd_create_term() for data parsers.
*
* @param[in] lydctx Data parser context.
- * @param[in] value_hints Data parser's hint for the value's type.
+ * @param[in] hints Data parser's hint for the value's type.
*/
LY_ERR lyd_parser_create_term(struct lyd_ctx *lydctx, const struct lysc_node *schema, const char *value, size_t value_len,
- ly_bool *dynamic, uint32_t value_hints, LY_PREFIX_FORMAT format, void *prefix_data, struct lyd_node **node);
+ ly_bool *dynamic, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints, struct lyd_node **node);
/**
* @brief Wrapper around lyd_create_meta() for data parsers.
*
* @param[in] lydctx Data parser context.
- * @param[in] value_hints [Value hint](@ref lydvalueparseopts) from the parser regarding the value type.
+ * @param[in] hints [Value hint](@ref lydvalhints) from the parser regarding the value type.
*/
LY_ERR lyd_parser_create_meta(struct lyd_ctx *lydctx, 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 *dynamic, uint32_t value_hints, LY_PREFIX_FORMAT format,
- void *prefix_data, const struct lysc_node *ctx_snode);
+ size_t value_len, ly_bool *dynamic, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints);
#endif /* LY_PARSER_INTERNAL_H_ */
diff --git a/src/parser_json.c b/src/parser_json.c
index 1e148a8..38e7d97 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -195,7 +195,7 @@
*snode_p = NULL;
/* get the element module */
- if (prefix_len || (parent && !parent->schema && (((struct lyd_node_opaq *)parent)->hint & LYD_NODE_OPAQ_ISENVELOPE))) {
+ if (prefix_len || (parent && !parent->schema && (((struct lyd_node_opaq *)parent)->hints & LYD_NODEHINT_ENVELOPE))) {
if (!prefix_len) {
/* opaq parent (envelope) - the second part of the condition */
lydjson_get_node_prefix((struct lyd_node *)parent, NULL, 0, &prefix, &prefix_len);
@@ -220,7 +220,7 @@
}
}
- if (parent && !parent->schema && (((struct lyd_node_opaq *)parent)->hint & LYD_NODE_OPAQ_ISENVELOPE)) {
+ if (parent && !parent->schema && (((struct lyd_node_opaq *)parent)->hints & LYD_NODEHINT_ENVELOPE)) {
/* ignore the envelope parent when searchinf for the schema node */
parent = NULL;
}
@@ -449,13 +449,13 @@
LY_CHECK_RET(lyjson_ctx_next(lydctx->jsonctx, NULL));
LY_CHECK_RET(lyjson_ctx_status(lydctx->jsonctx, 0) != LYJSON_ARRAY_CLOSED, LY_EINVAL);
- *type_hint_p = LYD_NODE_OPAQ_ISEMPTY;
+ *type_hint_p = LYD_VALHINT_EMPTY;
} else if (*status_p == LYJSON_STRING) {
- *type_hint_p = LYD_NODE_OPAQ_ISSTRING;
+ *type_hint_p = LYD_VALHINT_STRING | LYD_VALHINT_NUM64;
} else if (*status_p == LYJSON_NUMBER) {
- *type_hint_p = LYD_NODE_OPAQ_ISNUMBER;
+ *type_hint_p = LYD_VALHINT_DECNUM;
} else if (*status_p == LYJSON_FALSE || *status_p == LYJSON_TRUE) {
- *type_hint_p = LYD_NODE_OPAQ_ISBOOLEAN;
+ *type_hint_p = LYD_VALHINT_BOOLEAN;
} else if (*status_p == LYJSON_NULL) {
*type_hint_p = 0;
} else {
@@ -583,7 +583,7 @@
continue;
}
- if (((struct lyd_node_opaq *)node)->hint & LYD_NODE_OPAQ_ISLIST) {
+ if (((struct lyd_node_opaq *)node)->hints & LYD_NODEHINT_LIST) {
LOGVAL(lydctx->jsonctx->ctx, LY_VLOG_LYD, node, LYVE_SYNTAX,
"Metadata container references a sibling list node %s.", ((struct lyd_node_opaq *)node)->name);
ret = LY_EVALID;
@@ -603,11 +603,12 @@
ly_bool dynamic = 0;
/* get value prefixes */
- LY_CHECK_GOTO(ret = lydjson_get_value_prefixes(lydctx->jsonctx->ctx, lydctx->jsonctx->value, lydctx->jsonctx->value_len, &val_prefs), cleanup);
+ LY_CHECK_GOTO(ret = lydjson_get_value_prefixes(lydctx->jsonctx->ctx, lydctx->jsonctx->value,
+ lydctx->jsonctx->value_len, &val_prefs), cleanup);
- ret = lyd_create_attr(node, NULL, lydctx->jsonctx->ctx, meta->name, strlen(meta->name), meta->value, ly_strlen(meta->value),
- &dynamic, meta->hint, LYD_JSON, val_prefs, meta->prefix.id, ly_strlen(meta->prefix.id),
- meta->prefix.module_name, ly_strlen(meta->prefix.module_name));
+ ret = lyd_create_attr(node, NULL, lydctx->jsonctx->ctx, meta->name, strlen(meta->name), meta->value,
+ ly_strlen(meta->value), &dynamic, LYD_JSON, meta->hints, val_prefs, meta->prefix.id,
+ ly_strlen(meta->prefix.id), meta->prefix.module_name, ly_strlen(meta->prefix.module_name));
LY_CHECK_GOTO(ret, cleanup);
}
@@ -641,7 +642,7 @@
if (mod) {
ret = lyd_parser_create_meta((struct lyd_ctx *)lydctx, node, NULL, mod,
meta->name, strlen(meta->name), meta->value, ly_strlen(meta->value),
- &dynamic, meta->hint, LY_PREF_JSON, NULL, snode);
+ &dynamic, LY_PREF_JSON, NULL, meta->hints);
LY_CHECK_GOTO(ret, cleanup);
} else if (lydctx->parse_options & LYD_PARSE_STRICT) {
LOGVAL(lydctx->jsonctx->ctx, LY_VLOG_LYD, node, LYVE_REFERENCE,
@@ -824,7 +825,8 @@
/* create metadata */
meta = NULL;
ret = lyd_parser_create_meta((struct lyd_ctx *)lydctx, node, &meta, mod, name, name_len, lydctx->jsonctx->value,
- lydctx->jsonctx->value_len, &lydctx->jsonctx->dynamic, 0, LY_PREF_JSON, NULL, snode);
+ lydctx->jsonctx->value_len, &lydctx->jsonctx->dynamic, LY_PREF_JSON, NULL,
+ LYD_HINT_DATA);
LY_CHECK_GOTO(ret, cleanup);
/* add/correct flags */
@@ -842,7 +844,7 @@
/* attr2 is always changed to the created attribute */
ret = lyd_create_attr(node, NULL, lydctx->jsonctx->ctx, name, name_len, lydctx->jsonctx->value, lydctx->jsonctx->value_len,
- &lydctx->jsonctx->dynamic, 0, LYD_JSON, val_prefs, prefix, prefix_len, module_name, module_name_len);
+ &lydctx->jsonctx->dynamic, LYD_JSON, 0, val_prefs, prefix, prefix_len, module_name, module_name_len);
LY_CHECK_GOTO(ret, cleanup);
}
/* next member */
@@ -951,8 +953,8 @@
/* create node */
lydjson_get_node_prefix((struct lyd_node *)parent, prefix, prefix_len, &module_name, &module_name_len);
- ret = lyd_create_opaq(lydctx->jsonctx->ctx, name, name_len, value, value_len, &dynamic, type_hint,
- LYD_JSON, val_prefs, prefix, prefix_len, module_name, module_name_len, node_p);
+ ret = lyd_create_opaq(lydctx->jsonctx->ctx, name, name_len, value, value_len, &dynamic, LYD_JSON, type_hint,
+ val_prefs, prefix, prefix_len, module_name, module_name_len, node_p);
if (dynamic) {
free((char *)value);
}
@@ -967,7 +969,7 @@
} else if (*status_p == LYJSON_ARRAY || *status_p == LYJSON_ARRAY_EMPTY) {
/* process another instance of the same node */
/* but first mark the node to be expected a list or a leaf-list */
- ((struct lyd_node_opaq *)*node_p)->hint |= LYD_NODE_OPAQ_ISLIST;
+ ((struct lyd_node_opaq *)*node_p)->hints |= LYD_NODEHINT_LIST | LYD_NODEHINT_LEAFLIST;
if (*status_inner_p == LYJSON_OBJECT || *status_inner_p == LYJSON_OBJECT_EMPTY) {
/* but first process children of the object in the array */
@@ -1089,18 +1091,18 @@
enum LYJSON_PARSER_STATUS *status, struct lyd_node **node)
{
LY_ERR ret;
- uint32_t type_hint;
+ uint32_t type_hints;
uint32_t prev_opts;
struct lyd_node *tree = NULL;
- ret = lydjson_data_check_opaq(lydctx, snode, &type_hint);
+ ret = lydjson_data_check_opaq(lydctx, snode, &type_hints);
if (ret == LY_SUCCESS) {
assert(snode->nodetype & (LYD_NODE_TERM | LYD_NODE_INNER | LYD_NODE_ANY));
if (snode->nodetype & LYD_NODE_TERM) {
/* create terminal node */
ret = lyd_parser_create_term((struct lyd_ctx *)lydctx, snode, lydctx->jsonctx->value,
- lydctx->jsonctx->value_len, &lydctx->jsonctx->dynamic, type_hint,
- LY_PREF_JSON, NULL, node);
+ lydctx->jsonctx->value_len, &lydctx->jsonctx->dynamic, LY_PREF_JSON, NULL,
+ type_hints, node);
LY_CHECK_RET(ret);
/* move JSON parser */
@@ -1178,8 +1180,10 @@
status, status, first_p, node);
LY_CHECK_RET(ret);
- if (snode->nodetype & (LYS_LEAFLIST | LYS_LIST)) {
- ((struct lyd_node_opaq *)*node)->hint |= LYD_NODE_OPAQ_ISLIST;
+ if (snode->nodetype == LYS_LIST) {
+ ((struct lyd_node_opaq *)*node)->hints |= LYD_NODEHINT_LIST;
+ } else if (snode->nodetype == LYS_LEAFLIST) {
+ ((struct lyd_node_opaq *)*node)->hints |= LYD_NODEHINT_LEAFLIST;
}
}
@@ -1503,12 +1507,12 @@
/* now the notificationContent is expected, which will be parsed by the caller */
/* create notification envelope */
- ret = lyd_create_opaq(jsonctx->ctx, "notification", 12, "", 0, NULL, LYD_NODE_OPAQ_ISENVELOPE,
- LYD_JSON, NULL, NULL, 0, "ietf-restconf", 13, envp_p);
+ ret = lyd_create_opaq(jsonctx->ctx, "notification", 12, "", 0, NULL, LYD_JSON, LYD_NODEHINT_ENVELOPE, NULL, NULL,
+ 0, "ietf-restconf", 13, envp_p);
LY_CHECK_GOTO(ret, cleanup);
/* create notification envelope */
- ret = lyd_create_opaq(jsonctx->ctx, "eventTime", 9, value, value_len, &dynamic, LYD_NODE_OPAQ_ISSTRING,
- LYD_JSON, NULL, NULL, 0, "ietf-restconf", 13, &et);
+ ret = lyd_create_opaq(jsonctx->ctx, "eventTime", 9, value, value_len, &dynamic, LYD_JSON, LYD_VALHINT_STRING, NULL,
+ NULL, 0, "ietf-restconf", 13, &et);
LY_CHECK_GOTO(ret, cleanup);
/* insert eventTime into notification */
lyd_insert_node(*envp_p, NULL, et);
@@ -1647,9 +1651,8 @@
LY_CHECK_GOTO(status != LYJSON_OBJECT, cleanup);
/* create the object envelope */
- ret = lyd_create_opaq(jsonctx->ctx, object_id, strlen(object_id), "", 0, NULL,
- LYD_NODE_OPAQ_ISENVELOPE, LYD_JSON, NULL, NULL, 0,
- module_key, ly_strlen(module_key), envp_p);
+ ret = lyd_create_opaq(jsonctx->ctx, object_id, strlen(object_id), "", 0, NULL, LYD_JSON, LYD_NODEHINT_ENVELOPE,
+ NULL, NULL, 0, module_key, ly_strlen(module_key), envp_p);
LY_CHECK_GOTO(ret, cleanup);
if (parent) {
diff --git a/src/parser_lyb.c b/src/parser_lyb.c
index 9395a13..ea2a7aa 100644
--- a/src/parser_lyb.c
+++ b/src/parser_lyb.c
@@ -337,12 +337,11 @@
* @brief Parse YANG node metadata.
*
* @param[in] lybctx LYB context.
- * @param[in] sparent Schema parent node.
* @param[out] meta Parsed metadata.
* @return LY_ERR value.
*/
static LY_ERR
-lyb_parse_metadata(struct lyd_lyb_ctx *lybctx, const struct lysc_node *sparent, struct lyd_meta **meta)
+lyb_parse_metadata(struct lyd_lyb_ctx *lybctx, struct lyd_meta **meta)
{
LY_ERR ret = LY_SUCCESS;
ly_bool dynamic;
@@ -381,7 +380,7 @@
/* create metadata */
ret = lyd_parser_create_meta((struct lyd_ctx *)lybctx, NULL, meta, mod, meta_name, strlen(meta_name), meta_value,
- ly_strlen(meta_value), &dynamic, 0, LY_PREF_JSON, NULL, sparent);
+ ly_strlen(meta_value), &dynamic, LY_PREF_JSON, NULL, LYD_HINT_DATA);
/* free strings */
free(meta_name);
@@ -507,8 +506,8 @@
dynamic = 1;
/* attr2 is always changed to the created attribute */
- ret = lyd_create_attr(NULL, &attr2, lybctx->ctx, name, strlen(name), value, ly_strlen(value), &dynamic, 0, format,
- val_prefs, prefix, ly_strlen(prefix), module_name, ly_strlen(module_name));
+ ret = lyd_create_attr(NULL, &attr2, lybctx->ctx, name, strlen(name), value, ly_strlen(value), &dynamic, format,
+ 0, val_prefs, prefix, ly_strlen(prefix), module_name, ly_strlen(module_name));
LY_CHECK_GOTO(ret, cleanup);
free(prefix);
@@ -714,7 +713,7 @@
/* create metadata/attributes */
if (snode) {
- ret = lyb_parse_metadata(lybctx, snode, &meta);
+ ret = lyb_parse_metadata(lybctx, &meta);
LY_CHECK_GOTO(ret, cleanup);
} else {
ret = lyb_parse_attributes(lybctx->lybctx, &attr);
@@ -747,7 +746,7 @@
dynamic = 1;
/* create node */
- ret = lyd_create_opaq(ctx, name, strlen(name), value, strlen(value), &dynamic, 0, format, val_prefs, prefix,
+ ret = lyd_create_opaq(ctx, name, strlen(name), value, strlen(value), &dynamic, format, 0, val_prefs, prefix,
ly_strlen(prefix), module_key, ly_strlen(module_key), &node);
LY_CHECK_GOTO(ret, cleanup);
@@ -763,8 +762,8 @@
dynamic = 1;
/* create node */
- ret = lyd_parser_create_term((struct lyd_ctx *)lybctx, snode, value, ly_strlen(value), &dynamic, 0,
- LY_PREF_JSON, NULL, &node);
+ ret = lyd_parser_create_term((struct lyd_ctx *)lybctx, snode, value, ly_strlen(value), &dynamic, LY_PREF_JSON,
+ NULL, LYD_HINT_DATA, &node);
if (dynamic) {
free(value);
dynamic = 0;
diff --git a/src/parser_xml.c b/src/parser_xml.c
index 914b643..c4f0229 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -62,7 +62,7 @@
}
static LY_ERR
-lydxml_metadata(struct lyd_xml_ctx *lydctx, const struct lysc_node *sparent, struct lyd_meta **meta)
+lydxml_metadata(struct lyd_xml_ctx *lydctx, struct lyd_meta **meta)
{
LY_ERR ret = LY_EVALID;
const struct lyxml_ns *ns;
@@ -119,7 +119,7 @@
/* create metadata */
ret = lyd_parser_create_meta((struct lyd_ctx *)lydctx, NULL, meta, mod, name, name_len, xmlctx->value,
- xmlctx->value_len, &xmlctx->dynamic, 0, LY_PREF_XML, &xmlctx->ns, sparent);
+ xmlctx->value_len, &xmlctx->dynamic, LY_PREF_XML, &xmlctx->ns, LYD_HINT_DATA);
LY_CHECK_GOTO(ret, cleanup);
/* next attribute */
@@ -181,7 +181,7 @@
/* attr2 is always changed to the created attribute */
ret = lyd_create_attr(NULL, &attr2, xmlctx->ctx, name, name_len, xmlctx->value, xmlctx->value_len,
- &xmlctx->dynamic, 0, LYD_XML, val_prefs, prefix, prefix_len,
+ &xmlctx->dynamic, LYD_XML, 0, val_prefs, prefix, prefix_len,
ns ? ns->uri : NULL, ns ? strlen(ns->uri) : 0);
LY_CHECK_GOTO(ret, cleanup);
@@ -448,7 +448,7 @@
/* create metadata/attributes */
if (xmlctx->status == LYXML_ATTRIBUTE) {
if (snode) {
- ret = lydxml_metadata(lydctx, snode, &meta);
+ ret = lydxml_metadata(lydctx, &meta);
LY_CHECK_GOTO(ret, error);
} else {
assert(lydctx->parse_options & LYD_PARSE_OPAQ);
@@ -472,8 +472,8 @@
}
/* create node */
- ret = lyd_create_opaq(ctx, name, name_len, xmlctx->value, xmlctx->value_len, &xmlctx->dynamic, 0, LYD_XML,
- val_prefs, prefix, prefix_len, ns->uri, strlen(ns->uri), &node);
+ ret = lyd_create_opaq(ctx, name, name_len, xmlctx->value, xmlctx->value_len, &xmlctx->dynamic, LYD_XML,
+ LYD_HINT_DATA, val_prefs, prefix, prefix_len, ns->uri, strlen(ns->uri), &node);
LY_CHECK_GOTO(ret, error);
/* parser next */
@@ -487,7 +487,7 @@
} else if (snode->nodetype & LYD_NODE_TERM) {
/* create node */
LY_CHECK_GOTO(ret = lyd_parser_create_term((struct lyd_ctx *)lydctx, snode, xmlctx->value, xmlctx->value_len,
- &xmlctx->dynamic, 0, LY_PREF_XML, &xmlctx->ns, &node), error);
+ &xmlctx->dynamic, LY_PREF_XML, &xmlctx->ns, LYD_HINT_DATA, &node), error);
if (parent && (node->schema->flags & LYS_KEY)) {
/* check the key order, the anchor must never be a key */
@@ -701,8 +701,8 @@
LY_CHECK_GOTO(ret = lyxml_ctx_next(xmlctx), cleanup);
/* create node */
- ret = lyd_create_opaq(xmlctx->ctx, name, strlen(name), "", 0, NULL, 0, LYD_XML, NULL, prefix, prefix_len,
- uri, strlen(uri), envp);
+ ret = lyd_create_opaq(xmlctx->ctx, name, strlen(name), "", 0, NULL, LYD_XML, LYD_NODEHINT_ENVELOPE, NULL, prefix,
+ prefix_len, uri, strlen(uri), envp);
LY_CHECK_GOTO(ret, cleanup);
/* assign atributes */
@@ -872,8 +872,8 @@
}*/
/* create node */
- ret = lyd_create_opaq(xmlctx->ctx, "eventTime", 9, xmlctx->value, xmlctx->value_len, NULL, 0, LYD_XML, NULL,
- prefix, prefix_len, ns->uri, strlen(ns->uri), &et);
+ ret = lyd_create_opaq(xmlctx->ctx, "eventTime", 9, xmlctx->value, xmlctx->value_len, NULL, LYD_XML,
+ LYD_NODEHINT_ENVELOPE, NULL, prefix, prefix_len, ns->uri, strlen(ns->uri), &et);
LY_CHECK_GOTO(ret, cleanup);
/* assign atributes */
diff --git a/src/path.c b/src/path.c
index 07cd775..fe6adeb 100644
--- a/src/path.c
+++ b/src/path.c
@@ -490,8 +490,9 @@
/* Literal */
assert(expr->tokens[*tok_idx] == LYXP_TOKEN_LITERAL);
- LY_CHECK_RET(lyd_value_store(&p->value, key, expr->expr + expr->tok_pos[*tok_idx] + 1,
- expr->tok_len[*tok_idx] - 2, NULL, format, prefix_data));
+ LY_CHECK_RET(lyd_value_store(ctx, &p->value, ((struct lysc_node_leaf *)key)->type,
+ expr->expr + expr->tok_pos[*tok_idx] + 1, expr->tok_len[*tok_idx] - 2, NULL, format, prefix_data,
+ LYD_HINT_DATA, key, NULL, LY_VLOG_LYSC, key));
++(*tok_idx);
/* ']' */
@@ -533,8 +534,9 @@
assert(expr->tokens[*tok_idx] == LYXP_TOKEN_LITERAL);
/* store the value */
- LY_CHECK_RET(lyd_value_store(&p->value, ctx_node, expr->expr + expr->tok_pos[*tok_idx] + 1,
- expr->tok_len[*tok_idx] - 2, NULL, format, prefix_data));
+ LY_CHECK_RET(lyd_value_store(ctx, &p->value, ((struct lysc_node_leaflist *)ctx_node)->type,
+ expr->expr + expr->tok_pos[*tok_idx] + 1, expr->tok_len[*tok_idx] - 2, NULL, format, prefix_data,
+ LYD_HINT_DATA, ctx_node, NULL, LY_VLOG_LYSC, ctx_node));
++(*tok_idx);
/* ']' */
diff --git a/src/plugins_types.c b/src/plugins_types.c
index ed2981a..e4ce746 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -511,39 +511,124 @@
}
}
+static int
+type_get_hints_base(uint32_t hints)
+{
+ /* set allowed base */
+ switch (hints & (LYD_VALHINT_DECNUM | LYD_VALHINT_OCTNUM | LYD_VALHINT_HEXNUM)) {
+ case LYD_VALHINT_DECNUM:
+ return 10;
+ case LYD_VALHINT_OCTNUM:
+ return 8;
+ case LYD_VALHINT_HEXNUM:
+ return 16;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/**
+ * @brief Answer if the type is suitable for the parser's hit (if any) in the specified format
+ */
+static LY_ERR
+type_check_hints(uint32_t hints, const char *value, size_t value_len, LY_DATA_TYPE type, int *base, struct ly_err_item **err)
+{
+ char *msg;
+
+ switch (type) {
+ case LY_TYPE_UINT8:
+ case LY_TYPE_UINT16:
+ case LY_TYPE_UINT32:
+ case LY_TYPE_INT8:
+ case LY_TYPE_INT16:
+ case LY_TYPE_INT32:
+ if (!(hints & (LYD_VALHINT_DECNUM | LYD_VALHINT_OCTNUM | LYD_VALHINT_HEXNUM))) {
+ asprintf(&msg, "Invalid non-number-encoded %s value \"%.*s\".", lys_datatype2str(type), (int)value_len, value);
+ *err = ly_err_new(LY_LLERR, LY_EVALID, LYVE_DATA, msg, NULL, NULL);
+ return LY_EVALID;
+ }
+ *base = type_get_hints_base(hints);
+ break;
+ case LY_TYPE_UINT64:
+ case LY_TYPE_INT64:
+ if (!(hints & LYD_VALHINT_NUM64)) {
+ asprintf(&msg, "Invalid non-num64-encoded %s value \"%.*s\".", lys_datatype2str(type), (int)value_len, value);
+ *err = ly_err_new(LY_LLERR, LY_EVALID, LYVE_DATA, msg, NULL, NULL);
+ return LY_EVALID;
+ }
+ *base = type_get_hints_base(hints);
+ break;
+ case LY_TYPE_STRING:
+ case LY_TYPE_DEC64:
+ case LY_TYPE_ENUM:
+ case LY_TYPE_BITS:
+ case LY_TYPE_BINARY:
+ case LY_TYPE_IDENT:
+ case LY_TYPE_INST:
+ if (!(hints & LYD_VALHINT_STRING)) {
+ asprintf(&msg, "Invalid non-string-encoded %s value \"%.*s\".", lys_datatype2str(type), (int)value_len, value);
+ *err = ly_err_new(LY_LLERR, LY_EVALID, LYVE_DATA, msg, NULL, NULL);
+ return LY_EVALID;
+ }
+ break;
+ case LY_TYPE_BOOL:
+ if (!(hints & LYD_VALHINT_BOOLEAN)) {
+ asprintf(&msg, "Invalid non-boolean-encoded %s value \"%.*s\".", lys_datatype2str(type), (int)value_len, value);
+ *err = ly_err_new(LY_LLERR, LY_EVALID, LYVE_DATA, msg, NULL, NULL);
+ return LY_EVALID;
+ }
+ break;
+ case LY_TYPE_EMPTY:
+ if (!(hints & LYD_VALHINT_EMPTY)) {
+ asprintf(&msg, "Invalid non-empty-encoded %s value \"%.*s\".", lys_datatype2str(type), (int)value_len, value);
+ *err = ly_err_new(LY_LLERR, LY_EVALID, LYVE_DATA, msg, NULL, NULL);
+ return LY_EVALID;
+ }
+ break;
+ case LY_TYPE_UNKNOWN:
+ case LY_TYPE_LEAFREF:
+ case LY_TYPE_UNION:
+ LOGINT_RET(NULL);
+ }
+
+ return LY_SUCCESS;
+}
+
/**
* @brief Validate, canonize and store value of the YANG built-in signed integer types.
*
* Implementation of the ly_type_store_clb.
*/
static LY_ERR
-ly_type_store_int(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, uint32_t options,
- LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), const void *UNUSED(context_node),
- const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
+ly_type_store_int(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
+ uint32_t options, LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), uint32_t hints,
+ const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct ly_err_item **err)
{
LY_ERR ret;
int64_t num;
+ int base;
char *str;
struct lysc_type_num *type_num = (struct lysc_type_num *)type;
- if (options & LY_TYPE_OPTS_SECOND_CALL) {
- return LY_SUCCESS;
- }
+ /* check hints */
+ LY_CHECK_RET(type_check_hints(hints, value, value_len, type->basetype, &base, err));
switch (type->basetype) {
case LY_TYPE_INT8:
- LY_CHECK_RET(ly_type_parse_int("int8", (options & LY_TYPE_OPTS_SCHEMA) ? 0 : 10, INT64_C(-128), INT64_C(127), value, value_len, &num, err));
+ LY_CHECK_RET(ly_type_parse_int("int8", base, INT64_C(-128), INT64_C(127), value, value_len, &num, err));
break;
case LY_TYPE_INT16:
- LY_CHECK_RET(ly_type_parse_int("int16", (options & LY_TYPE_OPTS_SCHEMA) ? 0 : 10, INT64_C(-32768), INT64_C(32767), value, value_len, &num, err));
+ LY_CHECK_RET(ly_type_parse_int("int16", base, INT64_C(-32768), INT64_C(32767), value, value_len, &num, err));
break;
case LY_TYPE_INT32:
- LY_CHECK_RET(ly_type_parse_int("int32", (options & LY_TYPE_OPTS_SCHEMA) ? 0 : 10,
- INT64_C(-2147483648), INT64_C(2147483647), value, value_len, &num, err));
+ LY_CHECK_RET(ly_type_parse_int("int32", base, INT64_C(-2147483648), INT64_C(2147483647), value, value_len, &num,
+ err));
break;
case LY_TYPE_INT64:
- LY_CHECK_RET(ly_type_parse_int("int64", (options & LY_TYPE_OPTS_SCHEMA) ? 0 : 10,
- INT64_C(-9223372036854775807) - INT64_C(1), INT64_C(9223372036854775807), value, value_len, &num, err));
+ LY_CHECK_RET(ly_type_parse_int("int64", base, INT64_C(-9223372036854775807) - INT64_C(1),
+ INT64_C(9223372036854775807), value, value_len, &num, err));
break;
default:
LOGINT_RET(ctx);
@@ -573,31 +658,31 @@
* Implementation of the ly_type_store_clb.
*/
static LY_ERR
-ly_type_store_uint(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, uint32_t options,
- LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), const void *UNUSED(context_node),
- const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
+ly_type_store_uint(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
+ uint32_t options, LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), uint32_t hints,
+ const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct ly_err_item **err)
{
LY_ERR ret;
uint64_t num;
+ int base;
struct lysc_type_num *type_num = (struct lysc_type_num *)type;
char *str;
- if (options & LY_TYPE_OPTS_SECOND_CALL) {
- return LY_SUCCESS;
- }
+ /* check hints */
+ LY_CHECK_RET(type_check_hints(hints, value, value_len, type->basetype, &base, err));
switch (type->basetype) {
case LY_TYPE_UINT8:
- LY_CHECK_RET(ly_type_parse_uint("uint8", (options & LY_TYPE_OPTS_SCHEMA) ? 0 : 10, UINT64_C(255), value, value_len, &num, err));
+ LY_CHECK_RET(ly_type_parse_uint("uint8", base, UINT64_C(255), value, value_len, &num, err));
break;
case LY_TYPE_UINT16:
- LY_CHECK_RET(ly_type_parse_uint("uint16", (options & LY_TYPE_OPTS_SCHEMA) ? 0 : 10, UINT64_C(65535), value, value_len, &num, err));
+ LY_CHECK_RET(ly_type_parse_uint("uint16", base, UINT64_C(65535), value, value_len, &num, err));
break;
case LY_TYPE_UINT32:
- LY_CHECK_RET(ly_type_parse_uint("uint32", (options & LY_TYPE_OPTS_SCHEMA) ? 0 : 10, UINT64_C(4294967295), value, value_len, &num, err));
+ LY_CHECK_RET(ly_type_parse_uint("uint32", base, UINT64_C(4294967295), value, value_len, &num, err));
break;
case LY_TYPE_UINT64:
- LY_CHECK_RET(ly_type_parse_uint("uint64", (options & LY_TYPE_OPTS_SCHEMA) ? 0 : 10, UINT64_C(18446744073709551615), value, value_len, &num, err));
+ LY_CHECK_RET(ly_type_parse_uint("uint64", base, UINT64_C(18446744073709551615), value, value_len, &num, err));
break;
default:
LOGINT_RET(ctx);
@@ -627,23 +712,22 @@
* Implementation of the ly_type_store_clb.
*/
static LY_ERR
-ly_type_store_decimal64(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, uint32_t options,
- LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), const void *UNUSED(context_node),
- const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
+ly_type_store_decimal64(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
+ uint32_t options, LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), uint32_t hints,
+ const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct ly_err_item **err)
{
int64_t d;
struct lysc_type_dec *type_dec = (struct lysc_type_dec *)type;
char buf[22];
- if (options & LY_TYPE_OPTS_SECOND_CALL) {
- return LY_SUCCESS;
- }
-
if (!value || !value[0] || !value_len) {
*err = ly_err_new(LY_LLERR, LY_EVALID, LYVE_DATA, strdup("Invalid empty decimal64 value."), NULL, NULL);
return LY_EVALID;
}
+ /* check hints */
+ LY_CHECK_RET(type_check_hints(hints, value, value_len, type->basetype, NULL, err));
+
LY_CHECK_RET(ly_type_parse_dec64(type_dec->fraction_digits, value, value_len, &d, err));
/* prepare canonized value */
if (d) {
@@ -693,9 +777,9 @@
* Implementation of the ly_type_store_clb.
*/
static LY_ERR
-ly_type_store_binary(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, uint32_t options,
- LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), const void *UNUSED(context_node),
- const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
+ly_type_store_binary(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
+ uint32_t options, LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), uint32_t hints,
+ const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct ly_err_item **err)
{
size_t start = 0, stop = 0, count = 0, u, termination = 0;
struct lysc_type_bin *type_bin = (struct lysc_type_bin *)type;
@@ -707,9 +791,8 @@
/* initiate */
*err = NULL;
- if (options & LY_TYPE_OPTS_SECOND_CALL) {
- return LY_SUCCESS;
- }
+ /* check hints */
+ LY_CHECK_RET(type_check_hints(hints, value, value_len, type->basetype, NULL, err));
/* validate characters and remember the number of octets for length validation */
if (value_len) {
@@ -796,15 +879,14 @@
* Implementation of the ly_type_store_clb.
*/
static LY_ERR
-ly_type_store_string(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, uint32_t options,
- LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), const void *UNUSED(context_node),
- const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
+ly_type_store_string(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
+ uint32_t options, LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), uint32_t hints,
+ const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct ly_err_item **err)
{
struct lysc_type_str *type_str = (struct lysc_type_str *)type;
- if (options & LY_TYPE_OPTS_SECOND_CALL) {
- return LY_SUCCESS;
- }
+ /* check hints */
+ LY_CHECK_RET(type_check_hints(hints, value, value_len, type->basetype, NULL, err));
/* length restriction of the string */
if (type_str->length) {
@@ -836,9 +918,9 @@
* Implementation of the ly_type_store_clb.
*/
static LY_ERR
-ly_type_store_bits(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, uint32_t options,
- LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), const void *UNUSED(context_node),
- const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
+ly_type_store_bits(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
+ uint32_t options, LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), uint32_t hints,
+ const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct ly_err_item **err)
{
LY_ERR r, ret = LY_EVALID;
size_t item_len;
@@ -856,9 +938,8 @@
const char *can = NULL;
int rc = 0;
- if (options & LY_TYPE_OPTS_SECOND_CALL) {
- return LY_SUCCESS;
- }
+ /* check hints */
+ LY_CHECK_RET(type_check_hints(hints, value, value_len, type->basetype, NULL, err));
/* remember the present items for further work */
LY_CHECK_RET(ly_set_new(&items));
@@ -1028,18 +1109,17 @@
* Implementation of the ly_type_store_clb.
*/
static LY_ERR
-ly_type_store_enum(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, uint32_t options,
- LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), const void *UNUSED(context_node),
- const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
+ly_type_store_enum(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
+ uint32_t options, LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), uint32_t hints,
+ const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct ly_err_item **err)
{
LY_ARRAY_COUNT_TYPE u, v;
char *errmsg = NULL;
struct lysc_type_enum *type_enum = (struct lysc_type_enum *)type;
int rc = 0;
- if (options & LY_TYPE_OPTS_SECOND_CALL) {
- return LY_SUCCESS;
- }
+ /* check hints */
+ LY_CHECK_RET(type_check_hints(hints, value, value_len, type->basetype, NULL, err));
/* find the matching enumeration value item */
LY_ARRAY_FOR(type_enum->enums, u) {
@@ -1090,16 +1170,14 @@
* Implementation of the ly_type_store_clb.
*/
static LY_ERR
-ly_type_store_boolean(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len,
- uint32_t options, LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data),
- const void *UNUSED(context_node), const struct lyd_node *UNUSED(tree),
- struct lyd_value *storage, struct ly_err_item **err)
+ly_type_store_boolean(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
+ uint32_t options, LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), uint32_t hints,
+ const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct ly_err_item **err)
{
int8_t i;
- if (options & LY_TYPE_OPTS_SECOND_CALL) {
- return LY_SUCCESS;
- }
+ /* check hints */
+ LY_CHECK_RET(type_check_hints(hints, value, value_len, type->basetype, NULL, err));
if (value_len == 4 && !strncmp(value, "true", 4)) {
i = 1;
@@ -1133,14 +1211,12 @@
* Implementation of the ly_type_store_clb.
*/
static LY_ERR
-ly_type_store_empty(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, uint32_t options,
- LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data),
- const void *UNUSED(context_node), const struct lyd_node *UNUSED(tree),
- struct lyd_value *storage, struct ly_err_item **err)
+ly_type_store_empty(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
+ uint32_t UNUSED(options), LY_PREFIX_FORMAT UNUSED(format), void *UNUSED(prefix_data), uint32_t hints,
+ const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct ly_err_item **err)
{
- if (options & LY_TYPE_OPTS_SECOND_CALL) {
- return LY_SUCCESS;
- }
+ /* check hints */
+ LY_CHECK_RET(type_check_hints(hints, value, value_len, type->basetype, NULL, err));
if (value_len) {
char *errmsg;
@@ -1197,9 +1273,9 @@
* Implementation of the ly_type_store_clb.
*/
static LY_ERR
-ly_type_store_identityref(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, uint32_t options,
- LY_PREFIX_FORMAT format, void *prefix_data, const void *UNUSED(context_node),
- const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
+ly_type_store_identityref(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
+ uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints,
+ const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct ly_err_item **err)
{
struct lysc_type_identityref *type_ident = (struct lysc_type_identityref *)type;
const char *id_name, *prefix = value;
@@ -1211,9 +1287,8 @@
int rc = 0;
ly_bool dyn;
- if (options & LY_TYPE_OPTS_SECOND_CALL) {
- return LY_SUCCESS;
- }
+ /* check hints */
+ LY_CHECK_RET(type_check_hints(hints, value, value_len, type->basetype, NULL, err));
/* locate prefix if any */
for (prefix_len = 0; prefix_len < value_len && value[prefix_len] != ':'; ++prefix_len) {}
@@ -1334,31 +1409,24 @@
* Implementation of the ly_type_store_clb.
*/
static LY_ERR
-ly_type_store_instanceid(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, uint32_t options,
- LY_PREFIX_FORMAT format, void *prefix_data, const void *context_node, const struct lyd_node *tree,
+ly_type_store_instanceid(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
+ uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
struct lyd_value *storage, struct ly_err_item **err)
{
- LY_ERR ret = LY_EVALID;
+ LY_ERR ret = LY_SUCCESS;
struct lysc_type_instanceid *type_inst = (struct lysc_type_instanceid *)type;
char *errmsg = NULL, *str;
struct ly_path *path = NULL;
struct lyxp_expr *exp = NULL;
- const struct lysc_node *ctx_scnode;
int rc = 0;
uint32_t prefix_opt = 0;
ly_bool dyn;
/* init */
*err = NULL;
- ctx_scnode = (options & (LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_INCOMPLETE_DATA)) ?
- (struct lysc_node *)context_node : ((struct lyd_node *)context_node)->schema;
- if ((options & LY_TYPE_OPTS_SCHEMA) && (options & LY_TYPE_OPTS_INCOMPLETE_DATA)) {
- /* we have incomplete schema tree */
- /* HACK temporary storing of the original value */
- LY_CHECK_RET(lydict_insert(ctx, value_len ? value : "", value_len, &storage->canonical));
- goto cleanup;
- }
+ /* check hints */
+ LY_CHECK_RET(type_check_hints(hints, value, value_len, type->basetype, NULL, err));
switch (format) {
case LY_PREF_SCHEMA:
@@ -1370,27 +1438,8 @@
break;
}
- if (!(options & LY_TYPE_OPTS_SCHEMA) && (options & LY_TYPE_OPTS_SECOND_CALL)) {
- /* the second run in data tree, the first one ended with LY_EINCOMPLETE, but we have prepared the target structure */
- if (ly_path_eval(storage->target, tree, NULL)) {
- /* in error message we print the JSON format of the instance-identifier - in case of XML, it is not possible
- * to get the exactly same string as original, JSON is less demanding and still well readable/understandable. */
- ly_bool dynamic = 0;
- const char *id = storage->realtype->plugin->print(storage, LY_PREF_JSON, NULL, &dynamic);
- rc = asprintf(&errmsg, "Invalid instance-identifier \"%s\" value - required instance not found.", id);
- if (dynamic) {
- free((char *)id);
- }
- /* we have to clean up the storage */
- type->plugin->free(ctx, storage);
-
- goto error;
- }
- return LY_SUCCESS;
- }
-
/* parse the value */
- ret = ly_path_parse(ctx, ctx_scnode, value, value_len, LY_PATH_BEGIN_ABSOLUTE, LY_PATH_LREF_FALSE,
+ ret = ly_path_parse(ctx, ctx_node, value, value_len, LY_PATH_BEGIN_ABSOLUTE, LY_PATH_LREF_FALSE,
prefix_opt, LY_PATH_PRED_SIMPLE, &exp);
if (ret) {
rc = asprintf(&errmsg, "Invalid instance-identifier \"%.*s\" value - syntax error.", (int)value_len, value);
@@ -1398,25 +1447,13 @@
}
/* resolve it on schema tree */
- ret = ly_path_compile(ctx, ctx_scnode->module, NULL, exp, LY_PATH_LREF_FALSE, lysc_is_output(ctx_scnode) ?
- LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_SINGLE, format, prefix_data, &path);
+ ret = ly_path_compile(ctx, NULL, ctx_node, exp, LY_PATH_LREF_FALSE, lysc_is_output(ctx_node) ?
+ LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_SINGLE, format, prefix_data, &path);
if (ret) {
rc = asprintf(&errmsg, "Invalid instance-identifier \"%.*s\" value - semantic error.", (int)value_len, value);
goto error;
}
- /* find it in data */
- if (!(options & LY_TYPE_OPTS_INCOMPLETE_DATA) && !(options & LY_TYPE_OPTS_SCHEMA) && type_inst->require_instance) {
- ret = ly_path_eval(path, tree, NULL);
- if (ret) {
- rc = asprintf(&errmsg, "Invalid instance-identifier \"%.*s\" value - instance not found.", (int)value_len, value);
- goto error;
- }
- }
-
- /* HACK remove previously stored original value */
- lydict_remove(ctx, storage->canonical);
-
/* store resolved schema path */
storage->target = path;
path = NULL;
@@ -1428,7 +1465,7 @@
storage->realtype = type;
-cleanup:
+ /* cleanup */
lyxp_expr_free(ctx, exp);
ly_path_free(ctx, path);
@@ -1436,7 +1473,8 @@
free((char *)value);
}
- if ((options & LY_TYPE_OPTS_INCOMPLETE_DATA) && ((options & LY_TYPE_OPTS_SCHEMA) || type_inst->require_instance)) {
+ if (type_inst->require_instance) {
+ /* needs to be resolved */
return LY_EINCOMPLETE;
} else {
return LY_SUCCESS;
@@ -1458,6 +1496,38 @@
}
/**
+ * @brief Validate value of the YANG built-in instance-identifier type.
+ *
+ * Implementation of the ly_type_validate_clb.
+ */
+static LY_ERR
+ly_type_validate_instanceid(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *UNUSED(type),
+ const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *tree, struct lyd_value *storage,
+ struct ly_err_item **err)
+{
+ struct lysc_type_instanceid *type_inst = (struct lysc_type_instanceid *)storage->realtype;
+ LY_ERR ret;
+ char *errmsg;
+
+ *err = NULL;
+
+ if (!type_inst->require_instance) {
+ /* redundant to resolve */
+ return LY_SUCCESS;
+ }
+
+ /* find the target in data */
+ ret = ly_path_eval(storage->target, tree, NULL);
+ if (ret) {
+ asprintf(&errmsg, "Invalid instance-identifier \"%s\" value - required instance not found.", storage->canonical);
+ *err = ly_err_new(LY_LLERR, LY_EVALID, LYVE_DATA, errmsg, NULL, NULL);
+ return ret;
+ }
+
+ return LY_SUCCESS;
+}
+
+/**
* @brief Comparison callback checking the instance-identifier value.
*
* Implementation of the ly_type_compare_clb.
@@ -1728,69 +1798,63 @@
}
/**
- * @brief Validate, canonize and store value of the YANG built-in leafref type.
+ * @brief Store and canonize value of the YANG built-in leafref type.
*
* Implementation of the ly_type_store_clb.
*/
static LY_ERR
-ly_type_store_leafref(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, uint32_t options,
- LY_PREFIX_FORMAT format, void *prefix_data, const void *context_node, const struct lyd_node *tree,
+ly_type_store_leafref(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
+ uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
struct lyd_value *storage, struct ly_err_item **err)
{
LY_ERR ret = LY_SUCCESS;
- char *errmsg = NULL;
struct lysc_type_leafref *type_lr = (struct lysc_type_leafref *)type;
- struct ly_path *p = NULL;
- struct ly_set *set = NULL;
- if (!type_lr->realtype) {
- if ((options & LY_TYPE_OPTS_SCHEMA) && (options & LY_TYPE_OPTS_INCOMPLETE_DATA)) {
- /* leafref's path was not yet resolved - in schema trees, path can be resolved when
- * the complete schema tree is present, in such a case we need to wait with validating
- * default values */
- return LY_EINCOMPLETE;
- } else {
- LOGINT(ctx);
- return LY_EINT;
- }
- }
+ assert(type_lr->realtype);
- if ((options & LY_TYPE_OPTS_SCHEMA) && (options & LY_TYPE_OPTS_SECOND_CALL)) {
- /* hide the LY_TYPE_OPTS_SECOND_CALL option from the target's store callback, the option is connected
- * only with the leafref's path, so it is not supposed to be used here. If the previous LY_EINCOMPLETE would
- * be caused by the target's type, the target type's callback would be used directly, not via leafref's callback */
- options &= ~LY_TYPE_OPTS_SECOND_CALL;
- }
-
- /* check value according to the real type of the leafref target */
+ /* store the value as the real type of the leafref target */
ret = type_lr->realtype->plugin->store(ctx, type_lr->realtype, value, value_len, options, format, prefix_data,
- context_node, tree, storage, err);
- if (ret != LY_SUCCESS && ret != LY_EINCOMPLETE) {
- goto cleanup;
+ hints, ctx_node, storage, err);
+ if (ret == LY_EINCOMPLETE) {
+ /* it is irrelevant whether the target type needs some resolving */
+ ret = LY_SUCCESS;
+ }
+ LY_CHECK_RET(ret);
+
+ if (type_lr->require_instance) {
+ /* needs to be resolved */
+ return LY_EINCOMPLETE;
+ } else {
+ return LY_SUCCESS;
+ }
+}
+
+/**
+ * @brief Validate value of the YANG built-in leafref type.
+ *
+ * Implementation of the ly_type_validate_clb.
+ */
+static LY_ERR
+ly_type_validate_leafref(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *ctx_node,
+ const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err)
+{
+ struct lysc_type_leafref *type_lr = (struct lysc_type_leafref *)type;
+ char *errmsg = NULL;
+
+ *err = NULL;
+
+ if (!type_lr->require_instance) {
+ /* redundant to resolve */
+ return LY_SUCCESS;
}
- /* rewrite leafref plugin stored in the storage by default */
- storage->realtype = type_lr->realtype;
-
- if (!(options & LY_TYPE_OPTS_SCHEMA) && type_lr->require_instance) {
- if (options & LY_TYPE_OPTS_INCOMPLETE_DATA) {
- ret = LY_EINCOMPLETE;
- goto cleanup;
- }
-
- /* check leafref target existence */
- ret = ly_type_find_leafref(type_lr, (struct lyd_node *)context_node, storage, tree, NULL, &errmsg);
- if (ret) {
- *err = ly_err_new(LY_LLERR, LY_EVALID, LYVE_DATA, errmsg, NULL, NULL);
- ret = LY_EVALID;
- goto cleanup;
- }
+ /* check leafref target existence */
+ if (ly_type_find_leafref(type_lr, ctx_node, storage, tree, NULL, &errmsg)) {
+ *err = ly_err_new(LY_LLERR, LY_EVALID, LYVE_DATA, errmsg, NULL, NULL);
+ return LY_EVALID;
}
-cleanup:
- ly_path_free(ctx, p);
- ly_set_free(set, NULL);
- return ret;
+ return LY_SUCCESS;
}
/**
@@ -1840,55 +1904,6 @@
}
/**
- * @brief Answer if the type is suitable for the parser's hit (if any) in the specified format
- */
-LY_ERR
-type_check_parser_hint(LY_PREFIX_FORMAT format, uint32_t hint, LY_DATA_TYPE type)
-{
- if (format == LY_PREF_JSON && hint) {
- switch (type) {
- case LY_TYPE_UINT8:
- case LY_TYPE_UINT16:
- case LY_TYPE_UINT32:
- case LY_TYPE_INT8:
- case LY_TYPE_INT16:
- case LY_TYPE_INT32:
- if (hint != LY_TYPE_OPTS_ISNUMBER) {
- return LY_ENOT;
- }
- break;
- case LY_TYPE_STRING:
- case LY_TYPE_UINT64:
- case LY_TYPE_INT64:
- case LY_TYPE_DEC64:
- case LY_TYPE_ENUM:
- case LY_TYPE_BITS:
- case LY_TYPE_BINARY:
- case LY_TYPE_IDENT:
- case LY_TYPE_INST:
- if (hint != LY_TYPE_OPTS_ISSTRING) {
- return LY_ENOT;
- }
- break;
- case LY_TYPE_BOOL:
- if (hint != LY_TYPE_OPTS_ISBOOLEAN) {
- return LY_ENOT;
- }
- break;
- case LY_TYPE_EMPTY:
- if (hint != LY_TYPE_OPTS_ISEMPTY) {
- return LY_ENOT;
- }
- break;
- default:
- LOGINT_RET(NULL);
- }
- }
-
- return LY_SUCCESS;
-}
-
-/**
* @brief Free stored prefix data of a union.
*
* @param[in] format Format of the prefixes.
@@ -1900,6 +1915,10 @@
struct ly_set *ns_list;
uint32_t i;
+ if (!prefix_data) {
+ return;
+ }
+
switch (format) {
case LY_PREF_XML:
ns_list = prefix_data;
@@ -2055,131 +2074,161 @@
return NULL;
}
+static LY_ERR
+ly_type_union_store_type(const struct ly_ctx *ctx, struct lysc_type **types, struct lyd_value_subvalue *subvalue,
+ ly_bool resolve, const struct lyd_node *ctx_node, const struct lyd_node *tree, struct ly_err_item **err)
+{
+ LY_ERR ret = LY_SUCCESS;
+ LY_ARRAY_COUNT_TYPE u;
+ char *errmsg = NULL;
+ uint32_t prev_lo;
+
+ if (!types || !LY_ARRAY_COUNT(types)) {
+ return LY_EINVAL;
+ }
+
+ /* turn logging off */
+ prev_lo = ly_log_options(0);
+
+ /* use the first usable subtype to store the value */
+ for (u = 0; u < LY_ARRAY_COUNT(types); ++u) {
+ ret = types[u]->plugin->store(ctx, types[u], subvalue->original, strlen(subvalue->original),
+ 0, subvalue->format, subvalue->prefix_data,
+ subvalue->hints, subvalue->ctx_node, &subvalue->value, err);
+ if ((ret == LY_SUCCESS) || (ret == LY_EINCOMPLETE)) {
+ if (resolve && (ret == LY_EINCOMPLETE)) {
+ /* we need the value resolved */
+ ret = subvalue->value.realtype->plugin->validate(ctx, types[u], ctx_node, tree, &subvalue->value, err);
+ if (!ret) {
+ /* store and resolve successful */
+ break;
+ }
+
+ /* resolve failed, we need to free the stored value */
+ types[u]->plugin->free(ctx, &subvalue->value);
+ } else {
+ /* store successful */
+ break;
+ }
+ }
+ ly_err_free(*err);
+ *err = NULL;
+ }
+
+ if (u == LY_ARRAY_COUNT(types)) {
+ if (asprintf(&errmsg, "Invalid union value \"%s\" - no matching subtype found.", subvalue->original) == -1) {
+ *err = ly_err_new(LY_LLERR, LY_EMEM, 0, "Memory allocation failed.", NULL, NULL);
+ ret = LY_EMEM;
+ goto cleanup;
+ }
+ *err = ly_err_new(LY_LLERR, LY_EVALID, LYVE_DATA, errmsg, NULL, NULL);
+ ret = LY_EVALID;
+ goto cleanup;
+ }
+
+cleanup:
+ /* restore logging */
+ ly_log_options(prev_lo);
+ return ret;
+}
+
/**
- * @brief Validate, canonize and store value of the YANG built-in union type.
+ * @brief Store and canonize value of the YANG built-in union type.
*
* Implementation of the ly_type_store_clb.
*/
static LY_ERR
-ly_type_store_union(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, uint32_t options,
- LY_PREFIX_FORMAT format, void *prefix_data, const void *context_node, const struct lyd_node *tree,
+ly_type_store_union(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value, size_t value_len,
+ uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node,
struct lyd_value *storage, struct ly_err_item **err)
{
LY_ERR ret = LY_SUCCESS;
- LY_ARRAY_COUNT_TYPE u;
struct lysc_type_union *type_u = (struct lysc_type_union *)type;
- struct lyd_value_subvalue *subvalue;
- char *errmsg = NULL;
- uint32_t prev_lo;
+ struct lyd_value_subvalue *subvalue = NULL;
- if (options & LY_TYPE_OPTS_SECOND_CALL) {
- subvalue = storage->subvalue;
+ /* prepare subvalue storage */
+ subvalue = calloc(1, sizeof *subvalue);
+ if (!subvalue) {
+ *err = ly_err_new(LY_LLERR, LY_EMEM, 0, "Memory allocation failed.", NULL, NULL);
+ return LY_EMEM;
+ }
- /* call the callback second time */
- ret = subvalue->value->realtype->plugin->store(ctx, subvalue->value->realtype, subvalue->original,
- strlen(subvalue->original), options & ~LY_TYPE_OPTS_DYNAMIC,
- subvalue->format, subvalue->prefix_data, context_node, tree,
- subvalue->value, err);
- if (ret == LY_SUCCESS) {
- /* storing successful */
- return LY_SUCCESS;
- }
+ /* remember the original value */
+ if (options & LY_TYPE_OPTS_DYNAMIC) {
+ ret = lydict_insert_zc(ctx, (char *)value, &subvalue->original);
+ LY_CHECK_GOTO(ret, cleanup);
- /* second call failed, we have to try another subtype of the union.
- * Unfortunately, since the realtype can change (e.g. in leafref), we are not able to detect
- * which of the subtype's were tried the last time, so we have to try all of them.
- * We also have to remove the LY_TYPE_OPTS_SECOND_CALL flag since the callbacks will be now
- * called for the first time.
- * In the second call we should have all the data instances, so the LY_EINCOMPLETE should not
- * happen again.
- */
- options = options & ~LY_TYPE_OPTS_SECOND_CALL;
- ly_err_free(*err);
- *err = NULL;
+ options &= ~LY_TYPE_OPTS_DYNAMIC;
} else {
- /* prepare subvalue storage */
- subvalue = calloc(1, sizeof *subvalue);
- if (!subvalue) {
- *err = ly_err_new(LY_LLERR, LY_EMEM, 0, "Memory allocation failed.", NULL, NULL);
- return LY_EMEM;
- }
- subvalue->value = calloc(1, sizeof *subvalue->value);
- if (!subvalue->value) {
- free(subvalue);
- *err = ly_err_new(LY_LLERR, LY_EMEM, 0, "Memory allocation failed.", NULL, NULL);
- return LY_EMEM;
- }
-
- /* remember the original value */
ret = lydict_insert(ctx, value_len ? value : "", value_len, &subvalue->original);
- if (ret) {
- free(subvalue->value);
- free(subvalue);
- return ret;
- }
-
- /* store format-specific data for later prefix resolution */
- subvalue->format = format;
- subvalue->prefix_data = ly_type_union_store_prefix_data(ctx, value, value_len, format, prefix_data);
-
- /* remember the hint options */
- subvalue->parser_hint = options & LY_TYPE_PARSER_HINTS_MASK;
+ LY_CHECK_GOTO(ret, cleanup);
}
- /* use the first usable sybtype to store the value */
- LY_ARRAY_FOR(type_u->types, u) {
- if (type_check_parser_hint(format, subvalue->parser_hint, type_u->types[u]->basetype)) {
- /* not a suitable type */
- continue;
- }
+ /* store format-specific data for later prefix resolution */
+ subvalue->format = format;
+ subvalue->prefix_data = ly_type_union_store_prefix_data(ctx, value, value_len, format, prefix_data);
+ subvalue->hints = hints;
+ subvalue->ctx_node = ctx_node;
- /* turn logging off */
- prev_lo = ly_log_options(0);
- ret = type_u->types[u]->plugin->store(ctx, type_u->types[u], subvalue->original, strlen(subvalue->original),
- options & ~LY_TYPE_OPTS_DYNAMIC, subvalue->format, subvalue->prefix_data,
- context_node, tree, subvalue->value, err);
- /* restore logging */
- ly_log_options(prev_lo);
- if (ret == LY_SUCCESS || ret == LY_EINCOMPLETE) {
- /* success (or not yet complete) */
- break;
- }
- ly_err_free(*err);
- *err = NULL;
- }
+ /* use the first usable subtype to store the value */
+ ret = ly_type_union_store_type(ctx, type_u->types, subvalue, 0, NULL, NULL, err);
+ LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup);
- if (u == LY_ARRAY_COUNT(type_u->types)) {
- if (asprintf(&errmsg, "Invalid union value \"%.*s\" - no matching subtype found.", (int)value_len, value) == -1) {
- *err = ly_err_new(LY_LLERR, LY_EMEM, 0, "Memory allocation failed.", NULL, NULL);
- ret = LY_EMEM;
- } else {
- *err = ly_err_new(LY_LLERR, LY_EVALID, LYVE_DATA, errmsg, NULL, NULL);
- ret = LY_EVALID;
- }
- goto error;
- }
-
- ret = lydict_insert(ctx, subvalue->value->canonical, strlen(subvalue->value->canonical), &storage->canonical);
- if (ret) {
-error:
- /* free any stored information */
- free(subvalue->value);
+cleanup:
+ if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
lydict_remove(ctx, subvalue->original);
ly_type_union_free_prefix_data(subvalue->format, subvalue->prefix_data);
free(subvalue);
- if (options & LY_TYPE_OPTS_SECOND_CALL) {
- storage->subvalue = NULL;
- }
- return ret;
+ } else {
+ /* store it as union, the specific type is in the subvalue, but canonical value is the specific type value */
+ ret = lydict_insert(ctx, subvalue->value.canonical, 0, &storage->canonical);
+ LY_CHECK_GOTO(ret, cleanup);
+ storage->subvalue = subvalue;
+ storage->realtype = type;
+ }
+ return ret;
+}
+
+/**
+ * @brief Validate value of the YANG built-in union type.
+ *
+ * Implementation of the ly_type_validate_clb.
+ */
+static LY_ERR
+ly_type_validate_union(const struct ly_ctx *ctx, const struct lysc_type *type, const struct lyd_node *ctx_node,
+ const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err)
+{
+ LY_ERR ret = LY_SUCCESS;
+ struct lysc_type_union *type_u = (struct lysc_type_union *)storage->realtype;
+ struct lyd_value_subvalue *subvalue = storage->subvalue;
+
+ *err = NULL;
+
+ if (!subvalue->value.realtype->plugin->validate) {
+ /* nothing to resolve */
+ return LY_SUCCESS;
}
- /* success */
- storage->subvalue = subvalue;
- storage->realtype = type;
-
- if (options & LY_TYPE_OPTS_DYNAMIC) {
- free((char *)value);
+ /* resolve the stored value */
+ if (!subvalue->value.realtype->plugin->validate(ctx, type, ctx_node, tree, &subvalue->value, err)) {
+ /* resolve successful */
+ return LY_SUCCESS;
}
+
+ /* Resolve failed, we have to try another subtype of the union.
+ * Unfortunately, since the realtype can change (e.g. in leafref), we are not able to detect
+ * which of the subtype's were tried the last time, so we have to try all of them again.
+ */
+ ly_err_free(*err);
+ *err = NULL;
+
+ /* store and resolve the value */
+ ret = ly_type_union_store_type(ctx, type_u->types, subvalue, 1, ctx_node, tree, err);
+ LY_CHECK_RET(ret);
+
+ /* success, update the canonical value */
+ lydict_remove(ctx, storage->canonical);
+ LY_CHECK_RET(lydict_insert(ctx, subvalue->value.canonical, 0, &storage->canonical));
return LY_SUCCESS;
}
@@ -2191,10 +2240,10 @@
static LY_ERR
ly_type_compare_union(const struct lyd_value *val1, const struct lyd_value *val2)
{
- if (val1->subvalue->value->realtype != val2->subvalue->value->realtype) {
+ if (val1->subvalue->value.realtype != val2->subvalue->value.realtype) {
return LY_ENOT;
}
- return val1->subvalue->value->realtype->plugin->compare(val1->subvalue->value, val2->subvalue->value);
+ return val1->subvalue->value.realtype->plugin->compare(&val1->subvalue->value, &val2->subvalue->value);
}
/**
@@ -2205,7 +2254,7 @@
static const char *
ly_type_print_union(const struct lyd_value *value, LY_PREFIX_FORMAT format, void *prefix_data, ly_bool *dynamic)
{
- return value->subvalue->value->realtype->plugin->print(value->subvalue->value, format, prefix_data, dynamic);
+ return value->subvalue->value.realtype->plugin->print(&value->subvalue->value, format, prefix_data, dynamic);
}
/**
@@ -2220,11 +2269,10 @@
dup->subvalue = calloc(1, sizeof *dup->subvalue);
LY_CHECK_ERR_RET(!dup->subvalue, LOGMEM(ctx), LY_EMEM);
- dup->subvalue->value = calloc(1, sizeof *dup->subvalue->value);
- LY_CHECK_ERR_RET(!dup->subvalue->value, LOGMEM(ctx), LY_EMEM);
- LY_CHECK_RET(original->subvalue->value->realtype->plugin->duplicate(ctx, original->subvalue->value, dup->subvalue->value));
+ LY_CHECK_RET(original->subvalue->value.realtype->plugin->duplicate(ctx, &original->subvalue->value, &dup->subvalue->value));
- LY_CHECK_RET(lydict_insert(ctx, original->subvalue->original, strlen(original->subvalue->original), &dup->subvalue->original));
+ LY_CHECK_RET(lydict_insert(ctx, original->subvalue->original, strlen(original->subvalue->original),
+ &dup->subvalue->original));
dup->subvalue->format = original->subvalue->format;
dup->subvalue->prefix_data = ly_type_union_dup_prefix_data(ctx, original->subvalue->format,
original->subvalue->prefix_data);
@@ -2243,11 +2291,10 @@
{
lydict_remove(ctx, value->canonical);
if (value->subvalue) {
- if (value->subvalue->value) {
- value->subvalue->value->realtype->plugin->free(ctx, value->subvalue->value);
- free(value->subvalue->value);
- ly_type_union_free_prefix_data(value->subvalue->format, value->subvalue->prefix_data);
+ if (value->subvalue->value.realtype) {
+ value->subvalue->value.realtype->plugin->free(ctx, &value->subvalue->value);
}
+ ly_type_union_free_prefix_data(value->subvalue->format, value->subvalue->prefix_data);
lydict_remove(ctx, value->subvalue->original);
free(value->subvalue);
value->subvalue = NULL;
@@ -2259,61 +2306,61 @@
*/
struct lysc_type_plugin ly_builtin_type_plugins[LY_DATA_TYPE_COUNT] = {
{0}, /* LY_TYPE_UNKNOWN */
- {.type = LY_TYPE_BINARY, .store = ly_type_store_binary, .compare = ly_type_compare_simple,
+ {.type = LY_TYPE_BINARY, .store = ly_type_store_binary, .validate = NULL, .compare = ly_type_compare_simple,
.print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
.id = "libyang 2 - binary, version 1"},
- {.type = LY_TYPE_UINT8, .store = ly_type_store_uint, .compare = ly_type_compare_simple,
+ {.type = LY_TYPE_UINT8, .store = ly_type_store_uint, .validate = NULL, .compare = ly_type_compare_simple,
.print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
.id = "libyang 2 - unsigned integer, version 1"},
- {.type = LY_TYPE_UINT16, .store = ly_type_store_uint, .compare = ly_type_compare_simple,
+ {.type = LY_TYPE_UINT16, .store = ly_type_store_uint, .validate = NULL, .compare = ly_type_compare_simple,
.print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
.id = "libyang 2 - unsigned integer, version 1"},
- {.type = LY_TYPE_UINT32, .store = ly_type_store_uint, .compare = ly_type_compare_simple,
+ {.type = LY_TYPE_UINT32, .store = ly_type_store_uint, .validate = NULL, .compare = ly_type_compare_simple,
.print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
.id = "libyang 2 - unsigned integer, version 1"},
- {.type = LY_TYPE_UINT64, .store = ly_type_store_uint, .compare = ly_type_compare_simple,
+ {.type = LY_TYPE_UINT64, .store = ly_type_store_uint, .validate = NULL, .compare = ly_type_compare_simple,
.print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
.id = "libyang 2 - unsigned integer, version 1"},
- {.type = LY_TYPE_STRING, .store = ly_type_store_string, .compare = ly_type_compare_simple,
+ {.type = LY_TYPE_STRING, .store = ly_type_store_string, .validate = NULL, .compare = ly_type_compare_simple,
.print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
.id = "libyang 2 - string, version 1"},
- {.type = LY_TYPE_BITS, .store = ly_type_store_bits, .compare = ly_type_compare_simple,
+ {.type = LY_TYPE_BITS, .store = ly_type_store_bits, .validate = NULL, .compare = ly_type_compare_simple,
.print = ly_type_print_simple, .duplicate = ly_type_dup_bits, .free = ly_type_free_bits,
.id = "libyang 2 - bits, version 1"},
- {.type = LY_TYPE_BOOL, .store = ly_type_store_boolean, .compare = ly_type_compare_simple,
+ {.type = LY_TYPE_BOOL, .store = ly_type_store_boolean, .validate = NULL, .compare = ly_type_compare_simple,
.print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
.id = "libyang 2 - boolean, version 1"},
- {.type = LY_TYPE_DEC64, .store = ly_type_store_decimal64, .compare = ly_type_compare_simple,
+ {.type = LY_TYPE_DEC64, .store = ly_type_store_decimal64, .validate = NULL, .compare = ly_type_compare_simple,
.print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
.id = "libyang 2 - decimal64, version 1"},
- {.type = LY_TYPE_EMPTY, .store = ly_type_store_empty, .compare = ly_type_compare_empty,
+ {.type = LY_TYPE_EMPTY, .store = ly_type_store_empty, .validate = NULL, .compare = ly_type_compare_empty,
.print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
.id = "libyang 2 - empty, version 1"},
- {.type = LY_TYPE_ENUM, .store = ly_type_store_enum, .compare = ly_type_compare_simple,
+ {.type = LY_TYPE_ENUM, .store = ly_type_store_enum, .validate = NULL, .compare = ly_type_compare_simple,
.print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
.id = "libyang 2 - enumeration, version 1"},
- {.type = LY_TYPE_IDENT, .store = ly_type_store_identityref, .compare = ly_type_compare_identityref,
+ {.type = LY_TYPE_IDENT, .store = ly_type_store_identityref, .validate = NULL, .compare = ly_type_compare_identityref,
.print = ly_type_print_identityref, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
.id = "libyang 2 - identityref, version 1"},
- {.type = LY_TYPE_INST, .store = ly_type_store_instanceid, .compare = ly_type_compare_instanceid,
- .print = ly_type_print_instanceid, .duplicate = ly_type_dup_instanceid, .free = ly_type_free_instanceid,
- .id = "libyang 2 - instance-identifier, version 1"},
- {.type = LY_TYPE_LEAFREF, .store = ly_type_store_leafref, .compare = ly_type_compare_leafref,
- .print = ly_type_print_leafref, .duplicate = ly_type_dup_leafref, .free = ly_type_free_leafref,
- .id = "libyang 2 - leafref, version 1"},
- {.type = LY_TYPE_UNION, .store = ly_type_store_union, .compare = ly_type_compare_union,
+ {.type = LY_TYPE_INST, .store = ly_type_store_instanceid, .validate = ly_type_validate_instanceid,
+ .compare = ly_type_compare_instanceid, .print = ly_type_print_instanceid, .duplicate = ly_type_dup_instanceid,
+ .free = ly_type_free_instanceid, .id = "libyang 2 - instance-identifier, version 1"},
+ {.type = LY_TYPE_LEAFREF, .store = ly_type_store_leafref, .validate = ly_type_validate_leafref,
+ .compare = ly_type_compare_leafref, .print = ly_type_print_leafref, .duplicate = ly_type_dup_leafref,
+ .free = ly_type_free_leafref, .id = "libyang 2 - leafref, version 1"},
+ {.type = LY_TYPE_UNION, .store = ly_type_store_union, .validate = ly_type_validate_union, .compare = ly_type_compare_union,
.print = ly_type_print_union, .duplicate = ly_type_dup_union, .free = ly_type_free_union,
.id = "libyang 2 - union,version 1"},
- {.type = LY_TYPE_INT8, .store = ly_type_store_int, .compare = ly_type_compare_simple,
+ {.type = LY_TYPE_INT8, .store = ly_type_store_int, .validate = NULL, .compare = ly_type_compare_simple,
.print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
.id = "libyang 2 - integer, version 1"},
- {.type = LY_TYPE_INT16, .store = ly_type_store_int, .compare = ly_type_compare_simple,
+ {.type = LY_TYPE_INT16, .store = ly_type_store_int, .validate = NULL, .compare = ly_type_compare_simple,
.print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
.id = "libyang 2 - integer, version 1"},
- {.type = LY_TYPE_INT32, .store = ly_type_store_int, .compare = ly_type_compare_simple,
+ {.type = LY_TYPE_INT32, .store = ly_type_store_int, .validate = NULL, .compare = ly_type_compare_simple,
.print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
.id = "libyang 2 - integer, version 1"},
- {.type = LY_TYPE_INT64, .store = ly_type_store_int, .compare = ly_type_compare_simple,
+ {.type = LY_TYPE_INT64, .store = ly_type_store_int, .validate = NULL, .compare = ly_type_compare_simple,
.print = ly_type_print_simple, .duplicate = ly_type_dup_simple, .free = ly_type_free_simple,
.id = "libyang 2 - integer, version 1"},
};
diff --git a/src/plugins_types.h b/src/plugins_types.h
index 34dec40..3385b4f 100644
--- a/src/plugins_types.h
+++ b/src/plugins_types.h
@@ -134,7 +134,8 @@
const char *ly_get_prefix(const struct lys_module *mod, LY_PREFIX_FORMAT format, void *prefix_data);
/**
- * @defgroup plugintypeopts Options for type plugin callbacks. The same set of the options is passed to all the type's callbacks used together.
+ * @defgroup plugintypeopts Options for type plugin callbacks. The same set of the options is passed to
+ * all the type's callbacks used together.
*
* Options applicable to ly_type_store_clb().
* @{
@@ -144,70 +145,59 @@
(e.g. in case of canonization).
In any case, the caller of the callback does not free the provided string value after calling
the type's callbacks with this option */
-#define LY_TYPE_OPTS_SCHEMA 0x02 /**< Flag for the value used in schema instead of the data tree. With this flag also the meaning of
- LY_TYPE_OPTS_INCOMPLETE_DATA changes and means that the schema tree is not complete (data tree
- is not taken into account at all). */
-#define LY_TYPE_OPTS_INCOMPLETE_DATA 0x04 /**< Flag for the case the data trees (schema trees in case it is used in combination with
- LY_TYPE_OPTS_SCHEMA) are not yet complete. In this case the plugin should do what it
- can (e.g. store the canonical/auxiliary value if it is requested) and in the case of need to use
- data trees (checking require-instance), it returns LY_EINCOMPLETE.
- Caller is supposed to call such validation callback again later with complete data trees. */
-#define LY_TYPE_OPTS_SECOND_CALL 0x08 /**< Flag for the second call of the callback when the first call returns LY_EINCOMPLETE,
- other options should be the same as for the first call. **!!** Note that this second call
- can occur even if the first call succeeded, in which case the plugin should immediately
- return LY_SUCCESS. */
-#define LY_TYPE_OPTS_ISSTRING LYD_NODE_OPAQ_ISSTRING /**< Hint flag from the parser in case the source format provides some additional information
- about the type of the data. The flag is expected to be used in combination with the format information. */
-#define LY_TYPE_OPTS_ISNUMBER LYD_NODE_OPAQ_ISNUMBER /**< Hint flag from the parser in case the source format provides some additional information
- about the type of the data. The flag is expected to be used in combination with the format information. */
-#define LY_TYPE_OPTS_ISBOOLEAN LYD_NODE_OPAQ_ISBOOLEAN /**< Hint flag from the parser in case the source format provides some additional information
- about the type of the data. The flag is expected to be used in combination with the format information. */
-#define LY_TYPE_OPTS_ISEMPTY LYD_NODE_OPAQ_ISEMPTY /**< Hint flag from the parser in case the source format provides some additional information
- about the type of the data. The flag is expected to be used in combination with the format information. */
-#define LY_TYPE_PARSER_HINTS_MASK (LY_TYPE_OPTS_ISSTRING | LY_TYPE_OPTS_ISNUMBER | LY_TYPE_OPTS_ISBOOLEAN | LY_TYPE_OPTS_ISEMPTY)
-
/** @} plugintypeopts */
/**
- * @brief Callback to validate, canonize and store (optionally, according to the given @p options) the given @p value
- * according to the given @p type.
+ * @brief Callback to store and canonize the given @p value according to the given @p type.
*
- * Even when the callback returns #LY_EINCOMPLETE, the value must be normally stored in the structure
- * (meaning it can be printed/duplicated/compared). That basically means that the #LY_TYPE_OPTS_SECOND_CALL
- * should only validate the value but not change the internal value! The only exception is union, when this could
- * happen. However, even on the first call it is stored as a potentially matching value, which means the value
- * structure is valid. That is all that is required.
+ * Value must always be correctly stored meaning all the other type callbacks (such as print or compare)
+ * must function as expected.
*
* Note that the \p value string is not necessarily zero-terminated. The provided \p value_len is always correct.
*
* @param[in] ctx libyang Context
- * @param[in] type Type of the value being canonized.
- * @param[in] value Lexical representation of the value to be validated (and canonized).
+ * @param[in] type Type of the value being stored.
+ * @param[in] value Lexical representation of the value to be stored.
* It is never NULL, empty string is represented as "" with zero @p value_len.
* @param[in] value_len Length (number of bytes) of the given \p value.
* @param[in] options [Type plugin options](@ref plugintypeopts).
- * @param[in] format Input format of the data.
+ * @param[in] format Input format of the value.
* @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
- * @param[in] context_node The @p value's node for the case that the require-instance restriction is supposed to be resolved.
- * This argument is a lys_node (in case LY_TYPE_OPTS_INCOMPLETE_DATA or LY_TYPE_OPTS_SCHEMA set in @p options)
- * or lyd_node structure.
- * @param[in] tree External data tree (e.g. when validating RPC/Notification) where the required data instance can be placed.
- * @param[in] storage Storage for the value in the type's specific encoding. All the members should be filled by the plugin.
+ * @param[in] hints Bitmap of [value hints](@ref lydvalhints) of all the allowed value types.
+ * @param[in] ctx_node The @p value schema context node.
+ * @param[out] storage Storage for the value in the type's specific encoding. All the members should be filled by the plugin.
* @param[out] err Optionally provided error information in case of failure. If not provided to the caller, a generic
- * error message is prepared instead.
- * The error structure can be created by ly_err_new().
- * @return LY_SUCCESS on success
- * @return LY_EINCOMPLETE in case the option included LY_TYPE_OPTS_INCOMPLETE_DATA flag and the data @p trees are needed to finish the validation.
- * @return LY_ERR value if an error occurred and the value could not be canonized following the type's rules.
+ * error message is prepared instead. The error structure can be created by ly_err_new().
+ * @return LY_SUCCESS on success,
+ * @return LY_EINCOMPLETE in case the ::ly_type_validate_clb should be called to finish value validation in data,
+ * @return LY_ERR value on error.
*/
-typedef LY_ERR (*ly_type_store_clb)(const struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len,
- uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, const void *context_node,
- const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err);
+typedef LY_ERR (*ly_type_store_clb)(const struct ly_ctx *ctx, const struct lysc_type *type, const char *value,
+ size_t value_len, uint32_t options, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints,
+ const struct lysc_node *ctx_node, struct lyd_value *storage, struct ly_err_item **err);
+
+/**
+ * @brief Callback to validate the stored value in data.
+ *
+ * This callback is optional for types that can only be validated in a data tree. It must be called and succeed
+ * in case the ::ly_type_store_clb callback returned ::LY_EINCOMPLETE for the value to be valid. However, this
+ * callback can be called even in other cases (such as separate/repeated validation).
+ *
+ * @param[in] ctx libyang Context
+ * @param[in] type Original type of the value (not necessarily the stored one) being validated.
+ * @param[in] ctx_node The value data context node for validation.
+ * @param[in] tree External data tree (e.g. when validating RPC/Notification) with possibly referenced data.
+ * @param[in,out] storage Storage of the value successfully filled by ::ly_type_store_clb. May be modified.
+ * @param[out] err Optionally provided error information in case of failure. If not provided to the caller, a generic
+ * error message is prepared instead. The error structure can be created by ly_err_new().
+ * @return LY_SUCCESS on success,
+ * @return LY_ERR value on error.
+ */
+typedef LY_ERR (*ly_type_validate_clb)(const struct ly_ctx *ctx, const struct lysc_type *type,
+ const struct lyd_node *ctx_node, const struct lyd_node *tree, struct lyd_value *storage, struct ly_err_item **err);
/**
* @brief Callback for comparing 2 values of the same type.
- * Must be able to compare values that are not fully resolved! Meaning, whose storing callback returned
- * #LY_EINCOMPLETE and the was not called again.
*
* Caller is responsible to provide values of the SAME type.
*
@@ -219,9 +209,7 @@
typedef LY_ERR (*ly_type_compare_clb)(const struct lyd_value *val1, const struct lyd_value *val2);
/**
- * @brief Callback to receive printed (canonical) value of the data stored in @p value.
- * Must be able to print values that are not fully resolved! Meaning, whose storing callback returned
- * #LY_EINCOMPLETE and the was not called again.
+ * @brief Callback to getting the canonical value of the data stored in @p value.
*
* @param[in] value Value to print.
* @param[in] format Format in which the data are supposed to be printed.
@@ -237,15 +225,14 @@
ly_bool *dynamic);
/**
- * @brief Callback to duplicate data in data structure. Note that callback is even responsible for duplicating lyd_value::canonized.
- * Must be able to duplicate values that are not fully resolved! Meaning, whose storing callback returned
- * #LY_EINCOMPLETE and the was not called again.
+ * @brief Callback to duplicate data in data structure. Note that callback is even responsible for
+ * duplicating lyd_value::canonized.
*
* @param[in] ctx libyang context of the @p dup. Note that the context of @p original and @p dup might not be the same.
* @param[in] original Original data structure to be duplicated.
* @param[in,out] dup Prepared data structure to be filled with the duplicated data of @p original.
* @return LY_SUCCESS after successful duplication.
- * @return other LY_ERR values on error.
+ * @return LY_ERR value on error.
*/
typedef LY_ERR (*ly_type_dup_clb)(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup);
@@ -268,7 +255,8 @@
*/
struct lysc_type_plugin {
LY_DATA_TYPE type; /**< implemented type, use LY_TYPE_UNKNOWN for derived data types */
- ly_type_store_clb store; /**< function to validate, canonize and store (according to the options) the value in the type-specific way */
+ ly_type_store_clb store; /**< store and canonize the value in the type-specific way */
+ ly_type_validate_clb validate; /**< optional, validate the value in the type-specific way in data */
ly_type_compare_clb compare; /**< comparison callback to compare 2 values of the same type */
ly_type_print_clb print; /**< printer callback to get string representing the value */
ly_type_dup_clb duplicate; /**< data duplication callback */
diff --git a/src/printer_json.c b/src/printer_json.c
index 2cf8cef..3e488de 100644
--- a/src/printer_json.c
+++ b/src/printer_json.c
@@ -401,9 +401,9 @@
PRINT_COMMA;
json_print_member2(ctx, (struct lyd_node *)node, attr->format, &attr->prefix, attr->name, 0);
- if (attr->hint & (LYD_NODE_OPAQ_ISBOOLEAN | LYD_NODE_OPAQ_ISNUMBER)) {
+ if (attr->hints & (LYD_VALHINT_BOOLEAN | LYD_VALHINT_DECNUM)) {
ly_print_(ctx->out, "%s", attr->value[0] ? attr->value : "null");
- } else if (attr->hint & LYD_NODE_OPAQ_ISEMPTY) {
+ } else if (attr->hints & LYD_VALHINT_EMPTY) {
ly_print_(ctx->out, "[null]");
} else {
json_print_string(ctx->out, attr->value);
@@ -754,7 +754,7 @@
{
ly_bool first = 1, last = 1;
- if (node->hint & LYD_NODE_OPAQ_ISLIST) {
+ if (node->hints & (LYD_NODEHINT_LIST | LYD_NODEHINT_LEAFLIST)) {
const struct lyd_node_opaq *prev = (const struct lyd_node_opaq *)node->prev;
const struct lyd_node_opaq *next = (const struct lyd_node_opaq *)node->next;
if (prev->next && matching_node((const struct lyd_node *)prev, (const struct lyd_node *)node)) {
@@ -768,18 +768,18 @@
if (first) {
LY_CHECK_RET(json_print_member2(ctx, node->parent, node->format, &node->prefix, node->name, 0));
- if (node->hint & LYD_NODE_OPAQ_ISLIST) {
+ if (node->hints & (LYD_NODEHINT_LIST | LYD_NODEHINT_LEAFLIST)) {
LY_CHECK_RET(json_print_array_open(ctx, (struct lyd_node *)node));
LEVEL_INC;
}
}
- if (node->child || (node->hint & LYD_NODE_OPAQ_ISLIST)) {
+ if (node->child || (node->hints & (LYD_NODEHINT_LIST | LYD_NODEHINT_LEAFLIST))) {
LY_CHECK_RET(json_print_inner(ctx, (struct lyd_node *)node));
LEVEL_PRINTED;
} else {
- if (node->hint & LYD_VALUE_PARSE_ISEMPTY) {
+ if (node->hints & LYD_VALHINT_EMPTY) {
ly_print_(ctx->out, "[null]");
- } else if (node->hint & (LYD_VALUE_PARSE_ISBOOLEAN | LYD_VALUE_PARSE_ISNUMBER)) {
+ } else if (node->hints & (LYD_VALHINT_BOOLEAN | LYD_VALHINT_DECNUM)) {
ly_print_(ctx->out, "%s", node->value);
} else {
/* string */
@@ -791,7 +791,7 @@
json_print_attributes(ctx, (const struct lyd_node *)node, 0);
}
- if (last && (node->hint & LYD_NODE_OPAQ_ISLIST)) {
+ if (last && (node->hints & (LYD_NODEHINT_LIST | LYD_NODEHINT_LEAFLIST))) {
json_print_array_close(ctx);
LEVEL_DEC;
LEVEL_PRINTED;
diff --git a/src/printer_xml.c b/src/printer_xml.c
index 26fa401..eea1e76 100644
--- a/src/printer_xml.c
+++ b/src/printer_xml.c
@@ -105,7 +105,6 @@
static const char *
xml_print_ns_opaq(struct xmlpr_ctx *ctx, LYD_FORMAT format, const struct ly_prefix *prefix, uint32_t prefix_opts)
{
-
switch (format) {
case LYD_XML:
return xml_print_ns(ctx, prefix->module_ns, (prefix_opts & LYXML_PREFIX_DEFAULT) ? NULL : prefix->id, prefix_opts);
diff --git a/src/tree_data.c b/src/tree_data.c
index 6514520..a7db1bf 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -54,102 +54,60 @@
struct lyd_node **match);
LY_ERR
-lyd_value_parse(struct lyd_node_term *node, const char *value, size_t value_len, ly_bool *dynamic, ly_bool second,
- uint32_t value_hint, LY_PREFIX_FORMAT format, void *prefix_data, const struct lyd_node *tree)
+lyd_value_store(const struct ly_ctx *ctx, struct lyd_value *val, const struct lysc_type *type, const char *value,
+ size_t value_len, ly_bool *dynamic, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints,
+ const struct lysc_node *ctx_node, ly_bool *incomplete, enum LY_VLOG_ELEM log_elem_type, const void *log_elem)
{
- LY_ERR ret = LY_SUCCESS;
+ LY_ERR ret;
struct ly_err_item *err = NULL;
- struct ly_ctx *ctx;
- struct lysc_type *type;
- uint32_t options = value_hint | (second ? LY_TYPE_OPTS_SECOND_CALL : 0) |
- (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
- assert(node);
+ uint32_t options = (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0);
- ctx = node->schema->module->ctx;
-
- type = ((struct lysc_node_leaf *)node->schema)->type;
- ret = type->plugin->store(ctx, type, value, value_len, options, format, prefix_data,
- tree ? (void *)node : (void *)node->schema, tree, &node->value, &err);
- if (ret && (ret != LY_EINCOMPLETE)) {
- if (err) {
- /* node may not be connected yet so use the schema node */
- if (!node->parent && lysc_data_parent(node->schema)) {
- LOGVAL(ctx, LY_VLOG_LYSC, node->schema, err->vecode, err->msg);
- } else {
- LOGVAL(ctx, LY_VLOG_LYD, node, err->vecode, err->msg);
- }
- ly_err_free(err);
- }
- goto error;
- } else if (dynamic) {
- *dynamic = 0;
+ if (incomplete) {
+ *incomplete = 0;
}
-error:
- return ret;
-}
-
-/* similar to lyd_value_parse except can be used just to store the value, hence also does not support a second call */
-LY_ERR
-lyd_value_store(struct lyd_value *val, const struct lysc_node *schema, const char *value, size_t value_len, ly_bool *dynamic,
- LY_PREFIX_FORMAT format, void *prefix_data)
-{
- LY_ERR ret = LY_SUCCESS;
- struct ly_err_item *err = NULL;
- struct ly_ctx *ctx;
- struct lysc_type *type;
- uint32_t options = LY_TYPE_OPTS_INCOMPLETE_DATA | (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0);
-
- assert(val && schema && (schema->nodetype & LYD_NODE_TERM));
-
- ctx = schema->module->ctx;
- type = ((struct lysc_node_leaf *)schema)->type;
- ret = type->plugin->store(ctx, type, value, value_len, options, format, prefix_data, (void *)schema, NULL,
- val, &err);
+ ret = type->plugin->store(ctx, type, value, value_len, options, format, prefix_data, hints, ctx_node, val, &err);
if (ret == LY_EINCOMPLETE) {
- /* this is fine, we do not need it resolved */
- ret = LY_SUCCESS;
- } else if (ret && err) {
- ly_err_print(err);
- LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
- ly_err_free(err);
- }
- if (!ret && dynamic) {
- *dynamic = 0;
+ if (incomplete) {
+ *incomplete = 1;
+ }
+ } else if (ret) {
+ if (err) {
+ LOGVAL(ctx, log_elem_type, log_elem, err->vecode, err->msg);
+ ly_err_free(err);
+ } else {
+ LOGVAL(ctx, log_elem_type, log_elem, LYVE_OTHER, "Storing value \"%.*s\" failed.", (int)value_len, value);
+ }
+ return ret;
}
- return ret;
+ if (dynamic) {
+ *dynamic = 0;
+ }
+ return LY_SUCCESS;
}
LY_ERR
-lyd_value_parse_meta(const struct ly_ctx *ctx, struct lyd_meta *meta, const char *value, size_t value_len, ly_bool *dynamic,
- ly_bool second, uint32_t value_hint, LY_PREFIX_FORMAT format, void *prefix_data, const struct lysc_node *ctx_snode,
- const struct lyd_node *tree)
+lyd_value_validate_incomplete(const struct ly_ctx *ctx, const struct lysc_type *type, struct lyd_value *val,
+ const struct lyd_node *ctx_node, const struct lyd_node *tree, enum LY_VLOG_ELEM log_elem_type, const void *log_elem)
{
- LY_ERR ret = LY_SUCCESS;
+ LY_ERR ret;
struct ly_err_item *err = NULL;
- struct lyext_metadata *ant;
- uint32_t options = value_hint | (second ? LY_TYPE_OPTS_SECOND_CALL : 0) |
- (dynamic && *dynamic ? LY_TYPE_OPTS_DYNAMIC : 0) | (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
- assert(ctx && meta && ((tree && meta->parent) || ctx_snode));
+ assert(type->plugin->validate);
- ant = meta->annotation->data;
- ret = ant->type->plugin->store(ctx, ant->type, value, value_len, options, format, prefix_data,
- tree ? (void *)meta->parent : (void *)ctx_snode, tree, &meta->value, &err);
- if (ret && (ret != LY_EINCOMPLETE)) {
+ ret = type->plugin->validate(ctx, type, ctx_node, tree, val, &err);
+ if (ret) {
if (err) {
- ly_err_print(err);
- LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
+ LOGVAL(ctx, log_elem_type, log_elem, err->vecode, err->msg);
ly_err_free(err);
+ } else {
+ LOGVAL(ctx, log_elem_type, log_elem, LYVE_OTHER, "Resolving value \"%s\" failed.", val->canonical);
}
- goto error;
- } else if (dynamic) {
- *dynamic = 0;
+ return ret;
}
-error:
- return ret;
+ return LY_SUCCESS;
}
LY_ERR
@@ -169,9 +127,8 @@
}
type = ((struct lysc_node_leaf *)node)->type;
- /* just validate, no storing of enything */
- rc = type->plugin->store(ctx ? ctx : node->module->ctx, type, value, value_len, LY_TYPE_OPTS_INCOMPLETE_DATA,
- format, prefix_data, node, NULL, &storage, &err);
+ rc = type->plugin->store(ctx ? ctx : node->module->ctx, type, value, value_len, 0, format, prefix_data,
+ LYD_HINT_SCHEMA, node, &storage, &err);
if (rc == LY_EINCOMPLETE) {
/* actually success since we do not provide the context tree and call validation with
* LY_TYPE_OPTS_INCOMPLETE_DATA */
@@ -199,29 +156,37 @@
API LY_ERR
lyd_value_validate(const struct ly_ctx *ctx, const struct lyd_node_term *node, const char *value, size_t value_len,
- const struct lyd_node *tree, struct lysc_type **realtype)
+ const struct lyd_node *tree, const struct lysc_type **realtype)
{
LY_ERR rc;
struct ly_err_item *err = NULL;
struct lysc_type *type;
struct lyd_value val = {0};
- uint32_t options = (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
+ ly_bool stored = 0;
LY_CHECK_ARG_RET(ctx, node, value, LY_EINVAL);
type = ((struct lysc_node_leaf *)node->schema)->type;
- rc = type->plugin->store(ctx ? ctx : node->schema->module->ctx, type, value, value_len, options, LY_PREF_JSON, NULL,
- tree ? (void *)node : (void *)node->schema, tree, &val, &err);
+ /* store */
+ rc = type->plugin->store(ctx ? ctx : LYD_CTX(node), type, value, value_len, 0, LY_PREF_JSON, NULL,
+ LYD_HINT_DATA, node->schema, &val, &err);
if (rc == LY_EINCOMPLETE) {
- return rc;
- } else if (rc) {
+ stored = 1;
+
+ /* resolve */
+ rc = type->plugin->validate(ctx ? ctx : LYD_CTX(node), type, (struct lyd_node *)node, tree, &val, &err);
+ }
+
+ if (rc) {
if (err) {
if (ctx) {
- ly_err_print(err);
- LOGVAL(ctx, LY_VLOG_STR, err->path, err->vecode, err->msg);
+ LOGVAL(ctx, LY_VLOG_LYD, node, err->vecode, err->msg);
}
ly_err_free(err);
}
+ if (stored) {
+ type->plugin->free(ctx ? ctx : LYD_CTX(node), &val);
+ }
return rc;
}
@@ -229,47 +194,32 @@
*realtype = val.realtype;
}
- type->plugin->free(ctx ? ctx : node->schema->module->ctx, &val);
+ type->plugin->free(ctx ? ctx : LYD_CTX(node), &val);
return LY_SUCCESS;
}
API LY_ERR
-lyd_value_compare(const struct lyd_node_term *node, const char *value, size_t value_len, const struct lyd_node *tree)
+lyd_value_compare(const struct lyd_node_term *node, const char *value, size_t value_len)
{
- LY_ERR ret = LY_SUCCESS, rc;
- struct ly_err_item *err = NULL;
+ LY_ERR ret = LY_SUCCESS;
struct ly_ctx *ctx;
struct lysc_type *type;
- struct lyd_value data = {0};
- uint32_t options = (tree ? 0 : LY_TYPE_OPTS_INCOMPLETE_DATA);
+ struct lyd_value val = {0};
LY_CHECK_ARG_RET(node ? node->schema->module->ctx : NULL, node, value, LY_EINVAL);
ctx = node->schema->module->ctx;
type = ((struct lysc_node_leaf *)node->schema)->type;
- rc = type->plugin->store(ctx, type, value, value_len, options, LY_PREF_JSON, NULL, (struct lyd_node *)node, tree, &data,
- &err);
- if (rc == LY_EINCOMPLETE) {
- ret = rc;
- /* continue with comparing, just remember what to return if storing is ok */
- } else if (rc) {
- /* value to compare is invalid */
- ret = LY_EINVAL;
- if (err) {
- ly_err_free(err);
- }
- goto cleanup;
- }
- /* compare data */
- if (type->plugin->compare(&node->value, &data)) {
- /* do not assign it directly from the compare callback to keep possible LY_EINCOMPLETE from validation */
- ret = LY_ENOT;
- }
+ /* store the value */
+ ret = lyd_value_store(ctx, &val, type, value, value_len, NULL, LY_PREF_JSON, NULL, LYD_HINT_DATA, node->schema,
+ NULL, LY_VLOG_LYSC, node->schema);
+ LY_CHECK_RET(ret);
-cleanup:
- type->plugin->free(ctx, &data);
+ /* compare values */
+ ret = type->plugin->compare(&node->value, &val);
+ type->plugin->free(ctx, &val);
return ret;
}
@@ -400,19 +350,7 @@
LY_CHECK_GOTO(ret, cleanup);
/* finish incompletely validated terminal values/attributes and when conditions */
- switch (format) {
- case LYD_XML:
- ret = lyd_validate_unres(tree, &lydctx->when_check, &lydctx->unres_node_type, &lydctx->unres_meta_type,
- LY_PREF_XML, &((struct lyxml_ctx *)lydctx->data_ctx)->ns, NULL);
- break;
- case LYD_JSON:
- case LYD_LYB:
- ret = lyd_validate_unres(tree, &lydctx->when_check, &lydctx->unres_node_type, &lydctx->unres_meta_type,
- LY_PREF_JSON, NULL, NULL);
- break;
- case LYD_UNKNOWN:
- LOGINT_RET(ctx);
- }
+ ret = lyd_validate_unres(tree, &lydctx->when_check, &lydctx->unres_node_type, &lydctx->unres_meta_type, NULL);
LY_CHECK_GOTO(ret, cleanup);
/* perform final validation that assumes the data tree is final */
@@ -571,8 +509,8 @@
}
LY_ERR
-lyd_create_term(const struct lysc_node *schema, const char *value, size_t value_len, ly_bool *dynamic, uint32_t value_hint,
- LY_PREFIX_FORMAT format, void *prefix_data, struct lyd_node **node)
+lyd_create_term(const struct lysc_node *schema, const char *value, size_t value_len, ly_bool *dynamic,
+ LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints, ly_bool *incomplete, struct lyd_node **node)
{
LY_ERR ret;
struct lyd_node_term *term;
@@ -586,11 +524,9 @@
term->prev = (struct lyd_node *)term;
term->flags = LYD_NEW;
- ret = lyd_value_parse(term, value, value_len, dynamic, 0, value_hint, format, prefix_data, NULL);
- if (ret && (ret != LY_EINCOMPLETE)) {
- free(term);
- return ret;
- }
+ ret = lyd_value_store(schema->module->ctx, &term->value, ((struct lysc_node_leaf *)term->schema)->type, value,
+ value_len, dynamic, format, prefix_data, hints, schema, incomplete, LY_VLOG_LYSC, schema);
+ LY_CHECK_ERR_RET(ret, free(term), ret);
lyd_hash((struct lyd_node *)term);
*node = (struct lyd_node *)term;
@@ -731,13 +667,13 @@
LY_ERR
lyd_create_opaq(const struct ly_ctx *ctx, const char *name, size_t name_len, const char *value, size_t value_len,
- ly_bool *dynamic, uint32_t value_hint, LYD_FORMAT format, struct ly_prefix *val_prefs, const char *prefix, size_t pref_len,
+ ly_bool *dynamic, LYD_FORMAT format, uint32_t hints, struct ly_prefix *val_prefs, const char *prefix, size_t pref_len,
const char *module_key, size_t module_key_len, struct lyd_node **node)
{
LY_ERR ret = LY_SUCCESS;
struct lyd_node_opaq *opaq;
- assert(ctx && name && name_len);
+ assert(ctx && name && name_len && format);
if (!value_len) {
value = "";
@@ -764,7 +700,7 @@
} else {
LY_CHECK_GOTO(ret = lydict_insert(ctx, value, value_len, &opaq->value), finish);
}
- opaq->hint = value_hint;
+ opaq->hints = hints;
opaq->ctx = ctx;
finish:
@@ -832,9 +768,9 @@
for (key_s = lysc_node_children(schema, 0); 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, NULL, 0, LY_PREF_JSON, NULL, &key);
- LY_CHECK_GOTO(rc && (rc != LY_EINCOMPLETE), cleanup);
- rc = LY_SUCCESS;
+ rc = lyd_create_term(key_s, key_val, key_val ? strlen(key_val) : 0, NULL, LY_PREF_JSON, NULL, LYD_HINT_DATA,
+ NULL, &key);
+ LY_CHECK_GOTO(rc, cleanup);
lyd_insert_node(ret, NULL, key);
}
@@ -909,8 +845,9 @@
schema = lys_find_child(parent ? parent->schema : NULL, module, name, 0, LYD_NODE_TERM, 0);
LY_CHECK_ERR_RET(!schema, LOGERR(ctx, LY_EINVAL, "Term node \"%s\" not found.", name), LY_ENOTFOUND);
- rc = lyd_create_term(schema, val_str, val_str ? strlen(val_str) : 0, NULL, 0, LY_PREF_JSON, NULL, &ret);
- LY_CHECK_RET(rc && (rc != LY_EINCOMPLETE), rc);
+ rc = lyd_create_term(schema, val_str, val_str ? strlen(val_str) : 0, NULL, LY_PREF_JSON, NULL, LYD_HINT_DATA, NULL,
+ &ret);
+ LY_CHECK_RET(rc);
if (parent) {
lyd_insert_node(parent, NULL, ret);
}
@@ -1053,8 +990,8 @@
val_str = "";
}
- LY_CHECK_RET(lyd_create_meta(parent, &ret, module, name, name_len, val_str, strlen(val_str), NULL, 0,
- LY_PREF_JSON, NULL, parent->schema));
+ LY_CHECK_RET(lyd_create_meta(parent, &ret, module, name, name_len, val_str, strlen(val_str), NULL, LY_PREF_JSON,
+ NULL, LYD_HINT_DATA, NULL));
if (meta) {
*meta = ret;
@@ -1077,8 +1014,8 @@
value = "";
}
- LY_CHECK_RET(lyd_create_opaq(ctx, name, strlen(name), value, strlen(value), NULL, 0,
- LYD_JSON, NULL, NULL, 0, module_name, strlen(module_name), &ret));
+ LY_CHECK_RET(lyd_create_opaq(ctx, name, strlen(name), value, strlen(value), NULL, LYD_JSON, 0, NULL, NULL, 0,
+ module_name, strlen(module_name), &ret));
if (parent) {
lyd_insert_node(parent, NULL, ret);
}
@@ -1114,7 +1051,7 @@
val_str = "";
}
- LY_CHECK_RET(lyd_create_attr(parent, &ret, ctx, name, name_len, val_str, strlen(val_str), NULL, 0, LYD_JSON, NULL,
+ LY_CHECK_RET(lyd_create_attr(parent, &ret, ctx, name, name_len, val_str, strlen(val_str), NULL, LYD_JSON, 0, NULL,
prefix, pref_len, module_name, module_name ? strlen(module_name) : 0));
if (attr) {
@@ -1142,7 +1079,9 @@
type = ((struct lysc_node_leaf *)term->schema)->type;
/* parse the new value */
- LY_CHECK_GOTO(ret = lyd_value_store(&val, term->schema, val_str, strlen(val_str), NULL, LY_PREF_JSON, NULL), cleanup);
+ ret = lyd_value_store(LYD_CTX(term), &val, type, val_str, strlen(val_str), NULL, LY_PREF_JSON, NULL, LYD_HINT_DATA,
+ term->schema, NULL, LY_VLOG_LYD, term);
+ LY_CHECK_GOTO(ret, cleanup);
/* compare original and new value */
if (type->plugin->compare(&t->value, &val)) {
@@ -1217,7 +1156,7 @@
/* parse the new value into a new meta structure */
LY_CHECK_GOTO(ret = lyd_create_meta(NULL, &m2, meta->annotation->module, meta->name, strlen(meta->name), val_str,
- strlen(val_str), NULL, 0, LY_PREF_JSON, NULL, NULL), cleanup);
+ strlen(val_str), NULL, LY_PREF_JSON, NULL, LYD_HINT_DATA, NULL), cleanup);
/* compare original and new value */
if (lyd_compare_meta(meta, m2)) {
@@ -1295,7 +1234,9 @@
r = lys_value_validate(NULL, schema, value, strlen(value));
}
if (!r) {
- LY_CHECK_GOTO(ret = lyd_value_store(&pred->value, schema, value, strlen(value), NULL, LY_PREF_JSON, NULL), cleanup);
+ ret = lyd_value_store(ctx, &pred->value, ((struct lysc_node_leaflist *)schema)->type, value, strlen(value),
+ NULL, LY_PREF_JSON, NULL, LYD_HINT_DATA, schema, NULL, LY_VLOG_LYSC, schema);
+ LY_CHECK_GOTO(ret, cleanup);
} /* else we have opaq flag and the value is not valid, leavne no predicate and then create an opaque node */
}
@@ -1337,8 +1278,8 @@
if (!(schema->flags & LYS_KEYLESS)) {
if ((options & LYD_NEWOPT_OPAQ) && (p[path_idx].pred_type == LY_PATH_PREDTYPE_NONE)) {
/* creating opaque list without keys */
- LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, NULL, 0,
- LYD_JSON, NULL, NULL, 0, schema->module->name, strlen(schema->module->name), &node),
+ LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, NULL, LYD_JSON,
+ LYD_NODEHINT_LIST, NULL, NULL, 0, schema->module->name, strlen(schema->module->name), &node),
cleanup);
} else {
assert(p[path_idx].pred_type == LY_PATH_PREDTYPE_LIST);
@@ -1356,9 +1297,9 @@
case LYS_LEAFLIST:
if ((options & LYD_NEWOPT_OPAQ) && (p[path_idx].pred_type == LY_PATH_PREDTYPE_NONE)) {
/* creating opaque leaf-list without value */
- LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, NULL, 0,
- LYD_JSON, NULL, NULL, 0, schema->module->name, strlen(schema->module->name), &node),
- cleanup);
+ LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, NULL, LYD_JSON,
+ LYD_NODEHINT_LEAFLIST, NULL, NULL, 0, schema->module->name, strlen(schema->module->name), &node),
+ cleanup);
} else {
assert(p[path_idx].pred_type == LY_PATH_PREDTYPE_LEAFLIST);
LY_CHECK_GOTO(ret = lyd_create_term2(schema, &p[path_idx].predicates[0].value, &node), cleanup);
@@ -1375,11 +1316,12 @@
r = lys_value_validate(NULL, schema, value, strlen(value));
}
if (!r) {
- LY_CHECK_GOTO(ret = lyd_create_term(schema, value, strlen(value), NULL, 0, LY_PREF_JSON, NULL, &node), cleanup);
+ ret = lyd_create_term(schema, value, strlen(value), NULL, LY_PREF_JSON, NULL, LYD_HINT_DATA, NULL, &node);
+ LY_CHECK_GOTO(ret, cleanup);
} else {
/* creating opaque leaf without value */
- LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, NULL, 0,
- LYD_JSON, NULL, NULL, 0, schema->module->name,
+ LY_CHECK_GOTO(ret = lyd_create_opaq(ctx, schema->name, strlen(schema->name), NULL, 0, NULL, LYD_JSON,
+ 0, NULL, NULL, 0, schema->module->name,
strlen(schema->module->name), &node), cleanup);
}
break;
@@ -2162,10 +2104,10 @@
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 *dynamic, uint32_t value_hint, LY_PREFIX_FORMAT format,
- void *prefix_data, const struct lysc_node *ctx_snode)
+ size_t name_len, const char *value, size_t value_len, ly_bool *dynamic, LY_PREFIX_FORMAT format,
+ void *prefix_data, uint32_t hints, ly_bool *incomplete)
{
- LY_ERR ret, rc;
+ LY_ERR rc;
struct lysc_ext_instance *ant = NULL;
struct lyd_meta *mt, *last;
LY_ARRAY_COUNT_TYPE u;
@@ -2191,11 +2133,9 @@
LY_CHECK_ERR_RET(!mt, LOGMEM(mod->ctx), LY_EMEM);
mt->parent = parent;
mt->annotation = ant;
- ret = lyd_value_parse_meta(mod->ctx, mt, value, value_len, dynamic, 0, value_hint, format, prefix_data, ctx_snode, NULL);
- if ((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE)) {
- free(mt);
- return ret;
- }
+ rc = lyd_value_store(mod->ctx, &mt->value, ((struct lyext_metadata *)ant->data)->type, value, value_len, dynamic,
+ format, prefix_data, hints, parent ? parent->schema : NULL, incomplete, LY_VLOG_NONE, NULL);
+ LY_CHECK_ERR_RET(rc, free(mt), rc);
rc = lydict_insert(mod->ctx, name, name_len, &mt->name);
LY_CHECK_ERR_RET(rc, free(mt), rc);
@@ -2210,7 +2150,7 @@
if (meta) {
*meta = mt;
}
- return ret;
+ return LY_SUCCESS;
}
void
@@ -2240,15 +2180,15 @@
}
LY_ERR
-lyd_create_attr(struct lyd_node *parent, struct lyd_attr **attr, const struct ly_ctx *ctx, const char *name,
- size_t name_len, const char *value, size_t value_len, ly_bool *dynamic, uint32_t value_hint, LYD_FORMAT format,
+lyd_create_attr(struct lyd_node *parent, struct lyd_attr **attr, const struct ly_ctx *ctx, const char *name, size_t name_len,
+ const char *value, size_t value_len, ly_bool *dynamic, LYD_FORMAT format, uint32_t hints,
struct ly_prefix *val_prefs, const char *prefix, size_t prefix_len, const char *module_key, size_t module_key_len)
{
LY_ERR ret = LY_SUCCESS;
struct lyd_attr *at, *last;
assert(ctx && (parent || attr) && (!parent || !parent->schema));
- assert(name && name_len);
+ assert(name && name_len && format);
if (!value_len) {
value = "";
@@ -2256,7 +2196,7 @@
at = calloc(1, sizeof *at);
LY_CHECK_ERR_RET(!at, LOGMEM(ctx); ly_free_val_prefs(ctx, val_prefs), LY_EMEM);
- at->hint = value_hint;
+ at->hints = hints;
at->format = format;
at->val_prefs = val_prefs;
@@ -3356,8 +3296,8 @@
/* 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, NULL, 0, LY_PREF_JSON, NULL, &target);
- LY_CHECK_RET(rc && (rc != LY_EINCOMPLETE), rc);
+ rc = lyd_create_term(schema, key_or_value, val_len, NULL, LY_PREF_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));
diff --git a/src/tree_data.h b/src/tree_data.h
index 02e9252..6817d64 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -159,25 +159,6 @@
/** @} */
/**
- * @brief Special lyd_value structure for union.
- *
- * Represents data with multiple types (union). Original value is stored in the main lyd_value:canonical_cache while
- * the lyd_value_subvalue::value contains representation according to one of the union's types.
- * The lyd_value_subvalue:prefixes provides (possible) mappings from prefixes in the original value to YANG modules.
- * These prefixes are necessary to parse original value to the union's subtypes.
- */
-struct lyd_value_subvalue {
- struct lyd_value *value; /**< representation of the value according to the selected union's subtype
- (stored as lyd_value::realpath here, in subvalue structure */
- const char *original; /**< Original value in the dictionary. */
- LY_PREFIX_FORMAT format; /**< Prefix format of the value. However, this information is also used to decide
- whether a value is valid for the specific format or not on later validations
- (instance-identifier in XML looks different than in JSON). */
- void *prefix_data; /**< Format-specific data for prefix resolution (see ::ly_resolve_prefix) */
- uint32_t parser_hint; /**< Hint options from the parser */
-};
-
-/**
* @brief YANG data representation
*/
struct lyd_value {
@@ -203,13 +184,13 @@
}; /**< The union is just a list of shorthands to possible values stored by a type's plugin. libyang itself uses the lyd_value::realtype
plugin's callbacks to work with the data. */
- struct lysc_type *realtype; /**< pointer to the real type of the data stored in the value structure. This type can differ from the type
- in the schema node of the data node since the type's store plugin can use other types/plugins for
- storing data. Speaking about built-in types, this is the case of leafref which stores data as its
- target type. In contrast, union type also use its subtype's callbacks, but inside an internal data
- lyd_value::subvalue structure, so here is the pointer to the union type.
- In general, this type is used to get free callback for this lyd_value structure, so it must reflect
- the type used to store data directly in the same lyd_value instance. */
+ const struct lysc_type *realtype; /**< pointer to the real type of the data stored in the value structure. This type can differ from the type
+ in the schema node of the data node since the type's store plugin can use other types/plugins for
+ storing data. Speaking about built-in types, this is the case of leafref which stores data as its
+ target type. In contrast, union type also use its subtype's callbacks, but inside an internal data
+ lyd_value::subvalue structure, so here is the pointer to the union type.
+ In general, this type is used to get free callback for this lyd_value structure, so it must reflect
+ the type used to store data directly in the same lyd_value instance. */
};
/**
@@ -221,6 +202,26 @@
#define LYD_CANON_VALUE(node) ((struct lyd_node_term *)(node))->value.canonical
/**
+ * @brief Special lyd_value structure for union.
+ *
+ * Represents data with multiple types (union). Original value is stored in the main lyd_value:canonical_cache while
+ * the lyd_value_subvalue::value contains representation according to one of the union's types.
+ * The lyd_value_subvalue:prefixes provides (possible) mappings from prefixes in the original value to YANG modules.
+ * These prefixes are necessary to parse original value to the union's subtypes.
+ */
+struct lyd_value_subvalue {
+ struct lyd_value value; /**< representation of the value according to the selected union's subtype
+ (stored as lyd_value::realtype here, in subvalue structure */
+ const char *original; /**< Original value in the dictionary. */
+ LY_PREFIX_FORMAT format; /**< Prefix format of the value. However, this information is also used to decide
+ whether a value is valid for the specific format or not on later validations
+ (instance-identifier in XML looks different than in JSON). */
+ void *prefix_data; /**< Format-specific data for prefix resolution (see ::ly_resolve_prefix) */
+ uint32_t hints; /**< [Value hints](@ref lydvalhints) from the parser */
+ const struct lysc_node *ctx_node; /**< Context schema node. */
+};
+
+/**
* @brief Metadata structure.
*
* The structure provides information about metadata of a data element. Such attributes must map to
@@ -264,7 +265,7 @@
const char *value;
LYD_FORMAT format; /**< format of the prefixes, only LYD_XML and LYD_JSON values can appear at this place */
- uint32_t hint; /**< additional information about from the data source, see the [hints list](@ref lydopaqhints) */
+ uint32_t hints; /**< additional information about from the data source, see the [hints list](@ref lydhints) */
struct ly_prefix prefix; /**< name prefix, it is stored because they are a real pain to generate properly */
};
@@ -375,7 +376,7 @@
void *priv; /**< private user data, not used by libyang */
#endif
- struct lyd_value value; /**< node's value representation */
+ struct lyd_value value; /**< node's value representation */
};
/**
@@ -394,7 +395,7 @@
never NULL. If there is no sibling node, pointer points to the node
itself. In case of the first node, this pointer points to the last
node in the list. */
- struct lyd_meta *meta; /**< pointer to the list of attributes of this node */
+ struct lyd_meta *meta; /**< pointer to the list of metadata of this node */
#ifdef LY_ENABLED_LYD_PRIV
void *priv; /**< private user data, not used by libyang */
@@ -411,21 +412,53 @@
};
/**
- * @defgroup lydopaqhints Opaq data node hints.
+ * @defgroup lydvalhints Value format hints. Any information about value types encoded in the format
+ * is hinted this way.
*
- * Additional information about the opaq nodes from their source. The flags are stored in lyd_node_opaq::hint
- * and they can have a slightly different meaning for the specific lyd_node_opaq::format.
* @{
*/
-#define LYD_NODE_OPAQ_ISLIST 0x001 /**< LYD_JSON: node is expected to be a list or leaf-list */
-#define LYD_NODE_OPAQ_ISENVELOPE 0x002 /**< LYD_JSON, LYD_XML: RPC/Action/Notification envelope out of the YANG schemas */
+#define LYD_VALHINT_STRING 0x0001 /**< value is allowed to be a string */
+#define LYD_VALHINT_DECNUM 0x0002 /**< value is allowed to be a decimal number */
+#define LYD_VALHINT_OCTNUM 0x0004 /**< value is allowed to be an octal number */
+#define LYD_VALHINT_HEXNUM 0x0008 /**< value is allowed to be a hexadecimal number */
+#define LYD_VALHINT_NUM64 0x0010 /**< value is allowed to be an int64 or uint64 */
+#define LYD_VALHINT_BOOLEAN 0x0020 /**< value is allowed to be a boolean */
+#define LYD_VALHINT_EMPTY 0x0040 /**< value is allowed to be empty */
+/**
+ * @} lydvalhints
+ */
-#define LYD_NODE_OPAQ_ISSTRING 0x100 /**< LYD_JSON: value is expected to be string as defined in JSON encoding. */
-#define LYD_NODE_OPAQ_ISNUMBER 0x200 /**< LYD_JSON: value is expected to be number as defined in JSON encoding. */
-#define LYD_NODE_OPAQ_ISBOOLEAN 0x400 /**< LYD_JSON: value is expected to be boolean as defined in JSON encoding. */
-#define LYD_NODE_OPAQ_ISEMPTY 0x800 /**< LYD_JSON: value is expected to be empty as defined in JSON encoding. */
+/**
+ * @defgroup lydnodehints Node type format hints. Any information about node types encoded in the format
+ * is hinted this way.
+ *
+ * @{
+ */
+#define LYD_NODEHINT_LIST 0x0080 /**< node is allowed to be a list instance */
+#define LYD_NODEHINT_LEAFLIST 0x0100 /**< node is allowed to be a leaf-list instance */
+#define LYD_NODEHINT_ENVELOPE 0x8000 /**< only found in opaque node hints; node is a special protocol-dependent
+ RPC/Action/Notification envelope */
+/**
+ * @} lydnodehints
+ */
-/** @} lydopaqhints */
+/**
+ * @defgroup lydhints Value and node type format hints. Any information about value and node types encoded in the format
+ * is hinted this way. It combines [value hints](@ref lydvalhints) and [node hints](@ref lydnodehints).
+ *
+ * @{
+ */
+#define LYD_HINT_DATA 0x01F3 /**< special node/value hint to be used for generic data node/value (for cases when
+ there is no encoding or it does not provide any additional information about
+ a node/value type); do not combine with specific [value hints](@ref lydvalhints)
+ or [node hints](@ref lydnodehints). */
+#define LYD_HINT_SCHEMA 0x01FF /**< special node/value hint to be used for generic schema node/value(for cases when
+ there is no encoding or it does not provide any additional information about
+ a node/value type); do not combine with specific [value hints](@ref lydvalhints)
+ or [node hints](@ref lydnodehints). */
+/**
+ * @} lydhints
+ */
/**
* @brief Data node structure for unparsed (opaque) nodes.
@@ -437,7 +470,7 @@
struct lyd_node *parent; /**< pointer to the parent node (NULL in case of root node) */
struct lyd_node *next; /**< pointer to the next sibling node (NULL if there is no one) */
struct lyd_node *prev; /**< pointer to the previous sibling node (last sibling if there is none) */
- struct lyd_attr *attr;
+ struct lyd_attr *attr; /**< pointer to the list of generic attributes of this node */
#ifdef LY_ENABLED_LYD_PRIV
void *priv; /**< private user data, not used by libyang */
@@ -449,7 +482,7 @@
struct ly_prefix prefix; /**< name prefix */
struct ly_prefix *val_prefs; /**< list of prefixes in the value ([sized array](@ref sizedarrays)) */
const char *value; /**< original value */
- uint32_t hint; /**< additional information about from the data source, see the [hints list](@ref lydopaqhints) */
+ uint32_t hints; /**< additional information about from the data source, see the [hints list](@ref lydhints) */
const struct ly_ctx *ctx; /**< libyang context */
};
@@ -926,25 +959,21 @@
* @return LY_ERR value if an error occurred.
*/
LY_ERR lyd_value_validate(const struct ly_ctx *ctx, const struct lyd_node_term *node, const char *value, size_t value_len,
- const struct lyd_node *tree, struct lysc_type **realtype);
+ const struct lyd_node *tree, const struct lysc_type **realtype);
/**
- * @brief Compare the node's value with the given string value. The string value is first validated according to the node's type.
+ * @brief Compare the node's value with the given string value. The string value is first validated according to
+ * the (current) node's type.
*
* @param[in] node Data node to compare.
* @param[in] value String value to be compared. It does not need to be in a canonical form - as part of the process,
* it is validated and canonized if possible. But it is expected to be in JSON format.
* @param[in] value_len Length of the given @p value (mandatory).
- * @param[in] tree Data tree (e.g. when validating RPC/Notification) where the required data instance (leafref target,
- * instance-identifier) can be placed. NULL in case the data tree is not yet complete,
- * then LY_EINCOMPLETE can be returned.
- * @return LY_SUCCESS on success
- * @return LY_EINCOMPLETE in case of success when the @p trees is not provided and it was needed to finish the validation of
- * the given string @p value (e.g. due to require-instance).
- * @return LY_ENOT if the values do not match.
+ * @return LY_SUCCESS on success,
+ * @return LY_ENOT if the values do not match,
* @return LY_ERR value if an error occurred.
*/
-LY_ERR lyd_value_compare(const struct lyd_node_term *node, const char *value, size_t value_len, const struct lyd_node *tree);
+LY_ERR lyd_value_compare(const struct lyd_node_term *node, const char *value, size_t value_len);
/**
* @defgroup datacompareoptions Data compare options
diff --git a/src/tree_data_internal.h b/src/tree_data_internal.h
index d5bf168..d1f91b5 100644
--- a/src/tree_data_internal.h
+++ b/src/tree_data_internal.h
@@ -95,16 +95,17 @@
* @param[in] value String value to be parsed.
* @param[in] value_len Length of @p value, must be set correctly.
* @param[in,out] dynamic Flag if @p value is dynamically allocated, is adjusted when @p value is consumed.
- * @param[in] value_hint [Hint options](@ref lydvalueparseopts) from the parser regarding the value type.
* @param[in] format Input format of @p value.
* @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
+ * @param[in] hints [Value hints](@ref lydvalhints) from the parser regarding the value type.
+ * @param[out] incomplete Whether the value needs to be resolved.
* @param[out] node Created node.
* @return LY_SUCCESS on success.
* @return LY_EINCOMPLETE in case data tree is needed to finish the validation.
* @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 *dynamic, uint32_t value_hint,
- LY_PREFIX_FORMAT format, void *prefix_data, struct lyd_node **node);
+LY_ERR lyd_create_term(const struct lysc_node *schema, const char *value, size_t value_len, ly_bool *dynamic,
+ LY_PREFIX_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.
@@ -170,8 +171,8 @@
* @param[in] value String value to be parsed.
* @param[in] value_len Length of @p value, must be set correctly.
* @param[in,out] dynamic Flag if @p value is dynamically allocated, is adjusted when @p value is consumed.
- * @param[in] value_hint [Value hint](@ref lydvalueparseopts) from the parser regarding the value type.
* @param[in] format Input format of @p value and @p ns.
+ * @param[in] hints [Hints](@ref lydhints) from the parser regarding the node/value type.
* @param[in] val_prefs Possible value prefixes, array is spent (even in case the function fails).
* @param[in] prefix Element prefix.
* @param[in] pref_len Length of @p prefix, must be set correctly.
@@ -182,7 +183,7 @@
* @return LY_ERR value if an error occurred.
*/
LY_ERR lyd_create_opaq(const struct ly_ctx *ctx, const char *name, size_t name_len, const char *value, size_t value_len,
- ly_bool *dynamic, uint32_t value_hint, LYD_FORMAT format, struct ly_prefix *val_prefs, const char *prefix,
+ ly_bool *dynamic, LYD_FORMAT format, uint32_t hints, struct ly_prefix *val_prefs, const char *prefix,
size_t pref_len, const char *module_key, size_t module_key_len, struct lyd_node **node);
/**
@@ -240,17 +241,17 @@
* @param[in] value String value to be parsed.
* @param[in] value_len Length of @p value, must be set correctly.
* @param[in,out] dynamic Flag if @p value is dynamically allocated, is adjusted when @p value is consumed.
- * @param[in] value_hint [Value hint](@ref lydvalueparseopts) from the parser regarding the value type.
* @param[in] format Input format of @p value.
* @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
- * @param[in] ctx_snode Context node for value resolution in schema.
+ * @param[in] hints [Value hints](@ref lydvalhints) from the parser regarding the value type.
+ * @param[out] incomplete Whether the value needs to be resolved.
* @return LY_SUCCESS on success.
* @return LY_EINCOMPLETE in case data tree is needed to finish the validation.
* @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 *dynamic, uint32_t value_hint,
- LY_PREFIX_FORMAT format, void *prefix_data, const struct lysc_node *ctx_snode);
+ size_t name_len, const char *value, size_t value_len, ly_bool *dynamic, LY_PREFIX_FORMAT format,
+ void *prefix_data, uint32_t hints, ly_bool *incomplete);
/**
* @brief Insert an attribute (last) into a parent
@@ -271,81 +272,58 @@
* @param[in] value String value to be parsed.
* @param[in] value_len Length of @p value, must be set correctly.
* @param[in,out] dynamic Flag if @p value is dynamically allocated, is adjusted when @p value is consumed.
- * @param[in] value_hint [Value hint](@ref lydvalueparseopts) from the parser regarding the value type.
* @param[in] format Input format of @p value and @p ns.
+ * @param[in] hints [Hints](@ref lydhints) from the parser regarding the node/value type.
* @param[in] val_prefs Possible value prefixes, array is spent (even in case the function fails).
* @param[in] prefix Attribute prefix.
* @param[in] prefix_len Attribute prefix length.
* @param[in] module_key Mandatory key to reference module, can be namespace or name.
* @param[in] module_key_len Length of @p module_key, must be set correctly.
- * @return LY_SUCCESS on success.
- * @return LY_ERR value if an error occurred.
+ * @return LY_SUCCESS on success,
+ * @return LY_ERR value on error.
*/
LY_ERR lyd_create_attr(struct lyd_node *parent, struct lyd_attr **attr, const struct ly_ctx *ctx, const char *name,
- size_t name_len, const char *value, size_t value_len, ly_bool *dynamic, uint32_t value_hint, LYD_FORMAT format,
+ size_t name_len, const char *value, size_t value_len, ly_bool *dynamic, LYD_FORMAT format, uint32_t hints,
struct ly_prefix *val_prefs, const char *prefix, size_t prefix_len, const char *module_key, size_t module_key_len);
/**
- * @defgroup lydvalueparseopts Hint options for type plugin callbacks from the data parsers.
- *
- * Options applicable to ly_value_parse()
- * @{
- */
-#define LYD_VALUE_PARSE_ISSTRING LY_TYPE_OPTS_ISSTRING /**< The input value is supposed to be a string. */
-#define LYD_VALUE_PARSE_ISNUMBER LY_TYPE_OPTS_ISNUMBER /**< The input value is supposed to be a number. */
-#define LYD_VALUE_PARSE_ISBOOLEAN LY_TYPE_OPTS_ISBOOLEAN /**< The input value is supposed to be a boolean. */
-#define LYD_VALUE_PARSE_ISEMPTY LY_TYPE_OPTS_ISEMPTY /**< The input value is supposed to be empty type. */
-
-/** @} lydvalueparseopts */
-
-/**
- * @brief Validate, canonize and store the given @p value into the node according to the node's type's rules.
- *
- * @param[in] node Data node for the @p value.
- * @param[in] value String value to be parsed, must not be NULL.
- * @param[in] value_len Length of the give @p value, must be set correctly.
- * @param[in,out] dynamic Flag if @p value is dynamically allocated, is adjusted when @p value is consumed.
- * @param[in] second Flag for the second call after returning LY_EINCOMPLETE
- * @param[in] value_hint [Value hint](@ref lydvalueparseopts) from the parser.
- * @param[in] format Input format of @p value.
- * @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
- * @param[in] tree Data tree (e.g. when validating RPC/Notification) where the required
- * data instance (leafref target, instance-identifier) can be placed. NULL in case the data tree are not yet complete,
- * then LY_EINCOMPLETE can be returned.
- * @return LY_SUCCESS on success
- * @return LY_EINCOMPLETE in case the @p trees is not provided and it was needed to finish the validation.
- * @return LY_ERR value if an error occurred.
- */
-LY_ERR lyd_value_parse(struct lyd_node_term *node, const char *value, size_t value_len, ly_bool *dynamic, ly_bool second,
- uint32_t value_hint, LY_PREFIX_FORMAT format, void *prefix_data, const struct lyd_node *tree);
-
-/* similar to lyd_value_parse except can be used just to store the value, hence does also not support a second call */
-LY_ERR lyd_value_store(struct lyd_value *val, const struct lysc_node *schema, const char *value, size_t value_len,
- ly_bool *dynamic, LY_PREFIX_FORMAT format, void *prefix_data);
-
-/**
- * @brief Validate, canonize and store the given @p value into the metadata according to the annotation type's rules.
+ * @brief Store and canonize the given @p value into @p val according to the schema node type rules.
*
* @param[in] ctx libyang context.
- * @param[in] meta Metadata for the @p value.
+ * @param[in,out] val Storage for the value.
+ * @param[in] type Type of the value.
* @param[in] value String value to be parsed, must not be NULL.
* @param[in] value_len Length of the give @p value, must be set correctly.
* @param[in,out] dynamic Flag if @p value is dynamically allocated, is adjusted when @p value is consumed.
- * @param[in] second Flag for the second call after returning LY_EINCOMPLETE
- * @param[in] value_hint [Value hint](@ref lydvalueparseopts) from the parser.
- * @param[in] format Input format of the data.
+ * @param[in] format Input format of @p value.
* @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
- * @param[in] ctx_snode Context node for value resolution in schema.
- * @param[in] tree Data tree (e.g. when validating RPC/Notification) where the required
- * data instance (leafref target, instance-identifier) can be placed. NULL in case the data tree are not yet complete,
- * then LY_EINCOMPLETE can be returned.
- * @return LY_SUCCESS on success
- * @return LY_EINCOMPLETE in case the @p trees is not provided and it was needed to finish the validation.
- * @return LY_ERR value if an error occurred.
+ * @param[in] hints [Value hints](@ref lydvalhints) from the parser.
+ * @param[in] ctx_node Context schema node.
+ * @param[out] incomplete Optional, set if the value also needs to be resolved.
+ * @param[in] log_elem_type Elem type for logging.
+ * @param[in] log_elem Elem for logging.
+ * @return LY_SUCCESS on success,
+ * @return LY_ERR value on error.
*/
-LY_ERR lyd_value_parse_meta(const struct ly_ctx *ctx, struct lyd_meta *meta, const char *value, size_t value_len,
- ly_bool *dynamic, ly_bool second, uint32_t value_hint, LY_PREFIX_FORMAT format, void *prefix_data,
- const struct lysc_node *ctx_snode, const struct lyd_node *tree);
+LY_ERR lyd_value_store(const struct ly_ctx *ctx, struct lyd_value *val, const struct lysc_type *type, const char *value,
+ size_t value_len, ly_bool *dynamic, LY_PREFIX_FORMAT format, void *prefix_data, uint32_t hints,
+ const struct lysc_node *ctx_node, ly_bool *incomplete, enum LY_VLOG_ELEM log_elem_type, const void *log_elem);
+
+/**
+ * @brief Validate previously incompletely stored value.
+ *
+ * @param[in] ctx libyang context.
+ * @param[in] type Schema type of the value (not the stored one, but the original one).
+ * @param[in,out] val Stored value to resolve.
+ * @param[in] ctx_node Context node for the resolution.
+ * @param[in] tree Data tree for the resolution.
+ * @param[in] log_elem_type Elem type for logging.
+ * @param[in] log_elem Elem for logging.
+ * @return LY_SUCCESS on success,
+ * @return LY_ERR value on error.
+ */
+LY_ERR lyd_value_validate_incomplete(const struct ly_ctx *ctx, const struct lysc_type *type, struct lyd_value *val,
+ const struct lyd_node *ctx_node, const struct lyd_node *tree, enum LY_VLOG_ELEM log_elem_type, const void *log_elem);
/* generic function lys_value_validate */
LY_ERR _lys_value_validate(const struct ly_ctx *ctx, const struct lysc_node *node, const char *value, size_t value_len,
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index 2fcea59..b7d449e 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -3947,7 +3947,7 @@
/* ignore default values of the key */
if (key->dflt) {
key->dflt->realtype->plugin->free(ctx->ctx, key->dflt);
- lysc_type_free(ctx->ctx, key->dflt->realtype);
+ lysc_type_free(ctx->ctx, (struct lysc_type *)key->dflt->realtype);
free(key->dflt);
key->dflt = NULL;
}
@@ -7806,21 +7806,29 @@
LY_ERR ret;
struct ly_err_item *err = NULL;
- ret = type->plugin->store(ctx->ctx, type, dflt, strlen(dflt), LY_TYPE_OPTS_SCHEMA,
- LY_PREF_SCHEMA, (void *)dflt_mod, node, NULL, storage, &err);
- if (err) {
- ly_err_print(err);
+ ret = type->plugin->store(ctx->ctx, type, dflt, strlen(dflt), 0, LY_PREF_SCHEMA, (void *)dflt_mod, LYD_HINT_SCHEMA,
+ node, storage, &err);
+ if (ret == LY_EINCOMPLETE) {
+ /* we have no data so we will not be resolving it */
+ ret = LY_SUCCESS;
+ }
+
+ if (ret) {
ctx->path[0] = '\0';
lysc_path(node, LYSC_PATH_LOG, ctx->path, LYSC_CTX_BUFSIZE);
- LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
- "Invalid default - value does not fit the type (%s).", err->msg);
- ly_err_free(err);
+ if (err) {
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
+ "Invalid default - value does not fit the type (%s).", err->msg);
+ ly_err_free(err);
+ } else {
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
+ "Invalid default - value does not fit the type.");
+ }
+ return ret;
}
- if (!ret) {
- ++storage->realtype->refcount;
- return LY_SUCCESS;
- }
- return ret;
+
+ ++((struct lysc_type *)storage->realtype)->refcount;
+ return LY_SUCCESS;
}
/**
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index 673c4d9..a43ab9b 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -718,7 +718,7 @@
FREE_STRING(ctx, node->units);
if (node->dflt) {
node->dflt->realtype->plugin->free(ctx, node->dflt);
- lysc_type_free(ctx, node->dflt->realtype);
+ lysc_type_free(ctx, (struct lysc_type *)node->dflt->realtype);
free(node->dflt);
}
}
@@ -735,7 +735,7 @@
FREE_STRING(ctx, node->units);
LY_ARRAY_FOR(node->dflts, u) {
node->dflts[u]->realtype->plugin->free(ctx, node->dflts[u]);
- lysc_type_free(ctx, node->dflts[u]->realtype);
+ lysc_type_free(ctx, (struct lysc_type *)node->dflts[u]->realtype);
free(node->dflts[u]);
}
LY_ARRAY_FREE(node->dflts);
diff --git a/src/validation.c b/src/validation.c
index daa340b..4fc7158 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -25,6 +25,7 @@
#include "hash_table.h"
#include "log.h"
#include "parser_data.h"
+#include "plugins_exts_metadata.h"
#include "plugins_types.h"
#include "set.h"
#include "tree.h"
@@ -111,7 +112,7 @@
LY_ERR
lyd_validate_unres(struct lyd_node **tree, struct ly_set *node_when, struct ly_set *node_types, struct ly_set *meta_types,
- LY_PREFIX_FORMAT format, void *prefix_data, struct lyd_node **diff)
+ struct lyd_node **diff)
{
LY_ERR ret = LY_SUCCESS;
uint32_t i;
@@ -170,10 +171,11 @@
--i;
struct lyd_node_term *node = (struct lyd_node_term *)node_types->objs[i];
+ struct lysc_type *type = ((struct lysc_node_leaf *)node->schema)->type;
- /* validate and store the value of the node */
- ret = lyd_value_parse(node, node->value.canonical, strlen(node->value.canonical), 0, 1, 0, format,
- prefix_data, *tree);
+ /* resolve the value of the node */
+ ret = lyd_value_validate_incomplete(LYD_CTX(node), type, &node->value, (struct lyd_node *)node, *tree,
+ LY_VLOG_LYD, node);
LY_CHECK_RET(ret);
/* remove this node from the set */
@@ -188,10 +190,11 @@
--i;
struct lyd_meta *meta = (struct lyd_meta *)meta_types->objs[i];
+ struct lysc_type *type = ((struct lyext_metadata *)meta->annotation->data)->type;
/* validate and store the value of the metadata */
- ret = lyd_value_parse_meta(meta->parent->schema->module->ctx, meta, meta->value.canonical,
- strlen(meta->value.canonical), 0, 1, 0, format, prefix_data, NULL, *tree);
+ ret = lyd_value_validate_incomplete(LYD_CTX(meta->parent), type, &meta->value, meta->parent, *tree,
+ LY_VLOG_NONE, NULL);
LY_CHECK_RET(ret);
/* remove this attr from the set */
@@ -1037,11 +1040,13 @@
/* skip added default nodes */
if ((node->flags & (LYD_DEFAULT | LYD_NEW)) != (LYD_DEFAULT | LYD_NEW)) {
LY_LIST_FOR(node->meta, meta) {
- /* metadata type resolution */
- LY_CHECK_RET(ly_set_add(type_meta_check, (void *)meta, LY_SET_OPT_USEASLIST, NULL));
+ if (((struct lyext_metadata *)meta->annotation->data)->type->plugin->validate) {
+ /* metadata type resolution */
+ LY_CHECK_RET(ly_set_add(type_meta_check, (void *)meta, LY_SET_OPT_USEASLIST, NULL));
+ }
}
- if (node->schema->nodetype & LYD_NODE_TERM) {
+ if ((node->schema->nodetype & LYD_NODE_TERM) && ((struct lysc_node_leaf *)node->schema)->type->plugin->validate) {
/* node type resolution */
LY_CHECK_RET(ly_set_add(type_check, (void *)node, LY_SET_OPT_USEASLIST, NULL));
} else if (node->schema->nodetype & LYD_NODE_INNER) {
@@ -1125,7 +1130,7 @@
}
/* finish incompletely validated terminal values/attributes and when conditions */
- ret = lyd_validate_unres(tree, &when_check, &type_check, &type_meta_check, LY_PREF_JSON, NULL, diff);
+ ret = lyd_validate_unres(tree, &when_check, &type_check, &type_meta_check, diff);
LY_CHECK_GOTO(ret, cleanup);
/* perform final validation that assumes the data tree is final */
@@ -1256,7 +1261,7 @@
/* finish incompletely validated terminal values/attributes and when conditions on the full tree */
LY_CHECK_GOTO(ret = lyd_validate_unres((struct lyd_node **)&tree, &when_check, &type_check, &type_meta_check,
- LY_PREF_JSON, NULL, diff), cleanup);
+ diff), cleanup);
/* perform final validation of the operation/notification */
lyd_validate_obsolete(op_node);
diff --git a/src/validation.h b/src/validation.h
index 1a1a00a..3e2c5cd 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -41,13 +41,11 @@
* @param[in] node_when Set with nodes with "when" conditions, can be NULL.
* @param[in] node_types Set with nodes with unresolved types, can be NULL
* @param[in] meta_types Set with metdata with unresolved types, can be NULL.
- * @param[in] format Format of the unresolved data.
- * @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
* @param[in,out] diff Validation diff.
* @return LY_ERR value.
*/
LY_ERR lyd_validate_unres(struct lyd_node **tree, struct ly_set *node_when, struct ly_set *node_types, struct ly_set *meta_types,
- LY_PREFIX_FORMAT format, void *prefix_data, struct lyd_node **diff);
+ struct lyd_node **diff);
/**
* @brief Validate new siblings. Specifically, check duplicated instances, autodelete default values and cases.
diff --git a/src/xpath.c b/src/xpath.c
index a1376b4..56cfa2a 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -1515,7 +1515,7 @@
static LY_ERR
set_comp_canonize(struct lyxp_set *trg, const struct lyxp_set *src, const struct lyxp_set_node *xp_node)
{
- struct lysc_type *type = NULL;
+ const struct lysc_type *type = NULL;
struct lyd_value val;
struct ly_err_item *err = NULL;
char *str, *ptr;
@@ -1547,8 +1547,8 @@
}
/* ignore errors, the value may not satisfy schema constraints */
- rc = type->plugin->store(src->ctx, type, str, strlen(str), LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_DYNAMIC,
- LY_PREF_JSON, NULL, NULL, NULL, &val, &err);
+ rc = type->plugin->store(src->ctx, type, str, strlen(str), LY_TYPE_OPTS_DYNAMIC, LY_PREF_JSON, NULL, LYD_HINT_DATA,
+ xp_node->node->schema, &val, &err);
ly_err_free(err);
if (rc) {
/* invalid value */
@@ -3333,8 +3333,8 @@
type = ((struct lysc_node_leaf *)scnode)->type;
if (type->basetype != LY_TYPE_IDENT) {
- rc = type->plugin->store(set->ctx, type, value, strlen(value), LY_TYPE_OPTS_SCHEMA, LY_PREF_SCHEMA,
- (void *)set->local_mod, NULL, NULL, &storage, &err);
+ rc = type->plugin->store(set->ctx, type, value, strlen(value), 0, LY_PREF_SCHEMA, (void *)set->local_mod,
+ LYD_HINT_DATA, scnode, &storage, &err);
if (err) {
LOGWRN(set->ctx, "Invalid value \"%s\" which does not fit the type (%s).", value, err->msg);
@@ -3807,8 +3807,7 @@
/* store args[1] as ident */
rc = val->realtype->plugin->store(set->ctx, val->realtype, args[1]->val.str, strlen(args[1]->val.str),
- 0, set->format, (void *)set->local_mod,
- (struct lyd_node *)leaf, set->tree, &data, &err);
+ 0, set->format, (void *)set->local_mod, LYD_HINT_DATA, leaf->schema, &data, &err);
} else {
meta = args[0]->val.meta[i].meta;
val = &meta->value;
@@ -3818,9 +3817,8 @@
}
/* store args[1] as ident */
- rc = val->realtype->plugin->store(set->ctx, val->realtype, args[1]->val.str, strlen(args[1]->val.str),
- 0, set->format, (void *)meta->annotation->module,
- meta->parent, set->tree, &data, &err);
+ rc = val->realtype->plugin->store(set->ctx, val->realtype, args[1]->val.str, strlen(args[1]->val.str), 0,
+ set->format, (void *)meta->annotation->module, LYD_HINT_DATA, meta->parent->schema, &data, &err);
}
if (err) {
diff --git a/tests/utests/data/test_parser_json.c b/tests/utests/data/test_parser_json.c
index 34101be..0dfbaba 100644
--- a/tests/utests/data/test_parser_json.c
+++ b/tests/utests/data/test_parser_json.c
@@ -535,7 +535,7 @@
/* invalid value, no flags */
data = "{\"a:foo3\":[null]}";
assert_int_equal(LY_EVALID, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
- logbuf_assert("Invalid empty uint32 value. /a:foo3");
+ logbuf_assert("Invalid non-number-encoded uint32 value \"\". /a:foo3");
assert_null(tree);
/* opaq flag */
@@ -571,7 +571,7 @@
/* invalid key, no flags */
data = "{\"a:l1\":[{\"a\":\"val_a\",\"b\":\"val_b\",\"c\":\"val_c\"}]}";
assert_int_equal(LY_EVALID, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
- logbuf_assert("Invalid int16 value \"val_c\". /a:l1/c");
+ logbuf_assert("Invalid non-number-encoded int16 value \"val_c\". /a:l1/c");
assert_null(tree);
/* opaq flag */
diff --git a/tests/utests/data/test_types.c b/tests/utests/data/test_types.c
index ba2cd84..9c5730e 100644
--- a/tests/utests/data/test_types.c
+++ b/tests/utests/data/test_types.c
@@ -870,10 +870,12 @@
"Invalid instance-identifier \"/cont/leaftarget\" value - syntax error. /types:inst");
/* instance-identifier is here in JSON format because it is already in internal representation without canonical prefixes */
- TEST_DATA( "<cont xmlns=\"urn:tests:types\"/><t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaftarget</t:inst>", LY_EVALID, "Invalid instance-identifier \"/types:cont/leaftarget\" value - required instance not found. /types:inst");
+ TEST_DATA("<cont xmlns=\"urn:tests:types\"/><t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaftarget</t:inst>", LY_ENOTFOUND,
+ "Invalid instance-identifier \"/types:cont/leaftarget\" value - required instance not found. /types:inst");
/* instance-identifier is here in JSON format because it is already in internal representation without canonical prefixes */
- TEST_DATA( "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaftarget</t:inst>", LY_EVALID, "Invalid instance-identifier \"/types:cont/leaftarget\" value - required instance not found. /types:inst");
+ TEST_DATA("<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaftarget</t:inst>", LY_ENOTFOUND,
+ "Invalid instance-identifier \"/types:cont/leaftarget\" value - required instance not found. /types:inst");
TEST_DATA("<leaflisttarget xmlns=\"urn:tests:types\">x</leaflisttarget><t:inst xmlns:t=\"urn:tests:types\">/t:leaflisttarget[1</t:inst>", LY_EVALID,
"Invalid instance-identifier \"/t:leaflisttarget[1\" value - syntax error. /types:inst");
@@ -906,7 +908,7 @@
/* instance-identifier is here in JSON format because it is already in internal representation without canonical prefixes */
TEST_DATA("<cont xmlns=\"urn:tests:types\"><leaflisttarget>1</leaflisttarget></cont>"
- "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaflisttarget[.='2']</t:inst>", LY_EVALID,
+ "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaflisttarget[.='2']</t:inst>", LY_ENOTFOUND,
"Invalid instance-identifier \"/types:cont/leaflisttarget[.='2']\" value - required instance not found. /types:inst");
TEST_DATA("<cont xmlns=\"urn:tests:types\"><leaflisttarget>1</leaflisttarget></cont>"
"<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:leaflisttarget[.='x']</t:inst>", LY_EVALID,
@@ -917,7 +919,7 @@
/* instance-identifier is here in JSON format because it is already in internal representation without canonical prefixes */
TEST_DATA("<cont xmlns=\"urn:tests:types\"><listtarget><id>1</id><value>x</value></listtarget></cont>"
- "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:listtarget[t:id='2']</t:inst>", LY_EVALID,
+ "<t:inst xmlns:t=\"urn:tests:types\">/t:cont/t:listtarget[t:id='2']</t:inst>", LY_ENOTFOUND,
"Invalid instance-identifier \"/types:cont/listtarget[id='2']\" value - required instance not found. /types:inst");
TEST_DATA("<leaflisttarget xmlns=\"urn:tests:types\">a</leaflisttarget>"
"<leaflisttarget xmlns=\"urn:tests:types\">b</leaflisttarget>"
@@ -947,17 +949,17 @@
data = "/types:list2[id='a'][value='b']/id";
assert_int_equal(LY_ENOTFOUND, lyd_value_validate(s->ctx, (const struct lyd_node_term*)tree->prev->prev, data, strlen(data),
tree, NULL));
- logbuf_assert("Invalid instance-identifier \"/types:list2[id='a'][value='b']/id\" value - instance not found. /");
+ logbuf_assert("Invalid instance-identifier \"/types:list2[id='a'][value='b']/id\" value - required instance not found. /types:inst");
/* leaf-list-predicate */
data = "/types:leaflisttarget[.='c']";
assert_int_equal(LY_ENOTFOUND, lyd_value_validate(s->ctx, (const struct lyd_node_term*)tree->prev->prev, data, strlen(data),
tree, NULL));
- logbuf_assert("Invalid instance-identifier \"/types:leaflisttarget[.='c']\" value - instance not found. /");
+ logbuf_assert("Invalid instance-identifier \"/types:leaflisttarget[.='c']\" value - required instance not found. /types:inst");
/* position predicate */
data = "/types:list_keyless[4]";
assert_int_equal(LY_ENOTFOUND, lyd_value_validate(s->ctx, (const struct lyd_node_term*)tree->prev->prev, data, strlen(data),
tree, NULL));
- logbuf_assert("Invalid instance-identifier \"/types:list_keyless[4]\" value - instance not found. /");
+ logbuf_assert("Invalid instance-identifier \"/types:list_keyless[4]\" value - required instance not found. /types:inst");
lyd_free_all(tree);
@@ -1107,9 +1109,9 @@
assert_non_null(leaf->value.subvalue->prefix_data);
assert_int_equal(((struct ly_set *)leaf->value.subvalue->prefix_data)->count, 1);
assert_int_equal(LY_TYPE_UNION, leaf->value.realtype->basetype);
- assert_int_equal(LY_TYPE_INT8, leaf->value.subvalue->value->realtype->basetype);
- assert_string_equal("12", leaf->value.subvalue->value->canonical);
- assert_int_equal(12, leaf->value.subvalue->value->int8);
+ assert_int_equal(LY_TYPE_INT8, leaf->value.subvalue->value.realtype->basetype);
+ assert_string_equal("12", leaf->value.subvalue->value.canonical);
+ assert_int_equal(12, leaf->value.subvalue->value.int8);
test_printed_value(&leaf->value, "12", LY_PREF_SCHEMA, NULL);
@@ -1118,9 +1120,9 @@
assert_string_equal("12", value.canonical);
assert_non_null(value.subvalue->prefix_data);
assert_int_equal(((struct ly_set *)leaf->value.subvalue->prefix_data)->count, 1);
- assert_int_equal(LY_TYPE_INT8, value.subvalue->value->realtype->basetype);
- assert_string_equal("12", value.subvalue->value->canonical);
- assert_int_equal(12, leaf->value.subvalue->value->int8);
+ assert_int_equal(LY_TYPE_INT8, value.subvalue->value.realtype->basetype);
+ assert_string_equal("12", value.subvalue->value.canonical);
+ assert_int_equal(12, leaf->value.subvalue->value.int8);
value.realtype->plugin->free(s->ctx, &value);
lyd_free_all(tree);
@@ -1133,8 +1135,8 @@
assert_non_null(leaf->value.subvalue->prefix_data);
assert_int_equal(((struct ly_set *)leaf->value.subvalue->prefix_data)->count, 1);
assert_int_equal(LY_TYPE_UNION, leaf->value.realtype->basetype);
- assert_int_equal(LY_TYPE_STRING, leaf->value.subvalue->value->realtype->basetype);
- assert_string_equal("2", leaf->value.subvalue->value->canonical);
+ assert_int_equal(LY_TYPE_STRING, leaf->value.subvalue->value.realtype->basetype);
+ assert_string_equal("2", leaf->value.subvalue->value.canonical);
lyd_free_all(tree);
TEST_DATA("<un1 xmlns=\"urn:tests:types\" xmlns:x=\"urn:tests:defs\">x:fast-ethernet</un1>", LY_SUCCESS, "");
@@ -1145,20 +1147,20 @@
assert_non_null(leaf->value.subvalue->prefix_data);
assert_int_equal(((struct ly_set *)leaf->value.subvalue->prefix_data)->count, 2);
assert_int_equal(LY_TYPE_UNION, leaf->value.realtype->basetype);
- assert_int_equal(LY_TYPE_IDENT, leaf->value.subvalue->value->realtype->basetype);
- assert_string_equal("defs:fast-ethernet", leaf->value.subvalue->value->canonical);
+ assert_int_equal(LY_TYPE_IDENT, leaf->value.subvalue->value.realtype->basetype);
+ assert_string_equal("defs:fast-ethernet", leaf->value.subvalue->value.canonical);
test_printed_value(&leaf->value, "d:fast-ethernet", LY_PREF_SCHEMA, s->mod_defs);
- test_printed_value(leaf->value.subvalue->value, "d:fast-ethernet", LY_PREF_SCHEMA, s->mod_defs);
+ test_printed_value(&leaf->value.subvalue->value, "d:fast-ethernet", LY_PREF_SCHEMA, s->mod_defs);
value.realtype = leaf->value.realtype;
assert_int_equal(LY_SUCCESS, value.realtype->plugin->duplicate(s->ctx, &leaf->value, &value));
assert_string_equal("defs:fast-ethernet", value.canonical);
- assert_string_equal("defs:fast-ethernet", value.subvalue->value->canonical);
+ assert_string_equal("defs:fast-ethernet", value.subvalue->value.canonical);
assert_non_null(value.subvalue->prefix_data);
assert_int_equal(((struct ly_set *)leaf->value.subvalue->prefix_data)->count, 2);
- assert_int_equal(LY_TYPE_IDENT, value.subvalue->value->realtype->basetype);
- assert_string_equal("fast-ethernet", value.subvalue->value->ident->name);
+ assert_int_equal(LY_TYPE_IDENT, value.subvalue->value.realtype->basetype);
+ assert_string_equal("fast-ethernet", value.subvalue->value.ident->name);
value.realtype->plugin->free(s->ctx, &value);
lyd_free_all(tree);
@@ -1170,8 +1172,8 @@
assert_non_null(leaf->value.subvalue->prefix_data);
assert_int_equal(((struct ly_set *)leaf->value.subvalue->prefix_data)->count, 2);
assert_int_equal(LY_TYPE_UNION, leaf->value.realtype->basetype);
- assert_int_equal(LY_TYPE_STRING, leaf->value.subvalue->value->realtype->basetype);
- assert_string_equal("d:superfast-ethernet", leaf->value.subvalue->value->canonical);
+ assert_int_equal(LY_TYPE_STRING, leaf->value.subvalue->value.realtype->basetype);
+ assert_string_equal("d:superfast-ethernet", leaf->value.subvalue->value.canonical);
lyd_free_all(tree);
TEST_DATA("<leaflisttarget xmlns=\"urn:tests:types\">x</leaflisttarget><leaflisttarget xmlns=\"urn:tests:types\">y</leaflisttarget>"
@@ -1184,8 +1186,8 @@
assert_non_null(leaf->value.subvalue->prefix_data);
assert_int_equal(((struct ly_set *)leaf->value.subvalue->prefix_data)->count, 2);
assert_int_equal(LY_TYPE_UNION, leaf->value.realtype->basetype);
- assert_int_equal(LY_TYPE_INST, leaf->value.subvalue->value->realtype->basetype);
- assert_string_equal("/types:leaflisttarget[.='y']", leaf->value.subvalue->value->canonical);
+ assert_int_equal(LY_TYPE_INST, leaf->value.subvalue->value.realtype->basetype);
+ assert_string_equal("/types:leaflisttarget[.='y']", leaf->value.subvalue->value.canonical);
lyd_free_all(tree);
TEST_DATA("<leaflisttarget xmlns=\"urn:tests:types\">x</leaflisttarget><leaflisttarget xmlns=\"urn:tests:types\">y</leaflisttarget>"
@@ -1198,8 +1200,8 @@
assert_non_null(leaf->value.subvalue->prefix_data);
assert_int_equal(((struct ly_set *)leaf->value.subvalue->prefix_data)->count, 2);
assert_int_equal(LY_TYPE_UNION, leaf->value.realtype->basetype);
- assert_int_equal(LY_TYPE_STRING, leaf->value.subvalue->value->realtype->basetype);
- assert_string_equal("/a:leaflisttarget[3]", leaf->value.subvalue->value->canonical);
+ assert_int_equal(LY_TYPE_STRING, leaf->value.subvalue->value.realtype->basetype);
+ assert_string_equal("/a:leaflisttarget[3]", leaf->value.subvalue->value.canonical);
lyd_free_all(tree);
TEST_DATA("<un1 xmlns=\"urn:tests:types\">123456789012345678901</un1>", LY_EVALID, "Invalid union value \"123456789012345678901\" - no matching subtype found. /types:un1");
diff --git a/tools/re/main.c b/tools/re/main.c
index 8a313f0..f23d0ac 100644
--- a/tools/re/main.c
+++ b/tools/re/main.c
@@ -274,7 +274,8 @@
}
type = ((struct lysc_node_leaf *)mod->compiled->data)->type;
- match = type->plugin->store(ctx, type, str, strlen(str), 0, LY_PREF_JSON, NULL, NULL, NULL, &storage, &err);
+ match = type->plugin->store(ctx, type, str, strlen(str), 0, LY_PREF_JSON, NULL, LYD_HINT_SCHEMA,
+ mod->compiled->data, &storage, &err);
if ((match == LY_SUCCESS) || (match == LY_EINCOMPLETE)) {
storage.realtype->plugin->free(ctx, &storage);
}