blob: 36a11a06d3a82feae0ae6eae878eae4f81a48321 [file] [log] [blame]
Radek Krejcie7b95092019-05-15 11:03:07 +02001/**
2 * @file tree_data_free.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Freeing functions for data tree structures
5 *
6 * Copyright (c) 2019 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#include "common.h"
16
17#include <assert.h>
18#include <stdlib.h>
19
20#include "hash_table.h"
21#include "log.h"
22#include "tree.h"
23#include "tree_data.h"
24#include "tree_schema.h"
25#include "tree_data_internal.h"
Radek Krejci849a62a2019-05-22 15:29:05 +020026#include "plugins_types.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020027
Radek Krejci084289f2019-07-09 17:35:30 +020028void
29lyd_value_free_path(struct ly_ctx *ctx, struct lyd_value_path *path)
30{
31 unsigned int u, v;
32
33 LY_ARRAY_FOR(path, u) {
34 LY_ARRAY_FOR(path[u].predicates, v) {
35 if (path[u].predicates[v].type > 0) {
36 struct lysc_type *t = ((struct lysc_node_leaf*)path[u].predicates[v].key)->type;
Radek Krejci73dead22019-07-11 16:46:16 +020037 t->plugin->free(ctx, t, path[u].predicates[v].value);
Radek Krejci084289f2019-07-09 17:35:30 +020038 free(path[u].predicates[v].value);
39 }
40 }
41 LY_ARRAY_FREE(path[u].predicates);
42 }
43 LY_ARRAY_FREE(path);
44}
45
Radek Krejcie7b95092019-05-15 11:03:07 +020046API LY_ERR
47lyd_unlink_tree(struct lyd_node *node)
48{
49 struct lyd_node *iter;
50 struct lyd_node **first_sibling;
51
52 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
53
54 if (node->parent) {
55 first_sibling = lyd_node_children_p((struct lyd_node*)node->parent);
56 }
57
58 /* unlink from siblings */
59 if (node->prev->next) {
60 node->prev->next = node->next;
61 }
62 if (node->next) {
63 node->next->prev = node->prev;
64 } else {
65 /* unlinking the last node */
66 if (node->parent) {
67 iter = *first_sibling;
68 } else {
69 iter = node->prev;
70 while (iter->prev != node) {
71 iter = iter->prev;
72 }
73 }
74 /* update the "last" pointer from the first node */
75 iter->prev = node->prev;
76 }
77
78 /* unlink from parent */
79 if (node->parent) {
80 if (*first_sibling == node) {
81 /* the node is the first child */
82 *first_sibling = node->next;
83 }
84 lyd_unlink_hash(node);
85 node->parent = NULL;
86 }
87
88 node->next = NULL;
89 node->prev = node;
90
91 return EXIT_SUCCESS;
92}
93
Radek Krejcie7b95092019-05-15 11:03:07 +020094API void
95lyd_free_attr(struct ly_ctx *ctx, struct lyd_attr *attr, int recursive)
96{
97 struct lyd_attr *iter;
98
99 LY_CHECK_ARG_RET(NULL, ctx, );
100 if (!attr) {
101 return;
102 }
103
104 if (attr->parent) {
105 if (attr->parent->attr == attr) {
106 if (recursive) {
107 attr->parent->attr = NULL;
108 } else {
109 attr->parent->attr = attr->next;
110 }
111 } else {
112 for (iter = attr->parent->attr; iter->next != attr; iter = iter->next);
113 if (iter->next) {
114 if (recursive) {
115 iter->next = NULL;
116 } else {
117 iter->next = attr->next;
118 }
119 }
120 }
121 }
122
123 if (!recursive) {
124 attr->next = NULL;
125 }
126
127 for(iter = attr; iter; ) {
128 attr = iter;
129 iter = iter->next;
130
131 FREE_STRING(ctx, attr->name);
Radek Krejci73dead22019-07-11 16:46:16 +0200132 /* TODO type->plugin->free(ctx, type, &attr->value); */
Radek Krejcie7b95092019-05-15 11:03:07 +0200133 free(attr);
134 }
135}
136
137/**
138 * @brief Free Data (sub)tree.
139 * @param[in] ctx libyang context.
140 * @param[in] node Data node to be freed.
141 * @param[in] top Recursion flag to unlink the root of the subtree being freed.
142 */
143static void
144lyd_free_subtree(struct ly_ctx *ctx, struct lyd_node *node, int top)
145{
146 struct lyd_node *iter, *next;
147 struct lyd_node *children;
148
149 assert(node);
150
151 /* remove children hash table in case of inner data node */
152 if (node->schema->nodetype & LYD_NODE_INNER) {
153 lyht_free(((struct lyd_node_inner*)node)->children_ht);
154 ((struct lyd_node_inner*)node)->children_ht = NULL;
155
156 /* free the children */
157 children = (struct lyd_node*)lyd_node_children(node);
158 LY_LIST_FOR_SAFE(children, next, iter) {
159 lyd_free_subtree(ctx, iter, 0);
160 }
161 } else if (node->schema->nodetype & LYD_NODE_ANY) {
162 /* TODO anydata */
163#if 0
164 switch (((struct lyd_node_anydata *)node)->value_type) {
165 case LYD_ANYDATA_CONSTSTRING:
166 case LYD_ANYDATA_SXML:
167 case LYD_ANYDATA_JSON:
168 FREE_STRING(node->schema->module->ctx, ((struct lyd_node_anydata *)node)->value.str);
169 break;
170 case LYD_ANYDATA_DATATREE:
171 lyd_free_withsiblings(((struct lyd_node_anydata *)node)->value.tree);
172 break;
173 case LYD_ANYDATA_XML:
174 lyxml_free_withsiblings(node->schema->module->ctx, ((struct lyd_node_anydata *)node)->value.xml);
175 break;
176 case LYD_ANYDATA_LYB:
177 free(((struct lyd_node_anydata *)node)->value.mem);
178 break;
179 case LYD_ANYDATA_STRING:
180 case LYD_ANYDATA_SXMLD:
181 case LYD_ANYDATA_JSOND:
182 case LYD_ANYDATA_LYBD:
183 /* dynamic strings are used only as input parameters */
184 assert(0);
185 break;
186 }
187#endif
188 } else if (node->schema->nodetype & LYD_NODE_TERM) {
Radek Krejci73dead22019-07-11 16:46:16 +0200189 struct lysc_type *type = ((struct lysc_node_leaf*)node->schema)->type;
190 type->plugin->free(ctx, type, &((struct lyd_node_term*)node)->value);
Radek Krejcie7b95092019-05-15 11:03:07 +0200191 }
192
193 /* free the node's attributes */
194 lyd_free_attr(ctx, node->attr, 1);
195
196 /* unlink only the nodes from the first level, nodes in subtree are freed all, so no unlink is needed */
197 if (top) {
198 lyd_unlink_tree(node);
199 }
200
201 free(node);
202}
203
204API void
205lyd_free_tree(struct lyd_node *node)
206{
207 if (!node) {
208 return;
209 }
210
211 lyd_free_subtree(node->schema->module->ctx, node, 1);
212}
213
214API void
215lyd_free_all(struct lyd_node *node)
216{
217 struct lyd_node *iter, *next;
218
219 if (!node) {
220 return;
221 }
222
223 /* get the first top-level sibling */
224 for (; node->parent; node = (struct lyd_node*)node->parent);
225 while (node->prev->next) {
226 node = node->prev;
227 }
228
229 LY_LIST_FOR_SAFE(node, next, iter) {
230 /* in case of the top-level nodes (node->parent is NULL), no unlinking needed */
Radek Krejci35676302019-05-17 10:50:57 +0200231 lyd_free_subtree(iter->schema->module->ctx, iter, iter->parent ? 1 : 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200232 }
233}