data tree CHANGE lyd_attr -> lyd_meta
Also generic tree structures prepared.
diff --git a/src/parser_xml.c b/src/parser_xml.c
index f5c8cb8..28238bf 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -47,7 +47,7 @@
#define LYD_PARSER_BUFSIZE 4078
char path[LYD_PARSER_BUFSIZE]; /**< buffer for the generated path */
struct ly_set incomplete_type_validation; /**< set of nodes validated with LY_EINCOMPLETE result */
- struct ly_set incomplete_type_validation_attrs; /**< set of attributes validated with LY_EINCOMPLETE result */
+ struct ly_set incomplete_type_validation_meta; /**< set of metdata validated with LY_EINCOMPLETE result */
struct ly_set when_check; /**< set of nodes with "when" conditions */
};
@@ -133,7 +133,7 @@
}
static LY_ERR
-lydxml_attributes(struct lyd_xml_ctx *ctx, struct ly_set *attrs_data, const struct lysc_node *sparent, struct lyd_attr **attr)
+lydxml_metadata(struct lyd_xml_ctx *ctx, struct ly_set *attrs_data, const struct lysc_node *sparent, struct lyd_meta **meta)
{
LY_ERR ret = LY_EVALID, rc;
const struct lyxml_ns *ns;
@@ -146,7 +146,7 @@
/* in XML, all attributes must be prefixed
* TODO exception for NETCONF filters which are supposed to map to the ietf-netconf without prefix */
if (ctx->options & LYD_OPT_STRICT) {
- LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_REFERENCE, "Missing mandatory prefix for XML attribute \"%.*s\".",
+ LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_REFERENCE, "Missing mandatory prefix for XML metadata \"%.*s\".",
attr_data->name_len, attr_data->name);
}
skip_attr:
@@ -169,17 +169,17 @@
/* module is not implemented or not present in the schema */
if (ctx->options & LYD_OPT_STRICT) {
LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_REFERENCE,
- "Unknown (or not implemented) YANG module with namespace \"%s\" for attribute \"%.*s%s%.*s\".",
+ "Unknown (or not implemented) YANG module with namespace \"%s\" for metadata \"%.*s%s%.*s\".",
ns, attr_data->prefix_len, attr_data->prefix, attr_data->prefix_len ? ":" : "", attr_data->name_len,
attr_data->name);
}
goto skip_attr;
}
- rc = lyd_create_attr(NULL, attr, mod, attr_data->name, attr_data->name_len, attr_data->value,
+ rc = lyd_create_meta(NULL, meta, mod, attr_data->name, attr_data->name_len, attr_data->value,
attr_data->value_len, &attr_data->dynamic, lydxml_resolve_prefix, ctx, LYD_XML, sparent);
if (rc == LY_EINCOMPLETE) {
- ly_set_add(&ctx->incomplete_type_validation_attrs, attr, LY_SET_OPT_USEASLIST);
+ ly_set_add(&ctx->incomplete_type_validation_meta, meta, LY_SET_OPT_USEASLIST);
} else if (rc) {
ret = rc;
goto cleanup;
@@ -200,7 +200,7 @@
}
/**
- * @brief Parse XML elements as children YANG data node of the specified parent node.
+ * @brief Parse XML elements as YANG data node children the specified parent node.
*
* @param[in] ctx XML YANG data parser context.
* @param[in] parent Parent node where the children are inserted. NULL in case of parsing top-level elements.
@@ -209,14 +209,14 @@
* @return LY_ERR value.
*/
static LY_ERR
-lydxml_nodes(struct lyd_xml_ctx *ctx, struct lyd_node_inner *parent, const char **data, struct lyd_node **first)
+lydxml_data_r(struct lyd_xml_ctx *ctx, struct lyd_node_inner *parent, const char **data, struct lyd_node **first)
{
LY_ERR ret = LY_SUCCESS;
const char *prefix, *name;
size_t prefix_len, name_len;
struct ly_set attrs_data = {0};
const struct lyxml_ns *ns;
- struct lyd_attr *attr = NULL, *attr2;
+ struct lyd_meta *meta = NULL, *meta2;
const struct lysc_node *snode;
struct lys_module *mod;
unsigned int parents_count = ctx->elements.count;
@@ -271,9 +271,9 @@
return LY_EVALID;
}
- /* create actual attributes so that prefixes are available in the context */
+ /* create actual metadata so that prefixes are available in the context */
if (attrs_data.count) {
- LY_CHECK_GOTO(ret = lydxml_attributes(ctx, &attrs_data, snode, &attr), cleanup);
+ LY_CHECK_GOTO(ret = lydxml_metadata(ctx, &attrs_data, snode, &meta), cleanup);
}
if (snode->nodetype & (LYS_ACTION | LYS_NOTIF)) {
@@ -344,7 +344,13 @@
/* process children */
if (ctx->status == LYXML_ELEMENT && parents_count != ctx->elements.count) {
- ret = lydxml_nodes(ctx, (struct lyd_node_inner *)cur, data, lyd_node_children_p(cur));
+ ret = lydxml_data_r(ctx, (struct lyd_node_inner *)cur, data, lyd_node_children_p(cur));
+ LY_CHECK_GOTO(ret, cleanup);
+ }
+
+ if (snode->nodetype == LYS_LIST) {
+ /* check all keys exist */
+ ret = lyd_parse_check_keys(cur);
LY_CHECK_GOTO(ret, cleanup);
}
@@ -426,18 +432,18 @@
/* node is valid */
cur->flags &= ~LYD_NEW;
}
- LY_LIST_FOR(attr, attr2) {
- if (!strcmp(attr2->name, "default") && !strcmp(attr2->annotation->module->name, "ietf-netconf-with-defaults")
- && attr2->value.boolean) {
+ LY_LIST_FOR(meta, meta2) {
+ if (!strcmp(meta2->name, "default") && !strcmp(meta2->annotation->module->name, "ietf-netconf-with-defaults")
+ && meta2->value.boolean) {
/* node is default according to the metadata */
cur->flags |= LYD_DEFAULT;
}
}
- /* add attributes */
- assert(!cur->attr);
- cur->attr = attr;
- attr = NULL;
+ /* add metdata */
+ assert(!cur->meta);
+ cur->meta = meta;
+ meta = NULL;
/* insert */
lyd_insert_node((struct lyd_node *)parent, first, cur);
@@ -450,7 +456,7 @@
cleanup:
free(buffer);
- lyd_free_attr(ctx->ctx, attr, 1);
+ lyd_free_meta(ctx->ctx, meta, 1);
lyd_free_tree(cur);
for (unsigned int u = 0; u < attrs_data.count; ++u) {
if (((struct attr_data_s*)attrs_data.objs[u])->dynamic) {
@@ -466,7 +472,7 @@
}
LY_ERR
-lyd_parse_xml(struct ly_ctx *ctx, const char *data, int options, struct lyd_node **tree)
+lyd_parse_xml_data(struct ly_ctx *ctx, const char *data, int options, struct lyd_node **tree)
{
LY_ERR ret = LY_SUCCESS;
struct lyd_xml_ctx xmlctx = {0};
@@ -482,7 +488,7 @@
*tree = NULL;
/* parse XML data */
- ret = lydxml_nodes(&xmlctx, NULL, &data, tree);
+ ret = lydxml_data_r(&xmlctx, NULL, &data, tree);
LY_CHECK_GOTO(ret, cleanup);
if (!(options & LYD_OPT_PARSE_ONLY)) {
@@ -514,7 +520,7 @@
/* finish incompletely validated terminal values/attributes and when conditions */
ret = lyd_validate_unres(tree, &xmlctx.when_check, &xmlctx.incomplete_type_validation,
- &xmlctx.incomplete_type_validation_attrs, LYD_XML, lydxml_resolve_prefix, ctx);
+ &xmlctx.incomplete_type_validation_meta, LYD_XML, lydxml_resolve_prefix, ctx);
LY_CHECK_GOTO(ret, cleanup);
/* perform final validation that assumes the data tree is final */
@@ -526,10 +532,10 @@
cleanup:
/* there should be no unresolved types stored */
assert(!(options & LYD_OPT_PARSE_ONLY) || (!xmlctx.incomplete_type_validation.count
- && !xmlctx.incomplete_type_validation_attrs.count && !xmlctx.when_check.count));
+ && !xmlctx.incomplete_type_validation_meta.count && !xmlctx.when_check.count));
ly_set_erase(&xmlctx.incomplete_type_validation, NULL);
- ly_set_erase(&xmlctx.incomplete_type_validation_attrs, NULL);
+ ly_set_erase(&xmlctx.incomplete_type_validation_meta, NULL);
ly_set_erase(&xmlctx.when_check, NULL);
lyxml_context_clear((struct lyxml_context *)&xmlctx);
if (ret) {
@@ -538,3 +544,90 @@
}
return ret;
}
+
+static LY_ERR
+lydxml_rpc(struct lyd_xml_ctx *ctx, const char **data, struct ly_attr **attr)
+{
+ const char *prefix, *name;
+ size_t prefix_len, name_len;
+ struct ly_set attrs_data = {0};
+ const struct lyxml_ns *ns;
+
+ LY_CHECK_RET(lyxml_get_element((struct lyxml_context *)ctx, data, &prefix, &prefix_len, &name, &name_len));
+ if (ly_strncmp("rpc", name, name_len)) {
+ /* not an rpc */
+ return LY_ENOT;
+ }
+
+ if (ctx->status == LYXML_ATTRIBUTE) {
+ LY_CHECK_RET(lydxml_attributes_parse(ctx, data, &attrs_data));
+ }
+
+ ns = lyxml_ns_get((struct lyxml_context *)ctx, prefix, prefix_len);
+ if (!ns || strcmp(ns->uri, "urn:ietf:params:xml:ns:netconf:base:1.0")) {
+ /* wrong namespace */
+ return LY_ENOT;
+ }
+
+ /* all fine, just parse the rest of the attributes */
+ if (attrs_data.count) {
+ /* TODO parse into generic attribute structure, that will also be returned */
+ //LY_CHECK_RET(lydxml_attributes(ctx, &attrs_data, NULL, meta));
+ }
+
+ return LY_SUCCESS;
+}
+
+static LY_ERR
+lydxml_action(struct lyd_xml_ctx *ctx, const char **data)
+{
+ /* TODO */
+ return LY_ENOT;
+}
+
+LY_ERR
+lyd_parse_xml_rpc(struct ly_ctx *ctx, const char *data, struct lyd_node **tree, struct ly_attr **attr,
+ struct lyd_node **op)
+{
+ LY_ERR ret = LY_SUCCESS;
+ const char *data_p;
+ struct lyd_xml_ctx xmlctx = {0};
+
+ xmlctx.ctx = ctx;
+ xmlctx.line = 1;
+
+ /* init */
+ *tree = NULL;
+ data_p = data;
+
+ /* parse optional "rpc" element */
+ ret = lydxml_rpc(&xmlctx, &data_p, attr);
+ if (ret == LY_ENOT) {
+ /* reset data, nothing parsed */
+ data_p = data;
+ } else if (ret) {
+ goto cleanup;
+ } else {
+ /* successfully parsed */
+ data = data_p;
+
+ /* parse optional "action" element */
+ ret = lydxml_action(&xmlctx, &data_p);
+ if (ret == LY_ENOT) {
+ data_p = data;
+ } else if (ret) {
+ goto cleanup;
+ }
+ }
+
+ /* parse the rest of data tree normally */
+ ret = lydxml_data_r(&xmlctx, NULL, &data_p, tree);
+ LY_CHECK_GOTO(ret, cleanup);
+
+cleanup:
+ if (ret) {
+ lyd_free_all(*tree);
+ *tree = NULL;
+ }
+ return ret;
+}