yin parser CHANGE use generic function for content parsing in already implemented functions
diff --git a/src/common.h b/src/common.h
index a064cab..f62386a 100644
--- a/src/common.h
+++ b/src/common.h
@@ -312,7 +312,8 @@
YANG_RIGHT_BRACE,
YANG_CUSTOM,
- YANG_TEXT
+ YIN_TEXT,
+ YIN_VALUE
};
/* list of the YANG statements strings */
diff --git a/src/parser_yin.c b/src/parser_yin.c
index 8802267..b421657 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -13,6 +13,7 @@
*/
#include "common.h"
+#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -35,50 +36,6 @@
*/
#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
-/**
- * @brief loop over all subelements, automatically skip useles data and
- * unify inconsistencies in xml parser status when loading full vs self closing tags.
- * Use YIN_READ_SUBELEMS_END at the end.
- *
- * @param[in,out] CTX Xml parser context.
- * @param[in,out] DATA Data to read from, always moved to currently handeled character.
- * @param[in,out] RET Name of variable to store return values.
- * @param[in,out] CLEANUP_LABEL Goto label that will be used in case of error.
- * @param[in,out] KW Name of variable to store type of current subelement.
- * @param[in] TMP Name of variable to store temporary values (type yin_arg_record).
- * @param[in] SUBELEM_ARGS Name of variable to store array of subelements.
- */
-#define YIN_READ_SUBELEMS_START(CTX, DATA, RET, CLEANUP_LABEL, KW, TMP, SUBELEM_ARGS)\
-if (xml_ctx->status == LYXML_ELEM_CONTENT) {\
- ret = lyxml_get_string(CTX, DATA, &TMP.content, &TMP.content_len, &TMP.content, &TMP.content_len, &TMP.dynamic_content);\
- /* unknown element text content is ignored */\
- if (ret == LY_EINVAL) {\
- while (CTX->status == LYXML_ELEMENT) {\
- RET = lyxml_get_element(CTX, DATA, &TMP.prefix, &TMP.prefix_len, &TMP.name, &TMP.name_len);\
- LY_CHECK_GOTO(RET, CLEANUP_LABEL);\
- RET = yin_load_attributes(CTX, DATA, &SUBELEM_ARGS);\
- LY_CHECK_GOTO(RET, CLEANUP_LABEL);\
- KW = yin_match_keyword(CTX, TMP.name, TMP.name_len, TMP.prefix, TMP.prefix_len);\
- if (!TMP.name) {\
- /* end of element reached */\
- break;\
- }
-/**
- * Closing part of macro YIN_READ_SUBELEM_START
- *
- * @param[in] CTX Xml parser context.
- * @param[in,out] DATA Data to read from, always moved to currently handeled character.
- * @param[in,out] TMP Name of variable to store temporary values (type yin_arg_record).
- */
-#define YIN_READ_SUBELEMS_END(CTX, DATA, TMP)\
- }\
- } else {\
- /* load closing element */\
- LY_CHECK_RET(lyxml_get_element(CTX, DATA, &TMP.prefix, &TMP.prefix_len, &TMP.name, &TMP.name_len));\
- LY_CHECK_RET(TMP.name, LY_EINVAL);\
- }\
-}
-
const char *const yin_attr_list[] = {
[YIN_ARG_NAME] = "name",
[YIN_ARG_TARGET_NODE] = "target-node",
@@ -120,7 +77,13 @@
if (name - start == (long int)name_len) {
return kw;
} else {
- return YANG_NONE;
+ if (strncmp(start, "text", name_len) == 0) {
+ return YIN_TEXT;
+ } else if (strncmp(start, "value", name_len) == 0) {
+ return YIN_VALUE;
+ } else {
+ return YANG_NONE;
+ }
}
}
@@ -266,23 +229,6 @@
return ret;
}
-struct yin_attribute {
- enum YIN_ARGUMENT type;
- bool mandatory;
- const char *dest;
-};
-
-struct yin_subelement {
- enum yang_keyword type;
- bool mandatory;
- void *dest;
-};
-
-struct sized_string {
- const char *value;
- size_t len;
-};
-
/**
* @brief get record with given type.
*
@@ -305,33 +251,30 @@
}
/**
- * @brief Generic function for subelement parsing
+ * @brief Generic function for content parsing
*
* @param[in,out] xml_ctx Xml context.
- * @param[in] attrs Array of attributes.
- * @param[in] subelem_info array of valid subelement types and meta information.
+ * @param[in] subelem_info array of valid subelement types and meta information,
+ * array must be ordered by subelem_info->type in ascending order.
* @param[in] subelem_info_size Size of subelem_info array.
- * @param[in] current_element Type of current element.
* @param[in,out] data Data to read from, always moved to currently handled character.
- * @param[in] subelem Type of this subelement.
- * @param[in] subelem_index Index of this subelement.
- * @param[in] exts Extension instances to add to.
- *
+ * @param[in] current_element Type of current element.
+ * @param[out] Where the text content of element should be stored. Text content is ignored if set to NULL.
+ * @param[in] exts Extension instance to add to. Can be null if element cannot have extension as subelement.
* @return LY_ERR values.
*/
LY_ERR
-yin_parse_element(struct lyxml_context *xml_ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
- enum yang_keyword current_element, const char **data, LYEXT_SUBSTMT subelem,
- uint32_t subelem_index, struct lysp_ext_instance *exts)
+yin_parse_content(struct lyxml_context *xml_ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
+ const char **data, enum yang_keyword current_element, const char **text_content, struct lysp_ext_instance **exts)
{
LY_ERR ret = LY_SUCCESS;
struct sized_string prefix, name;
char *out;
size_t out_len;
int dynamic;
- struct yin_arg_record *subelem_attrs;
+ struct yin_arg_record *subelem_attrs = NULL;
enum yang_keyword kw = YANG_NONE;
- struct yin_subelement *subeleme_info_rec;
+ struct yin_subelement *subelem_info_rec = NULL;
if (xml_ctx->status == LYXML_ELEM_CONTENT) {
ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
@@ -349,19 +292,21 @@
kw = yin_match_keyword(xml_ctx, name.value, name.len, prefix.value, prefix.len);
/* check if this element can be child of current element */
- subeleme_info_rec = get_record(kw, subelem_info_size, subelem_info);
- if (!subeleme_info_rec) {
+ subelem_info_rec = get_record(kw, subelem_info_size, subelem_info);
+ if (!subelem_info_rec) {
LOGVAL_PARSER(xml_ctx, LY_VCODE_UNEXP_SUBELEM, name.len, name.value, ly_stmt2str(current_element));
ret = LY_EVALID;
goto cleanup;
}
/* TODO macro to check order */
-
+ /* TODO flag check */
switch (kw) {
case YANG_CUSTOM:
- yin_parse_extension_instance(xml_ctx, subelem_attrs, data, name2fullname(name.value, prefix.len),
- namelen2fulllen(name.len, prefix.len), subelem, subelem_index, &exts);
+ ret = yin_parse_extension_instance(xml_ctx, &subelem_attrs, data, name2fullname(name.value, prefix.len),
+ namelen2fulllen(name.len, prefix.len),
+ (struct yin_ext_meta *)subelem_info_rec->dest, exts);
+ LY_CHECK_GOTO(ret, cleanup);
break;
case YANG_ACTION:
break;
@@ -370,6 +315,7 @@
case YANG_ANYXML:
break;
case YANG_ARGUMENT:
+ ret = yin_parse_argument_element(xml_ctx, &subelem_attrs, data, (struct yin_argument_meta *)subelem_info_rec->dest, exts);
break;
case YANG_AUGMENT:
break;
@@ -392,6 +338,7 @@
case YANG_DEFAULT:
break;
case YANG_DESCRIPTION:
+ ret = yin_parse_meta_element(xml_ctx, data, YANG_DESCRIPTION, (const char **)subelem_info_rec->dest, exts);
break;
case YANG_DEVIATE:
break;
@@ -460,12 +407,14 @@
case YANG_POSITION:
break;
case YANG_PREFIX:
+ ret = yin_parse_prefix(xml_ctx, subelem_attrs, (const char **)subelem_info_rec->dest, data, exts);
break;
case YANG_PRESENCE:
break;
case YANG_RANGE:
break;
case YANG_REFERENCE:
+ ret = yin_parse_meta_element(xml_ctx, data, YANG_REFERENCE, (const char **)subelem_info_rec->dest, exts);
break;
case YANG_REFINE:
break;
@@ -474,12 +423,12 @@
case YANG_REVISION:
break;
case YANG_REVISION_DATE:
+ ret = yin_parse_revision_date(xml_ctx, &subelem_attrs, data, (char *)subelem_info_rec->dest, exts);
break;
case YANG_RPC:
break;
case YANG_STATUS:
- ret = yin_parse_status(xml_ctx, &subelem_attrs, data, subeleme_info_rec->dest, &exts);
- LY_CHECK_GOTO(ret, cleanup);
+ ret = yin_parse_status(xml_ctx, &subelem_attrs, data, (uint16_t *)subelem_info_rec->dest, exts);
break;
case YANG_SUBMODULE:
break;
@@ -500,17 +449,40 @@
case YANG_YANG_VERSION:
break;
case YANG_YIN_ELEMENT:
+ ret = yin_parse_yin_element_element(xml_ctx, subelem_attrs, data, (uint16_t *)subelem_info_rec->dest, exts);
+ break;
+ case YIN_TEXT:
+ ret = yin_parse_text_element(xml_ctx, data, (const char **)subelem_info_rec->dest);
+ break;
+ case YIN_VALUE:
break;
default:
- /* TODO specify special */
+ /* TODO special cases */
break;
}
+ LY_CHECK_GOTO(ret, cleanup);
FREE_ARRAY(xml_ctx, subelem_attrs, free_arg_rec);
subelem_attrs = NULL;
+ subelem_info_rec = NULL;
}
} else {
/* elements with text or none content */
- /* save text content */
+ /* save text content, if text_content isn't set, it's just ignored */
+ if (text_content) {
+ if (dynamic) {
+ *text_content = lydict_insert_zc(xml_ctx->ctx, out);
+ if (!*text_content) {
+ free(out);
+ return LY_EMEM;
+ }
+ } else {
+ if (out_len == 0) {
+ *text_content = NULL;
+ } else {
+ *text_content = lydict_insert(xml_ctx->ctx, out, out_len);
+ }
+ }
+ }
/* load closing element */
LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix.value, &prefix.len, &name.value, &name.len));
}
@@ -522,125 +494,76 @@
}
LY_ERR
-yin_parse_text_element(struct lyxml_context *xml_ctx, struct yin_arg_record **args, const char **data, const char **value)
+yin_parse_text_element(struct lyxml_context *xml_ctx, const char **data, const char **value)
{
LY_ERR ret = LY_SUCCESS;
- char *buf = NULL, *out = NULL;
- const char *prefix = NULL, *name = NULL;
- size_t buf_len = 0, out_len = 0, prefix_len = 0, name_len = 0;
- int dynamic = 0;
- if (xml_ctx->status == LYXML_ELEM_CONTENT) {
- ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
- LY_CHECK_RET(ret);
- if (dynamic) {
- *value = lydict_insert_zc(xml_ctx->ctx, buf);
- LY_CHECK_RET(!(*value), LY_EMEM);
- } else {
- *value = lydict_insert(xml_ctx->ctx, out, out_len);
- LY_CHECK_RET(!(*value), LY_EMEM);
- }
- }
+ ret = yin_parse_content(xml_ctx, NULL, 0, data, YIN_TEXT, value, NULL);
- LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
- /* probably should never happen, mixed content should be caught by lyxml_get_element call but
- * I will just leave it here for now to be sure */
- LY_CHECK_RET(name, LY_EVALID);
return ret;
}
/**
+ * @brief map keyword type to substatement info.
+ *
+ * @param[in] kw Keyword type.
+ * @param[out] sub Substatement info.
+ *
+ * @return LY_SUCCESS on success LY_EINVAL if kw can't be mapped.
+ */
+LY_ERR
+kw2lyext_substmt(enum yang_keyword kw, LYEXT_SUBSTMT *sub)
+{
+ switch (kw) {
+ case YANG_ORGANIZATION:
+ *sub = LYEXT_SUBSTMT_ORGANIZATION;
+ return LY_SUCCESS;
+ case YANG_CONTACT:
+ *sub = LYEXT_SUBSTMT_CONTACT;
+ return LY_SUCCESS;
+ case YANG_DESCRIPTION:
+ *sub = LYEXT_SUBSTMT_DESCRIPTION;
+ return LY_SUCCESS;
+ case YANG_REFERENCE:
+ *sub = LYEXT_SUBSTMT_REFERENCE;
+ return LY_SUCCESS;
+
+ default:
+ return LY_EINVAL;
+ }
+}
+
+/**
* @brief function to parse meta tags eg. elements with text element as child
*
* @param[in] xml_ctx Xml context.
- * @param[in] args Sized array of arguments of current elements.
+ * @param[in] args Sized array of arguments of current element.
* @param[in,out] data Data to read from.
* @param[out] value Where the content of meta tag should be stored.
*
* @return LY_ERR values.
*/
LY_ERR
-yin_parse_meta_element(struct lyxml_context *xml_ctx, struct yin_arg_record **args, const char **data, const char **value)
+yin_parse_meta_element(struct lyxml_context *xml_ctx, const char **data, enum yang_keyword elem_type,
+ const char **value, struct lysp_ext_instance **exts)
{
- LY_ERR ret = LY_SUCCESS;
- char *buf = NULL, *out = NULL;
- const char *prefix = NULL, *name = NULL;
- size_t buf_len = 0, out_len = 0, prefix_len = 0, name_len = 0;
- int dynamic = 0;
- enum YIN_ARGUMENT arg = YANG_NONE;
- struct yin_arg_record *subelem_args = NULL;
- enum yang_keyword kw = YANG_NONE;
+ assert(elem_type == YANG_ORGANIZATION || elem_type == YANG_CONTACT || elem_type == YANG_DESCRIPTION || elem_type == YANG_REFERENCE);
+ struct yin_ext_meta ext_info = {.subelem_index = 0};
+ struct yin_subelement subelems[2] = {{YIN_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
+ {YANG_CUSTOM, &ext_info, 0}};
+ /* set correct insubstmt info */
+ LY_CHECK_RET(kw2lyext_substmt(elem_type, &ext_info.subelem))
- LY_CHECK_ERR_RET(xml_ctx->status != LYXML_ELEM_CONTENT, LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Expected content of meta element."), LY_EVALID);
-
- ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
- LY_CHECK_ERR_RET(ret != LY_EINVAL, LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Expected \"text\" element as first child of meta element."), LY_EINVAL);
-
- /* first element should be argument element <text> */
- LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
- ret = yin_load_attributes(xml_ctx, data, &subelem_args);
- LY_CHECK_GOTO(ret, cleanup);
- arg = yin_match_argument_name(name, name_len);
- LY_CHECK_ERR_GOTO(arg != YIN_ARG_TEXT, LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Expected \"text\" element as first child of meta element.");
- ret = LY_EINVAL, cleanup);
- ret = yin_parse_text_element(xml_ctx, &subelem_args, data, value);
- LY_CHECK_GOTO(ret, cleanup);
-
- /* loop over all child elements and parse them */
- while (xml_ctx->status == LYXML_ELEMENT) {
- ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
- LY_CHECK_GOTO(ret, cleanup);
- ret = yin_load_attributes(xml_ctx, data, &subelem_args);
- LY_CHECK_GOTO(ret, cleanup);
- kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
-
- if (!name) {
- /* end of meta element reached */
- break;
- }
-
- switch (kw) {
- case YANG_CUSTOM:
- // TODO parse extension instance
- break;
-
- default:
- LOGERR(xml_ctx->ctx, LYVE_SYNTAX_YIN, "Unexpected child element \"%.*s\".", name_len, name);
- return LY_EVALID;
- }
- }
-
-cleanup:
- FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
- return ret;
+ return yin_parse_content(xml_ctx, subelems, 2, data, elem_type, NULL, exts);
}
-/**
- * @brief Parse revision date.
- *
- * @param[in] xml_ctx Xml context.
- * @param[in] args Sized array of arguments of current element.
- * @param[in,out] data Data to read from.
- * @param[in,out] rev Array to store the parsed value in.
- * @param[in,out] exts Extension instances to add to.
- *
- * @return LY_ERR values.
- */
-static LY_ERR
+LY_ERR
yin_parse_revision_date(struct lyxml_context *xml_ctx, struct yin_arg_record **args, const char **data, char *rev, struct lysp_ext_instance **exts)
{
LY_ERR ret = LY_SUCCESS;
- const char *temp_rev, *prefix = NULL, *name = NULL;
- char *out;
- struct yin_arg_record *subelem_args = NULL;
- size_t prefix_len = 0, name_len = 0;
- enum yang_keyword kw = YANG_NONE;
- int dynamic;
-
- if (rev[0]) {
- LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPSTMT, "revision-date");
- return LY_EVALID;
- }
+ const char *temp_rev;
+ struct yin_ext_meta ext_info = {LYEXT_SUBSTMT_REVISIONDATE, 0};
+ struct yin_subelement subelems[1] = {{YANG_CUSTOM, &ext_info, 0}};
LY_CHECK_RET(yin_parse_attribute(xml_ctx, args, YIN_ARG_DATE, &temp_rev))
LY_CHECK_RET(ret != LY_SUCCESS, ret);
@@ -649,121 +572,48 @@
strcpy(rev, temp_rev);
lydict_remove(xml_ctx->ctx, temp_rev);
- if (xml_ctx->status == LYXML_ELEM_CONTENT) {
- ret = lyxml_get_string(xml_ctx, data, &out, &name_len, &out, &name_len, &dynamic);
- /* unknown element text content is ignored */
- if (ret == LY_EINVAL) {
- while (xml_ctx->status == LYXML_ELEMENT) {
- ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
- LY_CHECK_GOTO(ret, cleanup);
- ret = yin_load_attributes(xml_ctx, data, &subelem_args);
- LY_CHECK_GOTO(ret, cleanup);
- kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
+ return yin_parse_content(xml_ctx, subelems, 1, data, YANG_REVISION_DATE, NULL, exts);
+}
- if (!name) {
- /* end of revisin-date element reached */
- break;
- }
+LY_ERR
+yin_parse_prefix(struct lyxml_context *xml_ctx, struct yin_arg_record *attrs, const char **prefix, const char **data, struct lysp_ext_instance **exts)
+{
+ struct yin_ext_meta ext_info = {LYEXT_SUBSTMT_PREFIX, 0};
+ struct yin_subelement subelems[1] = {{YANG_CUSTOM, &ext_info, 0}};
+ LY_CHECK_RET(yin_parse_attribute(xml_ctx, &attrs, YIN_ARG_VALUE, prefix));
- switch (kw) {
- case YANG_CUSTOM:
- // TODO parse extension instance
- break;
-
- default:
- LOGERR(xml_ctx->ctx, LYVE_SYNTAX_YIN, "Unexpected child element \"%.*s\".", name_len, name);
- return LY_EVALID;
- }
- }
- } else {
- /* load closing element */
- LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
- LY_CHECK_RET(name, LY_EINVAL);
- }
- }
-
-cleanup:
- FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
- return ret;
+ return yin_parse_content(xml_ctx, subelems, 1, data, YANG_REVISION_DATE, NULL, exts);
}
LY_ERR
yin_parse_import(struct lyxml_context *xml_ctx, struct yin_arg_record **import_args, const char *module_prefix, const char **data, struct lysp_import **imports)
{
- LY_ERR ret = LY_SUCCESS;
- enum yang_keyword kw;
struct lysp_import *imp;
- const char *prefix, *name;
- char *out;
- struct yin_arg_record *subelem_args = NULL;
- size_t prefix_len, name_len;
- int dynamic;
-
/* allocate new element in sized array for import */
- LY_ARRAY_NEW_GOTO(xml_ctx->ctx, *imports, imp, ret, validation_err);
+ LY_ARRAY_NEW_RET(xml_ctx->ctx, *imports, imp, LY_EMEM);
+
+ struct yin_ext_meta ext_info = {LYEXT_SUBSTMT_SELF, 0};
+ struct yin_subelement subelems[5] = {{YANG_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
+ {YANG_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
+ {YANG_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
+ {YANG_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
+ {YANG_CUSTOM, &ext_info, 0}};
/* parse import attributes */
- LY_CHECK_GOTO(yin_parse_attribute(xml_ctx, import_args, YIN_ARG_MODULE, &imp->name) != LY_SUCCESS, validation_err);
+ LY_CHECK_RET(yin_parse_attribute(xml_ctx, import_args, YIN_ARG_MODULE, &imp->name));
+ LY_CHECK_RET(yin_parse_content(xml_ctx, subelems, 5, data, YANG_IMPORT, NULL, &imp->exts));
+ LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)xml_ctx, *imports, module_prefix, &imp->prefix), LY_EVALID);
- ret = lyxml_get_string(xml_ctx, data, &out, &name_len, &out, &name_len, &dynamic);
- LY_CHECK_ERR_RET(ret != LY_EINVAL, LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Expected new element after import element"), LY_EINVAL);
-
- while (xml_ctx->status == LYXML_ELEMENT) {
- ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
- LY_CHECK_GOTO(ret, validation_err);
- if (!name) {
- /* end of import element reached */
- break;
- }
- LY_CHECK_GOTO(yin_load_attributes(xml_ctx, data, &subelem_args), validation_err);
- kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
-
- switch (kw) {
- case YANG_PREFIX:
- LY_CHECK_ERR_GOTO(imp->prefix, LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPSTMT, "prefix"), validation_err);
- LY_CHECK_GOTO(yin_parse_attribute(xml_ctx, &subelem_args, YIN_ARG_VALUE, &imp->prefix) != LY_SUCCESS, validation_err);
- LY_CHECK_GOTO(lysp_check_prefix((struct lys_parser_ctx *)xml_ctx, *imports, module_prefix, &imp->prefix) != LY_SUCCESS, validation_err);
- break;
- case YANG_DESCRIPTION:
- LY_CHECK_ERR_GOTO(imp->dsc, LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPSTMT, "description"), validation_err);
- LY_CHECK_GOTO(yin_parse_meta_element(xml_ctx, &subelem_args, data, &imp->dsc), validation_err);
- break;
- case YANG_REFERENCE:
- LY_CHECK_ERR_GOTO(imp->ref, LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPSTMT, "reference"), validation_err);
- LY_CHECK_GOTO(yin_parse_meta_element(xml_ctx, &subelem_args, data, &imp->ref), validation_err);
- break;
- case YANG_REVISION_DATE:
- LY_CHECK_GOTO(yin_parse_revision_date(xml_ctx, &subelem_args, data, imp->rev, &imp->exts), validation_err);
- break;
- case YANG_CUSTOM:
- /* TODO parse extension */
- break;
- default:
- LOGERR(xml_ctx->ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, "import");
- goto validation_err;
- }
- FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
- subelem_args = NULL;
- }
-
- LY_CHECK_ERR_GOTO(!imp->prefix, LOGVAL_PARSER(xml_ctx, LY_VCODE_MISSATTR, "prefix", "import"), validation_err);
- return ret;
-
-validation_err:
- FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
- return LY_EVALID;
+ return yin_parse_content(xml_ctx, subelems, 5, data, YANG_IMPORT, NULL, &imp->exts);
}
LY_ERR
yin_parse_status(struct lyxml_context *xml_ctx, struct yin_arg_record **status_args, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
{
- LY_ERR ret = LY_SUCCESS;
- enum yang_keyword kw = YANG_NONE;
- const char *value = NULL, *prefix = NULL, *name = NULL;
- char *out;
- size_t prefix_len = 0, name_len = 0, out_len = 0;
- int dynamic = 0;
- struct yin_arg_record *subelem_args = NULL;
+ const char *value = NULL;
+ struct yin_ext_meta ext_info = {LYEXT_SUBSTMT_STATUS, 0};
+ struct yin_subelement subelems[1] = {{YANG_CUSTOM, &ext_info, 0}};
+
if (*flags & LYS_STATUS_MASK) {
LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPELEM, "status");
return LY_EVALID;
@@ -783,64 +633,18 @@
}
lydict_remove(xml_ctx->ctx, value);
- /* TODO check if dynamic was set to 1 in case of error */
- if (xml_ctx->status == LYXML_ELEM_CONTENT) {
- ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
- /* if there are any xml subelements parse them, unknown text content is silently ignored */
- if (ret == LY_EINVAL) {
- /* load subelements */
- while (xml_ctx->status == LYXML_ELEMENT) {
- LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
- if (!name) {
- /* end of status reached */
- break;
- }
- ret = yin_load_attributes(xml_ctx, data, &subelem_args);
- LY_CHECK_GOTO(ret, cleanup);
- kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
- switch (kw) {
- case YANG_CUSTOM:
- /* TODO parse extension instance */
- break;
- default:
- LOGVAL_PARSER(xml_ctx, LY_VCODE_INCHILDSTMT_YIN, name_len, name, 6, "status");
- ret = LY_EVALID;
- goto cleanup;
- }
-
- FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
- subelem_args = NULL;
- }
- } else {
- /* load closing element */
- LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
- LY_CHECK_RET(name, LY_EINVAL);
- }
- }
-
- return ret;
-
-cleanup:
- FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
- return ret;
+ return yin_parse_content(xml_ctx, subelems, 1, data, YANG_STATUS, NULL, exts);
}
LY_ERR
-yin_parse_yin_element_element(struct lyxml_context *xml_ctx, struct yin_arg_record **attrs, const char **data, uint16_t *flags, struct lysp_ext **extensions)
+yin_parse_yin_element_element(struct lyxml_context *xml_ctx, struct yin_arg_record *attrs, const char **data,
+ uint16_t *flags, struct lysp_ext_instance **exts)
{
- LY_ERR ret = LY_SUCCESS;
- const char *temp_val = NULL, *name = NULL;
- size_t name_len = 0;
- struct yin_arg_record *subelem_args = NULL;
- enum yang_keyword kw = YANG_NONE;
- struct yin_arg_record temp_record;
+ const char *temp_val = NULL;
+ struct yin_ext_meta ext_info = {LYEXT_SUBSTMT_YINELEM, 0};
+ struct yin_subelement subelems[1] = {{YANG_CUSTOM, &ext_info, 0}};
- if (*flags & LYS_YINELEM_MASK) {
- LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPSTMT, "yin-element");
- return LY_EVALID;
- }
-
- LY_CHECK_RET(yin_parse_attribute(xml_ctx, attrs, YIN_ARG_VALUE, &temp_val));
+ LY_CHECK_RET(yin_parse_attribute(xml_ctx, &attrs, YIN_ARG_VALUE, &temp_val));
if (strcmp(temp_val, "true") == 0) {
*flags |= LYS_YINELEM_TRUE;
} else if (strcmp(temp_val, "false") == 0) {
@@ -852,27 +656,12 @@
}
lydict_remove(xml_ctx->ctx, temp_val);
- YIN_READ_SUBELEMS_START(xml_ctx, data, ret, cleanup, kw, temp_record, subelem_args);
- switch (kw) {
- case YANG_CUSTOM:
- // TODO parse extension instance
- break;
-
- default:
- LOGERR(xml_ctx->ctx, LYVE_SYNTAX_YIN, "Unexpected child element \"%.*s\".", name_len, name);
- return LY_EVALID;
- }
- YIN_READ_SUBELEMS_END(xml_ctx, data, temp_record);
-
-cleanup:
- FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
- return ret;
+ return yin_parse_content(xml_ctx, subelems, 1, data, YANG_YIN_ELEMENT, NULL, exts);
}
LY_ERR
-yin_parse_extension_instance(struct lyxml_context *xml_ctx, struct yin_arg_record **attrs, const char **data,
- const char *ext_name, int ext_name_len, LYEXT_SUBSTMT insubstmt,
- uint32_t insubstmt_index, struct lysp_ext_instance **exts)
+yin_parse_extension_instance(struct lyxml_context *xml_ctx, struct yin_arg_record **attrs, const char **data, const char *ext_name,
+ int ext_name_len, struct yin_ext_meta *metadata, struct lysp_ext_instance **exts)
{
LY_ERR ret = LY_SUCCESS;
char *out;
@@ -888,8 +677,8 @@
e->yin = 0;
/* store name and insubstmt info */
e->name = lydict_insert(xml_ctx->ctx, ext_name, ext_name_len);
- e->insubstmt = insubstmt;
- e->insubstmt_index = insubstmt_index;
+ e->insubstmt = metadata->subelem;
+ e->insubstmt_index = metadata->subelem_index;
e->yin |= LYS_YIN;
/* store attributes as subelements */
@@ -1042,104 +831,45 @@
return ret;
}
+/**
+ * @brief Parse argument element.
+ *
+ * @param[in,out] xml_ctx Xml context.
+ * @param[in] attrs Attributes of this element.
+ * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] arg_meta Meta information about destionation af prased data.
+ * @param[in,out] exts Extension instance to add to.
+ *
+ * @return LY_ERR values.
+ */
LY_ERR
yin_parse_argument_element(struct lyxml_context *xml_ctx, struct yin_arg_record **attrs, const char **data,
- uint16_t *flags, const char **argument, struct lysp_ext **extensions)
+ struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
{
- LY_ERR ret = LY_SUCCESS;
- const char *name = NULL;
- size_t name_len = 0;
- struct yin_arg_record *subelem_args = NULL;
- enum yang_keyword kw = YANG_NONE;
- struct yin_arg_record temp_record;
+ struct yin_ext_meta ext_info = {LYEXT_SUBSTMT_ARGUMENT, 0};
+ struct yin_subelement subelems[2] = {{YANG_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
+ {YANG_CUSTOM, &ext_info, 0}};
- LY_CHECK_RET(yin_parse_attribute(xml_ctx, attrs, YIN_ARG_NAME, argument));
+ LY_CHECK_RET(yin_parse_attribute(xml_ctx, attrs, YIN_ARG_NAME, arg_meta->argument));
- YIN_READ_SUBELEMS_START(xml_ctx, data, ret, cleanup, kw, temp_record, subelem_args);
- if (!name) {
- /* end of argument element reached */
- break;
- }
-
- switch (kw) {
- case YANG_YIN_ELEMENT:
- yin_parse_yin_element_element(xml_ctx, &subelem_args, data, flags, extensions);
- break;
- case YANG_CUSTOM:
- // TODO parse extension instance
- break;
-
- default:
- LOGERR(xml_ctx->ctx, LYVE_SYNTAX_YIN, "Unexpected child element \"%.*s\".", name_len, name);
- return LY_EVALID;
- }
- YIN_READ_SUBELEMS_END(xml_ctx, data, temp_record);
-
-cleanup:
- FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
- return ret;
+ return yin_parse_content(xml_ctx, subelems, 2, data, YANG_ARGUMENT, NULL, exts);
}
LY_ERR
yin_parse_extension(struct lyxml_context *xml_ctx, struct yin_arg_record **extension_args, const char **data, struct lysp_ext **extensions)
{
- LY_ERR ret = LY_SUCCESS;
struct lysp_ext *ex;
- const char *prefix = NULL, *name = NULL;
- char *out = NULL;
- size_t out_len = 0, prefix_len = 0, name_len = 0;
- int dynamic = 0;
- enum yang_keyword kw = YANG_NONE;
- struct yin_arg_record *subelem_args = NULL;
+ LY_ARRAY_NEW_RET(xml_ctx->ctx, *extensions, ex, LY_EMEM);
+ LY_CHECK_RET(yin_parse_attribute(xml_ctx, extension_args, YIN_ARG_NAME, &ex->name));
+ struct yin_ext_meta ext_info = {LYEXT_SUBSTMT_SELF, 0};
+ struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
+ struct yin_subelement subelems[5] = {{YANG_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
+ {YANG_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
+ {YANG_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
+ {YANG_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
+ {YANG_CUSTOM, &ext_info, 0}};
- LY_ARRAY_NEW_GOTO(xml_ctx->ctx, *extensions, ex, ret, cleanup);
- ret = yin_parse_attribute(xml_ctx, extension_args, YIN_ARG_NAME, &ex->name);
- LY_CHECK_GOTO(ret, cleanup);
- ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
- LY_CHECK_ERR_GOTO(ret != LY_EINVAL, LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Expected new element after extension element.");
- ret = LY_EINVAL, cleanup);
-
- while (xml_ctx->status == LYXML_ELEMENT) {
- ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
- LY_CHECK_GOTO(ret, cleanup);
- if (!name) {
- /* end of extension element reached */
- break;
- }
- ret = yin_load_attributes(xml_ctx, data, &subelem_args);
- LY_CHECK_GOTO(ret, cleanup);
- kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
- switch (kw) {
- case YANG_ARGUMENT:
- ret = yin_parse_argument_element(xml_ctx, &subelem_args, data, &ex->flags, &ex->argument, extensions);
- break;
- case YANG_DESCRIPTION:
- ret = yin_parse_meta_element(xml_ctx, &subelem_args, data, &ex->dsc);
- LY_CHECK_GOTO(ret, cleanup);
- break;
- case YANG_REFERENCE:
- ret = yin_parse_meta_element(xml_ctx, &subelem_args, data, &ex->ref);
- LY_CHECK_GOTO(ret, cleanup);
- break;
- case YANG_STATUS:
- ret = yin_parse_status(xml_ctx, &subelem_args, data, &ex->flags, &ex->exts);
- LY_CHECK_GOTO(ret, cleanup);
- break;
- case YANG_CUSTOM:
- /* TODO parse extension instance */
- break;
- default:
- LOGVAL_PARSER(xml_ctx, LY_VCODE_INCHILDSTMT_YIN, name_len, name, 9, "extension");
- ret = LY_EVALID;
- goto cleanup;
- }
- FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
- subelem_args = NULL;
- }
-
-cleanup:
- FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
- return ret;
+ return yin_parse_content(xml_ctx, subelems, 5, data, YANG_EXTENSION, NULL, &ex->exts);
}
/**
@@ -1252,19 +982,19 @@
/* meta */
case YANG_ORGANIZATION:
- ret = yin_parse_meta_element(xml_ctx, &substmt_args, data, &(*mod)->mod->org);
+ ret = yin_parse_meta_element(xml_ctx, data, YANG_ORGANIZATION, &(*mod)->mod->org, NULL);
LY_CHECK_GOTO(ret, error);
break;
case YANG_CONTACT:
- ret = yin_parse_meta_element(xml_ctx, &substmt_args, data, &(*mod)->mod->contact);
+ ret = yin_parse_meta_element(xml_ctx, data, YANG_CONTACT, &(*mod)->mod->contact, NULL);
LY_CHECK_GOTO(ret, error);
break;
case YANG_DESCRIPTION:
- ret = yin_parse_meta_element(xml_ctx, &substmt_args, data, &(*mod)->mod->dsc);
+ ret = yin_parse_meta_element(xml_ctx, data, YANG_DESCRIPTION, &(*mod)->mod->dsc, NULL);
LY_CHECK_GOTO(ret, error);
break;
case YANG_REFERENCE:
- ret = yin_parse_meta_element(xml_ctx, &substmt_args, data, &(*mod)->mod->ref);
+ ret = yin_parse_meta_element(xml_ctx, data, YANG_REFERENCE, &(*mod)->mod->ref, NULL);
LY_CHECK_GOTO(ret, error);
break;
/* revision */
diff --git a/src/parser_yin.h b/src/parser_yin.h
index 6d3af0f..86297f9 100644
--- a/src/parser_yin.h
+++ b/src/parser_yin.h
@@ -57,6 +57,34 @@
int dynamic_content; /**< is set to 1 iff content is dynamically allocated 0 otherwise */
};
+/* flags to encode cardinality of subelement */
+#define YIN_SUBELEM_MANDATORY 0x01 /**< is set when subelement is mandatory */
+#define YIN_SUBELEM_UNIQUE 0x02 /**< is set when subelement is unique */
+#define YIN_SUBELEM_PARSED 0x04 /**< is set during parsing when given subelement is encountered for the first
+ time to simply check validity of given constraints */
+
+struct yin_subelement {
+ enum yang_keyword type; /**< type of keyword */
+ void *dest; /**< meta infromation passed to responsible function (information about where parsed subelement should be stored) */
+ uint8_t flags; /**< describes carianlity of subelement can be set to YIN_SUBELEM_MANDATORY and YIN_SUBELEM_UNIQUE */
+};
+
+struct sized_string {
+ const char *value;
+ size_t len;
+};
+
+/** @brief meta information passed to yin_parse_ext */
+struct yin_ext_meta {
+ LYEXT_SUBSTMT subelem; /**< Type of this subelement */
+ uint32_t subelem_index; /**< Index of this current subelement */
+};
+
+struct yin_argument_meta {
+ uint16_t *flags; /**< */
+ const char **argument; /**< */
+};
+
/**
* @brief Match argument name.
*
@@ -68,6 +96,19 @@
enum YIN_ARGUMENT yin_match_argument_name(const char *name, size_t len);
/**
+ * @brief function to parse meta tags eg. elements with text element as child
+ *
+ * @param[in] xml_ctx Xml context.
+ * @param[in] args Sized array of arguments of current element.
+ * @param[in,out] data Data to read from.
+ * @param[out] value Where the content of meta tag should be stored.
+ *
+ * @return LY_ERR values.
+ */
+LY_ERR yin_parse_meta_element(struct lyxml_context *xml_ctx, const char **data, enum yang_keyword elem_type,
+ const char **value, struct lysp_ext_instance **exts);
+
+/**
* @brief Parse content of whole element as text.
*
* @param[in] xml_ctx Xml context.
@@ -77,8 +118,7 @@
*
* @return LY_ERR values.
*/
-LY_ERR yin_parse_text_element(struct lyxml_context *xml_ctx, struct yin_arg_record **args, const char **data,
- const char **value);
+LY_ERR yin_parse_text_element(struct lyxml_context *xml_ctx, const char **data, const char **value);
/**
* @brief Parse import element.
@@ -86,7 +126,7 @@
* @param[in] xml_ctx Xml context.
* @param[in] args Sized array of arguments of current element.
* @param[in] module_prefix Prefix of the module to check prefix collisions.
- * @param[in,out] data Dta to read from.
+ * @param[in,out] data Data to read from.
* @param[in,out] imports Parsed imports to add to.
*
* @return LY_ERR values.
@@ -122,7 +162,7 @@
uint16_t *flags, struct lysp_ext_instance **exts);
/**
- * @brief parse yin argument, arg_val is unchanged if argument arg_type wasn't found.
+ * @brief Parse yin argument, arg_val is unchanged if argument arg_type wasn't found.
*
* @param[in] xml_ctx XML parser context.
* @param[in,out] data Data to read from.
@@ -135,6 +175,34 @@
enum YIN_ARGUMENT arg_type, const char **arg_val);
/**
+ * @brief Parse prefix element.
+ *
+ * @param[in] xml_ctx Xml parser context.
+ * @param[in] attrs Attributes of prefix element.
+ * @param[in,out] prefix Where the value of prefix should be stored.
+ * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in] exts Extension instance to add to.
+ *
+ * @return LY_ERR values.
+ */
+LY_ERR yin_parse_prefix(struct lyxml_context *xml_ctx, struct yin_arg_record *attrs, const char **prefix,
+ const char **data, struct lysp_ext_instance **exts);
+
+/**
+ * @brief Parse revision date.
+ *
+ * @param[in] xml_ctx Xml context.
+ * @param[in] args Sized array of arguments of current element.
+ * @param[in,out] data Data to read from.
+ * @param[in,out] rev Array to store the parsed value in.
+ * @param[in,out] exts Extension instances to add to.
+ *
+ * @return LY_ERR values.
+ */
+LY_ERR yin_parse_revision_date(struct lyxml_context *xml_ctx, struct yin_arg_record **args, const char **data,
+ char *rev, struct lysp_ext_instance **exts);
+
+/**
* @brief Load all attributes from current element. Caller is supposed to free args array.
*
* @param[in,out] xml_ctx Xml context.
@@ -152,12 +220,26 @@
* @param[in] attrs Sized array of element attributes.
* @param[in,out] data Data to read from, always moved to currently handled position.
* @param[in,out] flags Flags to add to.
- * @prama[in,out] extensions Extension instance to add to.
+ * @prama[in,out] exts Extension instance to add to.
*
* @return LY_ERR values.
*/
-LY_ERR yin_parse_yin_element_element(struct lyxml_context *xml_ctx, struct yin_arg_record **attrs, const char **data,
- uint16_t *flags, struct lysp_ext **extensions);
+LY_ERR yin_parse_yin_element_element(struct lyxml_context *xml_ctx, struct yin_arg_record *attrs, const char **data,
+ uint16_t *flags, struct lysp_ext_instance **exts);
+
+/**
+ * @brief Parse argument element.
+ *
+ * @param[in,out] xml_ctx Xml context.
+ * @param[in] attrs Attributes of this element.
+ * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] arg_meta Meta information about destionation af prased data.
+ * @param[in,out] exts Extension instance to add to.
+ *
+ * @return LY_ERR values.
+ */
+LY_ERR yin_parse_argument_element(struct lyxml_context *xml_ctx, struct yin_arg_record **attrs, const char **data,
+ struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts);
/**
* @brief Parse the extension statement.
@@ -180,15 +262,13 @@
* @param[in,out] data Data to read from, always moved to currently handled character.
* @param[in] ext_name Name of the extension element.
* @param[in] ext_name_len Length of extension name.
- * @param[in] insubstmt Type of the parrent element.
- * @param[in] insubstmt_index Index of the keyword instance this extension instance is a substatement of.
- * @param[out] exts exts Extension instances to add to.
+ * @param[in,out] metadata Meta information about extension instance passed from caller function.
*
* @return LY_ERR values.
*/
LY_ERR yin_parse_extension_instance(struct lyxml_context *xml_ctx, struct yin_arg_record **attrs, const char **data,
- const char *ext_name, int ext_name_len, LYEXT_SUBSTMT insubstmt,
- uint32_t insubstmt_index, struct lysp_ext_instance **exts);
+ const char *ext_name, int ext_name_len, struct yin_ext_meta *metadata,
+ struct lysp_ext_instance **exts);
/**
* @brief Parse yin element into generic structure.