blob: 192f63ee8c5cdff6eeb02d49dc9381c670c41ded [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
Radek Krejcie7b95092019-05-15 11:03:07 +020015#include <assert.h>
16#include <stdlib.h>
17
Radek Krejci535ea9f2020-05-29 16:01:05 +020018#include "common.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020019#include "hash_table.h"
Radek Krejci47fab892020-11-05 17:02:41 +010020#include "log.h"
Radek Krejci849a62a2019-05-22 15:29:05 +020021#include "plugins_types.h"
Michal Vasko69730152020-10-09 16:30:07 +020022#include "tree.h"
Radek Krejci47fab892020-11-05 17:02:41 +010023#include "tree_data.h"
Michal Vasko69730152020-10-09 16:30:07 +020024#include "tree_data_internal.h"
25#include "tree_schema.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020026
Radek Krejcid46e46a2020-09-15 14:22:42 +020027void
28ly_free_val_prefs(const struct ly_ctx *ctx, struct ly_prefix *val_prefs)
29{
30 LY_ARRAY_COUNT_TYPE u;
31
32 LY_ARRAY_FOR(val_prefs, u) {
33 FREE_STRING(ctx, val_prefs[u].id);
34 FREE_STRING(ctx, val_prefs[u].module_ns);
35 }
36 LY_ARRAY_FREE(val_prefs);
37}
38
Michal Vasko3a41dff2020-07-15 14:30:28 +020039static void
Radek Krejci857189e2020-09-01 13:26:36 +020040lyd_free_meta(struct lyd_meta *meta, ly_bool siblings)
Radek Krejcie7b95092019-05-15 11:03:07 +020041{
Michal Vasko9f96a052020-03-10 09:41:45 +010042 struct lyd_meta *iter;
Radek Krejcie7b95092019-05-15 11:03:07 +020043
Michal Vasko9f96a052020-03-10 09:41:45 +010044 if (!meta) {
Radek Krejcie7b95092019-05-15 11:03:07 +020045 return;
46 }
47
Michal Vasko9f96a052020-03-10 09:41:45 +010048 if (meta->parent) {
49 if (meta->parent->meta == meta) {
Michal Vasko3a41dff2020-07-15 14:30:28 +020050 if (siblings) {
Michal Vasko9f96a052020-03-10 09:41:45 +010051 meta->parent->meta = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +020052 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010053 meta->parent->meta = meta->next;
Radek Krejcie7b95092019-05-15 11:03:07 +020054 }
55 } else {
Radek Krejci1e008d22020-08-17 11:37:37 +020056 for (iter = meta->parent->meta; iter->next != meta; iter = iter->next) {}
Radek Krejcie7b95092019-05-15 11:03:07 +020057 if (iter->next) {
Michal Vasko3a41dff2020-07-15 14:30:28 +020058 if (siblings) {
Radek Krejcie7b95092019-05-15 11:03:07 +020059 iter->next = NULL;
60 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010061 iter->next = meta->next;
Radek Krejcie7b95092019-05-15 11:03:07 +020062 }
63 }
64 }
65 }
66
Michal Vasko3a41dff2020-07-15 14:30:28 +020067 if (!siblings) {
Michal Vasko9f96a052020-03-10 09:41:45 +010068 meta->next = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +020069 }
70
Michal Vasko52927e22020-03-16 17:26:14 +010071 for (iter = meta; iter; ) {
Michal Vasko9f96a052020-03-10 09:41:45 +010072 meta = iter;
Radek Krejcie7b95092019-05-15 11:03:07 +020073 iter = iter->next;
74
Michal Vasko3a41dff2020-07-15 14:30:28 +020075 FREE_STRING(meta->annotation->module->ctx, meta->name);
76 meta->value.realtype->plugin->free(meta->annotation->module->ctx, &meta->value);
Michal Vasko9f96a052020-03-10 09:41:45 +010077 free(meta);
Radek Krejcie7b95092019-05-15 11:03:07 +020078 }
79}
80
Michal Vasko52927e22020-03-16 17:26:14 +010081API void
Michal Vasko3a41dff2020-07-15 14:30:28 +020082lyd_free_meta_single(struct lyd_meta *meta)
83{
84 lyd_free_meta(meta, 0);
85}
86
87API void
88lyd_free_meta_siblings(struct lyd_meta *meta)
89{
90 lyd_free_meta(meta, 1);
91}
92
93static void
Radek Krejci011e4aa2020-09-04 15:22:31 +020094lyd_free_attr(const struct ly_ctx *ctx, struct lyd_attr *attr, ly_bool siblings)
Michal Vasko52927e22020-03-16 17:26:14 +010095{
Radek Krejci1798aae2020-07-14 13:26:06 +020096 struct lyd_attr *iter;
Michal Vasko52927e22020-03-16 17:26:14 +010097
98 LY_CHECK_ARG_RET(NULL, ctx, );
99 if (!attr) {
100 return;
101 }
102
103 if (attr->parent) {
104 if (attr->parent->attr == attr) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200105 if (siblings) {
Michal Vasko52927e22020-03-16 17:26:14 +0100106 attr->parent->attr = NULL;
107 } else {
108 attr->parent->attr = attr->next;
109 }
110 } else {
Radek Krejci1e008d22020-08-17 11:37:37 +0200111 for (iter = attr->parent->attr; iter->next != attr; iter = iter->next) {}
Michal Vasko52927e22020-03-16 17:26:14 +0100112 if (iter->next) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200113 if (siblings) {
Michal Vasko52927e22020-03-16 17:26:14 +0100114 iter->next = NULL;
115 } else {
116 iter->next = attr->next;
117 }
118 }
119 }
120 }
121
Michal Vasko3a41dff2020-07-15 14:30:28 +0200122 if (!siblings) {
Michal Vasko52927e22020-03-16 17:26:14 +0100123 attr->next = NULL;
124 }
125
126 for (iter = attr; iter; ) {
127 attr = iter;
128 iter = iter->next;
129
Radek Krejcid46e46a2020-09-15 14:22:42 +0200130 ly_free_val_prefs(ctx, attr->val_prefs);
Michal Vasko52927e22020-03-16 17:26:14 +0100131 FREE_STRING(ctx, attr->name);
132 FREE_STRING(ctx, attr->value);
Radek Krejci1798aae2020-07-14 13:26:06 +0200133 FREE_STRING(ctx, attr->prefix.id);
134 FREE_STRING(ctx, attr->prefix.module_ns);
Michal Vasko52927e22020-03-16 17:26:14 +0100135 free(attr);
136 }
137}
138
Michal Vasko3a41dff2020-07-15 14:30:28 +0200139API void
Radek Krejci011e4aa2020-09-04 15:22:31 +0200140lyd_free_attr_single(const struct ly_ctx *ctx, struct lyd_attr *attr)
Michal Vasko3a41dff2020-07-15 14:30:28 +0200141{
Radek Krejci011e4aa2020-09-04 15:22:31 +0200142 lyd_free_attr(ctx, attr, 0);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200143}
144
145API void
Radek Krejci011e4aa2020-09-04 15:22:31 +0200146lyd_free_attr_siblings(const struct ly_ctx *ctx, struct lyd_attr *attr)
Michal Vasko3a41dff2020-07-15 14:30:28 +0200147{
Radek Krejci011e4aa2020-09-04 15:22:31 +0200148 lyd_free_attr(ctx, attr, 1);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200149}
150
Radek Krejcie7b95092019-05-15 11:03:07 +0200151/**
152 * @brief Free Data (sub)tree.
Radek Krejcie7b95092019-05-15 11:03:07 +0200153 * @param[in] node Data node to be freed.
154 * @param[in] top Recursion flag to unlink the root of the subtree being freed.
155 */
156static void
Radek Krejci857189e2020-09-01 13:26:36 +0200157lyd_free_subtree(struct lyd_node *node, ly_bool top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200158{
159 struct lyd_node *iter, *next;
160 struct lyd_node *children;
Michal Vaskoed4fcfe2020-07-08 10:38:56 +0200161 struct lyd_node_opaq *opaq = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +0200162
163 assert(node);
164
Michal Vasko52927e22020-03-16 17:26:14 +0100165 if (!node->schema) {
166 opaq = (struct lyd_node_opaq *)node;
Radek Krejcie7b95092019-05-15 11:03:07 +0200167
168 /* free the children */
Radek Krejcia1c1e542020-09-29 16:06:52 +0200169 children = lyd_child(node);
Radek Krejcie7b95092019-05-15 11:03:07 +0200170 LY_LIST_FOR_SAFE(children, next, iter) {
Michal Vasko52927e22020-03-16 17:26:14 +0100171 lyd_free_subtree(iter, 0);
172 }
173
Michal Vaskob7be7a82020-08-20 09:09:04 +0200174 FREE_STRING(LYD_CTX(opaq), opaq->name);
175 FREE_STRING(LYD_CTX(opaq), opaq->prefix.id);
176 FREE_STRING(LYD_CTX(opaq), opaq->prefix.module_ns);
177 ly_free_val_prefs(LYD_CTX(opaq), opaq->val_prefs);
178 FREE_STRING(LYD_CTX(opaq), opaq->value);
Michal Vasko52927e22020-03-16 17:26:14 +0100179 } else if (node->schema->nodetype & LYD_NODE_INNER) {
180 /* remove children hash table in case of inner data node */
181 lyht_free(((struct lyd_node_inner *)node)->children_ht);
182 ((struct lyd_node_inner *)node)->children_ht = NULL;
183
184 /* free the children */
Radek Krejcia1c1e542020-09-29 16:06:52 +0200185 children = lyd_child(node);
Michal Vasko52927e22020-03-16 17:26:14 +0100186 LY_LIST_FOR_SAFE(children, next, iter) {
187 lyd_free_subtree(iter, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200188 }
189 } else if (node->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko61551fa2020-07-09 15:45:45 +0200190 /* only frees the value this way */
191 lyd_any_copy_value(node, NULL, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200192 } else if (node->schema->nodetype & LYD_NODE_TERM) {
Michal Vaskob7be7a82020-08-20 09:09:04 +0200193 ((struct lysc_node_leaf *)node->schema)->type->plugin->free(LYD_CTX(node), &((struct lyd_node_term *)node)->value);
Radek Krejcie7b95092019-05-15 11:03:07 +0200194 }
195
Michal Vasko52927e22020-03-16 17:26:14 +0100196 if (!node->schema) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200197 lyd_free_attr_siblings(LYD_CTX(node), opaq->attr);
Michal Vasko52927e22020-03-16 17:26:14 +0100198 } else {
199 /* free the node's metadata */
Michal Vasko3a41dff2020-07-15 14:30:28 +0200200 lyd_free_meta_siblings(node->meta);
Michal Vasko52927e22020-03-16 17:26:14 +0100201 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200202
203 /* unlink only the nodes from the first level, nodes in subtree are freed all, so no unlink is needed */
204 if (top) {
205 lyd_unlink_tree(node);
206 }
207
208 free(node);
209}
210
211API void
212lyd_free_tree(struct lyd_node *node)
213{
214 if (!node) {
215 return;
216 }
217
Michal Vasko52927e22020-03-16 17:26:14 +0100218 lyd_free_subtree(node, 1);
Radek Krejcie7b95092019-05-15 11:03:07 +0200219}
220
Radek Krejcib0849a22019-07-25 12:31:04 +0200221static void
Radek Krejci857189e2020-09-01 13:26:36 +0200222lyd_free_(struct lyd_node *node, ly_bool top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200223{
224 struct lyd_node *iter, *next;
225
226 if (!node) {
227 return;
228 }
229
Radek Krejcib0849a22019-07-25 12:31:04 +0200230 /* get the first (top-level) sibling */
231 if (top) {
Michal Vaskod989ba02020-08-24 10:59:24 +0200232 for ( ; node->parent; node = (struct lyd_node *)node->parent) {}
Radek Krejcib0849a22019-07-25 12:31:04 +0200233 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200234 while (node->prev->next) {
235 node = node->prev;
236 }
237
238 LY_LIST_FOR_SAFE(node, next, iter) {
239 /* in case of the top-level nodes (node->parent is NULL), no unlinking needed */
Michal Vasko52927e22020-03-16 17:26:14 +0100240 lyd_free_subtree(iter, iter->parent ? 1 : 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200241 }
242}
Radek Krejcib0849a22019-07-25 12:31:04 +0200243
244API void
Michal Vaskof03ed032020-03-04 13:31:44 +0100245lyd_free_siblings(struct lyd_node *node)
Radek Krejcib0849a22019-07-25 12:31:04 +0200246{
247 lyd_free_(node, 0);
248}
249
250API void
251lyd_free_all(struct lyd_node *node)
252{
253 lyd_free_(node, 1);
254}