blob: 7c0a52a5042dd1f53478f40be2ff1504e43fd2b6 [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 Krejcie7b95092019-05-15 11:03:07 +020020#include "tree.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020021#include "tree_schema.h"
22#include "tree_data_internal.h"
Radek Krejci849a62a2019-05-22 15:29:05 +020023#include "plugins_types.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020024
Michal Vasko3a41dff2020-07-15 14:30:28 +020025static void
Radek Krejci1deb5be2020-08-26 16:43:36 +020026lyd_free_meta(struct lyd_meta *meta, uint8_t siblings)
Radek Krejcie7b95092019-05-15 11:03:07 +020027{
Michal Vasko9f96a052020-03-10 09:41:45 +010028 struct lyd_meta *iter;
Radek Krejcie7b95092019-05-15 11:03:07 +020029
Michal Vasko9f96a052020-03-10 09:41:45 +010030 if (!meta) {
Radek Krejcie7b95092019-05-15 11:03:07 +020031 return;
32 }
33
Michal Vasko9f96a052020-03-10 09:41:45 +010034 if (meta->parent) {
35 if (meta->parent->meta == meta) {
Michal Vasko3a41dff2020-07-15 14:30:28 +020036 if (siblings) {
Michal Vasko9f96a052020-03-10 09:41:45 +010037 meta->parent->meta = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +020038 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010039 meta->parent->meta = meta->next;
Radek Krejcie7b95092019-05-15 11:03:07 +020040 }
41 } else {
Radek Krejci1e008d22020-08-17 11:37:37 +020042 for (iter = meta->parent->meta; iter->next != meta; iter = iter->next) {}
Radek Krejcie7b95092019-05-15 11:03:07 +020043 if (iter->next) {
Michal Vasko3a41dff2020-07-15 14:30:28 +020044 if (siblings) {
Radek Krejcie7b95092019-05-15 11:03:07 +020045 iter->next = NULL;
46 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010047 iter->next = meta->next;
Radek Krejcie7b95092019-05-15 11:03:07 +020048 }
49 }
50 }
51 }
52
Michal Vasko3a41dff2020-07-15 14:30:28 +020053 if (!siblings) {
Michal Vasko9f96a052020-03-10 09:41:45 +010054 meta->next = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +020055 }
56
Michal Vasko52927e22020-03-16 17:26:14 +010057 for (iter = meta; iter; ) {
Michal Vasko9f96a052020-03-10 09:41:45 +010058 meta = iter;
Radek Krejcie7b95092019-05-15 11:03:07 +020059 iter = iter->next;
60
Michal Vasko3a41dff2020-07-15 14:30:28 +020061 FREE_STRING(meta->annotation->module->ctx, meta->name);
62 meta->value.realtype->plugin->free(meta->annotation->module->ctx, &meta->value);
Michal Vasko9f96a052020-03-10 09:41:45 +010063 free(meta);
Radek Krejcie7b95092019-05-15 11:03:07 +020064 }
65}
66
Michal Vasko52927e22020-03-16 17:26:14 +010067API void
Michal Vasko3a41dff2020-07-15 14:30:28 +020068lyd_free_meta_single(struct lyd_meta *meta)
69{
70 lyd_free_meta(meta, 0);
71}
72
73API void
74lyd_free_meta_siblings(struct lyd_meta *meta)
75{
76 lyd_free_meta(meta, 1);
77}
78
79static void
Radek Krejci1deb5be2020-08-26 16:43:36 +020080ly_free_attr(const struct ly_ctx *ctx, struct lyd_attr *attr, uint8_t siblings)
Michal Vasko52927e22020-03-16 17:26:14 +010081{
Radek Krejci1798aae2020-07-14 13:26:06 +020082 struct lyd_attr *iter;
Michal Vaskofd69e1d2020-07-03 11:57:17 +020083 LY_ARRAY_COUNT_TYPE u;
Michal Vasko52927e22020-03-16 17:26:14 +010084
85 LY_CHECK_ARG_RET(NULL, ctx, );
86 if (!attr) {
87 return;
88 }
89
90 if (attr->parent) {
91 if (attr->parent->attr == attr) {
Michal Vasko3a41dff2020-07-15 14:30:28 +020092 if (siblings) {
Michal Vasko52927e22020-03-16 17:26:14 +010093 attr->parent->attr = NULL;
94 } else {
95 attr->parent->attr = attr->next;
96 }
97 } else {
Radek Krejci1e008d22020-08-17 11:37:37 +020098 for (iter = attr->parent->attr; iter->next != attr; iter = iter->next) {}
Michal Vasko52927e22020-03-16 17:26:14 +010099 if (iter->next) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200100 if (siblings) {
Michal Vasko52927e22020-03-16 17:26:14 +0100101 iter->next = NULL;
102 } else {
103 iter->next = attr->next;
104 }
105 }
106 }
107 }
108
Michal Vasko3a41dff2020-07-15 14:30:28 +0200109 if (!siblings) {
Michal Vasko52927e22020-03-16 17:26:14 +0100110 attr->next = NULL;
111 }
112
113 for (iter = attr; iter; ) {
114 attr = iter;
115 iter = iter->next;
116
117 LY_ARRAY_FOR(attr->val_prefs, u) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200118 FREE_STRING(ctx, attr->val_prefs[u].id);
119 FREE_STRING(ctx, attr->val_prefs[u].module_ns);
Michal Vasko52927e22020-03-16 17:26:14 +0100120 }
121 LY_ARRAY_FREE(attr->val_prefs);
122 FREE_STRING(ctx, attr->name);
123 FREE_STRING(ctx, attr->value);
Radek Krejci1798aae2020-07-14 13:26:06 +0200124 FREE_STRING(ctx, attr->prefix.id);
125 FREE_STRING(ctx, attr->prefix.module_ns);
Michal Vasko52927e22020-03-16 17:26:14 +0100126 free(attr);
127 }
128}
129
Michal Vasko3a41dff2020-07-15 14:30:28 +0200130API void
Radek Krejci1798aae2020-07-14 13:26:06 +0200131ly_free_attr_single(const struct ly_ctx *ctx, struct lyd_attr *attr)
Michal Vasko3a41dff2020-07-15 14:30:28 +0200132{
133 ly_free_attr(ctx, attr, 0);
134}
135
136API void
Radek Krejci1798aae2020-07-14 13:26:06 +0200137ly_free_attr_siblings(const struct ly_ctx *ctx, struct lyd_attr *attr)
Michal Vasko3a41dff2020-07-15 14:30:28 +0200138{
139 ly_free_attr(ctx, attr, 1);
140}
141
Michal Vasko60ea6352020-06-29 13:39:39 +0200142void
143ly_free_val_prefs(const struct ly_ctx *ctx, struct ly_prefix *val_prefs)
144{
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200145 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +0200146
147 LY_ARRAY_FOR(val_prefs, u) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200148 FREE_STRING(ctx, val_prefs[u].id);
149 FREE_STRING(ctx, val_prefs[u].module_ns);
Michal Vasko60ea6352020-06-29 13:39:39 +0200150 }
151 LY_ARRAY_FREE(val_prefs);
152}
153
Radek Krejcie7b95092019-05-15 11:03:07 +0200154/**
155 * @brief Free Data (sub)tree.
Radek Krejcie7b95092019-05-15 11:03:07 +0200156 * @param[in] node Data node to be freed.
157 * @param[in] top Recursion flag to unlink the root of the subtree being freed.
158 */
159static void
Radek Krejci1deb5be2020-08-26 16:43:36 +0200160lyd_free_subtree(struct lyd_node *node, uint8_t top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200161{
162 struct lyd_node *iter, *next;
163 struct lyd_node *children;
Michal Vaskoed4fcfe2020-07-08 10:38:56 +0200164 struct lyd_node_opaq *opaq = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +0200165
166 assert(node);
167
Michal Vasko52927e22020-03-16 17:26:14 +0100168 if (!node->schema) {
169 opaq = (struct lyd_node_opaq *)node;
Radek Krejcie7b95092019-05-15 11:03:07 +0200170
171 /* free the children */
Michal Vasko5bfd4be2020-06-23 13:26:19 +0200172 children = lyd_node_children(node, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200173 LY_LIST_FOR_SAFE(children, next, iter) {
Michal Vasko52927e22020-03-16 17:26:14 +0100174 lyd_free_subtree(iter, 0);
175 }
176
Michal Vaskob7be7a82020-08-20 09:09:04 +0200177 FREE_STRING(LYD_CTX(opaq), opaq->name);
178 FREE_STRING(LYD_CTX(opaq), opaq->prefix.id);
179 FREE_STRING(LYD_CTX(opaq), opaq->prefix.module_ns);
180 ly_free_val_prefs(LYD_CTX(opaq), opaq->val_prefs);
181 FREE_STRING(LYD_CTX(opaq), opaq->value);
Michal Vasko52927e22020-03-16 17:26:14 +0100182 } else if (node->schema->nodetype & LYD_NODE_INNER) {
183 /* remove children hash table in case of inner data node */
184 lyht_free(((struct lyd_node_inner *)node)->children_ht);
185 ((struct lyd_node_inner *)node)->children_ht = NULL;
186
187 /* free the children */
Michal Vasko5bfd4be2020-06-23 13:26:19 +0200188 children = lyd_node_children(node, 0);
Michal Vasko52927e22020-03-16 17:26:14 +0100189 LY_LIST_FOR_SAFE(children, next, iter) {
190 lyd_free_subtree(iter, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200191 }
192 } else if (node->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko61551fa2020-07-09 15:45:45 +0200193 /* only frees the value this way */
194 lyd_any_copy_value(node, NULL, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200195 } else if (node->schema->nodetype & LYD_NODE_TERM) {
Michal Vaskob7be7a82020-08-20 09:09:04 +0200196 ((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 +0200197 }
198
Michal Vasko52927e22020-03-16 17:26:14 +0100199 if (!node->schema) {
Michal Vaskob7be7a82020-08-20 09:09:04 +0200200 ly_free_attr_siblings(LYD_CTX(node), opaq->attr);
Michal Vasko52927e22020-03-16 17:26:14 +0100201 } else {
202 /* free the node's metadata */
Michal Vasko3a41dff2020-07-15 14:30:28 +0200203 lyd_free_meta_siblings(node->meta);
Michal Vasko52927e22020-03-16 17:26:14 +0100204 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200205
206 /* unlink only the nodes from the first level, nodes in subtree are freed all, so no unlink is needed */
207 if (top) {
208 lyd_unlink_tree(node);
209 }
210
211 free(node);
212}
213
214API void
215lyd_free_tree(struct lyd_node *node)
216{
217 if (!node) {
218 return;
219 }
220
Michal Vasko52927e22020-03-16 17:26:14 +0100221 lyd_free_subtree(node, 1);
Radek Krejcie7b95092019-05-15 11:03:07 +0200222}
223
Radek Krejcib0849a22019-07-25 12:31:04 +0200224static void
Radek Krejci1deb5be2020-08-26 16:43:36 +0200225lyd_free_(struct lyd_node *node, uint8_t top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200226{
227 struct lyd_node *iter, *next;
228
229 if (!node) {
230 return;
231 }
232
Radek Krejcib0849a22019-07-25 12:31:04 +0200233 /* get the first (top-level) sibling */
234 if (top) {
Michal Vaskod989ba02020-08-24 10:59:24 +0200235 for ( ; node->parent; node = (struct lyd_node *)node->parent) {}
Radek Krejcib0849a22019-07-25 12:31:04 +0200236 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200237 while (node->prev->next) {
238 node = node->prev;
239 }
240
241 LY_LIST_FOR_SAFE(node, next, iter) {
242 /* in case of the top-level nodes (node->parent is NULL), no unlinking needed */
Michal Vasko52927e22020-03-16 17:26:14 +0100243 lyd_free_subtree(iter, iter->parent ? 1 : 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200244 }
245}
Radek Krejcib0849a22019-07-25 12:31:04 +0200246
247API void
Michal Vaskof03ed032020-03-04 13:31:44 +0100248lyd_free_siblings(struct lyd_node *node)
Radek Krejcib0849a22019-07-25 12:31:04 +0200249{
250 lyd_free_(node, 0);
251}
252
253API void
254lyd_free_all(struct lyd_node *node)
255{
256 lyd_free_(node, 1);
257}