- job_queue tested
[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 pfree(this);
38 return SUCCESS;
39 }
40
41 /*
42 * Creates a linked list (documented in header-file)
43 */
44 linked_list_element_t *linked_list_element_create(void *value)
45 {
46 linked_list_element_t *this = alloc_thing(linked_list_element_t, "linked_list_element_t");
47
48 this->destroy = linked_list_element_destroy;
49
50 this->previous=NULL;
51 this->next=NULL;
52 this->value = value;
53
54 return this;
55 }
56
57 /**
58 * @brief implements function insert_first of linked_list_t
59 */
60 static status_t insert_first(linked_list_t *linked_list, void *item)
61 {
62 linked_list_t *this = linked_list;
63
64 linked_list_element_t *element = linked_list_element_create(item);
65
66 if (this->count == 0)
67 {
68 /* first entry in list */
69 this->first = element;
70 this->last = element;
71 element->previous = NULL;
72 element->next = NULL;
73 }else
74 {
75 if ((this->first == NULL) || (this->last == NULL))
76 {
77 /* should never happen */
78 element->destroy(element);
79 return FAILED;
80 }
81 linked_list_element_t *old_first_element = this->first;
82 element->next = old_first_element;
83 old_first_element->previous = element;
84 this->first = element;
85 }
86
87 this->count++;
88
89 return SUCCESS;
90 }
91
92 /**
93 * @brief implements function remove_first of linked_list_t
94 */
95 static status_t remove_first(linked_list_t *linked_list, void **item)
96 {
97 linked_list_t *this = linked_list;
98
99 if (this->count == 0)
100 {
101 return FAILED;
102 }
103
104 if (this->first == NULL)
105 {
106 return FAILED;
107 }
108
109 linked_list_element_t *element = this->first;
110
111 if (element->next != NULL)
112 {
113 element->next->previous = NULL;
114 }
115 this->first = element->next;
116
117 *item = element->value;
118
119 this->count--;
120
121 return (element->destroy(element));
122 }
123
124 /**
125 * @brief implements function get_first of linked_list_t
126 */
127 static status_t get_first(linked_list_t *linked_list, void **item)
128 {
129 linked_list_t *this = linked_list;
130
131 if (this->count == 0)
132 {
133 return FAILED;
134 }
135
136 if (this->first == NULL)
137 {
138 return FAILED;
139 }
140
141 *item = this->first->value;
142
143 return SUCCESS;
144 }
145
146 /**
147 * @brief implements function insert_last of linked_list_t
148 */
149 static status_t insert_last(linked_list_t *linked_list, void *item)
150 {
151 linked_list_t *this = linked_list;
152
153 linked_list_element_t *element = linked_list_element_create(item);
154
155 if (this->count == 0)
156 {
157 /* first entry in list */
158 this->first = element;
159 this->last = element;
160 element->previous = NULL;
161 element->next = NULL;
162 }else
163 {
164 if ((this->first == NULL) || (this->last == NULL))
165 {
166 /* should never happen */
167 element->destroy(element);
168 return FAILED;
169 }
170 linked_list_element_t *old_last_element = this->last;
171 element->previous = old_last_element;
172 old_last_element->next = element;
173 this->last = element;
174 }
175
176 this->count++;
177
178 return SUCCESS;
179 }
180
181 /**
182 * @brief implements function remove_last of linked_list_t
183 */
184 static status_t remove_last(linked_list_t *linked_list, void **item)
185 {
186 linked_list_t *this = linked_list;
187
188 if (this->count == 0)
189 {
190 return FAILED;
191 }
192
193 if (this->last == NULL)
194 {
195 return FAILED;
196 }
197
198 linked_list_element_t *element = this->last;
199
200 if (element->previous != NULL)
201 {
202 element->previous->next = NULL;
203 }
204 this->last = element->previous;
205
206 *item = element->value;
207
208 this->count--;
209
210 return element->destroy(element);
211 }
212
213 /**
214 * @brief implements function get_last of linked_list_t
215 */
216 static status_t get_last(linked_list_t *linked_list, void **item)
217 {
218 linked_list_t *this = linked_list;
219
220 if (this->count == 0)
221 {
222 return FAILED;
223 }
224
225 if (this->last == NULL)
226 {
227 return FAILED;
228 }
229
230 *item = this->last->value;
231
232 return SUCCESS;
233 }
234
235 /**
236 * @brief implements function destroy of linked_list_t
237 */
238 static status_t linked_list_destroy(linked_list_t *linked_list)
239 {
240 linked_list_t *this = linked_list;
241
242 /* Delete all list items before deleting list */
243 while (this->count > 0)
244 {
245 void * value;
246 if (this->remove_first(this,&value) != SUCCESS)
247 {
248 pfree(this);
249 return FAILED;
250 }
251 }
252 pfree(this);
253 return SUCCESS;
254 }
255
256 /*
257 *
258 * Documented in header
259 */
260 linked_list_t *linked_list_create()
261 {
262 linked_list_t *this = alloc_thing(linked_list_t, "linked_list_t");
263
264 this->get_first = get_first;
265 this->get_last = get_last;
266 this->insert_first = insert_first;
267 this->insert_last = insert_last;
268 this->remove_first = remove_first;
269 this->remove_last = remove_last;
270 this->destroy = linked_list_destroy;
271
272 this->count = 0;
273 this->first = NULL;
274 this->last = NULL;
275
276 return this;
277 }