yin parser REFACTOR use function to parse yin attributes
diff --git a/src/parser_yin.c b/src/parser_yin.c
index b375c71..4f1df88 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -23,9 +23,9 @@
#include "tree_schema_internal.h"
enum YIN_ARGUMENT {
- YIN_ARG_NONE = 0, /**< unrecognized argument */
+ YIN_ARG_UNKNOWN = 0, /**< parsed argument can not be matched with any known yin argument keyword */
YIN_ARG_NAME, /**< argument name */
- YIN_ARG_TARGET_NODE, /**<argument target-node */
+ YIN_ARG_TARGET_NODE, /**< argument target-node */
YIN_ARG_MODULE, /**< argument module */
YIN_ARG_VALUE, /**< argument value */
YIN_ARG_TEXT, /**< argument text */
@@ -34,6 +34,7 @@
YIN_ARG_DATE, /**< argument data */
YIN_ARG_TAG, /**< argument tag */
YIN_ARG_XMLNS, /**< argument xmlns */
+ YIN_ARG_NONE, /**< special value to specify no valid argument except xmlns, do not confuse with YIN_ARG_NONE */
};
/**
@@ -47,9 +48,9 @@
enum YIN_ARGUMENT
match_argument_name(const char *name, size_t len)
{
- enum YIN_ARGUMENT arg = YIN_ARG_NONE;
+ enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
size_t already_read = 0;
- LY_CHECK_RET(len == 0, YIN_ARG_NONE);
+ LY_CHECK_RET(len == 0, YIN_ARG_UNKNOWN);
#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
@@ -102,7 +103,7 @@
/* whole argument must be matched */
if (already_read != len) {
- arg = YIN_ARG_NONE;
+ arg = YIN_ARG_UNKNOWN;
}
#undef IF_ARG
@@ -136,6 +137,58 @@
}
/**
+ * @brief parse yin argument and xmlns definition
+ *
+ * @param[in] xml_ctx XML parser context.
+ * @param[in, out] data Data to read from.
+ * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without special arguments).
+ * @param[out] arg_val Where value of argument should be stored. Can be NULL if arg_type is spedified as YIN_ARG_NONE.
+ * @param[in] elem_name Name of currently parse element, used to create namespace scoping
+ */
+static LY_ERR
+yin_parse_attribute(struct lyxml_context *xml_ctx, const char **data, enum YIN_ARGUMENT arg_type, const char **arg_val, char *elem_name)
+{
+ LY_ERR ret = LY_SUCCESS;
+ const char *prefix, *name;
+ size_t prefix_len, name_len;
+
+ char *buf = NULL, *out = NULL;
+ size_t buf_len = 0, out_len = 0;
+ int dynamic;
+ enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
+
+ while (xml_ctx->status == LYXML_ATTRIBUTE) {
+ ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
+ LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
+
+ arg = match_argument_name(name, name_len);
+
+ if (arg == YIN_ARG_XMLNS) {
+ parse_xmlns(xml_ctx, data, prefix, prefix_len, elem_name);
+ } else if (arg == arg_type) {
+ LY_CHECK_RET(ret);
+ ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
+ LY_CHECK_RET(ret);
+ *arg_val = lydict_insert(xml_ctx->ctx, out, out_len);
+ LY_CHECK_ERR_RET(!(*arg_val), LOGMEM(xml_ctx->ctx), LY_EMEM);
+ } else {
+ /* unrecognized attribute, still can be namespace definition eg. xmlns:foo=.... */
+ /* TODO this might be extension and not ns definition */
+ if (match_argument_name(prefix, prefix_len) == YIN_ARG_XMLNS) {
+ /* in this case prefix of namespace is actually name of attribute */
+ parse_xmlns(xml_ctx, data, name, name_len, elem_name);
+ } else {
+ /* unrecognized or unexpected attribute */
+ LOGERR(xml_ctx->ctx, LY_EDENIED, "Invalid argument in namespace element");
+ return LY_EVALID;
+ }
+ }
+ }
+
+ return LY_SUCCESS;
+}
+
+/**
* @brief Parse content of whole element as text.
*
* @param[in] xml_ctx Xml context.
@@ -148,35 +201,12 @@
{
LY_ERR ret = LY_SUCCESS;
char *buf = NULL, *out = NULL;
- size_t buf_len = 0, out_len = 0;
+ size_t buf_len = 0, out_len = 0, prefix_len, name_len;
int dynamic;
- enum YIN_ARGUMENT arg = YIN_ARG_NONE;
-
const char *prefix, *name;
- size_t prefix_len, name_len;
- /* parse module attributes */
- while (xml_ctx->status == LYXML_ATTRIBUTE) {
- ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
- LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
-
- arg = match_argument_name(name, name_len);
- if (arg) {
- parse_xmlns(xml_ctx, data, prefix, prefix_len, "module");
- } else {
- /* unrecognized attribute, still can be namespace definition eg. xmlns:foo=.... */
- if (match_argument_name(prefix, prefix_len) == YIN_ARG_XMLNS) {
- /* in this case prefix of namespace is actually name of attribute */
- parse_xmlns(xml_ctx, data, name, name_len, "module");
- } else {
- /* unrecognized or unexpected attribute */
- LOGERR(xml_ctx->ctx, LY_EDENIED, "Invalid argument in module element");
- return LY_EVALID;
- }
- break;
- }
- }
-
+ ret = yin_parse_attribute(xml_ctx, data, YIN_ARG_NONE, NULL, element_name);
+ LY_CHECK_RET(ret != LY_SUCCESS, ret);
LY_CHECK_RET(xml_ctx->status != LYXML_ELEM_CONTENT, LY_EVALID);
if (xml_ctx->status == LYXML_ELEM_CONTENT) {
@@ -258,99 +288,15 @@
parse_namespace(struct lyxml_context *xml_ctx, const char **data, struct lysp_module **mod)
{
LY_ERR ret = LY_SUCCESS;
- const char *prefix, *name;
- size_t prefix_len, name_len;
- char *buf = NULL, *out = NULL;
- size_t buf_len = 0, out_len = 0;
- int dynamic;
- enum YIN_ARGUMENT arg = YIN_ARG_NONE;
-
- /* parse namespace attributes */
- while (xml_ctx->status == LYXML_ATTRIBUTE) {
- ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
- LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
-
- arg = match_argument_name(name, name_len);
-
- switch (arg) {
- case YIN_ARG_XMLNS:
- parse_xmlns(xml_ctx, data, prefix, prefix_len, "namespace");
- break;
- case YIN_ARG_URI:
- LY_CHECK_RET(ret);
- if (match_argument_name(name, name_len) != YIN_ARG_URI) {
- LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Invalid argument name \"%s\", expected \"uri\".", name);
- return LY_EVALID;
- }
- ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
- LY_CHECK_RET(ret);
- (*mod)->mod->ns = lydict_insert(xml_ctx->ctx, out, out_len);
- LY_CHECK_ERR_RET(!(*mod)->mod->ns, LOGMEM(xml_ctx->ctx), LY_EMEM);
- break;
- default:
- /* unrecognized attribute, still can be namespace definition eg. xmlns:foo=.... */
- if (match_argument_name(prefix, prefix_len) == YIN_ARG_XMLNS) {
- /* in this case prefix of namespace is actually name of attribute */
- parse_xmlns(xml_ctx, data, name, name_len, "namespace");
- } else {
- /* unrecognized or unexpected attribute */
- LOGERR(xml_ctx->ctx, LY_EDENIED, "Invalid argument in namespace element");
- return LY_EVALID;
- }
- break;
- }
- }
+ ret = yin_parse_attribute(xml_ctx, data, YIN_ARG_URI, &((*mod)->mod->ns), "namespace");
+ LY_CHECK_RET(ret != LY_SUCCESS, ret);
/* remove local xmlns definitions */
lyxml_ns_rm(xml_ctx, "namespace");
return LY_SUCCESS;
}
-static LY_ERR
-yin_parse_arguments(struct lyxml_context *xml_ctx, const char **data, enum YIN_ARGUMENT arg_type, const char **arg_val, char *elem_name)
-{
- LY_ERR ret = LY_SUCCESS;
- const char *prefix, *name;
- size_t prefix_len, name_len;
-
- char *buf = NULL, *out = NULL;
- size_t buf_len = 0, out_len = 0;
- int dynamic;
- enum YIN_ARGUMENT arg = YIN_ARG_NONE;
-
- while (xml_ctx->status == LYXML_ATTRIBUTE) {
- ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
- LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
-
- arg = match_argument_name(name, name_len);
-
- if (arg == YIN_ARG_XMLNS) {
- parse_xmlns(xml_ctx, data, prefix, prefix_len, elem_name);
- break;
- } else if (arg == arg_type) {
- LY_CHECK_RET(ret);
- ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
- LY_CHECK_RET(ret);
- *arg_val = lydict_insert(xml_ctx->ctx, out, out_len);
- LY_CHECK_ERR_RET(!(*arg_val), LOGMEM(xml_ctx->ctx), LY_EMEM);
- break;
- } else {
- /* unrecognized attribute, still can be namespace definition eg. xmlns:foo=.... */
- if (match_argument_name(prefix, prefix_len) == YIN_ARG_XMLNS) {
- /* in this case prefix of namespace is actually name of attribute */
- parse_xmlns(xml_ctx, data, name, name_len, elem_name);
- } else {
- /* unrecognized or unexpected attribute */
- LOGERR(xml_ctx->ctx, LY_EDENIED, "Invalid argument in namespace element");
- return LY_EVALID;
- }
- }
- }
-
- return LY_SUCCESS;
-}
-
/**
* @brief Parse prefix statement.
*
@@ -366,7 +312,7 @@
LY_ERR ret = LY_SUCCESS;
/* parse attributes */
- ret = yin_parse_arguments(xml_ctx, data, YIN_ARG_VALUE, &(*mod)->mod->prefix, "prefix");
+ ret = yin_parse_attribute(xml_ctx, data, YIN_ARG_VALUE, &(*mod)->mod->prefix, "prefix");
LY_CHECK_RET(ret != LY_SUCCESS, ret);
/* remove local xmlns definitions */
ret = lyxml_ns_rm(xml_ctx, "prefix");
@@ -392,47 +338,9 @@
char *buf = NULL, *out = NULL;
size_t buf_len = 0, out_len = 0;
int dynamic;
- enum YIN_ARGUMENT arg = YIN_ARG_NONE;
- /* TODO fix attribute parsing and yin_parse_revision_date function */
- /* valid attributes module, xmlns */
- /* parse import attributes */
- while (xml_ctx->status == LYXML_ATTRIBUTE) {
- ret = lyxml_get_attribute(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
- LY_CHECK_ERR_RET(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), LY_EMEM);
-
- arg = match_argument_name(name, name_len);
-
- switch (arg) {
- case YIN_ARG_XMLNS:
- parse_xmlns(xml_ctx, data, prefix, prefix_len, "prefix");
- break;
- case YIN_ARG_MODULE:
- LY_CHECK_RET(ret);
- if (match_argument_name(name, name_len) != YIN_ARG_VALUE) {
- LOGVAL(xml_ctx->ctx, LY_VLOG_LINE, &xml_ctx->line, LYVE_SYNTAX, "Invalid argument name \"%s\", expected \"value\".", name);
- return LY_EVALID;
- }
- ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
- LY_CHECK_RET(ret);
- (*mod)->mod->prefix = lydict_insert(xml_ctx->ctx, out, out_len);
- LY_CHECK_ERR_RET(!(*mod)->mod->ns, LOGMEM(xml_ctx->ctx), LY_EMEM);
- break;
- default:
- /* unrecognized attribute, still can be namespace definition eg. xmlns:foo=.... */
- if (match_argument_name(prefix, prefix_len) == YIN_ARG_XMLNS) {
- /* in this case prefix of namespace is actually name of attribute */
- parse_xmlns(xml_ctx, data, name, name_len, "prefix");
- } else {
- /* unrecognized or unexpected attribute */
- LOGERR(xml_ctx->ctx, LY_EDENIED, "Invalid argument in prefix element");
- return LY_EVALID;
- }
- break;
- }
- }
-
-
+ /* parse import attributes */
+ ret = yin_parse_attribute(xml_ctx, data, YIN_ARG_MODULE, &(*mod)->mod->prefix, "import");
/* valid subelements description, prefix, reference, revision-data */
/* allocate sized array for imports */
@@ -474,6 +382,7 @@
/* TODO add log macro and log error */
LY_CHECK_RET(!imp->prefix);
+ ret = lyxml_ns_rm(xml_ctx, "import");
return ret;
}
@@ -494,7 +403,7 @@
const char *prefix, *name;
size_t prefix_len, name_len;
enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
- enum YIN_ARGUMENT arg = YIN_ARG_NONE;
+ enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
char *buf = NULL, *out = NULL;
size_t buf_len = 0, out_len = 0;
diff --git a/tests/src/test_parser_yin.c b/tests/src/test_parser_yin.c
index 4853f8d..deb6645 100644
--- a/tests/src/test_parser_yin.c
+++ b/tests/src/test_parser_yin.c
@@ -73,7 +73,7 @@
xmlns:foo=\"urn:example:foo\"\
xmlns:myext=\"urn:example:extensions\">\
<namespace uri=\"urn:example:foo\" xmlns:myext=\"urn:example:extensions\"/>\
- <prefix value=\"foo\"/>\
+ <prefix xmlns:myxt=\"urn:emple:extensions\" value=\"foo\" xmlns:myext=\"urn:example:extensions\"/>\
</module>",
st->mod);
@@ -165,9 +165,9 @@
{
(void)state; /* unused */
- assert_int_equal(match_argument_name("", 5), YIN_ARG_NONE);
- assert_int_equal(match_argument_name("qwertyasd", 5), YIN_ARG_NONE);
- assert_int_equal(match_argument_name("conditionasd", 8), YIN_ARG_NONE);
+ assert_int_equal(match_argument_name("", 5), YIN_ARG_UNKNOWN);
+ assert_int_equal(match_argument_name("qwertyasd", 5), YIN_ARG_UNKNOWN);
+ assert_int_equal(match_argument_name("conditionasd", 8), YIN_ARG_UNKNOWN);
assert_int_equal(match_argument_name("condition", 9), YIN_ARG_CONDITION);
assert_int_equal(match_argument_name("date", 4), YIN_ARG_DATE);
assert_int_equal(match_argument_name("module", 6), YIN_ARG_MODULE);
@@ -186,14 +186,14 @@
struct state *st = *state;
ret = yin_parse_module(st->ctx,"<module name=\"example-foo\">\
- <organization xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">organiz<ation...</organization>\
+ <organization xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">organization...</organization>\
<contact>contact...</contact>\
<description>description...</description>\
<reference>reference...</reference>\
</module>", st->mod);
assert_int_equal(ret, LY_SUCCESS);
- assert_string_equal(st->mod->parsed->mod->org, "organiz<ation...");
+ assert_string_equal(st->mod->parsed->mod->org, "organization...");
assert_string_equal(st->mod->parsed->mod->contact, "contact...");
assert_string_equal(st->mod->parsed->mod->dsc, "description...");
assert_string_equal(st->mod->parsed->mod->ref, "reference...");