blob: aea9f7b0cccd7e8b80247f0281cbb0470a865108 [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
15#include "common.h"
16
17#include <assert.h>
18#include <stdlib.h>
19
20#include "hash_table.h"
21#include "log.h"
22#include "tree.h"
23#include "tree_data.h"
24#include "tree_schema.h"
25#include "tree_data_internal.h"
Radek Krejci849a62a2019-05-22 15:29:05 +020026#include "plugins_types.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020027
Radek Krejci084289f2019-07-09 17:35:30 +020028void
29lyd_value_free_path(struct ly_ctx *ctx, struct lyd_value_path *path)
30{
31 unsigned int u, v;
32
33 LY_ARRAY_FOR(path, u) {
34 LY_ARRAY_FOR(path[u].predicates, v) {
35 if (path[u].predicates[v].type > 0) {
Radek Krejci62903c32019-07-15 14:42:05 +020036 ((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 +020037 free(path[u].predicates[v].value);
38 }
39 }
40 LY_ARRAY_FREE(path[u].predicates);
41 }
42 LY_ARRAY_FREE(path);
43}
44
Radek Krejcie7b95092019-05-15 11:03:07 +020045API void
46lyd_free_attr(struct ly_ctx *ctx, struct lyd_attr *attr, int recursive)
47{
48 struct lyd_attr *iter;
49
50 LY_CHECK_ARG_RET(NULL, ctx, );
51 if (!attr) {
52 return;
53 }
54
55 if (attr->parent) {
56 if (attr->parent->attr == attr) {
57 if (recursive) {
58 attr->parent->attr = NULL;
59 } else {
60 attr->parent->attr = attr->next;
61 }
62 } else {
63 for (iter = attr->parent->attr; iter->next != attr; iter = iter->next);
64 if (iter->next) {
65 if (recursive) {
66 iter->next = NULL;
67 } else {
68 iter->next = attr->next;
69 }
70 }
71 }
72 }
73
74 if (!recursive) {
75 attr->next = NULL;
76 }
77
78 for(iter = attr; iter; ) {
79 attr = iter;
80 iter = iter->next;
81
82 FREE_STRING(ctx, attr->name);
Radek Krejci28681fa2019-09-06 13:08:45 +020083 attr->value.realtype->plugin->free(ctx, &attr->value);
Radek Krejcie7b95092019-05-15 11:03:07 +020084 free(attr);
85 }
86}
87
88/**
89 * @brief Free Data (sub)tree.
90 * @param[in] ctx libyang context.
91 * @param[in] node Data node to be freed.
92 * @param[in] top Recursion flag to unlink the root of the subtree being freed.
93 */
94static void
95lyd_free_subtree(struct ly_ctx *ctx, struct lyd_node *node, int top)
96{
97 struct lyd_node *iter, *next;
98 struct lyd_node *children;
99
100 assert(node);
101
102 /* remove children hash table in case of inner data node */
103 if (node->schema->nodetype & LYD_NODE_INNER) {
104 lyht_free(((struct lyd_node_inner*)node)->children_ht);
105 ((struct lyd_node_inner*)node)->children_ht = NULL;
106
107 /* free the children */
108 children = (struct lyd_node*)lyd_node_children(node);
109 LY_LIST_FOR_SAFE(children, next, iter) {
110 lyd_free_subtree(ctx, iter, 0);
111 }
112 } else if (node->schema->nodetype & LYD_NODE_ANY) {
Radek Krejciee4cab22019-07-17 17:07:47 +0200113 switch (((struct lyd_node_any*)node)->value_type) {
Radek Krejcie7b95092019-05-15 11:03:07 +0200114 case LYD_ANYDATA_DATATREE:
Radek Krejciee4cab22019-07-17 17:07:47 +0200115 lyd_free_all(((struct lyd_node_any*)node)->value.tree);
Radek Krejcie7b95092019-05-15 11:03:07 +0200116 break;
117 case LYD_ANYDATA_STRING:
Radek Krejciee4cab22019-07-17 17:07:47 +0200118 case LYD_ANYDATA_XML:
119 case LYD_ANYDATA_JSON:
120 FREE_STRING(node->schema->module->ctx, ((struct lyd_node_any*)node)->value.str);
121 break;
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200122#if 0 /* TODO LYB format */
Radek Krejciee4cab22019-07-17 17:07:47 +0200123 case LYD_ANYDATA_LYB:
124 free(((struct lyd_node_any*)node)->value.mem);
Radek Krejcie7b95092019-05-15 11:03:07 +0200125 break;
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200126#endif
Radek Krejcie7b95092019-05-15 11:03:07 +0200127 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200128 } else if (node->schema->nodetype & LYD_NODE_TERM) {
Radek Krejci62903c32019-07-15 14:42:05 +0200129 ((struct lysc_node_leaf*)node->schema)->type->plugin->free(ctx, &((struct lyd_node_term*)node)->value);
Radek Krejcie7b95092019-05-15 11:03:07 +0200130 }
131
132 /* free the node's attributes */
133 lyd_free_attr(ctx, node->attr, 1);
134
135 /* unlink only the nodes from the first level, nodes in subtree are freed all, so no unlink is needed */
136 if (top) {
137 lyd_unlink_tree(node);
138 }
139
140 free(node);
141}
142
143API void
144lyd_free_tree(struct lyd_node *node)
145{
146 if (!node) {
147 return;
148 }
149
150 lyd_free_subtree(node->schema->module->ctx, node, 1);
151}
152
Radek Krejcib0849a22019-07-25 12:31:04 +0200153static void
154lyd_free_(struct lyd_node *node, int top)
Radek Krejcie7b95092019-05-15 11:03:07 +0200155{
156 struct lyd_node *iter, *next;
157
158 if (!node) {
159 return;
160 }
161
Radek Krejcib0849a22019-07-25 12:31:04 +0200162 /* get the first (top-level) sibling */
163 if (top) {
164 for (; node->parent; node = (struct lyd_node*)node->parent);
165 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200166 while (node->prev->next) {
167 node = node->prev;
168 }
169
170 LY_LIST_FOR_SAFE(node, next, iter) {
171 /* in case of the top-level nodes (node->parent is NULL), no unlinking needed */
Radek Krejci35676302019-05-17 10:50:57 +0200172 lyd_free_subtree(iter->schema->module->ctx, iter, iter->parent ? 1 : 0);
Radek Krejcie7b95092019-05-15 11:03:07 +0200173 }
174}
Radek Krejcib0849a22019-07-25 12:31:04 +0200175
176API void
Michal Vaskof03ed032020-03-04 13:31:44 +0100177lyd_free_siblings(struct lyd_node *node)
Radek Krejcib0849a22019-07-25 12:31:04 +0200178{
179 lyd_free_(node, 0);
180}
181
182API void
183lyd_free_all(struct lyd_node *node)
184{
185 lyd_free_(node, 1);
186}