blob: 274897a585aded1d2bb9be9237725b0b811706cd [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
Michal Vasko3a41dff2020-07-15 14:30:28 +020027static void
Radek Krejci857189e2020-09-01 13:26:36 +020028lyd_free_meta(struct lyd_meta *meta, ly_bool siblings)
Radek Krejcie7b95092019-05-15 11:03:07 +020029{
Michal Vasko9f96a052020-03-10 09:41:45 +010030 struct lyd_meta *iter;
Radek Krejcie7b95092019-05-15 11:03:07 +020031
Michal Vasko9f96a052020-03-10 09:41:45 +010032 if (!meta) {
Radek Krejcie7b95092019-05-15 11:03:07 +020033 return;
34 }
35
Michal Vasko9f96a052020-03-10 09:41:45 +010036 if (meta->parent) {
37 if (meta->parent->meta == meta) {
Michal Vasko3a41dff2020-07-15 14:30:28 +020038 if (siblings) {
Michal Vasko9f96a052020-03-10 09:41:45 +010039 meta->parent->meta = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +020040 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010041 meta->parent->meta = meta->next;
Radek Krejcie7b95092019-05-15 11:03:07 +020042 }
43 } else {
Radek Krejci1e008d22020-08-17 11:37:37 +020044 for (iter = meta->parent->meta; iter->next != meta; iter = iter->next) {}
Radek Krejcie7b95092019-05-15 11:03:07 +020045 if (iter->next) {
Michal Vasko3a41dff2020-07-15 14:30:28 +020046 if (siblings) {
Radek Krejcie7b95092019-05-15 11:03:07 +020047 iter->next = NULL;
48 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010049 iter->next = meta->next;
Radek Krejcie7b95092019-05-15 11:03:07 +020050 }
51 }
52 }
53 }
54
Michal Vasko3a41dff2020-07-15 14:30:28 +020055 if (!siblings) {
Michal Vasko9f96a052020-03-10 09:41:45 +010056 meta->next = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +020057 }
58
Michal Vasko52927e22020-03-16 17:26:14 +010059 for (iter = meta; iter; ) {
Michal Vasko9f96a052020-03-10 09:41:45 +010060 meta = iter;
Radek Krejcie7b95092019-05-15 11:03:07 +020061 iter = iter->next;
62
Michal Vasko3a41dff2020-07-15 14:30:28 +020063 FREE_STRING(meta->annotation->module->ctx, meta->name);
64 meta->value.realtype->plugin->free(meta->annotation->module->ctx, &meta->value);
Michal Vasko9f96a052020-03-10 09:41:45 +010065 free(meta);
Radek Krejcie7b95092019-05-15 11:03:07 +020066 }
67}
68
Michal Vasko52927e22020-03-16 17:26:14 +010069API void
Michal Vasko3a41dff2020-07-15 14:30:28 +020070lyd_free_meta_single(struct lyd_meta *meta)
71{
72 lyd_free_meta(meta, 0);
73}
74
75API void
76lyd_free_meta_siblings(struct lyd_meta *meta)
77{
78 lyd_free_meta(meta, 1);
79}
80
81static void
Radek Krejci011e4aa2020-09-04 15:22:31 +020082lyd_free_attr(const struct ly_ctx *ctx, struct lyd_attr *attr, ly_bool siblings)
Michal Vasko52927e22020-03-16 17:26:14 +010083{
Radek Krejci1798aae2020-07-14 13:26:06 +020084 struct lyd_attr *iter;
Michal Vasko52927e22020-03-16 17:26:14 +010085
86 LY_CHECK_ARG_RET(NULL, ctx, );
87 if (!attr) {
88 return;
89 }
90
91 if (attr->parent) {
92 if (attr->parent->attr == attr) {
Michal Vasko3a41dff2020-07-15 14:30:28 +020093 if (siblings) {
Michal Vasko52927e22020-03-16 17:26:14 +010094 attr->parent->attr = NULL;
95 } else {
96 attr->parent->attr = attr->next;
97 }
98 } else {
Radek Krejci1e008d22020-08-17 11:37:37 +020099 for (iter = attr->parent->attr; iter->next != attr; iter = iter->next) {}
Michal Vasko52927e22020-03-16 17:26:14 +0100100 if (iter->next) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200101 if (siblings) {
Michal Vasko52927e22020-03-16 17:26:14 +0100102 iter->next = NULL;
103 } else {
104 iter->next = attr->next;
105 }
106 }
107 }
108 }
109
Michal Vasko3a41dff2020-07-15 14:30:28 +0200110 if (!siblings) {
Michal Vasko52927e22020-03-16 17:26:14 +0100111 attr->next = NULL;
112 }
113
114 for (iter = attr; iter; ) {
115 attr = iter;
116 iter = iter->next;
117
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100118 ly_free_prefix_data(attr->format, attr->val_prefix_data);
Michal Vaskoad92b672020-11-12 13:11:31 +0100119 FREE_STRING(ctx, attr->name.name);
120 FREE_STRING(ctx, attr->name.prefix);
121 FREE_STRING(ctx, attr->name.module_ns);
Michal Vasko52927e22020-03-16 17:26:14 +0100122 FREE_STRING(ctx, attr->value);
Michal Vasko52927e22020-03-16 17:26:14 +0100123 free(attr);
124 }
125}
126
Michal Vasko3a41dff2020-07-15 14:30:28 +0200127API void
Radek Krejci011e4aa2020-09-04 15:22:31 +0200128lyd_free_attr_single(const struct ly_ctx *ctx, struct lyd_attr *attr)
Michal Vasko3a41dff2020-07-15 14:30:28 +0200129{
Radek Krejci011e4aa2020-09-04 15:22:31 +0200130 lyd_free_attr(ctx, attr, 0);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200131}
132
133API void
Radek Krejci011e4aa2020-09-04 15:22:31 +0200134lyd_free_attr_siblings(const struct ly_ctx *ctx, struct lyd_attr *attr)
Michal Vasko3a41dff2020-07-15 14:30:28 +0200135{
Radek Krejci011e4aa2020-09-04 15:22:31 +0200136 lyd_free_attr(ctx, attr, 1);
Michal Vasko3a41dff2020-07-15 14:30:28 +0200137}
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
Radek Krejci857189e2020-09-01 13:26:36 +0200145lyd_free_subtree(struct lyd_node *node, ly_bool top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200146{
147 struct lyd_node *iter, *next;
Michal Vaskoed4fcfe2020-07-08 10:38:56 +0200148 struct lyd_node_opaq *opaq = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +0200149
150 assert(node);
151
Michal Vasko52927e22020-03-16 17:26:14 +0100152 if (!node->schema) {
153 opaq = (struct lyd_node_opaq *)node;
Radek Krejcie7b95092019-05-15 11:03:07 +0200154
155 /* free the children */
Michal Vasko501af032020-11-11 20:27:44 +0100156 LY_LIST_FOR_SAFE(lyd_child(node), next, iter) {
Michal Vasko52927e22020-03-16 17:26:14 +0100157 lyd_free_subtree(iter, 0);
158 }
159
Michal Vaskoad92b672020-11-12 13:11:31 +0100160 FREE_STRING(LYD_CTX(opaq), opaq->name.name);
161 FREE_STRING(LYD_CTX(opaq), opaq->name.prefix);
162 FREE_STRING(LYD_CTX(opaq), opaq->name.module_ns);
Michal Vaskob7be7a82020-08-20 09:09:04 +0200163 FREE_STRING(LYD_CTX(opaq), opaq->value);
Michal Vasko501af032020-11-11 20:27:44 +0100164 ly_free_prefix_data(opaq->format, opaq->val_prefix_data);
Michal Vasko52927e22020-03-16 17:26:14 +0100165 } else if (node->schema->nodetype & LYD_NODE_INNER) {
166 /* remove children hash table in case of inner data node */
167 lyht_free(((struct lyd_node_inner *)node)->children_ht);
168 ((struct lyd_node_inner *)node)->children_ht = NULL;
169
170 /* free the children */
Michal Vasko501af032020-11-11 20:27:44 +0100171 LY_LIST_FOR_SAFE(lyd_child(node), next, iter) {
Michal Vasko52927e22020-03-16 17:26:14 +0100172 lyd_free_subtree(iter, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200173 }
174 } else if (node->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko61551fa2020-07-09 15:45:45 +0200175 /* only frees the value this way */
176 lyd_any_copy_value(node, NULL, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200177 } else if (node->schema->nodetype & LYD_NODE_TERM) {
Michal Vaskob7be7a82020-08-20 09:09:04 +0200178 ((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 +0200179 }
180
Michal Vasko52927e22020-03-16 17:26:14 +0100181 if (!node->schema) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200182 lyd_free_attr_siblings(LYD_CTX(node), opaq->attr);
Michal Vasko52927e22020-03-16 17:26:14 +0100183 } else {
184 /* free the node's metadata */
Michal Vasko3a41dff2020-07-15 14:30:28 +0200185 lyd_free_meta_siblings(node->meta);
Michal Vasko52927e22020-03-16 17:26:14 +0100186 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200187
188 /* unlink only the nodes from the first level, nodes in subtree are freed all, so no unlink is needed */
189 if (top) {
190 lyd_unlink_tree(node);
191 }
192
193 free(node);
194}
195
196API void
197lyd_free_tree(struct lyd_node *node)
198{
199 if (!node) {
200 return;
201 }
202
Michal Vasko52927e22020-03-16 17:26:14 +0100203 lyd_free_subtree(node, 1);
Radek Krejcie7b95092019-05-15 11:03:07 +0200204}
205
Radek Krejcib0849a22019-07-25 12:31:04 +0200206static void
Radek Krejci857189e2020-09-01 13:26:36 +0200207lyd_free_(struct lyd_node *node, ly_bool top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200208{
209 struct lyd_node *iter, *next;
210
211 if (!node) {
212 return;
213 }
214
Radek Krejcib0849a22019-07-25 12:31:04 +0200215 /* get the first (top-level) sibling */
216 if (top) {
Michal Vaskod989ba02020-08-24 10:59:24 +0200217 for ( ; node->parent; node = (struct lyd_node *)node->parent) {}
Radek Krejcib0849a22019-07-25 12:31:04 +0200218 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200219 while (node->prev->next) {
220 node = node->prev;
221 }
222
223 LY_LIST_FOR_SAFE(node, next, iter) {
224 /* in case of the top-level nodes (node->parent is NULL), no unlinking needed */
Michal Vasko52927e22020-03-16 17:26:14 +0100225 lyd_free_subtree(iter, iter->parent ? 1 : 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200226 }
227}
Radek Krejcib0849a22019-07-25 12:31:04 +0200228
229API void
Michal Vaskof03ed032020-03-04 13:31:44 +0100230lyd_free_siblings(struct lyd_node *node)
Radek Krejcib0849a22019-07-25 12:31:04 +0200231{
232 lyd_free_(node, 0);
233}
234
235API void
236lyd_free_all(struct lyd_node *node)
237{
238 lyd_free_(node, 1);
239}