data tree NEW opaque data node

Used for unknown anyxml/anydata nodes.
Some refactoring including making context
const for cases when only the dictionary
is modified or replacing unsigned int with
uint32_t.
diff --git a/src/tree_data_free.c b/src/tree_data_free.c
index 7aa63ae..beb1f40 100644
--- a/src/tree_data_free.c
+++ b/src/tree_data_free.c
@@ -26,7 +26,7 @@
 #include "plugins_types.h"
 
 void
-lyd_value_free_path(struct ly_ctx *ctx, struct lyd_value_path *path)
+lyd_value_free_path(const struct ly_ctx *ctx, struct lyd_value_path *path)
 {
     unsigned int u, v;
 
@@ -43,7 +43,7 @@
 }
 
 API void
-lyd_free_meta(struct ly_ctx *ctx, struct lyd_meta *meta, int recursive)
+lyd_free_meta(const struct ly_ctx *ctx, struct lyd_meta *meta, int recursive)
 {
     struct lyd_meta *iter;
 
@@ -75,7 +75,7 @@
         meta->next = NULL;
     }
 
-    for(iter = meta; iter; ) {
+    for (iter = meta; iter; ) {
         meta = iter;
         iter = iter->next;
 
@@ -85,52 +85,128 @@
     }
 }
 
+API void
+ly_free_attr(const struct ly_ctx *ctx, struct ly_attr *attr, int recursive)
+{
+    struct ly_attr *iter;
+    uint32_t u;
+
+    LY_CHECK_ARG_RET(NULL, ctx, );
+    if (!attr) {
+        return;
+    }
+
+    if (attr->parent) {
+        if (attr->parent->attr == attr) {
+            if (recursive) {
+                attr->parent->attr = NULL;
+            } else {
+                attr->parent->attr = attr->next;
+            }
+        } else {
+            for (iter = attr->parent->attr; iter->next != attr; iter = iter->next);
+            if (iter->next) {
+                if (recursive) {
+                    iter->next = NULL;
+                } else {
+                    iter->next = attr->next;
+                }
+            }
+        }
+    }
+
+    if (!recursive) {
+        attr->next = NULL;
+    }
+
+    for (iter = attr; iter; ) {
+        attr = iter;
+        iter = iter->next;
+
+        LY_ARRAY_FOR(attr->val_prefs, u) {
+            FREE_STRING(ctx, attr->val_prefs[u].pref);
+            FREE_STRING(ctx, attr->val_prefs[u].ns);
+        }
+        LY_ARRAY_FREE(attr->val_prefs);
+        FREE_STRING(ctx, attr->name);
+        FREE_STRING(ctx, attr->value);
+        FREE_STRING(ctx, attr->prefix.pref);
+        FREE_STRING(ctx, attr->prefix.ns);
+        free(attr);
+    }
+}
+
 /**
  * @brief Free Data (sub)tree.
- * @param[in] ctx libyang context.
  * @param[in] node Data node to be freed.
  * @param[in] top Recursion flag to unlink the root of the subtree being freed.
  */
 static void
-lyd_free_subtree(struct ly_ctx *ctx, struct lyd_node *node, int top)
+lyd_free_subtree(struct lyd_node *node, int top)
 {
     struct lyd_node *iter, *next;
     struct lyd_node *children;
+    struct lyd_node_opaq *opaq;
+    uint32_t u;
 
     assert(node);
 
-    /* remove children hash table in case of inner data node */
-    if (node->schema->nodetype & LYD_NODE_INNER) {
-        lyht_free(((struct lyd_node_inner*)node)->children_ht);
-        ((struct lyd_node_inner*)node)->children_ht = NULL;
+    if (!node->schema) {
+        opaq = (struct lyd_node_opaq *)node;
 
         /* free the children */
-        children = (struct lyd_node*)lyd_node_children(node);
+        children = (struct lyd_node *)lyd_node_children(node);
         LY_LIST_FOR_SAFE(children, next, iter) {
-            lyd_free_subtree(ctx, iter, 0);
+            lyd_free_subtree(iter, 0);
+        }
+
+        FREE_STRING(LYD_NODE_CTX(opaq), opaq->name);
+        FREE_STRING(LYD_NODE_CTX(opaq), opaq->prefix.pref);
+        FREE_STRING(LYD_NODE_CTX(opaq), opaq->prefix.ns);
+        if (opaq->val_prefs) {
+            LY_ARRAY_FOR(opaq->val_prefs, u) {
+                FREE_STRING(LYD_NODE_CTX(opaq), opaq->val_prefs[u].pref);
+                FREE_STRING(LYD_NODE_CTX(opaq), opaq->val_prefs[u].ns);
+            }
+            LY_ARRAY_FREE(opaq->val_prefs);
+        }
+        FREE_STRING(LYD_NODE_CTX(opaq), opaq->value);
+    } else if (node->schema->nodetype & LYD_NODE_INNER) {
+        /* remove children hash table in case of inner data node */
+        lyht_free(((struct lyd_node_inner *)node)->children_ht);
+        ((struct lyd_node_inner *)node)->children_ht = NULL;
+
+        /* free the children */
+        children = (struct lyd_node *)lyd_node_children(node);
+        LY_LIST_FOR_SAFE(children, next, iter) {
+            lyd_free_subtree(iter, 0);
         }
     } else if (node->schema->nodetype & LYD_NODE_ANY) {
-        switch (((struct lyd_node_any*)node)->value_type) {
+        switch (((struct lyd_node_any *)node)->value_type) {
         case LYD_ANYDATA_DATATREE:
-            lyd_free_all(((struct lyd_node_any*)node)->value.tree);
+            lyd_free_all(((struct lyd_node_any *)node)->value.tree);
             break;
         case LYD_ANYDATA_STRING:
         case LYD_ANYDATA_XML:
         case LYD_ANYDATA_JSON:
-            FREE_STRING(node->schema->module->ctx, ((struct lyd_node_any*)node)->value.str);
+            FREE_STRING(LYD_NODE_CTX(node), ((struct lyd_node_any *)node)->value.str);
             break;
 #if 0 /* TODO LYB format */
         case LYD_ANYDATA_LYB:
-            free(((struct lyd_node_any*)node)->value.mem);
+            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);
+        ((struct lysc_node_leaf *)node->schema)->type->plugin->free(LYD_NODE_CTX(node), &((struct lyd_node_term *)node)->value);
     }
 
-    /* free the node's metadata */
-    lyd_free_meta(ctx, node->meta, 1);
+    if (!node->schema) {
+        ly_free_attr(LYD_NODE_CTX(node), opaq->attr, 1);
+    } else {
+        /* free the node's metadata */
+        lyd_free_meta(LYD_NODE_CTX(node), node->meta, 1);
+    }
 
     /* unlink only the nodes from the first level, nodes in subtree are freed all, so no unlink is needed */
     if (top) {
@@ -147,7 +223,7 @@
         return;
     }
 
-    lyd_free_subtree(node->schema->module->ctx, node, 1);
+    lyd_free_subtree(node, 1);
 }
 
 static void
@@ -161,7 +237,7 @@
 
     /* get the first (top-level) sibling */
     if (top) {
-        for (; node->parent; node = (struct lyd_node*)node->parent);
+        for (; node->parent; node = (struct lyd_node *)node->parent);
     }
     while (node->prev->next) {
         node = node->prev;
@@ -169,7 +245,7 @@
 
     LY_LIST_FOR_SAFE(node, next, iter) {
         /* in case of the top-level nodes (node->parent is NULL), no unlinking needed */
-        lyd_free_subtree(iter->schema->module->ctx, iter, iter->parent ? 1 : 0);
+        lyd_free_subtree(iter, iter->parent ? 1 : 0);
     }
 }