blob: cf70bf7b7cb660453dfbdc8fd96f9d4fcd4696cc [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 Krejci77114102021-03-10 15:21:57 +010019#include "dict.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020020#include "hash_table.h"
Radek Krejci47fab892020-11-05 17:02:41 +010021#include "log.h"
Radek Krejci849a62a2019-05-22 15:29:05 +020022#include "plugins_types.h"
Michal Vasko69730152020-10-09 16:30:07 +020023#include "tree.h"
Radek Krejci47fab892020-11-05 17:02:41 +010024#include "tree_data.h"
Michal Vasko69730152020-10-09 16:30:07 +020025#include "tree_data_internal.h"
26#include "tree_schema.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020027
Michal Vasko3a41dff2020-07-15 14:30:28 +020028static void
Radek Krejci857189e2020-09-01 13:26:36 +020029lyd_free_meta(struct lyd_meta *meta, ly_bool siblings)
Radek Krejcie7b95092019-05-15 11:03:07 +020030{
Michal Vasko9f96a052020-03-10 09:41:45 +010031 struct lyd_meta *iter;
Radek Krejcie7b95092019-05-15 11:03:07 +020032
Michal Vasko9f96a052020-03-10 09:41:45 +010033 if (!meta) {
Radek Krejcie7b95092019-05-15 11:03:07 +020034 return;
35 }
36
Michal Vasko9f96a052020-03-10 09:41:45 +010037 if (meta->parent) {
38 if (meta->parent->meta == meta) {
Michal Vasko3a41dff2020-07-15 14:30:28 +020039 if (siblings) {
Michal Vasko9f96a052020-03-10 09:41:45 +010040 meta->parent->meta = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +020041 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010042 meta->parent->meta = meta->next;
Radek Krejcie7b95092019-05-15 11:03:07 +020043 }
44 } else {
Radek Krejci1e008d22020-08-17 11:37:37 +020045 for (iter = meta->parent->meta; iter->next != meta; iter = iter->next) {}
Radek Krejcie7b95092019-05-15 11:03:07 +020046 if (iter->next) {
Michal Vasko3a41dff2020-07-15 14:30:28 +020047 if (siblings) {
Radek Krejcie7b95092019-05-15 11:03:07 +020048 iter->next = NULL;
49 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010050 iter->next = meta->next;
Radek Krejcie7b95092019-05-15 11:03:07 +020051 }
52 }
53 }
54 }
55
Michal Vasko3a41dff2020-07-15 14:30:28 +020056 if (!siblings) {
Michal Vasko9f96a052020-03-10 09:41:45 +010057 meta->next = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +020058 }
59
Michal Vasko52927e22020-03-16 17:26:14 +010060 for (iter = meta; iter; ) {
Michal Vasko9f96a052020-03-10 09:41:45 +010061 meta = iter;
Radek Krejcie7b95092019-05-15 11:03:07 +020062 iter = iter->next;
63
Michal Vaskoe180ed02021-02-05 16:31:20 +010064 lydict_remove(meta->annotation->module->ctx, meta->name);
Michal Vasko3a41dff2020-07-15 14:30:28 +020065 meta->value.realtype->plugin->free(meta->annotation->module->ctx, &meta->value);
Michal Vasko9f96a052020-03-10 09:41:45 +010066 free(meta);
Radek Krejcie7b95092019-05-15 11:03:07 +020067 }
68}
69
Michal Vasko52927e22020-03-16 17:26:14 +010070API void
Michal Vasko3a41dff2020-07-15 14:30:28 +020071lyd_free_meta_single(struct lyd_meta *meta)
72{
73 lyd_free_meta(meta, 0);
74}
75
76API void
77lyd_free_meta_siblings(struct lyd_meta *meta)
78{
79 lyd_free_meta(meta, 1);
80}
81
82static void
Radek Krejci011e4aa2020-09-04 15:22:31 +020083lyd_free_attr(const struct ly_ctx *ctx, struct lyd_attr *attr, ly_bool siblings)
Michal Vasko52927e22020-03-16 17:26:14 +010084{
Radek Krejci1798aae2020-07-14 13:26:06 +020085 struct lyd_attr *iter;
Michal Vasko52927e22020-03-16 17:26:14 +010086
87 LY_CHECK_ARG_RET(NULL, ctx, );
88 if (!attr) {
89 return;
90 }
91
92 if (attr->parent) {
93 if (attr->parent->attr == attr) {
Michal Vasko3a41dff2020-07-15 14:30:28 +020094 if (siblings) {
Michal Vasko52927e22020-03-16 17:26:14 +010095 attr->parent->attr = NULL;
96 } else {
97 attr->parent->attr = attr->next;
98 }
99 } else {
Radek Krejci1e008d22020-08-17 11:37:37 +0200100 for (iter = attr->parent->attr; iter->next != attr; iter = iter->next) {}
Michal Vasko52927e22020-03-16 17:26:14 +0100101 if (iter->next) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200102 if (siblings) {
Michal Vasko52927e22020-03-16 17:26:14 +0100103 iter->next = NULL;
104 } else {
105 iter->next = attr->next;
106 }
107 }
108 }
109 }
110
Michal Vasko3a41dff2020-07-15 14:30:28 +0200111 if (!siblings) {
Michal Vasko52927e22020-03-16 17:26:14 +0100112 attr->next = NULL;
113 }
114
115 for (iter = attr; iter; ) {
116 attr = iter;
117 iter = iter->next;
118
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100119 ly_free_prefix_data(attr->format, attr->val_prefix_data);
Michal Vaskoe180ed02021-02-05 16:31:20 +0100120 lydict_remove(ctx, attr->name.name);
121 lydict_remove(ctx, attr->name.prefix);
122 lydict_remove(ctx, attr->name.module_ns);
123 lydict_remove(ctx, attr->value);
Michal Vasko52927e22020-03-16 17:26:14 +0100124 free(attr);
125 }
126}
127
Michal Vasko3a41dff2020-07-15 14:30:28 +0200128API void
Radek Krejci011e4aa2020-09-04 15:22:31 +0200129lyd_free_attr_single(const struct ly_ctx *ctx, struct lyd_attr *attr)
Michal Vasko3a41dff2020-07-15 14:30:28 +0200130{
Radek Krejci011e4aa2020-09-04 15:22:31 +0200131 lyd_free_attr(ctx, attr, 0);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200132}
133
134API void
Radek Krejci011e4aa2020-09-04 15:22:31 +0200135lyd_free_attr_siblings(const struct ly_ctx *ctx, struct lyd_attr *attr)
Michal Vasko3a41dff2020-07-15 14:30:28 +0200136{
Radek Krejci011e4aa2020-09-04 15:22:31 +0200137 lyd_free_attr(ctx, attr, 1);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200138}
139
Radek Krejcie7b95092019-05-15 11:03:07 +0200140/**
141 * @brief Free Data (sub)tree.
Radek Krejcie7b95092019-05-15 11:03:07 +0200142 * @param[in] node Data node to be freed.
143 * @param[in] top Recursion flag to unlink the root of the subtree being freed.
144 */
145static void
Radek Krejci857189e2020-09-01 13:26:36 +0200146lyd_free_subtree(struct lyd_node *node, ly_bool top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200147{
148 struct lyd_node *iter, *next;
Michal Vaskoed4fcfe2020-07-08 10:38:56 +0200149 struct lyd_node_opaq *opaq = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +0200150
151 assert(node);
152
Michal Vasko52927e22020-03-16 17:26:14 +0100153 if (!node->schema) {
154 opaq = (struct lyd_node_opaq *)node;
Radek Krejcie7b95092019-05-15 11:03:07 +0200155
156 /* free the children */
Michal Vasko501af032020-11-11 20:27:44 +0100157 LY_LIST_FOR_SAFE(lyd_child(node), next, iter) {
Michal Vasko52927e22020-03-16 17:26:14 +0100158 lyd_free_subtree(iter, 0);
159 }
160
Michal Vaskoe180ed02021-02-05 16:31:20 +0100161 lydict_remove(LYD_CTX(opaq), opaq->name.name);
162 lydict_remove(LYD_CTX(opaq), opaq->name.prefix);
163 lydict_remove(LYD_CTX(opaq), opaq->name.module_ns);
164 lydict_remove(LYD_CTX(opaq), opaq->value);
Michal Vasko501af032020-11-11 20:27:44 +0100165 ly_free_prefix_data(opaq->format, opaq->val_prefix_data);
Michal Vasko52927e22020-03-16 17:26:14 +0100166 } else if (node->schema->nodetype & LYD_NODE_INNER) {
167 /* remove children hash table in case of inner data node */
168 lyht_free(((struct lyd_node_inner *)node)->children_ht);
169 ((struct lyd_node_inner *)node)->children_ht = NULL;
170
171 /* free the children */
Michal Vasko501af032020-11-11 20:27:44 +0100172 LY_LIST_FOR_SAFE(lyd_child(node), next, iter) {
Michal Vasko52927e22020-03-16 17:26:14 +0100173 lyd_free_subtree(iter, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200174 }
175 } else if (node->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko61551fa2020-07-09 15:45:45 +0200176 /* only frees the value this way */
177 lyd_any_copy_value(node, NULL, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200178 } else if (node->schema->nodetype & LYD_NODE_TERM) {
Michal Vaskob7be7a82020-08-20 09:09:04 +0200179 ((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 +0200180 }
181
Michal Vasko52927e22020-03-16 17:26:14 +0100182 if (!node->schema) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200183 lyd_free_attr_siblings(LYD_CTX(node), opaq->attr);
Michal Vasko52927e22020-03-16 17:26:14 +0100184 } else {
185 /* free the node's metadata */
Michal Vasko3a41dff2020-07-15 14:30:28 +0200186 lyd_free_meta_siblings(node->meta);
Michal Vasko52927e22020-03-16 17:26:14 +0100187 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200188
189 /* unlink only the nodes from the first level, nodes in subtree are freed all, so no unlink is needed */
190 if (top) {
191 lyd_unlink_tree(node);
192 }
193
194 free(node);
195}
196
197API void
198lyd_free_tree(struct lyd_node *node)
199{
200 if (!node) {
201 return;
202 }
203
Michal Vasko52927e22020-03-16 17:26:14 +0100204 lyd_free_subtree(node, 1);
Radek Krejcie7b95092019-05-15 11:03:07 +0200205}
206
Radek Krejcib0849a22019-07-25 12:31:04 +0200207static void
Radek Krejci857189e2020-09-01 13:26:36 +0200208lyd_free_(struct lyd_node *node, ly_bool top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200209{
210 struct lyd_node *iter, *next;
211
212 if (!node) {
213 return;
214 }
215
Radek Krejcib0849a22019-07-25 12:31:04 +0200216 /* get the first (top-level) sibling */
217 if (top) {
Michal Vasko9e685082021-01-29 14:49:09 +0100218 for ( ; node->parent; node = lyd_parent(node)) {}
Radek Krejcib0849a22019-07-25 12:31:04 +0200219 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200220 while (node->prev->next) {
221 node = node->prev;
222 }
223
224 LY_LIST_FOR_SAFE(node, next, iter) {
225 /* in case of the top-level nodes (node->parent is NULL), no unlinking needed */
Michal Vasko52927e22020-03-16 17:26:14 +0100226 lyd_free_subtree(iter, iter->parent ? 1 : 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200227 }
228}
Radek Krejcib0849a22019-07-25 12:31:04 +0200229
230API void
Michal Vaskof03ed032020-03-04 13:31:44 +0100231lyd_free_siblings(struct lyd_node *node)
Radek Krejcib0849a22019-07-25 12:31:04 +0200232{
233 lyd_free_(node, 0);
234}
235
236API void
237lyd_free_all(struct lyd_node *node)
238{
239 lyd_free_(node, 1);
240}