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