blob: 5b0eef5962e47dd15eefdcd488eb60d43c4768c9 [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
Radek Krejci084289f2019-07-09 17:35:30 +020026void
Michal Vasko52927e22020-03-16 17:26:14 +010027lyd_value_free_path(const struct ly_ctx *ctx, struct lyd_value_path *path)
Radek Krejci084289f2019-07-09 17:35:30 +020028{
Radek Krejci7eb54ba2020-05-18 16:30:04 +020029 LY_ARRAY_SIZE_TYPE u, v;
Radek Krejci084289f2019-07-09 17:35:30 +020030
31 LY_ARRAY_FOR(path, u) {
32 LY_ARRAY_FOR(path[u].predicates, v) {
33 if (path[u].predicates[v].type > 0) {
Radek Krejci62903c32019-07-15 14:42:05 +020034 ((struct lysc_node_leaf*)path[u].predicates[v].key)->type->plugin->free(ctx, path[u].predicates[v].value);
Radek Krejci084289f2019-07-09 17:35:30 +020035 free(path[u].predicates[v].value);
36 }
37 }
38 LY_ARRAY_FREE(path[u].predicates);
39 }
40 LY_ARRAY_FREE(path);
41}
42
Radek Krejcie7b95092019-05-15 11:03:07 +020043API void
Michal Vasko52927e22020-03-16 17:26:14 +010044lyd_free_meta(const struct ly_ctx *ctx, struct lyd_meta *meta, int recursive)
Radek Krejcie7b95092019-05-15 11:03:07 +020045{
Michal Vasko9f96a052020-03-10 09:41:45 +010046 struct lyd_meta *iter;
Radek Krejcie7b95092019-05-15 11:03:07 +020047
48 LY_CHECK_ARG_RET(NULL, ctx, );
Michal Vasko9f96a052020-03-10 09:41:45 +010049 if (!meta) {
Radek Krejcie7b95092019-05-15 11:03:07 +020050 return;
51 }
52
Michal Vasko9f96a052020-03-10 09:41:45 +010053 if (meta->parent) {
54 if (meta->parent->meta == meta) {
Radek Krejcie7b95092019-05-15 11:03:07 +020055 if (recursive) {
Michal Vasko9f96a052020-03-10 09:41:45 +010056 meta->parent->meta = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +020057 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010058 meta->parent->meta = meta->next;
Radek Krejcie7b95092019-05-15 11:03:07 +020059 }
60 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010061 for (iter = meta->parent->meta; iter->next != meta; iter = iter->next);
Radek Krejcie7b95092019-05-15 11:03:07 +020062 if (iter->next) {
63 if (recursive) {
64 iter->next = NULL;
65 } else {
Michal Vasko9f96a052020-03-10 09:41:45 +010066 iter->next = meta->next;
Radek Krejcie7b95092019-05-15 11:03:07 +020067 }
68 }
69 }
70 }
71
72 if (!recursive) {
Michal Vasko9f96a052020-03-10 09:41:45 +010073 meta->next = NULL;
Radek Krejcie7b95092019-05-15 11:03:07 +020074 }
75
Michal Vasko52927e22020-03-16 17:26:14 +010076 for (iter = meta; iter; ) {
Michal Vasko9f96a052020-03-10 09:41:45 +010077 meta = iter;
Radek Krejcie7b95092019-05-15 11:03:07 +020078 iter = iter->next;
79
Michal Vasko9f96a052020-03-10 09:41:45 +010080 FREE_STRING(ctx, meta->name);
81 meta->value.realtype->plugin->free(ctx, &meta->value);
82 free(meta);
Radek Krejcie7b95092019-05-15 11:03:07 +020083 }
84}
85
Michal Vasko52927e22020-03-16 17:26:14 +010086API void
87ly_free_attr(const struct ly_ctx *ctx, struct ly_attr *attr, int recursive)
88{
89 struct ly_attr *iter;
Radek Krejci7eb54ba2020-05-18 16:30:04 +020090 LY_ARRAY_SIZE_TYPE u;
Michal Vasko52927e22020-03-16 17:26:14 +010091
92 LY_CHECK_ARG_RET(NULL, ctx, );
93 if (!attr) {
94 return;
95 }
96
97 if (attr->parent) {
98 if (attr->parent->attr == attr) {
99 if (recursive) {
100 attr->parent->attr = NULL;
101 } else {
102 attr->parent->attr = attr->next;
103 }
104 } else {
105 for (iter = attr->parent->attr; iter->next != attr; iter = iter->next);
106 if (iter->next) {
107 if (recursive) {
108 iter->next = NULL;
109 } else {
110 iter->next = attr->next;
111 }
112 }
113 }
114 }
115
116 if (!recursive) {
117 attr->next = NULL;
118 }
119
120 for (iter = attr; iter; ) {
121 attr = iter;
122 iter = iter->next;
123
124 LY_ARRAY_FOR(attr->val_prefs, u) {
125 FREE_STRING(ctx, attr->val_prefs[u].pref);
126 FREE_STRING(ctx, attr->val_prefs[u].ns);
127 }
128 LY_ARRAY_FREE(attr->val_prefs);
129 FREE_STRING(ctx, attr->name);
130 FREE_STRING(ctx, attr->value);
131 FREE_STRING(ctx, attr->prefix.pref);
132 FREE_STRING(ctx, attr->prefix.ns);
133 free(attr);
134 }
135}
136
Radek Krejcie7b95092019-05-15 11:03:07 +0200137/**
138 * @brief Free Data (sub)tree.
Radek Krejcie7b95092019-05-15 11:03:07 +0200139 * @param[in] node Data node to be freed.
140 * @param[in] top Recursion flag to unlink the root of the subtree being freed.
141 */
142static void
Michal Vasko52927e22020-03-16 17:26:14 +0100143lyd_free_subtree(struct lyd_node *node, int top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200144{
145 struct lyd_node *iter, *next;
146 struct lyd_node *children;
Michal Vasko52927e22020-03-16 17:26:14 +0100147 struct lyd_node_opaq *opaq;
Radek Krejci7eb54ba2020-05-18 16:30:04 +0200148 LY_ARRAY_SIZE_TYPE u;
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 */
Radek Krejcidae0ee82020-05-06 16:53:24 +0200156 children = lyd_node_children(node);
Radek Krejcie7b95092019-05-15 11:03:07 +0200157 LY_LIST_FOR_SAFE(children, next, iter) {
Michal Vasko52927e22020-03-16 17:26:14 +0100158 lyd_free_subtree(iter, 0);
159 }
160
161 FREE_STRING(LYD_NODE_CTX(opaq), opaq->name);
162 FREE_STRING(LYD_NODE_CTX(opaq), opaq->prefix.pref);
163 FREE_STRING(LYD_NODE_CTX(opaq), opaq->prefix.ns);
164 if (opaq->val_prefs) {
165 LY_ARRAY_FOR(opaq->val_prefs, u) {
166 FREE_STRING(LYD_NODE_CTX(opaq), opaq->val_prefs[u].pref);
167 FREE_STRING(LYD_NODE_CTX(opaq), opaq->val_prefs[u].ns);
168 }
169 LY_ARRAY_FREE(opaq->val_prefs);
170 }
171 FREE_STRING(LYD_NODE_CTX(opaq), opaq->value);
172 } else if (node->schema->nodetype & LYD_NODE_INNER) {
173 /* remove children hash table in case of inner data node */
174 lyht_free(((struct lyd_node_inner *)node)->children_ht);
175 ((struct lyd_node_inner *)node)->children_ht = NULL;
176
177 /* free the children */
Radek Krejcidae0ee82020-05-06 16:53:24 +0200178 children = lyd_node_children(node);
Michal Vasko52927e22020-03-16 17:26:14 +0100179 LY_LIST_FOR_SAFE(children, next, iter) {
180 lyd_free_subtree(iter, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200181 }
182 } else if (node->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko52927e22020-03-16 17:26:14 +0100183 switch (((struct lyd_node_any *)node)->value_type) {
Radek Krejcie7b95092019-05-15 11:03:07 +0200184 case LYD_ANYDATA_DATATREE:
Michal Vasko52927e22020-03-16 17:26:14 +0100185 lyd_free_all(((struct lyd_node_any *)node)->value.tree);
Radek Krejcie7b95092019-05-15 11:03:07 +0200186 break;
187 case LYD_ANYDATA_STRING:
Radek Krejciee4cab22019-07-17 17:07:47 +0200188 case LYD_ANYDATA_XML:
189 case LYD_ANYDATA_JSON:
Michal Vasko52927e22020-03-16 17:26:14 +0100190 FREE_STRING(LYD_NODE_CTX(node), ((struct lyd_node_any *)node)->value.str);
Radek Krejciee4cab22019-07-17 17:07:47 +0200191 break;
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200192#if 0 /* TODO LYB format */
Radek Krejciee4cab22019-07-17 17:07:47 +0200193 case LYD_ANYDATA_LYB:
Michal Vasko52927e22020-03-16 17:26:14 +0100194 free(((struct lyd_node_any *)node)->value.mem);
Radek Krejcie7b95092019-05-15 11:03:07 +0200195 break;
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200196#endif
Radek Krejcie7b95092019-05-15 11:03:07 +0200197 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200198 } else if (node->schema->nodetype & LYD_NODE_TERM) {
Michal Vasko52927e22020-03-16 17:26:14 +0100199 ((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 +0200200 }
201
Michal Vasko52927e22020-03-16 17:26:14 +0100202 if (!node->schema) {
203 ly_free_attr(LYD_NODE_CTX(node), opaq->attr, 1);
204 } else {
205 /* free the node's metadata */
206 lyd_free_meta(LYD_NODE_CTX(node), node->meta, 1);
207 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200208
209 /* unlink only the nodes from the first level, nodes in subtree are freed all, so no unlink is needed */
210 if (top) {
211 lyd_unlink_tree(node);
212 }
213
214 free(node);
215}
216
217API void
218lyd_free_tree(struct lyd_node *node)
219{
220 if (!node) {
221 return;
222 }
223
Michal Vasko52927e22020-03-16 17:26:14 +0100224 lyd_free_subtree(node, 1);
Radek Krejcie7b95092019-05-15 11:03:07 +0200225}
226
Radek Krejcib0849a22019-07-25 12:31:04 +0200227static void
228lyd_free_(struct lyd_node *node, int top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200229{
230 struct lyd_node *iter, *next;
231
232 if (!node) {
233 return;
234 }
235
Radek Krejcib0849a22019-07-25 12:31:04 +0200236 /* get the first (top-level) sibling */
237 if (top) {
Michal Vasko52927e22020-03-16 17:26:14 +0100238 for (; node->parent; node = (struct lyd_node *)node->parent);
Radek Krejcib0849a22019-07-25 12:31:04 +0200239 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200240 while (node->prev->next) {
241 node = node->prev;
242 }
243
244 LY_LIST_FOR_SAFE(node, next, iter) {
245 /* in case of the top-level nodes (node->parent is NULL), no unlinking needed */
Michal Vasko52927e22020-03-16 17:26:14 +0100246 lyd_free_subtree(iter, iter->parent ? 1 : 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200247 }
248}
Radek Krejcib0849a22019-07-25 12:31:04 +0200249
250API void
Michal Vaskof03ed032020-03-04 13:31:44 +0100251lyd_free_siblings(struct lyd_node *node)
Radek Krejcib0849a22019-07-25 12:31:04 +0200252{
253 lyd_free_(node, 0);
254}
255
256API void
257lyd_free_all(struct lyd_node *node)
258{
259 lyd_free_(node, 1);
260}