blob: a8b072c4e513d5e1fce65f5b0aadd517744426ba [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
Michal Vasko52927e22020-03-16 17:26:14 +010029lyd_value_free_path(const struct ly_ctx *ctx, struct lyd_value_path *path)
Radek Krejci084289f2019-07-09 17:35:30 +020030{
Radek Krejci7eb54ba2020-05-18 16:30:04 +020031 LY_ARRAY_SIZE_TYPE u, v;
Radek Krejci084289f2019-07-09 17:35:30 +020032
33 LY_ARRAY_FOR(path, u) {
34 LY_ARRAY_FOR(path[u].predicates, v) {
35 if (path[u].predicates[v].type > 0) {
Radek Krejci62903c32019-07-15 14:42:05 +020036 ((struct lysc_node_leaf*)path[u].predicates[v].key)->type->plugin->free(ctx, path[u].predicates[v].value);
Radek Krejci084289f2019-07-09 17:35:30 +020037 free(path[u].predicates[v].value);
38 }
39 }
40 LY_ARRAY_FREE(path[u].predicates);
41 }
42 LY_ARRAY_FREE(path);
43}
44
Radek Krejcie7b95092019-05-15 11:03:07 +020045API void
Michal Vasko52927e22020-03-16 17:26:14 +010046lyd_free_meta(const struct ly_ctx *ctx, struct lyd_meta *meta, int recursive)
Radek Krejcie7b95092019-05-15 11:03:07 +020047{
Michal Vasko9f96a052020-03-10 09:41:45 +010048 struct lyd_meta *iter;
Radek Krejcie7b95092019-05-15 11:03:07 +020049
50 LY_CHECK_ARG_RET(NULL, ctx, );
Michal Vasko9f96a052020-03-10 09:41:45 +010051 if (!meta) {
Radek Krejcie7b95092019-05-15 11:03:07 +020052 return;
53 }
54
Michal Vasko9f96a052020-03-10 09:41:45 +010055 if (meta->parent) {
56 if (meta->parent->meta == meta) {
Radek Krejcie7b95092019-05-15 11:03:07 +020057 if (recursive) {
Michal Vasko9f96a052020-03-10 09:41:45 +010058 meta->parent->meta = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +020059 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010060 meta->parent->meta = meta->next;
Radek Krejcie7b95092019-05-15 11:03:07 +020061 }
62 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010063 for (iter = meta->parent->meta; iter->next != meta; iter = iter->next);
Radek Krejcie7b95092019-05-15 11:03:07 +020064 if (iter->next) {
65 if (recursive) {
66 iter->next = NULL;
67 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010068 iter->next = meta->next;
Radek Krejcie7b95092019-05-15 11:03:07 +020069 }
70 }
71 }
72 }
73
74 if (!recursive) {
Michal Vasko9f96a052020-03-10 09:41:45 +010075 meta->next = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +020076 }
77
Michal Vasko52927e22020-03-16 17:26:14 +010078 for (iter = meta; iter; ) {
Michal Vasko9f96a052020-03-10 09:41:45 +010079 meta = iter;
Radek Krejcie7b95092019-05-15 11:03:07 +020080 iter = iter->next;
81
Michal Vasko9f96a052020-03-10 09:41:45 +010082 FREE_STRING(ctx, meta->name);
83 meta->value.realtype->plugin->free(ctx, &meta->value);
84 free(meta);
Radek Krejcie7b95092019-05-15 11:03:07 +020085 }
86}
87
Michal Vasko52927e22020-03-16 17:26:14 +010088API void
89ly_free_attr(const struct ly_ctx *ctx, struct ly_attr *attr, int recursive)
90{
91 struct ly_attr *iter;
Radek Krejci7eb54ba2020-05-18 16:30:04 +020092 LY_ARRAY_SIZE_TYPE u;
Michal Vasko52927e22020-03-16 17:26:14 +010093
94 LY_CHECK_ARG_RET(NULL, ctx, );
95 if (!attr) {
96 return;
97 }
98
99 if (attr->parent) {
100 if (attr->parent->attr == attr) {
101 if (recursive) {
102 attr->parent->attr = NULL;
103 } else {
104 attr->parent->attr = attr->next;
105 }
106 } else {
107 for (iter = attr->parent->attr; iter->next != attr; iter = iter->next);
108 if (iter->next) {
109 if (recursive) {
110 iter->next = NULL;
111 } else {
112 iter->next = attr->next;
113 }
114 }
115 }
116 }
117
118 if (!recursive) {
119 attr->next = NULL;
120 }
121
122 for (iter = attr; iter; ) {
123 attr = iter;
124 iter = iter->next;
125
126 LY_ARRAY_FOR(attr->val_prefs, u) {
127 FREE_STRING(ctx, attr->val_prefs[u].pref);
128 FREE_STRING(ctx, attr->val_prefs[u].ns);
129 }
130 LY_ARRAY_FREE(attr->val_prefs);
131 FREE_STRING(ctx, attr->name);
132 FREE_STRING(ctx, attr->value);
133 FREE_STRING(ctx, attr->prefix.pref);
134 FREE_STRING(ctx, attr->prefix.ns);
135 free(attr);
136 }
137}
138
Radek Krejcie7b95092019-05-15 11:03:07 +0200139/**
140 * @brief Free Data (sub)tree.
Radek Krejcie7b95092019-05-15 11:03:07 +0200141 * @param[in] node Data node to be freed.
142 * @param[in] top Recursion flag to unlink the root of the subtree being freed.
143 */
144static void
Michal Vasko52927e22020-03-16 17:26:14 +0100145lyd_free_subtree(struct lyd_node *node, int top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200146{
147 struct lyd_node *iter, *next;
148 struct lyd_node *children;
Michal Vasko52927e22020-03-16 17:26:14 +0100149 struct lyd_node_opaq *opaq;
Radek Krejci7eb54ba2020-05-18 16:30:04 +0200150 LY_ARRAY_SIZE_TYPE u;
Radek Krejcie7b95092019-05-15 11:03:07 +0200151
152 assert(node);
153
Michal Vasko52927e22020-03-16 17:26:14 +0100154 if (!node->schema) {
155 opaq = (struct lyd_node_opaq *)node;
Radek Krejcie7b95092019-05-15 11:03:07 +0200156
157 /* free the children */
Radek Krejcidae0ee82020-05-06 16:53:24 +0200158 children = lyd_node_children(node);
Radek Krejcie7b95092019-05-15 11:03:07 +0200159 LY_LIST_FOR_SAFE(children, next, iter) {
Michal Vasko52927e22020-03-16 17:26:14 +0100160 lyd_free_subtree(iter, 0);
161 }
162
163 FREE_STRING(LYD_NODE_CTX(opaq), opaq->name);
164 FREE_STRING(LYD_NODE_CTX(opaq), opaq->prefix.pref);
165 FREE_STRING(LYD_NODE_CTX(opaq), opaq->prefix.ns);
166 if (opaq->val_prefs) {
167 LY_ARRAY_FOR(opaq->val_prefs, u) {
168 FREE_STRING(LYD_NODE_CTX(opaq), opaq->val_prefs[u].pref);
169 FREE_STRING(LYD_NODE_CTX(opaq), opaq->val_prefs[u].ns);
170 }
171 LY_ARRAY_FREE(opaq->val_prefs);
172 }
173 FREE_STRING(LYD_NODE_CTX(opaq), opaq->value);
174 } else if (node->schema->nodetype & LYD_NODE_INNER) {
175 /* remove children hash table in case of inner data node */
176 lyht_free(((struct lyd_node_inner *)node)->children_ht);
177 ((struct lyd_node_inner *)node)->children_ht = NULL;
178
179 /* free the children */
Radek Krejcidae0ee82020-05-06 16:53:24 +0200180 children = lyd_node_children(node);
Michal Vasko52927e22020-03-16 17:26:14 +0100181 LY_LIST_FOR_SAFE(children, next, iter) {
182 lyd_free_subtree(iter, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200183 }
184 } else if (node->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko52927e22020-03-16 17:26:14 +0100185 switch (((struct lyd_node_any *)node)->value_type) {
Radek Krejcie7b95092019-05-15 11:03:07 +0200186 case LYD_ANYDATA_DATATREE:
Michal Vasko52927e22020-03-16 17:26:14 +0100187 lyd_free_all(((struct lyd_node_any *)node)->value.tree);
Radek Krejcie7b95092019-05-15 11:03:07 +0200188 break;
189 case LYD_ANYDATA_STRING:
Radek Krejciee4cab22019-07-17 17:07:47 +0200190 case LYD_ANYDATA_XML:
191 case LYD_ANYDATA_JSON:
Michal Vasko52927e22020-03-16 17:26:14 +0100192 FREE_STRING(LYD_NODE_CTX(node), ((struct lyd_node_any *)node)->value.str);
Radek Krejciee4cab22019-07-17 17:07:47 +0200193 break;
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200194#if 0 /* TODO LYB format */
Radek Krejciee4cab22019-07-17 17:07:47 +0200195 case LYD_ANYDATA_LYB:
Michal Vasko52927e22020-03-16 17:26:14 +0100196 free(((struct lyd_node_any *)node)->value.mem);
Radek Krejcie7b95092019-05-15 11:03:07 +0200197 break;
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200198#endif
Radek Krejcie7b95092019-05-15 11:03:07 +0200199 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200200 } else if (node->schema->nodetype & LYD_NODE_TERM) {
Michal Vasko52927e22020-03-16 17:26:14 +0100201 ((struct lysc_node_leaf *)node->schema)->type->plugin->free(LYD_NODE_CTX(node), &((struct lyd_node_term *)node)->value);
Radek Krejcie7b95092019-05-15 11:03:07 +0200202 }
203
Michal Vasko52927e22020-03-16 17:26:14 +0100204 if (!node->schema) {
205 ly_free_attr(LYD_NODE_CTX(node), opaq->attr, 1);
206 } else {
207 /* free the node's metadata */
208 lyd_free_meta(LYD_NODE_CTX(node), node->meta, 1);
209 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200210
211 /* unlink only the nodes from the first level, nodes in subtree are freed all, so no unlink is needed */
212 if (top) {
213 lyd_unlink_tree(node);
214 }
215
216 free(node);
217}
218
219API void
220lyd_free_tree(struct lyd_node *node)
221{
222 if (!node) {
223 return;
224 }
225
Michal Vasko52927e22020-03-16 17:26:14 +0100226 lyd_free_subtree(node, 1);
Radek Krejcie7b95092019-05-15 11:03:07 +0200227}
228
Radek Krejcib0849a22019-07-25 12:31:04 +0200229static void
230lyd_free_(struct lyd_node *node, int top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200231{
232 struct lyd_node *iter, *next;
233
234 if (!node) {
235 return;
236 }
237
Radek Krejcib0849a22019-07-25 12:31:04 +0200238 /* get the first (top-level) sibling */
239 if (top) {
Michal Vasko52927e22020-03-16 17:26:14 +0100240 for (; node->parent; node = (struct lyd_node *)node->parent);
Radek Krejcib0849a22019-07-25 12:31:04 +0200241 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200242 while (node->prev->next) {
243 node = node->prev;
244 }
245
246 LY_LIST_FOR_SAFE(node, next, iter) {
247 /* in case of the top-level nodes (node->parent is NULL), no unlinking needed */
Michal Vasko52927e22020-03-16 17:26:14 +0100248 lyd_free_subtree(iter, iter->parent ? 1 : 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200249 }
250}
Radek Krejcib0849a22019-07-25 12:31:04 +0200251
252API void
Michal Vaskof03ed032020-03-04 13:31:44 +0100253lyd_free_siblings(struct lyd_node *node)
Radek Krejcib0849a22019-07-25 12:31:04 +0200254{
255 lyd_free_(node, 0);
256}
257
258API void
259lyd_free_all(struct lyd_node *node)
260{
261 lyd_free_(node, 1);
262}