blob: d47e19c3f7a3cd0b4d7e1046a6f671447239d170 [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 Krejcie7b95092019-05-15 11:03:07 +020026API void
Michal Vasko52927e22020-03-16 17:26:14 +010027lyd_free_meta(const struct ly_ctx *ctx, struct lyd_meta *meta, int recursive)
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
31 LY_CHECK_ARG_RET(NULL, ctx, );
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) {
Radek Krejcie7b95092019-05-15 11:03:07 +020038 if (recursive) {
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 {
Michal Vasko9f96a052020-03-10 09:41:45 +010044 for (iter = meta->parent->meta; iter->next != meta; iter = iter->next);
Radek Krejcie7b95092019-05-15 11:03:07 +020045 if (iter->next) {
46 if (recursive) {
47 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
55 if (!recursive) {
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 Vasko9f96a052020-03-10 09:41:45 +010063 FREE_STRING(ctx, meta->name);
64 meta->value.realtype->plugin->free(ctx, &meta->value);
65 free(meta);
Radek Krejcie7b95092019-05-15 11:03:07 +020066 }
67}
68
Michal Vasko52927e22020-03-16 17:26:14 +010069API void
70ly_free_attr(const struct ly_ctx *ctx, struct ly_attr *attr, int recursive)
71{
72 struct ly_attr *iter;
Radek Krejci7eb54ba2020-05-18 16:30:04 +020073 LY_ARRAY_SIZE_TYPE u;
Michal Vasko52927e22020-03-16 17:26:14 +010074
75 LY_CHECK_ARG_RET(NULL, ctx, );
76 if (!attr) {
77 return;
78 }
79
80 if (attr->parent) {
81 if (attr->parent->attr == attr) {
82 if (recursive) {
83 attr->parent->attr = NULL;
84 } else {
85 attr->parent->attr = attr->next;
86 }
87 } else {
88 for (iter = attr->parent->attr; iter->next != attr; iter = iter->next);
89 if (iter->next) {
90 if (recursive) {
91 iter->next = NULL;
92 } else {
93 iter->next = attr->next;
94 }
95 }
96 }
97 }
98
99 if (!recursive) {
100 attr->next = NULL;
101 }
102
103 for (iter = attr; iter; ) {
104 attr = iter;
105 iter = iter->next;
106
107 LY_ARRAY_FOR(attr->val_prefs, u) {
108 FREE_STRING(ctx, attr->val_prefs[u].pref);
109 FREE_STRING(ctx, attr->val_prefs[u].ns);
110 }
111 LY_ARRAY_FREE(attr->val_prefs);
112 FREE_STRING(ctx, attr->name);
113 FREE_STRING(ctx, attr->value);
114 FREE_STRING(ctx, attr->prefix.pref);
115 FREE_STRING(ctx, attr->prefix.ns);
116 free(attr);
117 }
118}
119
Michal Vasko60ea6352020-06-29 13:39:39 +0200120void
121ly_free_val_prefs(const struct ly_ctx *ctx, struct ly_prefix *val_prefs)
122{
123 LY_ARRAY_SIZE_TYPE u;
124
125 LY_ARRAY_FOR(val_prefs, u) {
126 FREE_STRING(ctx, val_prefs[u].pref);
127 FREE_STRING(ctx, val_prefs[u].ns);
128 }
129 LY_ARRAY_FREE(val_prefs);
130}
131
Radek Krejcie7b95092019-05-15 11:03:07 +0200132/**
133 * @brief Free Data (sub)tree.
Radek Krejcie7b95092019-05-15 11:03:07 +0200134 * @param[in] node Data node to be freed.
135 * @param[in] top Recursion flag to unlink the root of the subtree being freed.
136 */
137static void
Michal Vasko52927e22020-03-16 17:26:14 +0100138lyd_free_subtree(struct lyd_node *node, int top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200139{
140 struct lyd_node *iter, *next;
141 struct lyd_node *children;
Michal Vasko52927e22020-03-16 17:26:14 +0100142 struct lyd_node_opaq *opaq;
Radek Krejcie7b95092019-05-15 11:03:07 +0200143
144 assert(node);
145
Michal Vasko52927e22020-03-16 17:26:14 +0100146 if (!node->schema) {
147 opaq = (struct lyd_node_opaq *)node;
Radek Krejcie7b95092019-05-15 11:03:07 +0200148
149 /* free the children */
Michal Vasko5bfd4be2020-06-23 13:26:19 +0200150 children = lyd_node_children(node, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200151 LY_LIST_FOR_SAFE(children, next, iter) {
Michal Vasko52927e22020-03-16 17:26:14 +0100152 lyd_free_subtree(iter, 0);
153 }
154
155 FREE_STRING(LYD_NODE_CTX(opaq), opaq->name);
156 FREE_STRING(LYD_NODE_CTX(opaq), opaq->prefix.pref);
157 FREE_STRING(LYD_NODE_CTX(opaq), opaq->prefix.ns);
Michal Vasko60ea6352020-06-29 13:39:39 +0200158 ly_free_val_prefs(LYD_NODE_CTX(opaq), opaq->val_prefs);
Michal Vasko52927e22020-03-16 17:26:14 +0100159 FREE_STRING(LYD_NODE_CTX(opaq), opaq->value);
160 } else if (node->schema->nodetype & LYD_NODE_INNER) {
161 /* remove children hash table in case of inner data node */
162 lyht_free(((struct lyd_node_inner *)node)->children_ht);
163 ((struct lyd_node_inner *)node)->children_ht = NULL;
164
165 /* free the children */
Michal Vasko5bfd4be2020-06-23 13:26:19 +0200166 children = lyd_node_children(node, 0);
Michal Vasko52927e22020-03-16 17:26:14 +0100167 LY_LIST_FOR_SAFE(children, next, iter) {
168 lyd_free_subtree(iter, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200169 }
170 } else if (node->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko52927e22020-03-16 17:26:14 +0100171 switch (((struct lyd_node_any *)node)->value_type) {
Radek Krejcie7b95092019-05-15 11:03:07 +0200172 case LYD_ANYDATA_DATATREE:
Michal Vasko52927e22020-03-16 17:26:14 +0100173 lyd_free_all(((struct lyd_node_any *)node)->value.tree);
Radek Krejcie7b95092019-05-15 11:03:07 +0200174 break;
175 case LYD_ANYDATA_STRING:
Radek Krejciee4cab22019-07-17 17:07:47 +0200176 case LYD_ANYDATA_XML:
177 case LYD_ANYDATA_JSON:
Michal Vasko52927e22020-03-16 17:26:14 +0100178 FREE_STRING(LYD_NODE_CTX(node), ((struct lyd_node_any *)node)->value.str);
Radek Krejciee4cab22019-07-17 17:07:47 +0200179 break;
180 case LYD_ANYDATA_LYB:
Michal Vasko52927e22020-03-16 17:26:14 +0100181 free(((struct lyd_node_any *)node)->value.mem);
Radek Krejcie7b95092019-05-15 11:03:07 +0200182 break;
183 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200184 } else if (node->schema->nodetype & LYD_NODE_TERM) {
Michal Vasko52927e22020-03-16 17:26:14 +0100185 ((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 +0200186 }
187
Michal Vasko52927e22020-03-16 17:26:14 +0100188 if (!node->schema) {
189 ly_free_attr(LYD_NODE_CTX(node), opaq->attr, 1);
190 } else {
191 /* free the node's metadata */
192 lyd_free_meta(LYD_NODE_CTX(node), node->meta, 1);
193 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200194
195 /* unlink only the nodes from the first level, nodes in subtree are freed all, so no unlink is needed */
196 if (top) {
197 lyd_unlink_tree(node);
198 }
199
200 free(node);
201}
202
203API void
204lyd_free_tree(struct lyd_node *node)
205{
206 if (!node) {
207 return;
208 }
209
Michal Vasko52927e22020-03-16 17:26:14 +0100210 lyd_free_subtree(node, 1);
Radek Krejcie7b95092019-05-15 11:03:07 +0200211}
212
Radek Krejcib0849a22019-07-25 12:31:04 +0200213static void
214lyd_free_(struct lyd_node *node, int top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200215{
216 struct lyd_node *iter, *next;
217
218 if (!node) {
219 return;
220 }
221
Radek Krejcib0849a22019-07-25 12:31:04 +0200222 /* get the first (top-level) sibling */
223 if (top) {
Michal Vasko52927e22020-03-16 17:26:14 +0100224 for (; node->parent; node = (struct lyd_node *)node->parent);
Radek Krejcib0849a22019-07-25 12:31:04 +0200225 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200226 while (node->prev->next) {
227 node = node->prev;
228 }
229
230 LY_LIST_FOR_SAFE(node, next, iter) {
231 /* in case of the top-level nodes (node->parent is NULL), no unlinking needed */
Michal Vasko52927e22020-03-16 17:26:14 +0100232 lyd_free_subtree(iter, iter->parent ? 1 : 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200233 }
234}
Radek Krejcib0849a22019-07-25 12:31:04 +0200235
236API void
Michal Vaskof03ed032020-03-04 13:31:44 +0100237lyd_free_siblings(struct lyd_node *node)
Radek Krejcib0849a22019-07-25 12:31:04 +0200238{
239 lyd_free_(node, 0);
240}
241
242API void
243lyd_free_all(struct lyd_node *node)
244{
245 lyd_free_(node, 1);
246}