yin parser CHANGE add support for extension instances
diff --git a/src/parser_yin.c b/src/parser_yin.c
index d93e0df..a5321c2 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -59,7 +59,7 @@
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 yin-element element reached */\
+ /* end of element reached */\
break;\
}
/**
@@ -613,78 +613,19 @@
return ret;
}
-/**
- * @brief take attributes from sized_array of yin_arg_record and save them as linked list lysp_statement.
- *
- * @param[in] attributes sized arry of element attributes.
- * @param[out] elems linked list elements.
- *
- * @return LY_ERR values.
- */
-LY_ERR
-yin_save_attrs_as_subelems(struct lyxml_context *xml_ctx, struct yin_arg_record *attrs, struct lysp_stmt **elems)
-{
- LY_ERR ret = LY_SUCCESS;
- struct yin_arg_record *iter;
- struct lysp_stmt *new, *current, *temp;
-
- current = *elems;
- LY_ARRAY_FOR_ITER(attrs, struct yin_arg_record, iter) {
- if (iter->prefix_len == 0) {
- new = calloc(1, sizeof(*new));
- LY_CHECK_ERR_RET(new, LOGMEM(xml_ctx->ctx), LY_EMEM);
- temp = current;
- current = new;
- current->next = temp;
- new->flags |= LYS_YIN_ATTR;
- new->stmt = lydict_insert(xml_ctx->ctx, iter->name - iter->prefix_len + 1, iter->name_len + iter->prefix_len + 1);
- if (iter->dynamic_content) {
- new->arg = iter->content;
- new->arg = lydict_insert(xml_ctx->ctx, iter->content, iter->content_len);
- } else {
- new->arg = lydict_insert_zc(xml_ctx->ctx, iter->content);
- }
- }
- }
-
- *elems = new;
-
- return ret;
-}
-
-/**
- * @brief parse element and it's content into generic structure.
- *
- * @param[in,out] xml_ctx Xml context.
- * @param[in,out] data Data to read from, always moved to currently handled character.
- * @param[in] name Name of element.
- * @param[in] name_len Length of element name.
- *
- * @return LY_ERR values.
- */
-LY_ERR
-yin_parse_extension_subelem(struct lyxml_context *xml_ctx, const char **data, const char *name, size_t name_len)
-{
- LY_ERR ret = LY_SUCCESS;
- struct yin_arg_record *attributes;
-
- yin_load_attributes(xml_ctx, data, &attributes);
-
-
-
- return ret;
-}
-
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)
{
LY_ERR ret = LY_SUCCESS;
+ char *out;
+ const char *name, *prefix;
+ size_t out_len, prefix_len, name_len;
+ int dynamic;
struct lysp_ext_instance *e;
- struct yin_arg_record *iter, *subelem_args = NULL, temp_record;
- struct lysp_stmt *new, *current;
- enum yang_keyword kw = YANG_NONE;
+ struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
+ struct yin_arg_record *iter;
LY_ARRAY_NEW_RET(xml_ctx->ctx, *exts, e, LY_EMEM);
@@ -695,28 +636,149 @@
e->insubstmt_index = insubstmt_index;
e->yin |= LYS_YIN;
- current = e->child;
- LY_ARRAY_FOR_ITER(attrs, struct yin_arg_record, iter) {
- if (iter->prefix_len == 0) {
- new = calloc(1, sizeof(*new));
- LY_CHECK_ERR_RET(new, LOGMEM(xml_ctx->ctx), LY_EMEM);
- current->next = new;
- current = new;
- new->flags |= LYS_YIN_ATTR;
- new->stmt = lydict_insert(xml_ctx->ctx, iter->name - iter->prefix_len + 1, iter->name_len + iter->prefix_len + 1);
- if (iter->dynamic_content) {
- new->arg = iter->content;
- new->arg = lydict_insert(xml_ctx->ctx, iter->content, iter->content_len);
+ /* store attributes as subelements */
+ LY_ARRAY_FOR_ITER(*attrs, struct yin_arg_record, iter) {
+ if (!iter->prefix) {
+ new_subelem = calloc(1, sizeof(*new_subelem));
+ if (!e->child) {
+ e->child = new_subelem;
} else {
- new->arg = lydict_insert_zc(xml_ctx->ctx, iter->content);
+ last_subelem->next = new_subelem;
+ }
+ last_subelem = new_subelem;
+
+ last_subelem->flags |= LYS_YIN_ATTR;
+ last_subelem->stmt = lydict_insert(xml_ctx->ctx, iter->name, iter->name_len);
+ LY_CHECK_ERR_RET(!last_subelem->stmt, LOGMEM(xml_ctx->ctx), LY_EMEM);
+ if (iter->dynamic_content) {
+ last_subelem->arg = lydict_insert_zc(xml_ctx->ctx, iter->content);
+ LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(xml_ctx->ctx), LY_EMEM);
+ } else {
+ last_subelem->arg = lydict_insert(xml_ctx->ctx, iter->content, iter->content_len);
+ LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(xml_ctx->ctx), LY_EMEM);
}
}
}
- YIN_READ_SUBELEMS_START(xml_ctx, data, ret, cleanup, kw, temp_record, subelem_args);
- /* parse subelems */
- YIN_READ_SUBELEMS_END(xml_ctx, data, temp_record);
-cleanup:
+ if (xml_ctx->status == LYXML_ELEM_CONTENT) {
+ ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
+ if (ret == LY_EINVAL) {
+ 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 extension instance reached */
+ break;
+ }
+ LY_CHECK_RET(yin_parse_element_generic(xml_ctx, name, name_len, data, &new_subelem))
+ if (!e->child) {
+ e->child = new_subelem;
+ } else {
+ last_subelem->next = new_subelem;
+ }
+ last_subelem = new_subelem;
+ }
+ }
+ } else {
+ LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
+ LY_CHECK_RET(name, LY_EINVAL);
+ }
+
+ return LY_SUCCESS;
+}
+
+LY_ERR
+yin_parse_element_generic(struct lyxml_context *xml_ctx, const char *name, size_t name_len,
+ const char **data, struct lysp_stmt **element)
+{
+ LY_ERR ret = LY_SUCCESS;
+ const char *temp_prefix, *temp_name;
+ char *out = NULL;
+ size_t out_len, temp_name_len, prefix_len;
+ int dynamic;
+ struct yin_arg_record *subelem_args = NULL;
+ struct lysp_stmt *last = NULL, *new = NULL;
+
+ /* allocate new structure for element */
+ *element = calloc(1, sizeof(**element));
+ (*element)->stmt = lydict_insert(xml_ctx->ctx, name, name_len);
+ LY_CHECK_ERR_RET(!(*element)->stmt, LOGMEM(xml_ctx->ctx), LY_EMEM);
+
+ last = (*element)->child;
+ while(xml_ctx->status == LYXML_ATTRIBUTE) {
+ /* add new element to linked-list */
+ new = calloc(1, sizeof(*last));
+ LY_CHECK_ERR_GOTO(ret, LOGMEM(xml_ctx->ctx), err);
+ if (!(*element)->child) {
+ /* save first */
+ (*element)->child = new;
+ } else {
+ last->next = new;
+ }
+ last = new;
+
+ last->flags |= LYS_YIN_ATTR;
+ ret = lyxml_get_attribute(xml_ctx, data, &temp_prefix, &prefix_len, &temp_name, &temp_name_len);
+ LY_CHECK_GOTO(ret, err);
+ ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
+ LY_CHECK_GOTO(ret, err);
+ last->stmt = lydict_insert(xml_ctx->ctx, temp_name, temp_name_len);
+ LY_CHECK_ERR_GOTO(!last->stmt, LOGMEM(xml_ctx->ctx); ret = LY_EMEM, err);
+ /* attributes with prefix are ignored */
+ if (!temp_prefix) {
+ if (dynamic) {
+ last->arg = lydict_insert_zc(xml_ctx->ctx, out);
+ if (!last->arg) {
+ free(out);
+ LOGMEM(xml_ctx->ctx);
+ ret = LY_EMEM;
+ goto err;
+ }
+ } else {
+ last->arg = lydict_insert(xml_ctx->ctx, out, out_len);
+ LY_CHECK_ERR_GOTO(!last->arg, LOGMEM(xml_ctx->ctx); ret = LY_EMEM, err);
+ }
+ }
+ }
+
+ /* parse content of element */
+ ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
+ if (ret == LY_EINVAL) {
+ while (xml_ctx->status == LYXML_ELEMENT) {
+ /* parse subelements */
+ ret = lyxml_get_element(xml_ctx, data, &temp_prefix, &prefix_len, &name, &name_len);
+ LY_CHECK_GOTO(ret, err);
+ if (!name) {
+ /* end of element reached */
+ break;
+ }
+ ret = yin_parse_element_generic(xml_ctx, name, name_len, data, &last->next);
+ LY_CHECK_GOTO(ret, err);
+ last = last->next;
+ }
+ } else {
+ /* save element content */
+ if (dynamic) {
+ (*element)->arg = lydict_insert_zc(xml_ctx->ctx, out);
+ if (!(*element)->arg) {
+ free(out);
+ LOGMEM(xml_ctx->ctx);
+ ret = LY_EMEM;
+ goto err;
+ }
+ } else {
+ (*element)->arg = lydict_insert(xml_ctx->ctx, out, out_len);
+ LY_CHECK_ERR_GOTO(!(*element)->arg, LOGMEM(xml_ctx->ctx); ret = LY_EMEM, err);
+ }
+ /* read closing tag */
+ ret = lyxml_get_element(xml_ctx, data, &temp_prefix, &prefix_len, &temp_name, &temp_name_len);
+ LY_CHECK_GOTO(ret, err);
+ }
+
+ FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
+ return LY_SUCCESS;
+
+err:
+ FREE_ARRAY(xml_ctx, subelem_args, free_arg_rec);
return ret;
}
diff --git a/src/parser_yin.h b/src/parser_yin.h
index c3d9166..4bfa783 100644
--- a/src/parser_yin.h
+++ b/src/parser_yin.h
@@ -170,4 +170,37 @@
LY_ERR yin_parse_extension(struct lyxml_context *xml_ctx, struct yin_arg_record **extension_args,
const char **data, struct lysp_ext **extensions);
+/**
+ * @brief Parse instance of extension.
+ *
+ * @param[in,out] xml_ctx Xml context.
+ * @param[in] attrs Sized array of attributes.
+ * @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.
+ *
+ * @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);
+
+/**
+ * @brief Parse yin element into generic structure.
+ *
+ * @param[in,out] xml_ctx Xml context.
+ * @param[in] name Name of element.
+ * @param[in] name_len Length of elements Name.
+ * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[out] element Where the element structure should be stored.
+ *
+ * @return LY_ERR values.
+ */
+LY_ERR
+yin_parse_element_generic(struct lyxml_context *xml_ctx, const char *name, size_t name_len,
+ const char **data, struct lysp_stmt **element);
+
#endif /* LY_PARSER_YIN_H_*/
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 65321eb..22c6554 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -125,7 +125,7 @@
struct lysp_stmt *child; /**< list of the statement's substatements (linked list) */
uint16_t flags; /**< */
};
-#define LYS_YIN 0x1;
+#define LYS_YIN 0x1
/**
* @brief YANG extension instance
*/
diff --git a/tests/src/test_parser_yin.c b/tests/src/test_parser_yin.c
index 761cd93..01cd7c6 100644
--- a/tests/src/test_parser_yin.c
+++ b/tests/src/test_parser_yin.c
@@ -597,6 +597,72 @@
st->finished_correctly = true;
}
+static void
+test_yin_parse_element_generic(void **state)
+{
+ const char *prefix, *name;
+ struct state *st = *state;
+ struct lysp_ext_instance exts;
+ size_t prefix_len, name_len;
+ LY_ERR ret;
+
+ memset(&exts, 0, sizeof(exts));
+
+ const char *data = "<elem attr=\"value\">text_value</elem>";
+ lyxml_get_element(st->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
+ ret = yin_parse_element_generic(st->xml_ctx, name, name_len, &data, &exts.child);
+ assert_int_equal(ret, LY_SUCCESS);
+ assert_string_equal(exts.child->stmt, "elem");
+ assert_string_equal(exts.child->arg, "text_value");
+
+ assert_string_equal(exts.child->child->stmt, "attr");
+ assert_string_equal(exts.child->child->arg, "value");
+ assert_true(exts.child->child->flags & LYS_YIN_ATTR);
+
+ lysp_ext_instance_free(st->ctx, &exts);
+ st->finished_correctly = true;
+}
+
+static void
+test_yin_parse_extension_instance(void **state)
+{
+ LY_ERR ret;
+ struct state *st = *state;
+ const char *prefix, *name;
+ size_t prefix_len, name_len;
+ struct yin_arg_record *args = NULL;
+ struct lysp_ext_instance *exts = NULL;
+
+ const char *data = "<ext value1=\"test\" value=\"test2\"><subelem>text</subelem></ext>";
+ lyxml_get_element(st->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
+ yin_load_attributes(st->xml_ctx, &data, &args);
+ ret = yin_parse_extension_instance(st->xml_ctx, &args, &data, name, name_len, LYEXT_SUBSTMT_CONTACT, 0, &exts);
+ assert_int_equal(ret, LY_SUCCESS);
+ assert_string_equal(exts->name, "ext");
+ assert_int_equal(exts->insubstmt_index, 0);
+ assert_true(exts->insubstmt == LYEXT_SUBSTMT_CONTACT);
+ assert_true(exts->yin & LYS_YIN);
+ assert_string_equal(exts->child->stmt, "value1");
+ assert_string_equal(exts->child->arg, "test");
+ assert_null(exts->child->child);
+ assert_true(exts->child->flags & LYS_YIN_ATTR);
+ assert_string_equal(exts->child->next->stmt, "value");
+ assert_string_equal(exts->child->next->arg, "test2");
+ assert_null(exts->child->next->child);
+ assert_true(exts->child->next->flags & LYS_YIN_ATTR);
+
+ assert_string_equal(exts->child->next->next->stmt, "subelem");
+ assert_string_equal(exts->child->next->next->arg, "text");
+ assert_null(exts->child->next->next->child);
+ assert_null(exts->child->next->next->next);
+ assert_false(exts->child->next->next->flags & LYS_YIN_ATTR);
+ assert_int_equal(st->xml_ctx->status, LYXML_END);
+ LY_ARRAY_FREE(args);
+ lysp_ext_instance_free(st->ctx, exts);
+ LY_ARRAY_FREE(exts);
+ st->finished_correctly = true;
+}
+
int
main(void)
{
@@ -610,6 +676,8 @@
cmocka_unit_test_setup_teardown(test_yin_match_keyword, setup_f, teardown_f),
cmocka_unit_test_setup_teardown(test_yin_parse_extension, setup_f, teardown_f),
cmocka_unit_test_setup_teardown(test_yin_parse_yin_element_element, setup_f, teardown_f),
+ cmocka_unit_test_setup_teardown(test_yin_parse_element_generic, setup_f, teardown_f),
+ cmocka_unit_test_setup_teardown(test_yin_parse_extension_instance, setup_f, teardown_f),
cmocka_unit_test(test_yin_match_argument_name),
};