blob: 7975b87955f7ba4a35658691ce1e00eefd4bae12 [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
Radek Krejcie7b95092019-05-15 11:03:07 +0200120/**
121 * @brief Free Data (sub)tree.
Radek Krejcie7b95092019-05-15 11:03:07 +0200122 * @param[in] node Data node to be freed.
123 * @param[in] top Recursion flag to unlink the root of the subtree being freed.
124 */
125static void
Michal Vasko52927e22020-03-16 17:26:14 +0100126lyd_free_subtree(struct lyd_node *node, int top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200127{
128 struct lyd_node *iter, *next;
129 struct lyd_node *children;
Michal Vasko52927e22020-03-16 17:26:14 +0100130 struct lyd_node_opaq *opaq;
Radek Krejci7eb54ba2020-05-18 16:30:04 +0200131 LY_ARRAY_SIZE_TYPE u;
Radek Krejcie7b95092019-05-15 11:03:07 +0200132
133 assert(node);
134
Michal Vasko52927e22020-03-16 17:26:14 +0100135 if (!node->schema) {
136 opaq = (struct lyd_node_opaq *)node;
Radek Krejcie7b95092019-05-15 11:03:07 +0200137
138 /* free the children */
Radek Krejcidae0ee82020-05-06 16:53:24 +0200139 children = lyd_node_children(node);
Radek Krejcie7b95092019-05-15 11:03:07 +0200140 LY_LIST_FOR_SAFE(children, next, iter) {
Michal Vasko52927e22020-03-16 17:26:14 +0100141 lyd_free_subtree(iter, 0);
142 }
143
144 FREE_STRING(LYD_NODE_CTX(opaq), opaq->name);
145 FREE_STRING(LYD_NODE_CTX(opaq), opaq->prefix.pref);
146 FREE_STRING(LYD_NODE_CTX(opaq), opaq->prefix.ns);
147 if (opaq->val_prefs) {
148 LY_ARRAY_FOR(opaq->val_prefs, u) {
149 FREE_STRING(LYD_NODE_CTX(opaq), opaq->val_prefs[u].pref);
150 FREE_STRING(LYD_NODE_CTX(opaq), opaq->val_prefs[u].ns);
151 }
152 LY_ARRAY_FREE(opaq->val_prefs);
153 }
154 FREE_STRING(LYD_NODE_CTX(opaq), opaq->value);
155 } else if (node->schema->nodetype & LYD_NODE_INNER) {
156 /* remove children hash table in case of inner data node */
157 lyht_free(((struct lyd_node_inner *)node)->children_ht);
158 ((struct lyd_node_inner *)node)->children_ht = NULL;
159
160 /* free the children */
Radek Krejcidae0ee82020-05-06 16:53:24 +0200161 children = lyd_node_children(node);
Michal Vasko52927e22020-03-16 17:26:14 +0100162 LY_LIST_FOR_SAFE(children, next, iter) {
163 lyd_free_subtree(iter, 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200164 }
165 } else if (node->schema->nodetype & LYD_NODE_ANY) {
Michal Vasko52927e22020-03-16 17:26:14 +0100166 switch (((struct lyd_node_any *)node)->value_type) {
Radek Krejcie7b95092019-05-15 11:03:07 +0200167 case LYD_ANYDATA_DATATREE:
Michal Vasko52927e22020-03-16 17:26:14 +0100168 lyd_free_all(((struct lyd_node_any *)node)->value.tree);
Radek Krejcie7b95092019-05-15 11:03:07 +0200169 break;
170 case LYD_ANYDATA_STRING:
Radek Krejciee4cab22019-07-17 17:07:47 +0200171 case LYD_ANYDATA_XML:
172 case LYD_ANYDATA_JSON:
Michal Vasko52927e22020-03-16 17:26:14 +0100173 FREE_STRING(LYD_NODE_CTX(node), ((struct lyd_node_any *)node)->value.str);
Radek Krejciee4cab22019-07-17 17:07:47 +0200174 break;
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200175#if 0 /* TODO LYB format */
Radek Krejciee4cab22019-07-17 17:07:47 +0200176 case LYD_ANYDATA_LYB:
Michal Vasko52927e22020-03-16 17:26:14 +0100177 free(((struct lyd_node_any *)node)->value.mem);
Radek Krejcie7b95092019-05-15 11:03:07 +0200178 break;
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200179#endif
Radek Krejcie7b95092019-05-15 11:03:07 +0200180 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200181 } else if (node->schema->nodetype & LYD_NODE_TERM) {
Michal Vasko52927e22020-03-16 17:26:14 +0100182 ((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 +0200183 }
184
Michal Vasko52927e22020-03-16 17:26:14 +0100185 if (!node->schema) {
186 ly_free_attr(LYD_NODE_CTX(node), opaq->attr, 1);
187 } else {
188 /* free the node's metadata */
189 lyd_free_meta(LYD_NODE_CTX(node), node->meta, 1);
190 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200191
192 /* unlink only the nodes from the first level, nodes in subtree are freed all, so no unlink is needed */
193 if (top) {
194 lyd_unlink_tree(node);
195 }
196
197 free(node);
198}
199
200API void
201lyd_free_tree(struct lyd_node *node)
202{
203 if (!node) {
204 return;
205 }
206
Michal Vasko52927e22020-03-16 17:26:14 +0100207 lyd_free_subtree(node, 1);
Radek Krejcie7b95092019-05-15 11:03:07 +0200208}
209
Radek Krejcib0849a22019-07-25 12:31:04 +0200210static void
211lyd_free_(struct lyd_node *node, int top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200212{
213 struct lyd_node *iter, *next;
214
215 if (!node) {
216 return;
217 }
218
Radek Krejcib0849a22019-07-25 12:31:04 +0200219 /* get the first (top-level) sibling */
220 if (top) {
Michal Vasko52927e22020-03-16 17:26:14 +0100221 for (; node->parent; node = (struct lyd_node *)node->parent);
Radek Krejcib0849a22019-07-25 12:31:04 +0200222 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200223 while (node->prev->next) {
224 node = node->prev;
225 }
226
227 LY_LIST_FOR_SAFE(node, next, iter) {
228 /* in case of the top-level nodes (node->parent is NULL), no unlinking needed */
Michal Vasko52927e22020-03-16 17:26:14 +0100229 lyd_free_subtree(iter, iter->parent ? 1 : 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200230 }
231}
Radek Krejcib0849a22019-07-25 12:31:04 +0200232
233API void
Michal Vaskof03ed032020-03-04 13:31:44 +0100234lyd_free_siblings(struct lyd_node *node)
Radek Krejcib0849a22019-07-25 12:31:04 +0200235{
236 lyd_free_(node, 0);
237}
238
239API void
240lyd_free_all(struct lyd_node *node)
241{
242 lyd_free_(node, 1);
243}