]> git.proxmox.com Git - mirror_frr.git/blob - pceplib/pcep_utils_double_linked_list.c
doc: Add `show ipv6 rpf X:X::X:X` command to docs
[mirror_frr.git] / pceplib / pcep_utils_double_linked_list.c
1 /*
2 * This file is part of the PCEPlib, a PCEP protocol library.
3 *
4 * Copyright (C) 2020 Volta Networks https://voltanet.io/
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 *
19 * Author : Brady Johnson <brady@voltanet.io>
20 *
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <stddef.h>
28 #include <string.h>
29
30 #include "pcep_utils_double_linked_list.h"
31 #include "pcep_utils_logging.h"
32 #include "pcep_utils_memory.h"
33
34 double_linked_list *dll_initialize(void)
35 {
36 double_linked_list *handle =
37 pceplib_malloc(PCEPLIB_INFRA, sizeof(double_linked_list));
38 if (handle != NULL) {
39 memset(handle, 0, sizeof(double_linked_list));
40 handle->num_entries = 0;
41 handle->head = NULL;
42 handle->tail = NULL;
43 } else {
44 pcep_log(LOG_WARNING,
45 "%s: dll_initialize cannot allocate memory for handle",
46 __func__);
47 return NULL;
48 }
49
50 return handle;
51 }
52
53
54 void dll_destroy(double_linked_list *handle)
55 {
56 if (handle == NULL) {
57 pcep_log(LOG_WARNING,
58 "%s: dll_destroy cannot destroy NULL handle",
59 __func__);
60 return;
61 }
62
63 double_linked_list_node *node = handle->head;
64 while (node != NULL) {
65 double_linked_list_node *node_to_delete = node;
66 node = node->next_node;
67 pceplib_free(PCEPLIB_INFRA, node_to_delete);
68 }
69
70 pceplib_free(PCEPLIB_INFRA, handle);
71 }
72
73
74 void dll_destroy_with_data_memtype(double_linked_list *handle,
75 void *data_memory_type)
76 {
77 if (handle == NULL) {
78 pcep_log(LOG_WARNING,
79 "%s: dll_destroy_with_data cannot destroy NULL handle",
80 __func__);
81 return;
82 }
83
84 double_linked_list_node *node = handle->head;
85 while (node != NULL) {
86 double_linked_list_node *node_to_delete = node;
87 pceplib_free(data_memory_type, node->data);
88 node = node->next_node;
89 pceplib_free(PCEPLIB_INFRA, node_to_delete);
90 }
91
92 pceplib_free(PCEPLIB_INFRA, handle);
93 }
94
95
96 void dll_destroy_with_data(double_linked_list *handle)
97 {
98 /* Default to destroying the data with the INFRA mem type */
99 dll_destroy_with_data_memtype(handle, PCEPLIB_INFRA);
100 }
101
102
103 /* Creates a node and adds it as the first item in the list */
104 double_linked_list_node *dll_prepend(double_linked_list *handle, void *data)
105 {
106 if (handle == NULL) {
107 pcep_log(LOG_WARNING, "%s: dll_prepend_data NULL handle",
108 __func__);
109 return NULL;
110 }
111
112 /* Create the new node */
113 double_linked_list_node *new_node =
114 pceplib_malloc(PCEPLIB_INFRA, sizeof(double_linked_list_node));
115 memset(new_node, 0, sizeof(double_linked_list_node));
116 new_node->data = data;
117
118 if (handle->head == NULL) {
119 handle->head = new_node;
120 handle->tail = new_node;
121 } else {
122 new_node->next_node = handle->head;
123 handle->head->prev_node = new_node;
124 handle->head = new_node;
125 }
126
127 (handle->num_entries)++;
128
129 return new_node;
130 }
131
132
133 /* Creates a node and adds it as the last item in the list */
134 double_linked_list_node *dll_append(double_linked_list *handle, void *data)
135 {
136 if (handle == NULL) {
137 pcep_log(LOG_WARNING, "%s: dll_append_data NULL handle",
138 __func__);
139 return NULL;
140 }
141
142 /* Create the new node */
143 double_linked_list_node *new_node =
144 pceplib_malloc(PCEPLIB_INFRA, sizeof(double_linked_list_node));
145 memset(new_node, 0, sizeof(double_linked_list_node));
146 new_node->data = data;
147
148 if (handle->head == NULL) {
149 handle->head = new_node;
150 handle->tail = new_node;
151 } else {
152 new_node->prev_node = handle->tail;
153 handle->tail->next_node = new_node;
154 handle->tail = new_node;
155 }
156
157 (handle->num_entries)++;
158
159 return new_node;
160 }
161
162
163 /* Delete the first node in the list, and return the data */
164 void *dll_delete_first_node(double_linked_list *handle)
165 {
166 if (handle == NULL) {
167 pcep_log(LOG_WARNING, "%s: dll_delete_first_node NULL handle",
168 __func__);
169 return NULL;
170 }
171
172 if (handle->head == NULL) {
173 return NULL;
174 }
175
176 double_linked_list_node *delete_node = handle->head;
177 void *data = delete_node->data;
178
179 if (delete_node->next_node == NULL) {
180 /* Its the last node in the list */
181 handle->head = NULL;
182 handle->tail = NULL;
183 } else {
184 handle->head = delete_node->next_node;
185 handle->head->prev_node = NULL;
186 }
187
188 pceplib_free(PCEPLIB_INFRA, delete_node);
189 (handle->num_entries)--;
190
191 return data;
192 }
193
194
195 /* Delete the last node in the list, and return the data */
196 void *dll_delete_last_node(double_linked_list *handle)
197 {
198 if (handle == NULL) {
199 pcep_log(LOG_WARNING, "%s: dll_delete_last_node NULL handle",
200 __func__);
201 return NULL;
202 }
203
204 if (handle->head == NULL) {
205 return NULL;
206 }
207
208 double_linked_list_node *delete_node = handle->tail;
209 void *data = delete_node->data;
210
211 if (delete_node->prev_node == NULL) {
212 /* Its the last node in the list */
213 handle->head = NULL;
214 handle->tail = NULL;
215 } else {
216 handle->tail = delete_node->prev_node;
217 handle->tail->next_node = NULL;
218 }
219
220 pceplib_free(PCEPLIB_INFRA, delete_node);
221 (handle->num_entries)--;
222
223 return data;
224 }
225
226
227 /* Delete the designated node in the list, and return the data */
228 void *dll_delete_node(double_linked_list *handle, double_linked_list_node *node)
229 {
230 if (handle == NULL) {
231 pcep_log(LOG_WARNING, "%s: dll_delete_node NULL handle",
232 __func__);
233 return NULL;
234 }
235
236 if (node == NULL) {
237 return NULL;
238 }
239
240 if (handle->head == NULL) {
241 return NULL;
242 }
243
244 void *data = node->data;
245
246 if (handle->head == handle->tail) {
247 /* Its the last node in the list */
248 handle->head = NULL;
249 handle->tail = NULL;
250 } else if (handle->head == node) {
251 handle->head = node->next_node;
252 handle->head->prev_node = NULL;
253 } else if (handle->tail == node) {
254 handle->tail = node->prev_node;
255 handle->tail->next_node = NULL;
256 } else {
257 /* Its somewhere in the middle of the list */
258 node->next_node->prev_node = node->prev_node;
259 node->prev_node->next_node = node->next_node;
260 }
261
262 pceplib_free(PCEPLIB_INFRA, node);
263 (handle->num_entries)--;
264
265 return data;
266 }