4 * @brief Implementation of linked_list_t.
9 * Copyright (C) 2005-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26 #include "linked_list.h"
28 typedef struct element_t element_t
;
31 * This element holds a pointer to the value it represents.
36 * Value of a list item.
41 * Previous list element.
43 * NULL if first element in list.
50 * NULL if last element in list.
56 * Creates an empty linked list object.
58 element_t
*element_create(void *value
)
60 element_t
*this = malloc_thing(element_t
);
62 this->previous
= NULL
;
70 typedef struct private_linked_list_t private_linked_list_t
;
73 * Private data of a linked_list_t object.
76 struct private_linked_list_t
{
78 * Public part of linked list.
83 * Number of items in the list.
88 * First element in list.
89 * NULL if no elements in list.
94 * Last element in list.
95 * NULL if no elements in list.
101 typedef struct private_iterator_t private_iterator_t
;
104 * Private variables and functions of linked list iterator.
106 struct private_iterator_t
{
108 * Public part of linked list iterator.
113 * Associated linked list.
115 private_linked_list_t
* list
;
118 * Current element of the iterator.
123 * Direction of iterator.
128 * Mutex to use to synchronize access
130 pthread_mutex_t
*mutex
;
135 iterator_hook_t
*hook
;
138 * user parameter for iterator hook
144 * Implementation of iterator_t.get_count.
146 static int get_list_count(private_iterator_t
*this)
148 return this->list
->count
;
152 * default iterator hook which does nothing
154 static bool iterator_hook(void *param
, void *in
, void **out
)
161 * Implementation of iterator_t.set_iterator_hook.
163 static void set_iterator_hook(private_iterator_t
*this, iterator_hook_t
*hook
,
168 this->hook
= iterator_hook
;
169 this->hook_param
= NULL
;
174 this->hook_param
= param
;
179 * Implementation of iterator_t.iterate.
181 static bool iterate(private_iterator_t
*this, void** value
)
183 if (this->list
->count
== 0)
187 if (this->current
== NULL
)
189 this->current
= (this->forward
) ?
this->list
->first
: this->list
->last
;
190 if (!this->hook(this->hook_param
, this->current
->value
, value
))
192 return iterate(this, value
);
198 if (this->current
->next
== NULL
)
202 this->current
= this->current
->next
;
203 if (!this->hook(this->hook_param
, this->current
->value
, value
))
205 return iterate(this, value
);
209 if (this->current
->previous
== NULL
)
213 this->current
= this->current
->previous
;
214 if (!this->hook(this->hook_param
, this->current
->value
, value
))
216 return iterate(this, value
);
222 * Implementation of iterator_t.reset.
224 static void iterator_reset(private_iterator_t
*this)
226 this->current
= NULL
;
230 * Implementation of iterator_t.remove.
232 static status_t
remove_(private_iterator_t
*this)
234 element_t
*new_current
;
236 if (this->current
== NULL
)
241 if (this->list
->count
== 0)
245 /* find out the new iterator position, depending on iterator direction */
246 if (this->forward
&& this->current
->previous
!= NULL
)
248 new_current
= this->current
->previous
;
250 else if (!this->forward
&& this->current
->next
!= NULL
)
252 new_current
= this->current
->next
;
259 /* now delete the entry :-) */
260 if (this->current
->previous
== NULL
)
262 if (this->current
->next
== NULL
)
264 this->list
->first
= NULL
;
265 this->list
->last
= NULL
;
269 this->current
->next
->previous
= NULL
;
270 this->list
->first
= this->current
->next
;
273 else if (this->current
->next
== NULL
)
275 this->current
->previous
->next
= NULL
;
276 this->list
->last
= this->current
->previous
;
280 this->current
->previous
->next
= this->current
->next
;
281 this->current
->next
->previous
= this->current
->previous
;
286 /* set the new iterator position */
287 this->current
= new_current
;
292 * Implementation of iterator_t.insert_before.
294 static void insert_before(private_iterator_t
* iterator
, void *item
)
296 if (iterator
->current
== NULL
)
298 iterator
->list
->public.insert_first(&(iterator
->list
->public), item
);
301 element_t
*element
= element_create(item
);
302 if (iterator
->current
->previous
== NULL
)
304 iterator
->current
->previous
= element
;
305 element
->next
= iterator
->current
;
306 iterator
->list
->first
= element
;
310 iterator
->current
->previous
->next
= element
;
311 element
->previous
= iterator
->current
->previous
;
312 iterator
->current
->previous
= element
;
313 element
->next
= iterator
->current
;
315 iterator
->list
->count
++;
319 * Implementation of iterator_t.replace.
321 static status_t
replace(private_iterator_t
*this, void **old_item
, void *new_item
)
323 if (this->current
== NULL
)
327 if (old_item
!= NULL
)
329 *old_item
= this->current
->value
;
331 this->current
->value
= new_item
;
337 * Implementation of iterator_t.insert_after.
339 static void insert_after(private_iterator_t
*iterator
, void *item
)
341 if (iterator
->current
== NULL
)
343 iterator
->list
->public.insert_first(&(iterator
->list
->public),item
);
347 element_t
*element
= element_create(item
);
348 if (iterator
->current
->next
== NULL
)
350 iterator
->current
->next
= element
;
351 element
->previous
= iterator
->current
;
352 iterator
->list
->last
= element
;
356 iterator
->current
->next
->previous
= element
;
357 element
->next
= iterator
->current
->next
;
358 iterator
->current
->next
= element
;
359 element
->previous
= iterator
->current
;
361 iterator
->list
->count
++;
365 * Implementation of iterator_t.destroy.
367 static void iterator_destroy(private_iterator_t
*this)
371 pthread_mutex_unlock(this->mutex
);
377 * Implementation of linked_list_t.get_count.
379 static int get_count(private_linked_list_t
*this)
385 * Implementation of linked_list_t.insert_first.
387 static void insert_first(private_linked_list_t
*this, void *item
)
391 element
= element_create(item
);
392 if (this->count
== 0)
394 /* first entry in list */
395 this->first
= element
;
396 this->last
= element
;
397 element
->previous
= NULL
;
398 element
->next
= NULL
;
402 element_t
*old_first_element
= this->first
;
403 element
->next
= old_first_element
;
404 element
->previous
= NULL
;
405 old_first_element
->previous
= element
;
406 this->first
= element
;
412 * Implementation of linked_list_t.remove_first.
414 static status_t
remove_first(private_linked_list_t
*this, void **item
)
416 element_t
*element
= this->first
;
422 if (element
->next
!= NULL
)
424 element
->next
->previous
= NULL
;
426 this->first
= element
->next
;
430 *item
= element
->value
;
432 if (--this->count
== 0)
443 * Implementation of linked_list_t.get_first.
445 static status_t
get_first(private_linked_list_t
*this, void **item
)
447 if (this->count
== 0)
451 *item
= this->first
->value
;
456 * Implementation of linked_list_t.insert_last.
458 static void insert_last(private_linked_list_t
*this, void *item
)
460 element_t
*element
= element_create(item
);
462 if (this->count
== 0)
464 /* first entry in list */
465 this->first
= element
;
466 this->last
= element
;
467 element
->previous
= NULL
;
468 element
->next
= NULL
;
472 element_t
*old_last_element
= this->last
;
473 element
->previous
= old_last_element
;
474 element
->next
= NULL
;
475 old_last_element
->next
= element
;
476 this->last
= element
;
482 * Implementation of linked_list_t.remove_last.
484 static status_t
remove_last(private_linked_list_t
*this, void **item
)
486 element_t
*element
= this->last
;
492 if (element
->previous
!= NULL
)
494 element
->previous
->next
= NULL
;
496 this->last
= element
->previous
;
500 *item
= element
->value
;
502 if (--this->count
== 0)
513 * Implementation of linked_list_t.insert_at_position.
515 static status_t
insert_at_position (private_linked_list_t
*this,size_t position
, void *item
)
517 element_t
*current_element
;
520 if (this->count
<= position
)
525 current_element
= this->first
;
527 for (i
= 0; i
< position
;i
++)
529 current_element
= current_element
->next
;
532 if (current_element
== NULL
)
534 this->public.insert_last(&(this->public),item
);
538 element_t
*element
= element_create(item
);
539 if (current_element
->previous
== NULL
)
541 current_element
->previous
= element
;
542 element
->next
= current_element
;
543 this->first
= element
;
547 current_element
->previous
->next
= element
;
548 element
->previous
= current_element
->previous
;
549 current_element
->previous
= element
;
550 element
->next
= current_element
;
559 * Implementation of linked_list_t.remove_at_position.
561 static status_t
remove_at_position(private_linked_list_t
*this,size_t position
, void **item
)
563 iterator_t
*iterator
;
566 if (this->count
<= position
)
571 iterator
= this->public.create_iterator(&(this->public),TRUE
);
572 iterator
->iterate(iterator
, item
);
573 for (i
= 0; i
< position
; i
++)
575 if (!iterator
->iterate(iterator
, item
))
577 iterator
->destroy(iterator
);
581 iterator
->remove(iterator
);
582 iterator
->destroy(iterator
);
588 * Implementation of linked_list_t.get_at_position.
590 static status_t
get_at_position(private_linked_list_t
*this,size_t position
, void **item
)
593 iterator_t
*iterator
;
595 if (this->count
<= position
)
600 iterator
= this->public.create_iterator(&(this->public),TRUE
);
601 iterator
->iterate(iterator
, item
);
602 for (i
= 0; i
< position
; i
++)
604 if (!iterator
->iterate(iterator
, item
))
606 iterator
->destroy(iterator
);
610 iterator
->destroy(iterator
);
615 * Implementation of linked_list_t.get_last.
617 static status_t
get_last(private_linked_list_t
*this, void **item
)
619 if (this->count
== 0)
624 *item
= this->last
->value
;
630 * Implementation of linked_list_t.invoke.
632 static void invoke(private_linked_list_t
*this, size_t offset
)
634 element_t
*current
= this->first
;
638 void (**method
)(void*) = current
->value
+ offset
;
639 (*method
)(current
->value
);
640 current
= current
->next
;
645 * Implementation of linked_list_t.destroy.
647 static void destroy(private_linked_list_t
*this)
650 /* Remove all list items before destroying list */
651 while (this->public.remove_first(&(this->public), &value
) == SUCCESS
)
653 /* values are not destroyed so memory leaks are possible
654 * if list is not empty when deleting */
660 * Implementation of linked_list_t.destroy_offset.
662 static void destroy_offset(private_linked_list_t
*this, size_t offset
)
664 element_t
*current
= this->first
, *next
;
668 void (**method
)(void*) = current
->value
+ offset
;
669 (*method
)(current
->value
);
670 next
= current
->next
;
678 * Implementation of linked_list_t.destroy_function.
680 static void destroy_function(private_linked_list_t
*this, void (*fn
)(void*))
682 element_t
*current
= this->first
, *next
;
687 next
= current
->next
;
695 * Implementation of linked_list_t.create_iterator.
697 static iterator_t
*create_iterator(private_linked_list_t
*linked_list
, bool forward
)
699 private_iterator_t
*this = malloc_thing(private_iterator_t
);
701 this->public.get_count
= (int (*) (iterator_t
*)) get_list_count
;
702 this->public.iterate
= (bool (*) (iterator_t
*, void **value
)) iterate
;
703 this->public.set_iterator_hook
= (void(*)(iterator_t
*, iterator_hook_t
*, void*))set_iterator_hook
;
704 this->public.insert_before
= (void (*) (iterator_t
*, void *item
)) insert_before
;
705 this->public.insert_after
= (void (*) (iterator_t
*, void *item
)) insert_after
;
706 this->public.replace
= (status_t (*) (iterator_t
*, void **, void *)) replace
;
707 this->public.remove
= (status_t (*) (iterator_t
*)) remove_
;
708 this->public.reset
= (void (*) (iterator_t
*)) iterator_reset
;
709 this->public.destroy
= (void (*) (iterator_t
*)) iterator_destroy
;
711 this->forward
= forward
;
712 this->current
= NULL
;
713 this->list
= linked_list
;
715 this->hook
= iterator_hook
;
717 return &this->public;
721 * Implementation of linked_list_t.create_iterator_locked.
723 static iterator_t
*create_iterator_locked(private_linked_list_t
*linked_list
,
724 pthread_mutex_t
*mutex
)
726 private_iterator_t
*this = (private_iterator_t
*)create_iterator(linked_list
, TRUE
);
729 pthread_mutex_lock(mutex
);
731 return &this->public;
735 * Described in header.
737 linked_list_t
*linked_list_create()
739 private_linked_list_t
*this = malloc_thing(private_linked_list_t
);
741 this->public.get_count
= (int (*) (linked_list_t
*)) get_count
;
742 this->public.create_iterator
= (iterator_t
* (*) (linked_list_t
*,bool))create_iterator
;
743 this->public.create_iterator_locked
= (iterator_t
* (*) (linked_list_t
*,pthread_mutex_t
*))create_iterator_locked
;
744 this->public.get_first
= (status_t (*) (linked_list_t
*, void **item
))get_first
;
745 this->public.get_last
= (status_t (*) (linked_list_t
*, void **item
))get_last
;
746 this->public.insert_first
= (void (*) (linked_list_t
*, void *item
))insert_first
;
747 this->public.insert_last
= (void (*) (linked_list_t
*, void *item
))insert_last
;
748 this->public.remove_first
= (status_t (*) (linked_list_t
*, void **item
))remove_first
;
749 this->public.remove_last
= (status_t (*) (linked_list_t
*, void **item
))remove_last
;
750 this->public.insert_at_position
= (status_t (*) (linked_list_t
*,size_t, void *))insert_at_position
;
751 this->public.remove_at_position
= (status_t (*) (linked_list_t
*,size_t, void **))remove_at_position
;
752 this->public.get_at_position
= (status_t (*) (linked_list_t
*,size_t, void **))get_at_position
;
753 this->public.invoke
= (void (*)(linked_list_t
*,size_t))invoke
;
754 this->public.destroy
= (void (*) (linked_list_t
*))destroy
;
755 this->public.destroy_offset
= (void (*) (linked_list_t
*,size_t))destroy_offset
;
756 this->public.destroy_function
= (void (*)(linked_list_t
*,void(*)(void*)))destroy_function
;
762 return &this->public;