yin parser CHANGE validate argument value according to its type
helpful functions and macros were moved from yang_parser and are used also in yin parser.
diff --git a/src/parser_yang.c b/src/parser_yang.c
index 42eb69d..5489051 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -31,18 +31,6 @@
 #include "tree_schema.h"
 #include "tree_schema_internal.h"
 
-/* Macro to check YANG's yang-char grammar rule */
-#define is_yangutf8char(c) ((c >= 0x20 && c <= 0xd77) || c == 0x09 || c == 0x0a || c == 0x0d || \
-        (c >= 0xe000 && c <= 0xfdcf) || (c >= 0xfdf0 && c <= 0xfffd) || \
-        (c >= 0x10000 && c <= 0x1fffd) || (c >= 0x20000 && c <= 0x2fffd) || \
-        (c >= 0x30000 && c <= 0x3fffd) || (c >= 0x40000 && c <= 0x2fffd) || \
-        (c >= 0x50000 && c <= 0x5fffd) || (c >= 0x60000 && c <= 0x6fffd) || \
-        (c >= 0x70000 && c <= 0x7fffd) || (c >= 0x80000 && c <= 0x8fffd) || \
-        (c >= 0x90000 && c <= 0x9fffd) || (c >= 0xa0000 && c <= 0xafffd) || \
-        (c >= 0xb0000 && c <= 0xbfffd) || (c >= 0xc0000 && c <= 0xcfffd) || \
-        (c >= 0xd0000 && c <= 0xdfffd) || (c >= 0xe0000 && c <= 0xefffd) || \
-        (c >= 0xf0000 && c <= 0xffffd) || (c >= 0x100000 && c <= 0x10fffd))
-
 /**
  * @brief Try to find object with MEMBER string matching the IDENT in the given ARRAY.
  * Macro logs an error message and returns LY_EVALID in case of existence of a matching object.
@@ -169,62 +157,6 @@
 }
 
 /**
- * @brief Check that \p c is valid UTF8 code point for YANG string.
- *
- * @param[in] ctx yang parser context for logging.
- * @param[in] c UTF8 code point of a character to check.
- * @return LY_ERR values.
- */
-static LY_ERR
-check_stringchar(struct lys_parser_ctx *ctx, unsigned int c)
-{
-    if (!is_yangutf8char(c)) {
-        LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, c);
-        return LY_EVALID;
-    }
-    return LY_SUCCESS;
-}
-
-/**
- * @brief Check that \p c is valid UTF8 code point for YANG identifier.
- *
- * @param[in] ctx yang parser context for logging.
- * @param[in] c UTF8 code point of a character to check.
- * @param[in] first Flag to check the first character of an identifier, which is more restricted.
- * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
- * 0 - colon not yet found (no prefix)
- * 1 - \p c is the colon character
- * 2 - prefix already processed, now processing the identifier
- *
- * If the identifier cannot be prefixed, NULL is expected.
- * @return LY_ERR values.
- */
-LY_ERR
-check_identifierchar(struct lys_parser_ctx *ctx, unsigned int c, int first, int *prefix)
-{
-    if (first || (prefix && (*prefix) == 1)) {
-        if (!is_yangidentstartchar(c)) {
-            LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
-            return LY_EVALID;
-        }
-        if (prefix) {
-            if (first) {
-                (*prefix) = 0;
-            } else {
-                (*prefix) = 2;
-            }
-        }
-    } else if (c == ':' && prefix && (*prefix) == 0) {
-        (*prefix) = 1;
-    } else if (!is_yangidentchar(c)) {
-        LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
-        return LY_EVALID;
-    }
-
-    return LY_SUCCESS;
-}
-
-/**
  * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
  *
  * @param[in] ctx yang parser context for logging.
@@ -265,14 +197,14 @@
     /* check character validity */
     switch (arg) {
     case Y_IDENTIF_ARG:
-        LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), NULL));
+        LY_CHECK_RET(lysp_check_identifierchar(ctx, c, !(*word_len), NULL));
         break;
     case Y_PREF_IDENTIF_ARG:
-        LY_CHECK_RET(check_identifierchar(ctx, c, !(*word_len), &prefix));
+        LY_CHECK_RET(lysp_check_identifierchar(ctx, c, !(*word_len), &prefix));
         break;
     case Y_STR_ARG:
     case Y_MAYBE_STR_ARG:
-        LY_CHECK_RET(check_stringchar(ctx, c));
+        LY_CHECK_RET(lysp_check_stringchar(ctx, c));
         break;
     }
 
@@ -809,7 +741,7 @@
                              LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
             ++ctx->indent;
             /* check character validity */
-            LY_CHECK_RET(check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
+            LY_CHECK_RET(lysp_check_identifierchar(ctx, c, *data - len == word_start ? 1 : 0, &prefix));
         }
         if (!**data) {
             LOGVAL_PARSER(ctx, LY_VCODE_EOF);
diff --git a/src/parser_yin.c b/src/parser_yin.c
index b1de36f..dfbba27 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -193,13 +193,44 @@
     return ret;
 }
 
+LY_ERR
+yin_validate_value(struct yin_parser_ctx *ctx, enum yang_arg val_type, char *val, size_t len)
+{
+    int prefix = 0;
+    unsigned int c;
+    size_t utf8_char_len;
+    size_t already_read = 0;
+    while (already_read < len) {
+        LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
+                         LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
+        already_read += utf8_char_len;
+        LY_CHECK_ERR_RET(already_read > len, LOGINT(ctx->xml_ctx.ctx), LY_EINT);
+
+        switch (val_type) {
+        case Y_IDENTIF_ARG:
+            LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, NULL));
+            break;
+        case Y_PREF_IDENTIF_ARG:
+            LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, &prefix));
+            break;
+        case Y_STR_ARG:
+        case Y_MAYBE_STR_ARG:
+            LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
+            break;
+        }
+    }
+
+    return LY_SUCCESS;
+}
+
 /**
  * @brief Parse yin argument.
  *
  * @param[in,out] ctx Yin parser context for logging and to store current state.
  * @param[in] attrs ([Sized array](@ref sizedarrays)) of attributes.
  * @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 argument).
+ * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
+ *            special argument).
  * @param[out] arg_val Where value of argument should be stored. Can be NULL if arg_type is specified as YIN_ARG_NONE.
  * @param[in] val_type Type of expected value of attribute.
  * @param[in] current_element Identification of current element, used for logging.
@@ -225,6 +256,7 @@
                 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Duplicit definition of %s attribute in %s element",
                                  yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
                 found = true;
+                LY_CHECK_RET(yin_validate_value(ctx, val_type, iter->content, iter->content_len));
                 if (iter->dynamic_content) {
                     *arg_val = lydict_insert_zc(ctx->xml_ctx.ctx, iter->content);
                     LY_CHECK_RET(!(*arg_val), LY_EMEM);
@@ -247,8 +279,6 @@
         return LY_EVALID;
     }
 
-    /* TODO check validity according to val_type */
-
     return LY_SUCCESS;
 }
 
diff --git a/src/parser_yin.h b/src/parser_yin.h
index b4ef46b..d4e22bf 100644
--- a/src/parser_yin.h
+++ b/src/parser_yin.h
@@ -71,7 +71,7 @@
 
 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) */
+    void *dest;             /**< meta infromation passed to responsible function (mostly information about where parsed subelement should be stored) */
     uint8_t flags;          /**< describes cardianlity of subelement can be set to YIN_SUBELEM_MANDATORY and YIN_SUBELEM_UNIQUE and YIN_SUBELEM_FIRST */
 };
 
@@ -131,6 +131,19 @@
                              struct lysp_ext_instance **exts);
 
 /**
+ * @brief Check that val is valid UTF8 character sequence of val_type.
+ *        Doesn't check empty string, only character validity.
+ *
+ * @param[in] ctx Yin parser context for logging.
+ * @param[in] val_type Type of the input string to select method of checking character validity.
+ * @param[in] val Input to validate.
+ * @param[in] len Length of input.
+ *
+ * @return LY_ERR values.
+ */
+LY_ERR yin_validate_value(struct yin_parser_ctx *ctx, enum yang_arg val_type, char *val, size_t len);
+
+/**
  * @brief Parse import element.
  *
  * @param[in,out] ctx Yin parser context for logging and to store current state.
diff --git a/src/tree_schema_helpers.c b/src/tree_schema_helpers.c
index 8cfdbc7..c367f96 100644
--- a/src/tree_schema_helpers.c
+++ b/src/tree_schema_helpers.c
@@ -796,6 +796,41 @@
 }
 
 LY_ERR
+lysp_check_stringchar(struct lys_parser_ctx *ctx, unsigned int c)
+{
+    if (!is_yangutf8char(c)) {
+        LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, c);
+        return LY_EVALID;
+    }
+    return LY_SUCCESS;
+}
+
+LY_ERR
+lysp_check_identifierchar(struct lys_parser_ctx *ctx, unsigned int c, int first, int *prefix)
+{
+    if (first || (prefix && (*prefix) == 1)) {
+        if (!is_yangidentstartchar(c)) {
+            LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '%c'.", c);
+            return LY_EVALID;
+        }
+        if (prefix) {
+            if (first) {
+                (*prefix) = 0;
+            } else {
+                (*prefix) = 2;
+            }
+        }
+    } else if (c == ':' && prefix && (*prefix) == 0) {
+        (*prefix) = 1;
+    } else if (!is_yangidentchar(c)) {
+        LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Invalid identifier character '%c'.", c);
+        return LY_EVALID;
+    }
+
+    return LY_SUCCESS;
+}
+
+LY_ERR
 lysp_load_submodule(struct lys_parser_ctx *ctx, struct lysp_module *mod, struct lysp_include *inc)
 {
     struct lysp_submodule *submod = NULL;
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index 5720e65..813dede 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -27,6 +27,18 @@
 #define is_yangidentchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || \
         c == '_' || c == '-' || c == '.')
 
+/* Macro to check YANG's yang-char grammar rule */
+#define is_yangutf8char(c) ((c >= 0x20 && c <= 0xd77) || c == 0x09 || c == 0x0a || c == 0x0d || \
+                            (c >= 0xe000 && c <= 0xfdcf)   || (c >= 0xfdf0 && c <= 0xfffd)   || \
+                            (c >= 0x10000 && c <= 0x1fffd) || (c >= 0x20000 && c <= 0x2fffd) || \
+                            (c >= 0x30000 && c <= 0x3fffd) || (c >= 0x40000 && c <= 0x2fffd) || \
+                            (c >= 0x50000 && c <= 0x5fffd) || (c >= 0x60000 && c <= 0x6fffd) || \
+                            (c >= 0x70000 && c <= 0x7fffd) || (c >= 0x80000 && c <= 0x8fffd) || \
+                            (c >= 0x90000 && c <= 0x9fffd) || (c >= 0xa0000 && c <= 0xafffd) || \
+                            (c >= 0xb0000 && c <= 0xbfffd) || (c >= 0xc0000 && c <= 0xcfffd) || \
+                            (c >= 0xd0000 && c <= 0xdfffd) || (c >= 0xe0000 && c <= 0xefffd) || \
+                            (c >= 0xf0000 && c <= 0xffffd) || (c >= 0x100000 && c <= 0x10fffd))
+
 /**
  * @brief List of YANG statement groups - the (sub)module's substatements
  */
@@ -80,6 +92,31 @@
 };
 
 /**
+ * @brief Check that \p c is valid UTF8 code point for YANG string.
+ *
+ * @param[in] ctx yang parser context for logging.
+ * @param[in] c UTF8 code point of a character to check.
+ * @return LY_ERR values.
+ */
+LY_ERR lysp_check_stringchar(struct lys_parser_ctx *ctx, unsigned int c);
+
+/**
+ * @brief Check that \p c is valid UTF8 code point for YANG identifier.
+ *
+ * @param[in] ctx yang parser context for logging.
+ * @param[in] c UTF8 code point of a character to check.
+ * @param[in] first Flag to check the first character of an identifier, which is more restricted.
+ * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
+ * 0 - colon not yet found (no prefix)
+ * 1 - \p c is the colon character
+ * 2 - prefix already processed, now processing the identifier
+ *
+ * If the identifier cannot be prefixed, NULL is expected.
+ * @return LY_ERR values.
+ */
+LY_ERR lysp_check_identifierchar(struct lys_parser_ctx *ctx, unsigned int c, int first, int *prefix);
+
+/**
  * @brief Check the currently present prefixes in the module for collision with the new one.
  *
  * @param[in] ctx Context for logging.