blob: 519ce06d00f5fbbe5cadb4249254da7142ef3a7a [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
16#include <assert.h>
17#include <stdlib.h>
18
Radek Krejci535ea9f2020-05-29 16:01:05 +020019#include "common.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020020#include "hash_table.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020021#include "tree.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020022#include "tree_schema.h"
23#include "tree_data_internal.h"
Radek Krejci849a62a2019-05-22 15:29:05 +020024#include "plugins_types.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020025
Michal Vasko3a41dff2020-07-15 14:30:28 +020026static void
27lyd_free_meta(struct lyd_meta *meta, int siblings)
Radek Krejcie7b95092019-05-15 11:03:07 +020028{
Michal Vasko9f96a052020-03-10 09:41:45 +010029 struct lyd_meta *iter;
Radek Krejcie7b95092019-05-15 11:03:07 +020030
Michal Vasko9f96a052020-03-10 09:41:45 +010031 if (!meta) {
Radek Krejcie7b95092019-05-15 11:03:07 +020032 return;
33 }
34
Michal Vasko9f96a052020-03-10 09:41:45 +010035 if (meta->parent) {
36 if (meta->parent->meta == meta) {
Michal Vasko3a41dff2020-07-15 14:30:28 +020037 if (siblings) {
Michal Vasko9f96a052020-03-10 09:41:45 +010038 meta->parent->meta = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +020039 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010040 meta->parent->meta = meta->next;
Radek Krejcie7b95092019-05-15 11:03:07 +020041 }
42 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010043 for (iter = meta->parent->meta; iter->next != meta; iter = iter->next);
Radek Krejcie7b95092019-05-15 11:03:07 +020044 if (iter->next) {
Michal Vasko3a41dff2020-07-15 14:30:28 +020045 if (siblings) {
Radek Krejcie7b95092019-05-15 11:03:07 +020046 iter->next = NULL;
47 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010048 iter->next = meta->next;
Radek Krejcie7b95092019-05-15 11:03:07 +020049 }
50 }
51 }
52 }
53
Michal Vasko3a41dff2020-07-15 14:30:28 +020054 if (!siblings) {
Michal Vasko9f96a052020-03-10 09:41:45 +010055 meta->next = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +020056 }
57
Michal Vasko52927e22020-03-16 17:26:14 +010058 for (iter = meta; iter; ) {
Michal Vasko9f96a052020-03-10 09:41:45 +010059 meta = iter;
Radek Krejcie7b95092019-05-15 11:03:07 +020060 iter = iter->next;
61
Michal Vasko3a41dff2020-07-15 14:30:28 +020062 FREE_STRING(meta->annotation->module->ctx, meta->name);
63 meta->value.realtype->plugin->free(meta->annotation->module->ctx, &meta->value);
Michal Vasko9f96a052020-03-10 09:41:45 +010064 free(meta);
Radek Krejcie7b95092019-05-15 11:03:07 +020065 }
66}
67
Michal Vasko52927e22020-03-16 17:26:14 +010068API void
Michal Vasko3a41dff2020-07-15 14:30:28 +020069lyd_free_meta_single(struct lyd_meta *meta)
70{
71 lyd_free_meta(meta, 0);
72}
73
74API void
75lyd_free_meta_siblings(struct lyd_meta *meta)
76{
77 lyd_free_meta(meta, 1);
78}
79
80static void
Radek Krejci1798aae2020-07-14 13:26:06 +020081ly_free_attr(const struct ly_ctx *ctx, struct lyd_attr *attr, int siblings)
Michal Vasko52927e22020-03-16 17:26:14 +010082{
Radek Krejci1798aae2020-07-14 13:26:06 +020083 struct lyd_attr *iter;
Michal Vaskofd69e1d2020-07-03 11:57:17 +020084 LY_ARRAY_COUNT_TYPE u;
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 {
99 for (iter = attr->parent->attr; iter->next != attr; iter = iter->next);
100 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
118 LY_ARRAY_FOR(attr->val_prefs, u) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200119 FREE_STRING(ctx, attr->val_prefs[u].id);
120 FREE_STRING(ctx, attr->val_prefs[u].module_ns);
Michal Vasko52927e22020-03-16 17:26:14 +0100121 }
122 LY_ARRAY_FREE(attr->val_prefs);
123 FREE_STRING(ctx, attr->name);
124 FREE_STRING(ctx, attr->value);
Radek Krejci1798aae2020-07-14 13:26:06 +0200125 FREE_STRING(ctx, attr->prefix.id);
126 FREE_STRING(ctx, attr->prefix.module_ns);
Michal Vasko52927e22020-03-16 17:26:14 +0100127 free(attr);
128 }
129}
130
Michal Vasko3a41dff2020-07-15 14:30:28 +0200131API void
Radek Krejci1798aae2020-07-14 13:26:06 +0200132ly_free_attr_single(const struct ly_ctx *ctx, struct lyd_attr *attr)
Michal Vasko3a41dff2020-07-15 14:30:28 +0200133{
134 ly_free_attr(ctx, attr, 0);
135}
136
137API void
Radek Krejci1798aae2020-07-14 13:26:06 +0200138ly_free_attr_siblings(const struct ly_ctx *ctx, struct lyd_attr *attr)
Michal Vasko3a41dff2020-07-15 14:30:28 +0200139{
140 ly_free_attr(ctx, attr, 1);
141}
142
Michal Vasko60ea6352020-06-29 13:39:39 +0200143void
144ly_free_val_prefs(const struct ly_ctx *ctx, struct ly_prefix *val_prefs)
145{
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200146 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +0200147
148 LY_ARRAY_FOR(val_prefs, u) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200149 FREE_STRING(ctx, val_prefs[u].id);
150 FREE_STRING(ctx, val_prefs[u].module_ns);
Michal Vasko60ea6352020-06-29 13:39:39 +0200151 }
152 LY_ARRAY_FREE(val_prefs);
153}
154
Radek Krejcie7b95092019-05-15 11:03:07 +0200155/**
156 * @brief Free Data (sub)tree.
Radek Krejcie7b95092019-05-15 11:03:07 +0200157 * @param[in] node Data node to be freed.
158 * @param[in] top Recursion flag to unlink the root of the subtree being freed.
159 */
160static void
Michal Vasko52927e22020-03-16 17:26:14 +0100161lyd_free_subtree(struct lyd_node *node, int top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200162{
163 struct lyd_node *iter, *next;
164 struct lyd_node *children;
Michal Vaskoed4fcfe2020-07-08 10:38:56 +0200165 struct lyd_node_opaq *opaq = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +0200166
167 assert(node);
168
Michal Vasko52927e22020-03-16 17:26:14 +0100169 if (!node->schema) {
170 opaq = (struct lyd_node_opaq *)node;
Radek Krejcie7b95092019-05-15 11:03:07 +0200171
172 /* free the children */
Michal Vasko5bfd4be2020-06-23 13:26:19 +0200173 children = lyd_node_children(node, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200174 LY_LIST_FOR_SAFE(children, next, iter) {
Michal Vasko52927e22020-03-16 17:26:14 +0100175 lyd_free_subtree(iter, 0);
176 }
177
178 FREE_STRING(LYD_NODE_CTX(opaq), opaq->name);
Radek Krejci1798aae2020-07-14 13:26:06 +0200179 FREE_STRING(LYD_NODE_CTX(opaq), opaq->prefix.id);
180 FREE_STRING(LYD_NODE_CTX(opaq), opaq->prefix.module_ns);
Michal Vasko60ea6352020-06-29 13:39:39 +0200181 ly_free_val_prefs(LYD_NODE_CTX(opaq), opaq->val_prefs);
Michal Vasko52927e22020-03-16 17:26:14 +0100182 FREE_STRING(LYD_NODE_CTX(opaq), opaq->value);
183 } else if (node->schema->nodetype & LYD_NODE_INNER) {
184 /* remove children hash table in case of inner data node */
185 lyht_free(((struct lyd_node_inner *)node)->children_ht);
186 ((struct lyd_node_inner *)node)->children_ht = NULL;
187
188 /* free the children */
Michal Vasko5bfd4be2020-06-23 13:26:19 +0200189 children = lyd_node_children(node, 0);
Michal Vasko52927e22020-03-16 17:26:14 +0100190 LY_LIST_FOR_SAFE(children, next, iter) {
191 lyd_free_subtree(iter, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200192 }
193 } else if (node->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko61551fa2020-07-09 15:45:45 +0200194 /* only frees the value this way */
195 lyd_any_copy_value(node, NULL, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200196 } else if (node->schema->nodetype & LYD_NODE_TERM) {
Michal Vasko52927e22020-03-16 17:26:14 +0100197 ((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 +0200198 }
199
Michal Vasko52927e22020-03-16 17:26:14 +0100200 if (!node->schema) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200201 ly_free_attr_siblings(LYD_NODE_CTX(node), opaq->attr);
Michal Vasko52927e22020-03-16 17:26:14 +0100202 } else {
203 /* free the node's metadata */
Michal Vasko3a41dff2020-07-15 14:30:28 +0200204 lyd_free_meta_siblings(node->meta);
Michal Vasko52927e22020-03-16 17:26:14 +0100205 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200206
207 /* unlink only the nodes from the first level, nodes in subtree are freed all, so no unlink is needed */
208 if (top) {
209 lyd_unlink_tree(node);
210 }
211
212 free(node);
213}
214
215API void
216lyd_free_tree(struct lyd_node *node)
217{
218 if (!node) {
219 return;
220 }
221
Michal Vasko52927e22020-03-16 17:26:14 +0100222 lyd_free_subtree(node, 1);
Radek Krejcie7b95092019-05-15 11:03:07 +0200223}
224
Radek Krejcib0849a22019-07-25 12:31:04 +0200225static void
226lyd_free_(struct lyd_node *node, int top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200227{
228 struct lyd_node *iter, *next;
229
230 if (!node) {
231 return;
232 }
233
Radek Krejcib0849a22019-07-25 12:31:04 +0200234 /* get the first (top-level) sibling */
235 if (top) {
Michal Vasko52927e22020-03-16 17:26:14 +0100236 for (; node->parent; node = (struct lyd_node *)node->parent);
Radek Krejcib0849a22019-07-25 12:31:04 +0200237 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200238 while (node->prev->next) {
239 node = node->prev;
240 }
241
242 LY_LIST_FOR_SAFE(node, next, iter) {
243 /* in case of the top-level nodes (node->parent is NULL), no unlinking needed */
Michal Vasko52927e22020-03-16 17:26:14 +0100244 lyd_free_subtree(iter, iter->parent ? 1 : 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200245 }
246}
Radek Krejcib0849a22019-07-25 12:31:04 +0200247
248API void
Michal Vaskof03ed032020-03-04 13:31:44 +0100249lyd_free_siblings(struct lyd_node *node)
Radek Krejcib0849a22019-07-25 12:31:04 +0200250{
251 lyd_free_(node, 0);
252}
253
254API void
255lyd_free_all(struct lyd_node *node)
256{
257 lyd_free_(node, 1);
258}