e9a6b6d4a4a04fbc996666ce2c27a4c1ab658bef
[strongswan.git] / Source / charon / linked_list.c
1 /**
2 * @file linked_list.c
3 *
4 * @brief Generic Double Linked List
5 *
6 */
7
8 /*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include <stdlib.h>
24 #include <freeswan.h>
25 #include <pluto/constants.h>
26 #include <pluto/defs.h>
27
28 #include "linked_list.h"
29
30
31 /**
32 * @brief implements function destroy of linked_list_item_t
33 */
34 static status_t linked_list_element_destroy(linked_list_element_t *linked_list_element)
35 {
36 linked_list_element_t * this = linked_list_element;
37 if (this == NULL)
38 {
39 return FAILED;
40 }
41 pfree(this);
42 return SUCCESS;
43 }
44
45 /*
46 * Creates an empty linked list (described in header-file)
47 */
48 linked_list_element_t *linked_list_element_create(void *value)
49 {
50 linked_list_element_t *this = alloc_thing(linked_list_element_t, "linked_list_element_t");
51
52 if (this == NULL)
53 {
54 return NULL;
55 }
56
57 this->destroy = linked_list_element_destroy;
58
59 this->previous=NULL;
60 this->next=NULL;
61 this->value = value;
62
63 return this;
64 }
65
66 /**
67 * @brief implements function insert_first of linked_list_t
68 */
69 static status_t insert_first(linked_list_t *linked_list, void *item)
70 {
71 linked_list_t *this = linked_list;
72
73 linked_list_element_t *element = linked_list_element_create(item);
74
75 if (element == NULL)
76 {
77 return FAILED;
78 }
79
80 if (this->count == 0)
81 {
82 /* first entry in list */
83 this->first = element;
84 this->last = element;
85 element->previous = NULL;
86 element->next = NULL;
87 }
88 else
89 {
90 if ((this->first == NULL) || (this->last == NULL))
91 {
92 /* should never happen */
93 element->destroy(element);
94 return FAILED;
95 }
96 linked_list_element_t *old_first_element = this->first;
97 element->next = old_first_element;
98 old_first_element->previous = element;
99 this->first = element;
100 }
101
102 this->count++;
103
104 return SUCCESS;
105 }
106
107 /**
108 * @brief implements function remove_first of linked_list_t
109 */
110 static status_t remove_first(linked_list_t *linked_list, void **item)
111 {
112 linked_list_t *this = linked_list;
113
114 if (this->count == 0)
115 {
116 return FAILED;
117 }
118
119 if (this->first == NULL)
120 {
121 return FAILED;
122 }
123
124 linked_list_element_t *element = this->first;
125
126 if (element->next != NULL)
127 {
128 element->next->previous = NULL;
129 }
130 this->first = element->next;
131
132 *item = element->value;
133
134 this->count--;
135
136 return (element->destroy(element));
137 }
138
139 /**
140 * @brief implements function get_first of linked_list_t
141 */
142 static status_t get_first(linked_list_t *linked_list, void **item)
143 {
144 linked_list_t *this = linked_list;
145
146 if (this->count == 0)
147 {
148 return FAILED;
149 }
150
151 if (this->first == NULL)
152 {
153 return FAILED;
154 }
155
156 *item = this->first->value;
157
158 return SUCCESS;
159 }
160
161 /**
162 * @brief implements function insert_last of linked_list_t
163 */
164 static status_t insert_last(linked_list_t *linked_list, void *item)
165 {
166 linked_list_t *this = linked_list;
167
168 linked_list_element_t *element = linked_list_element_create(item);
169
170 if (element == NULL)
171 {
172 return FAILED;
173 }
174
175 if (this->count == 0)
176 {
177 /* first entry in list */
178 this->first = element;
179 this->last = element;
180 element->previous = NULL;
181 element->next = NULL;
182 }else
183 {
184 if ((this->first == NULL) || (this->last == NULL))
185 {
186 /* should never happen */
187 element->destroy(element);
188 return FAILED;
189 }
190 linked_list_element_t *old_last_element = this->last;
191 element->previous = old_last_element;
192 old_last_element->next = element;
193 this->last = element;
194 }
195
196 this->count++;
197
198 return SUCCESS;
199 }
200
201 /**
202 * @brief implements function remove_last of linked_list_t
203 */
204 static status_t remove_last(linked_list_t *linked_list, void **item)
205 {
206 linked_list_t *this = linked_list;
207
208 if (this->count == 0)
209 {
210 return FAILED;
211 }
212
213 if (this->last == NULL)
214 {
215 return FAILED;
216 }
217
218 linked_list_element_t *element = this->last;
219
220 if (element->previous != NULL)
221 {
222 element->previous->next = NULL;
223 }
224 this->last = element->previous;
225
226 *item = element->value;
227
228 this->count--;
229
230 return (element->destroy(element));
231 }
232
233 /**
234 * @brief implements function get_last of linked_list_t
235 */
236 static status_t get_last(linked_list_t *linked_list, void **item)
237 {
238 linked_list_t *this = linked_list;
239
240 if (this->count == 0)
241 {
242 return FAILED;
243 }
244
245 if (this->last == NULL)
246 {
247 return FAILED;
248 }
249
250 *item = this->last->value;
251
252 return SUCCESS;
253 }
254
255 /**
256 * @brief implements function destroy of linked_list_t
257 */
258 static status_t linked_list_destroy(linked_list_t *linked_list)
259 {
260 linked_list_t *this = linked_list;
261
262 /* Remove all list items before destroying list */
263 while (this->count > 0)
264 {
265 void * value;
266 /* values are not destroyed so memory leaks are possible
267 * if list is not empty when deleting */
268 if (this->remove_first(this,&value) != SUCCESS)
269 {
270 pfree(this);
271 return FAILED;
272 }
273 }
274 pfree(this);
275 return SUCCESS;
276 }
277
278 /*
279 * Described in header
280 */
281 linked_list_t *linked_list_create()
282 {
283 linked_list_t *this = alloc_thing(linked_list_t, "linked_list_t");
284
285 this->get_first = get_first;
286 this->get_last = get_last;
287 this->insert_first = insert_first;
288 this->insert_last = insert_last;
289 this->remove_first = remove_first;
290 this->remove_last = remove_last;
291 this->destroy = linked_list_destroy;
292
293 this->count = 0;
294 this->first = NULL;
295 this->last = NULL;
296
297 return this;
298 }