blob: 6e28fdbd368931a15e453d5965a22abace52b0ca [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;
37 if (t->plugin->free) {
38 t->plugin->free(ctx, t, path[u].predicates[v].value);
39 }
40 lydict_remove(ctx, path[u].predicates[v].value->canonized);
41 free(path[u].predicates[v].value);
42 }
43 }
44 LY_ARRAY_FREE(path[u].predicates);
45 }
46 LY_ARRAY_FREE(path);
47}
48
Radek Krejcie7b95092019-05-15 11:03:07 +020049API LY_ERR
50lyd_unlink_tree(struct lyd_node *node)
51{
52 struct lyd_node *iter;
53 struct lyd_node **first_sibling;
54
55 LY_CHECK_ARG_RET(NULL, node, LY_EINVAL);
56
57 if (node->parent) {
58 first_sibling = lyd_node_children_p((struct lyd_node*)node->parent);
59 }
60
61 /* unlink from siblings */
62 if (node->prev->next) {
63 node->prev->next = node->next;
64 }
65 if (node->next) {
66 node->next->prev = node->prev;
67 } else {
68 /* unlinking the last node */
69 if (node->parent) {
70 iter = *first_sibling;
71 } else {
72 iter = node->prev;
73 while (iter->prev != node) {
74 iter = iter->prev;
75 }
76 }
77 /* update the "last" pointer from the first node */
78 iter->prev = node->prev;
79 }
80
81 /* unlink from parent */
82 if (node->parent) {
83 if (*first_sibling == node) {
84 /* the node is the first child */
85 *first_sibling = node->next;
86 }
87 lyd_unlink_hash(node);
88 node->parent = NULL;
89 }
90
91 node->next = NULL;
92 node->prev = node;
93
94 return EXIT_SUCCESS;
95}
96
97/**
98 * @brief Free the YANG data value content.
99 * @param[in] ctx libyang context
100 * @param[in] value Data value structure to clean - since it is mostly part of other structure, only content is freed.
101 */
102static void
Radek Krejci849a62a2019-05-22 15:29:05 +0200103lyd_free_value(struct ly_ctx *ctx, struct lyd_value *value, struct lysc_type *type)
Radek Krejcie7b95092019-05-15 11:03:07 +0200104{
Radek Krejci849a62a2019-05-22 15:29:05 +0200105 if (type->plugin->free) {
106 type->plugin->free(ctx, type, value);
107 }
108
Radek Krejcie7b95092019-05-15 11:03:07 +0200109 FREE_STRING(ctx, value->canonized);
Radek Krejci849a62a2019-05-22 15:29:05 +0200110
Radek Krejcie7b95092019-05-15 11:03:07 +0200111}
112
113API void
114lyd_free_attr(struct ly_ctx *ctx, struct lyd_attr *attr, int recursive)
115{
116 struct lyd_attr *iter;
117
118 LY_CHECK_ARG_RET(NULL, ctx, );
119 if (!attr) {
120 return;
121 }
122
123 if (attr->parent) {
124 if (attr->parent->attr == attr) {
125 if (recursive) {
126 attr->parent->attr = NULL;
127 } else {
128 attr->parent->attr = attr->next;
129 }
130 } else {
131 for (iter = attr->parent->attr; iter->next != attr; iter = iter->next);
132 if (iter->next) {
133 if (recursive) {
134 iter->next = NULL;
135 } else {
136 iter->next = attr->next;
137 }
138 }
139 }
140 }
141
142 if (!recursive) {
143 attr->next = NULL;
144 }
145
146 for(iter = attr; iter; ) {
147 attr = iter;
148 iter = iter->next;
149
150 FREE_STRING(ctx, attr->name);
Radek Krejci849a62a2019-05-22 15:29:05 +0200151 lyd_free_value(ctx, &attr->value, NULL /* TODO */);
Radek Krejcie7b95092019-05-15 11:03:07 +0200152 free(attr);
153 }
154}
155
156/**
157 * @brief Free Data (sub)tree.
158 * @param[in] ctx libyang context.
159 * @param[in] node Data node to be freed.
160 * @param[in] top Recursion flag to unlink the root of the subtree being freed.
161 */
162static void
163lyd_free_subtree(struct ly_ctx *ctx, struct lyd_node *node, int top)
164{
165 struct lyd_node *iter, *next;
166 struct lyd_node *children;
167
168 assert(node);
169
170 /* remove children hash table in case of inner data node */
171 if (node->schema->nodetype & LYD_NODE_INNER) {
172 lyht_free(((struct lyd_node_inner*)node)->children_ht);
173 ((struct lyd_node_inner*)node)->children_ht = NULL;
174
175 /* free the children */
176 children = (struct lyd_node*)lyd_node_children(node);
177 LY_LIST_FOR_SAFE(children, next, iter) {
178 lyd_free_subtree(ctx, iter, 0);
179 }
180 } else if (node->schema->nodetype & LYD_NODE_ANY) {
181 /* TODO anydata */
182#if 0
183 switch (((struct lyd_node_anydata *)node)->value_type) {
184 case LYD_ANYDATA_CONSTSTRING:
185 case LYD_ANYDATA_SXML:
186 case LYD_ANYDATA_JSON:
187 FREE_STRING(node->schema->module->ctx, ((struct lyd_node_anydata *)node)->value.str);
188 break;
189 case LYD_ANYDATA_DATATREE:
190 lyd_free_withsiblings(((struct lyd_node_anydata *)node)->value.tree);
191 break;
192 case LYD_ANYDATA_XML:
193 lyxml_free_withsiblings(node->schema->module->ctx, ((struct lyd_node_anydata *)node)->value.xml);
194 break;
195 case LYD_ANYDATA_LYB:
196 free(((struct lyd_node_anydata *)node)->value.mem);
197 break;
198 case LYD_ANYDATA_STRING:
199 case LYD_ANYDATA_SXMLD:
200 case LYD_ANYDATA_JSOND:
201 case LYD_ANYDATA_LYBD:
202 /* dynamic strings are used only as input parameters */
203 assert(0);
204 break;
205 }
206#endif
207 } else if (node->schema->nodetype & LYD_NODE_TERM) {
Radek Krejci849a62a2019-05-22 15:29:05 +0200208 lyd_free_value(ctx, &((struct lyd_node_term*)node)->value, ((struct lysc_node_leaf*)node->schema)->type);
Radek Krejcie7b95092019-05-15 11:03:07 +0200209 }
210
211 /* free the node's attributes */
212 lyd_free_attr(ctx, node->attr, 1);
213
214 /* unlink only the nodes from the first level, nodes in subtree are freed all, so no unlink is needed */
215 if (top) {
216 lyd_unlink_tree(node);
217 }
218
219 free(node);
220}
221
222API void
223lyd_free_tree(struct lyd_node *node)
224{
225 if (!node) {
226 return;
227 }
228
229 lyd_free_subtree(node->schema->module->ctx, node, 1);
230}
231
232API void
233lyd_free_all(struct lyd_node *node)
234{
235 struct lyd_node *iter, *next;
236
237 if (!node) {
238 return;
239 }
240
241 /* get the first top-level sibling */
242 for (; node->parent; node = (struct lyd_node*)node->parent);
243 while (node->prev->next) {
244 node = node->prev;
245 }
246
247 LY_LIST_FOR_SAFE(node, next, iter) {
248 /* in case of the top-level nodes (node->parent is NULL), no unlinking needed */
Radek Krejci35676302019-05-17 10:50:57 +0200249 lyd_free_subtree(iter->schema->module->ctx, iter, iter->parent ? 1 : 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200250 }
251}