data tree FEATURE support for anydata

Defined and supported in XML parser.
diff --git a/src/parser_xml.c b/src/parser_xml.c
index 75e3c55..a6193c0 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -275,12 +275,47 @@
                     goto cleanup;
                 }
             }
+            /* process children */
             if (ctx->status == LYXML_ELEMENT && parents_count != ctx->elements.count) {
                 ret = lydxml_nodes(ctx, (struct lyd_node_inner*)cur, data, lyd_node_children_p(cur));
                 LY_CHECK_GOTO(ret, cleanup);
             }
+        } else if (snode->nodetype & LYD_NODE_ANY) {
+            unsigned int cur_element_index = ctx->elements.count;
+            const char *start = *data, *stop;
+            const char *p, *n;
+            size_t p_len, n_len;
+
+            /* skip children data and store them as a string */
+            while (cur_element_index <= ctx->elements.count) {
+                switch (ctx->status) {
+                case LYXML_ELEMENT:
+                    ret = lyxml_get_element((struct lyxml_context *)ctx, data, &p, &p_len, &n, &n_len);
+                    break;
+                case LYXML_ATTRIBUTE:
+                    lyxml_get_attribute((struct lyxml_context*)ctx, data, &p, &p_len, &n, &n_len);
+                    break;
+                case LYXML_ELEM_CONTENT:
+                case LYXML_ATTR_CONTENT:
+                    ret = lyxml_get_string((struct lyxml_context *)ctx, data, NULL, NULL, NULL, NULL, NULL);
+                    if (ret == LY_EINVAL) {
+                        /* not an error, just incorrect XML parser status */
+                        ret = LY_SUCCESS;
+                    }
+                    break;
+                case LYXML_END:
+                    /* unexpected end of data */
+                    LOGINT(ctx->ctx);
+                    goto cleanup;
+                }
+                LY_CHECK_GOTO(ret, cleanup);
+            }
+            /* data now points after the anydata's closing element tag, we need just end of its content */
+            for (stop = *data - 1; *stop != '<'; --stop);
+
+            ((struct lyd_node_any*)cur)->value_type = LYD_ANYDATA_XML;
+            ((struct lyd_node_any*)cur)->value.xml = lydict_insert(ctx->ctx, start, stop - start);
         }
-        /* TODO anyxml/anydata */
     }
 
 cleanup:
diff --git a/src/tree_data.h b/src/tree_data.h
index 1cf0e8f..12e2859 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -121,44 +121,15 @@
  * @brief List of possible value types stored in ::lyd_node_anydata.
  */
 typedef enum {
-    LYD_ANYDATA_CONSTSTRING = 0x00, /**< value is constant string (const char *) which is internally duplicated for
-                                         storing in the anydata structure; XML sensitive characters (such as & or \>)
-                                         are automatically escaped when the anydata is printed in XML format. */
-    LYD_ANYDATA_STRING = 0x01,      /**< value is dynamically allocated string (char*), so the data are used directly
-                                         without duplication and caller is supposed to not manipulate with the data
-                                         after a successful call (including calling free() on the provided data); XML
-                                         sensitive characters (such as & or \>) are automatically escaped when the
-                                         anydata is printed in XML format */
-    LYD_ANYDATA_JSON = 0x02,        /**< value is string containing the data modeled by YANG and encoded as I-JSON. The
-                                         string is handled as constant string. In case of using the value as input
-                                         parameter, the #LYD_ANYDATA_JSOND can be used for dynamically allocated
-                                         string. */
-    LYD_ANYDATA_JSOND = 0x03,       /**< In case of using value as input parameter, this enumeration is supposed to be
-                                         used for dynamically allocated strings (it is actually combination of
-                                         #LYD_ANYDATA_JSON and #LYD_ANYDATA_STRING (and it can be also specified as
-                                         ORed value of the mentioned values. */
-    LYD_ANYDATA_SXML = 0x04,        /**< value is string containing the serialized XML data. The string is handled as
-                                         constant string. In case of using the value as input parameter, the
-                                         #LYD_ANYDATA_SXMLD can be used for dynamically allocated string. */
-    LYD_ANYDATA_SXMLD = 0x05,       /**< In case of using serialized XML value as input parameter, this enumeration is
-                                         supposed to be used for dynamically allocated strings (it is actually
-                                         combination of #LYD_ANYDATA_SXML and #LYD_ANYDATA_STRING (and it can be also
-                                         specified as ORed value of the mentioned values). */
-    LYD_ANYDATA_XML = 0x08,         /**< value is struct lyxml_elem*, the structure is directly connected into the
-                                         anydata node without duplication, caller is supposed to not manipulate with the
-                                         data after a successful call (including calling lyxml_free() on the provided
-                                         data) */
-    LYD_ANYDATA_DATATREE = 0x10,    /**< value is struct lyd_node* (first sibling), the structure is directly connected
-                                         into the anydata node without duplication, caller is supposed to not manipulate
-                                         with the data after a successful call (including calling lyd_free() on the
-                                         provided data) */
-    LYD_ANYDATA_LYB = 0x20,         /**< value is a memory with serialized data tree in LYB format. The data are handled
-                                         as a constant string. In case of using the value as input parameter,
-                                         the #LYD_ANYDATA_LYBD can be used for dynamically allocated string. */
-    LYD_ANYDATA_LYBD = 0x21,        /**< In case of using LYB value as input parameter, this enumeration is
-                                         supposed to be used for dynamically allocated strings (it is actually
-                                         combination of #LYD_ANYDATA_LYB and #LYD_ANYDATA_STRING (and it can be also
-                                         specified as ORed value of the mentioned values). */
+    LYD_ANYDATA_DATATREE = 0x01,     /**< Value is a pointer to lyd_node structure (first sibling). When provided as input parameter, the pointer
+                                          is directly connected into the anydata node without duplication, caller is supposed to not manipulate
+                                          with the data after a successful call (including calling lyd_free() on the provided data) */
+    LYD_ANYDATA_STRING = 0x02,       /**< Value is a generic string without any knowledge about its format (e.g. anyxml value in JSON encoded
+                                          as string). XML sensitive characters (such as & or \>) are automatically escaped when the anydata
+                                          is printed in XML format. */
+    LYD_ANYDATA_XML = 0x04,          /**< Value is a string containing the serialized XML data. */
+    LYD_ANYDATA_JSON = 0x08,         /**< Value is a string containing the data modeled by YANG and encoded as I-JSON. */
+    LYD_ANYDATA_LYB = 0x10,          /**< Value is a memory chunk with the serialized data tree in LYB format. */
 } LYD_ANYDATA_VALUETYPE;
 
 /** @} */
@@ -332,7 +303,14 @@
     void *priv;                      /**< private user data, not used by libyang */
 #endif
 
-    /* TODO - anydata representation */
+    union {
+        struct lyd_node *tree;       /**< data tree */
+        const char *str;             /**< Generic string data */
+        const char *xml;             /**< Serialized XML data */
+        const char *json;            /**< I-JSON encoded string */
+        char *mem;                   /**< LYD_ANYDATA_LYB memory chunk */
+    } value;                         /**< pointer to the stored value representation of the anydata/anyxml node */
+    LYD_ANYDATA_VALUETYPE value_type;/**< type of the data stored as lyd_node_any::value */
 };
 
 /**
diff --git a/src/tree_data_free.c b/src/tree_data_free.c
index 80653d8..42797b2 100644
--- a/src/tree_data_free.c
+++ b/src/tree_data_free.c
@@ -158,32 +158,19 @@
             lyd_free_subtree(ctx, iter, 0);
         }
     } else if (node->schema->nodetype & LYD_NODE_ANY) {
-        /* TODO anydata */
-#if 0
-        switch (((struct lyd_node_anydata *)node)->value_type) {
-        case LYD_ANYDATA_CONSTSTRING:
-        case LYD_ANYDATA_SXML:
-        case LYD_ANYDATA_JSON:
-            FREE_STRING(node->schema->module->ctx, ((struct lyd_node_anydata *)node)->value.str);
-            break;
+        switch (((struct lyd_node_any*)node)->value_type) {
         case LYD_ANYDATA_DATATREE:
-            lyd_free_withsiblings(((struct lyd_node_anydata *)node)->value.tree);
-            break;
-        case LYD_ANYDATA_XML:
-            lyxml_free_withsiblings(node->schema->module->ctx, ((struct lyd_node_anydata *)node)->value.xml);
-            break;
-        case LYD_ANYDATA_LYB:
-            free(((struct lyd_node_anydata *)node)->value.mem);
+            lyd_free_all(((struct lyd_node_any*)node)->value.tree);
             break;
         case LYD_ANYDATA_STRING:
-        case LYD_ANYDATA_SXMLD:
-        case LYD_ANYDATA_JSOND:
-        case LYD_ANYDATA_LYBD:
-            /* dynamic strings are used only as input parameters */
-            assert(0);
+        case LYD_ANYDATA_XML:
+        case LYD_ANYDATA_JSON:
+            FREE_STRING(node->schema->module->ctx, ((struct lyd_node_any*)node)->value.str);
+            break;
+        case LYD_ANYDATA_LYB:
+            free(((struct lyd_node_any*)node)->value.mem);
             break;
         }
-#endif
     } else if (node->schema->nodetype & LYD_NODE_TERM) {
         ((struct lysc_node_leaf*)node->schema)->type->plugin->free(ctx, &((struct lyd_node_term*)node)->value);
     }
diff --git a/src/xml.c b/src/xml.c
index 95b0e64..8a70445 100644
--- a/src/xml.c
+++ b/src/xml.c
@@ -562,40 +562,52 @@
     /* parse */
     while (in[offset]) {
         if (in[offset] == '&') {
-            if (!buf) {
-                /* it is necessary to modify the input, so we will need a dynamically allocated buffer */
-                goto getbuffer;
-            }
+            if (output) {
+                if (!buf) {
+                    /* it is necessary to modify the input, so we will need a dynamically allocated buffer */
+                    goto getbuffer;
+                }
 
-            if (offset) {
-                /* store what we have so far */
-                BUFSIZE_CHECK(ctx, buf, size, len, offset);
-                memcpy(&buf[len], in, offset);
-                len += offset;
-                in += offset;
-                offset = 0;
+                if (offset) {
+                    /* store what we have so far */
+                    BUFSIZE_CHECK(ctx, buf, size, len, offset);
+                    memcpy(&buf[len], in, offset);
+                    len += offset;
+                    in += offset;
+                    offset = 0;
+                }
+                /* process reference */
+                /* we will need 4 bytes at most since we support only the predefined
+                 * (one-char) entities and character references */
+                BUFSIZE_CHECK(ctx, buf, size, len, 4);
             }
-            /* process reference */
-            /* we will need 4 bytes at most since we support only the predefined
-             * (one-char) entities and character references */
-            BUFSIZE_CHECK(ctx, buf, size, len, 4);
             ++offset;
             if (in[offset] != '#') {
                 /* entity reference - only predefined references are supported */
                 if (!strncmp(&in[offset], "lt;", 3)) {
-                    buf[len++] = '<';
+                    if (output) {
+                        buf[len++] = '<';
+                    }
                     in += 4; /* &lt; */
                 } else if (!strncmp(&in[offset], "gt;", 3)) {
-                    buf[len++] = '>';
+                    if (output) {
+                        buf[len++] = '>';
+                    }
                     in += 4; /* &gt; */
                 } else if (!strncmp(&in[offset], "amp;", 4)) {
-                    buf[len++] = '&';
+                    if (output) {
+                        buf[len++] = '&';
+                    }
                     in += 5; /* &amp; */
                 } else if (!strncmp(&in[offset], "apos;", 5)) {
-                    buf[len++] = '\'';
+                    if (output) {
+                        buf[len++] = '\'';
+                    }
                     in += 6; /* &apos; */
                 } else if (!strncmp(&in[offset], "quot;", 5)) {
-                    buf[len++] = '\"';
+                    if (output) {
+                        buf[len++] = '\"';
+                    }
                     in += 6; /* &quot; */
                 } else {
                     LOGVAL(ctx, LY_VLOG_LINE, &context->line, LYVE_SYNTAX,
@@ -632,7 +644,12 @@
                                          LY_VCODE_INSTREXP_len(&in[offset]), &in[offset], ";"),
                                   error);
                 ++offset;
-                rc = lyxml_pututf8(&buf[len], n, &u);
+                if (output) {
+                    rc = lyxml_pututf8(&buf[len], n, &u);
+                } else {
+                    char utf8[4];
+                    rc = lyxml_pututf8(&utf8[0], n, &u);
+                }
                 LY_CHECK_ERR_GOTO(rc, LOGVAL(ctx, LY_VLOG_LINE, &context->line, LYVE_SYNTAX,
                                              "Invalid character reference \"%.*s\" (0x%08x).", 12, p, n),
                                   error);
@@ -758,11 +775,12 @@
         (*buffer_size) = size;
         (*output) = buf;
         (*dynamic) = 1;
-    } else {
+        (*length) = len;
+    } else if (output) {
         (*output) = (char*)start;
         (*dynamic) = 0;
+        (*length) = len;
     }
-    (*length) = len;
 
     if (context->status == LYXML_ATTRIBUTE) {
         /* skip whitespaces after the value */
diff --git a/src/xml.h b/src/xml.h
index b5e40a3..2795d62 100644
--- a/src/xml.h
+++ b/src/xml.h
@@ -146,6 +146,9 @@
  * reference which modify the input data. These constructs are replaced by their real value, so in case the output
  * string will be again printed as an XML data, it may be necessary to correctly encode such characters.
  *
+ * Optionally, the buffer, buffer_size, output, length and dynamic arguments (altogether) can be NULL.
+ * In such a case, the XML text in @p input is just checked, the @p input pointer is moved after the XML text, but nothing is stored.
+ *
  * @param[in] context XML context to track lines or store errors into libyang context.
  * @param[in,out] input Input string to process, updated according to the processed/read data.
  * @param[in, out] buffer Storage for the output string. If the parameter points to NULL, the buffer is allocated if needed.