yin parser CHANGE generalize subelement parsing
diff --git a/src/parser_yin.c b/src/parser_yin.c
index 0b49741..8802267 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -17,6 +17,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
+#include <stdbool.h>
 
 #include "context.h"
 #include "dict.h"
@@ -265,6 +266,261 @@
     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.
+ *
+ * @param[in] type Type of wanted record.
+ * @param[in] array_size Size of array.
+ * @param[in] array Searched array.
+ *
+ * @return Pointer to desired record on success, NULL if element is not in the array.
+ */
+struct yin_subelement *
+get_record(enum yang_keyword type, size_t array_size, struct yin_subelement *array)
+{
+    for (size_t i = 0; i < array_size; ++i) {
+        if (array[i].type == type) {
+            return &array[i];
+        }
+    }
+
+    return NULL;
+}
+
+/**
+ * @brief Generic function for subelement 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_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.
+ *
+ * @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)
+{
+    LY_ERR ret = LY_SUCCESS;
+    struct sized_string prefix, name;
+    char *out;
+    size_t out_len;
+    int dynamic;
+    struct yin_arg_record *subelem_attrs;
+    enum yang_keyword kw = YANG_NONE;
+    struct yin_subelement *subeleme_info_rec;
+
+    if (xml_ctx->status == LYXML_ELEM_CONTENT) {
+        ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
+        /* current element has subelements as content */
+        if (ret == LY_EINVAL) {
+            while (xml_ctx->status == LYXML_ELEMENT) {
+                ret = lyxml_get_element(xml_ctx, data, &prefix.value, &prefix.len, &name.value, &name.len);
+                LY_CHECK_GOTO(ret, cleanup);
+                if (!name.value) {
+                    /* end of current element reached */
+                    break;
+                }
+                ret = yin_load_attributes(xml_ctx, data, &subelem_attrs);
+                LY_CHECK_GOTO(ret, cleanup);
+                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) {
+                    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 */
+
+                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);
+                    break;
+                case YANG_ACTION:
+                    break;
+                case YANG_ANYDATA:
+                    break;
+                case YANG_ANYXML:
+                    break;
+                case YANG_ARGUMENT:
+                    break;
+                case YANG_AUGMENT:
+                    break;
+                case YANG_BASE:
+                    break;
+                case YANG_BELONGS_TO:
+                    break;
+                case YANG_BIT:
+                    break;
+                case YANG_CASE:
+                    break;
+                case YANG_CHOICE:
+                    break;
+                case YANG_CONFIG:
+                    break;
+                case YANG_CONTACT:
+                    break;
+                case YANG_CONTAINER:
+                    break;
+                case YANG_DEFAULT:
+                    break;
+                case YANG_DESCRIPTION:
+                    break;
+                case YANG_DEVIATE:
+                    break;
+                case YANG_DEVIATION:
+                    break;
+                case YANG_ENUM:
+                    break;
+                case YANG_ERROR_APP_TAG:
+                    break;
+                case YANG_ERROR_MESSAGE:
+                    break;
+                case YANG_EXTENSION:
+                    break;
+                case YANG_FEATURE:
+                    break;
+                case YANG_FRACTION_DIGITS:
+                    break;
+                case YANG_GROUPING:
+                    break;
+                case YANG_IDENTITY:
+                    break;
+                case YANG_IF_FEATURE:
+                    break;
+                case YANG_IMPORT:
+                    break;
+                case YANG_INCLUDE:
+                    break;
+                case YANG_INPUT:
+                    break;
+                case YANG_KEY:
+                    break;
+                case YANG_LEAF:
+                    break;
+                case YANG_LEAF_LIST:
+                    break;
+                case YANG_LENGTH:
+                    break;
+                case YANG_LIST:
+                    break;
+                case YANG_MANDATORY:
+                    break;
+                case YANG_MAX_ELEMENTS:
+                    break;
+                case YANG_MIN_ELEMENTS:
+                    break;
+                case YANG_MODIFIER:
+                    break;
+                case YANG_MODULE:
+                    break;
+                case YANG_MUST:
+                    break;
+                case YANG_NAMESPACE:
+                    break;
+                case YANG_NOTIFICATION:
+                    break;
+                case YANG_ORDERED_BY:
+                    break;
+                case YANG_ORGANIZATION:
+                    break;
+                case YANG_OUTPUT:
+                    break;
+                case YANG_PATH:
+                    break;
+                case YANG_PATTERN:
+                    break;
+                case YANG_POSITION:
+                    break;
+                case YANG_PREFIX:
+                    break;
+                case YANG_PRESENCE:
+                    break;
+                case YANG_RANGE:
+                    break;
+                case YANG_REFERENCE:
+                    break;
+                case YANG_REFINE:
+                    break;
+                case YANG_REQUIRE_INSTANCE:
+                    break;
+                case YANG_REVISION:
+                    break;
+                case YANG_REVISION_DATE:
+                    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);
+                    break;
+                case YANG_SUBMODULE:
+                    break;
+                case YANG_TYPE:
+                    break;
+                case YANG_TYPEDEF:
+                    break;
+                case YANG_UNIQUE:
+                    break;
+                case YANG_UNITS:
+                    break;
+                case YANG_USES:
+                    break;
+                case YANG_VALUE:
+                    break;
+                case YANG_WHEN:
+                    break;
+                case YANG_YANG_VERSION:
+                    break;
+                case YANG_YIN_ELEMENT:
+                    break;
+                default:
+                    /* TODO specify special  */
+                    break;
+                }
+                FREE_ARRAY(xml_ctx, subelem_attrs, free_arg_rec);
+                subelem_attrs = NULL;
+            }
+        } else {
+            /* elements with text or none content */
+            /* save text content */
+            /* load closing element */
+            LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix.value, &prefix.len, &name.value, &name.len));
+        }
+    }
+
+cleanup:
+    FREE_ARRAY(xml_ctx, subelem_attrs, free_arg_rec);
+    return ret;
+}
+
 LY_ERR
 yin_parse_text_element(struct lyxml_context *xml_ctx, struct yin_arg_record **args, const char **data, const char **value)
 {