2 * Copyright (C) 2007-2011 Tobias Brunner
3 * Copyright (C) 2005-2006 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 #include "linked_list.h"
22 typedef struct element_t element_t
;
25 * This element holds a pointer to the value it represents.
30 * Value of a list item.
35 * Previous list element.
37 * NULL if first element in list.
44 * NULL if last element in list.
50 * Creates an empty linked list object.
52 element_t
*element_create(void *value
)
62 typedef struct private_linked_list_t private_linked_list_t
;
65 * Private data of a linked_list_t object.
68 struct private_linked_list_t
{
70 * Public part of linked list.
75 * Number of items in the list.
80 * First element in list.
81 * NULL if no elements in list.
86 * Last element in list.
87 * NULL if no elements in list.
92 typedef struct private_enumerator_t private_enumerator_t
;
95 * linked lists enumerator implementation
97 struct private_enumerator_t
{
100 * implements enumerator interface
102 enumerator_t enumerator
;
105 * associated linked list
107 private_linked_list_t
*list
;
115 METHOD(enumerator_t
, enumerate
, bool,
116 private_enumerator_t
*this, void **item
)
120 this->current
= this->list
->first
;
124 this->current
= this->current
->next
;
130 *item
= this->current
->value
;
134 METHOD(linked_list_t
, create_enumerator
, enumerator_t
*,
135 private_linked_list_t
*this)
137 private_enumerator_t
*enumerator
;
141 .enumerate
= (void*)_enumerate
,
142 .destroy
= (void*)free
,
147 return &enumerator
->enumerator
;
150 METHOD(linked_list_t
, reset_enumerator
, void,
151 private_linked_list_t
*this, private_enumerator_t
*enumerator
)
153 enumerator
->current
= NULL
;
156 METHOD(linked_list_t
, get_count
, int,
157 private_linked_list_t
*this)
162 METHOD(linked_list_t
, insert_first
, void,
163 private_linked_list_t
*this, void *item
)
167 element
= element_create(item
);
168 if (this->count
== 0)
170 /* first entry in list */
171 this->first
= element
;
172 this->last
= element
;
173 element
->previous
= NULL
;
174 element
->next
= NULL
;
178 element_t
*old_first_element
= this->first
;
179 element
->next
= old_first_element
;
180 element
->previous
= NULL
;
181 old_first_element
->previous
= element
;
182 this->first
= element
;
188 * unlink an element form the list, returns following element
190 static element_t
* remove_element(private_linked_list_t
*this,
193 element_t
*next
, *previous
;
195 next
= element
->next
;
196 previous
= element
->previous
;
200 next
->previous
= previous
;
204 this->last
= previous
;
208 previous
->next
= next
;
214 if (--this->count
== 0)
222 METHOD(linked_list_t
, get_first
, status_t
,
223 private_linked_list_t
*this, void **item
)
225 if (this->count
== 0)
229 *item
= this->first
->value
;
233 METHOD(linked_list_t
, remove_first
, status_t
,
234 private_linked_list_t
*this, void **item
)
236 if (get_first(this, item
) == SUCCESS
)
238 remove_element(this, this->first
);
244 METHOD(linked_list_t
, insert_last
, void,
245 private_linked_list_t
*this, void *item
)
247 element_t
*element
= element_create(item
);
249 if (this->count
== 0)
251 /* first entry in list */
252 this->first
= element
;
253 this->last
= element
;
254 element
->previous
= NULL
;
255 element
->next
= NULL
;
259 element_t
*old_last_element
= this->last
;
260 element
->previous
= old_last_element
;
261 element
->next
= NULL
;
262 old_last_element
->next
= element
;
263 this->last
= element
;
268 METHOD(linked_list_t
, insert_before
, void,
269 private_linked_list_t
*this, private_enumerator_t
*enumerator
,
272 element_t
*current
= enumerator
->current
;
275 this->public.insert_last(&this->public, item
);
278 element_t
*element
= element_create(item
);
279 if (current
->previous
)
281 current
->previous
->next
= element
;
282 element
->previous
= current
->previous
;
283 current
->previous
= element
;
284 element
->next
= current
;
288 current
->previous
= element
;
289 element
->next
= current
;
290 this->first
= element
;
295 METHOD(linked_list_t
, replace
, void*,
296 private_linked_list_t
*this, private_enumerator_t
*enumerator
,
300 if (enumerator
->current
)
302 old
= enumerator
->current
->value
;
303 enumerator
->current
->value
= item
;
308 METHOD(linked_list_t
, get_last
, status_t
,
309 private_linked_list_t
*this, void **item
)
311 if (this->count
== 0)
315 *item
= this->last
->value
;
319 METHOD(linked_list_t
, remove_last
, status_t
,
320 private_linked_list_t
*this, void **item
)
322 if (get_last(this, item
) == SUCCESS
)
324 remove_element(this, this->last
);
330 METHOD(linked_list_t
, remove_
, int,
331 private_linked_list_t
*this, void *item
, bool (*compare
)(void*,void*))
333 element_t
*current
= this->first
;
338 if ((compare
&& compare(current
->value
, item
)) ||
339 (!compare
&& current
->value
== item
))
342 current
= remove_element(this, current
);
346 current
= current
->next
;
352 METHOD(linked_list_t
, remove_at
, void,
353 private_linked_list_t
*this, private_enumerator_t
*enumerator
)
357 if (enumerator
->current
)
359 current
= enumerator
->current
;
360 enumerator
->current
= current
->previous
;
361 remove_element(this, current
);
365 METHOD(linked_list_t
, find_first
, status_t
,
366 private_linked_list_t
*this, linked_list_match_t match
,
367 void **item
, void *d1
, void *d2
, void *d3
, void *d4
, void *d5
)
369 element_t
*current
= this->first
;
373 if ((match
&& match(current
->value
, d1
, d2
, d3
, d4
, d5
)) ||
374 (!match
&& item
&& current
->value
== *item
))
378 *item
= current
->value
;
382 current
= current
->next
;
387 METHOD(linked_list_t
, find_last
, status_t
,
388 private_linked_list_t
*this, linked_list_match_t match
,
389 void **item
, void *d1
, void *d2
, void *d3
, void *d4
, void *d5
)
391 element_t
*current
= this->last
;
395 if ((match
&& match(current
->value
, d1
, d2
, d3
, d4
, d5
)) ||
396 (!match
&& item
&& current
->value
== *item
))
400 *item
= current
->value
;
404 current
= current
->previous
;
409 METHOD(linked_list_t
, invoke_offset
, void,
410 private_linked_list_t
*this, size_t offset
,
411 void *d1
, void *d2
, void *d3
, void *d4
, void *d5
)
413 element_t
*current
= this->first
;
417 linked_list_invoke_t
*method
= current
->value
+ offset
;
418 (*method
)(current
->value
, d1
, d2
, d3
, d4
, d5
);
419 current
= current
->next
;
423 METHOD(linked_list_t
, invoke_function
, void,
424 private_linked_list_t
*this, linked_list_invoke_t fn
,
425 void *d1
, void *d2
, void *d3
, void *d4
, void *d5
)
427 element_t
*current
= this->first
;
431 fn(current
->value
, d1
, d2
, d3
, d4
, d5
);
432 current
= current
->next
;
436 METHOD(linked_list_t
, clone_offset
, linked_list_t
*,
437 private_linked_list_t
*this, size_t offset
)
439 linked_list_t
*clone
= linked_list_create();
440 element_t
*current
= this->first
;
444 void* (**method
)(void*) = current
->value
+ offset
;
445 clone
->insert_last(clone
, (*method
)(current
->value
));
446 current
= current
->next
;
452 METHOD(linked_list_t
, clone_function
, linked_list_t
*,
453 private_linked_list_t
*this, void* (*fn
)(void*))
455 linked_list_t
*clone
= linked_list_create();
456 element_t
*current
= this->first
;
460 clone
->insert_last(clone
, fn(current
->value
));
461 current
= current
->next
;
467 METHOD(linked_list_t
, destroy
, void,
468 private_linked_list_t
*this)
471 /* Remove all list items before destroying list */
472 while (remove_first(this, &value
) == SUCCESS
)
474 /* values are not destroyed so memory leaks are possible
475 * if list is not empty when deleting */
480 METHOD(linked_list_t
, destroy_offset
, void,
481 private_linked_list_t
*this, size_t offset
)
483 element_t
*current
= this->first
, *next
;
487 void (**method
)(void*) = current
->value
+ offset
;
488 (*method
)(current
->value
);
489 next
= current
->next
;
496 METHOD(linked_list_t
, destroy_function
, void,
497 private_linked_list_t
*this, void (*fn
)(void*))
499 element_t
*current
= this->first
, *next
;
504 next
= current
->next
;
512 * Described in header.
514 linked_list_t
*linked_list_create()
516 private_linked_list_t
*this;
520 .get_count
= _get_count
,
521 .create_enumerator
= _create_enumerator
,
522 .reset_enumerator
= (void*)_reset_enumerator
,
523 .get_first
= _get_first
,
524 .get_last
= _get_last
,
525 .find_first
= (void*)_find_first
,
526 .find_last
= (void*)_find_last
,
527 .insert_first
= _insert_first
,
528 .insert_last
= _insert_last
,
529 .insert_before
= (void*)_insert_before
,
530 .replace
= (void*)_replace
,
531 .remove_first
= _remove_first
,
532 .remove_last
= _remove_last
,
534 .remove_at
= (void*)_remove_at
,
535 .invoke_offset
= (void*)_invoke_offset
,
536 .invoke_function
= (void*)_invoke_function
,
537 .clone_offset
= _clone_offset
,
538 .clone_function
= _clone_function
,
540 .destroy_offset
= _destroy_offset
,
541 .destroy_function
= _destroy_function
,
545 return &this->public;