4 * @brief Implementation of linked_list_t.
9 * Copyright (C) 2007 Tobias Brunner
10 * Copyright (C) 2005-2006 Martin Willi
11 * Copyright (C) 2005 Jan Hutter
12 * Hochschule fuer Technik Rapperswil
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27 #include "linked_list.h"
29 typedef struct element_t element_t
;
32 * This element holds a pointer to the value it represents.
37 * Value of a list item.
42 * Previous list element.
44 * NULL if first element in list.
51 * NULL if last element in list.
57 * Creates an empty linked list object.
59 element_t
*element_create(void *value
)
61 element_t
*this = malloc_thing(element_t
);
63 this->previous
= NULL
;
71 typedef struct private_linked_list_t private_linked_list_t
;
74 * Private data of a linked_list_t object.
77 struct private_linked_list_t
{
79 * Public part of linked list.
84 * Number of items in the list.
89 * First element in list.
90 * NULL if no elements in list.
95 * Last element in list.
96 * NULL if no elements in list.
102 typedef struct private_iterator_t private_iterator_t
;
105 * Private variables and functions of linked list iterator.
107 struct private_iterator_t
{
109 * Public part of linked list iterator.
114 * Associated linked list.
116 private_linked_list_t
* list
;
119 * Current element of the iterator.
124 * Direction of iterator.
129 * Mutex to use to synchronize access
131 pthread_mutex_t
*mutex
;
136 iterator_hook_t
*hook
;
139 * user parameter for iterator hook
144 typedef struct private_enumerator_t private_enumerator_t
;
147 * linked lists enumerator implementation
149 struct private_enumerator_t
{
152 * implements enumerator interface
154 enumerator_t enumerator
;
157 * next item to enumerate
163 * Implementation of private_enumerator_t.enumerator.enumerate.
165 static bool enumerate(private_enumerator_t
*this, void **item
)
167 if (this->next
== NULL
)
171 *item
= this->next
->value
;
172 this->next
= this->next
->next
;
177 * Implementation of linked_list_t.create_enumerator.
179 static enumerator_t
* create_enumerator(private_linked_list_t
*this)
181 private_enumerator_t
*enumerator
= malloc_thing(private_enumerator_t
);
183 enumerator
->enumerator
.enumerate
= (void*)enumerate
;
184 enumerator
->enumerator
.destroy
= (void*)free
;
185 enumerator
->next
= this->first
;
187 return &enumerator
->enumerator
;
191 * Implementation of iterator_t.get_count.
193 static int get_list_count(private_iterator_t
*this)
195 return this->list
->count
;
199 * default iterator hook which does nothing
201 static hook_result_t
iterator_hook(void *param
, void *in
, void **out
)
208 * Implementation of iterator_t.set_iterator_hook.
210 static void set_iterator_hook(private_iterator_t
*this, iterator_hook_t
*hook
,
215 this->hook
= iterator_hook
;
216 this->hook_param
= NULL
;
221 this->hook_param
= param
;
226 * Implementation of iterator_t.iterate.
228 static bool iterate(private_iterator_t
*this, void** value
)
234 this->current
= this->current ?
this->current
->next
: this->list
->first
;
238 this->current
= this->current ?
this->current
->previous
: this->list
->last
;
241 if (this->current
== NULL
)
246 switch (this->hook(this->hook_param
, this->current
->value
, value
))
252 this->current
= this->current
->previous
;
256 this->current
= this->current
->next
;
260 /* normal iteration */
272 * Implementation of iterator_t.reset.
274 static void iterator_reset(private_iterator_t
*this)
276 this->current
= NULL
;
280 * Implementation of iterator_t.remove.
282 static status_t
remove_(private_iterator_t
*this)
284 element_t
*new_current
;
286 if (this->current
== NULL
)
291 if (this->list
->count
== 0)
295 /* find out the new iterator position, depending on iterator direction */
296 if (this->forward
&& this->current
->previous
!= NULL
)
298 new_current
= this->current
->previous
;
300 else if (!this->forward
&& this->current
->next
!= NULL
)
302 new_current
= this->current
->next
;
309 /* now delete the entry :-) */
310 if (this->current
->previous
== NULL
)
312 if (this->current
->next
== NULL
)
314 this->list
->first
= NULL
;
315 this->list
->last
= NULL
;
319 this->current
->next
->previous
= NULL
;
320 this->list
->first
= this->current
->next
;
323 else if (this->current
->next
== NULL
)
325 this->current
->previous
->next
= NULL
;
326 this->list
->last
= this->current
->previous
;
330 this->current
->previous
->next
= this->current
->next
;
331 this->current
->next
->previous
= this->current
->previous
;
336 /* set the new iterator position */
337 this->current
= new_current
;
342 * Implementation of iterator_t.insert_before.
344 static void insert_before(private_iterator_t
* iterator
, void *item
)
346 if (iterator
->current
== NULL
)
348 iterator
->list
->public.insert_first(&(iterator
->list
->public), item
);
351 element_t
*element
= element_create(item
);
352 if (iterator
->current
->previous
== NULL
)
354 iterator
->current
->previous
= element
;
355 element
->next
= iterator
->current
;
356 iterator
->list
->first
= element
;
360 iterator
->current
->previous
->next
= element
;
361 element
->previous
= iterator
->current
->previous
;
362 iterator
->current
->previous
= element
;
363 element
->next
= iterator
->current
;
365 iterator
->list
->count
++;
369 * Implementation of iterator_t.replace.
371 static status_t
replace(private_iterator_t
*this, void **old_item
, void *new_item
)
373 if (this->current
== NULL
)
377 if (old_item
!= NULL
)
379 *old_item
= this->current
->value
;
381 this->current
->value
= new_item
;
387 * Implementation of iterator_t.insert_after.
389 static void insert_after(private_iterator_t
*iterator
, void *item
)
391 if (iterator
->current
== NULL
)
393 iterator
->list
->public.insert_first(&(iterator
->list
->public),item
);
397 element_t
*element
= element_create(item
);
398 if (iterator
->current
->next
== NULL
)
400 iterator
->current
->next
= element
;
401 element
->previous
= iterator
->current
;
402 iterator
->list
->last
= element
;
406 iterator
->current
->next
->previous
= element
;
407 element
->next
= iterator
->current
->next
;
408 iterator
->current
->next
= element
;
409 element
->previous
= iterator
->current
;
411 iterator
->list
->count
++;
415 * Implementation of iterator_t.destroy.
417 static void iterator_destroy(private_iterator_t
*this)
421 pthread_mutex_unlock(this->mutex
);
427 * Implementation of linked_list_t.get_count.
429 static int get_count(private_linked_list_t
*this)
435 * Implementation of linked_list_t.insert_first.
437 static void insert_first(private_linked_list_t
*this, void *item
)
441 element
= element_create(item
);
442 if (this->count
== 0)
444 /* first entry in list */
445 this->first
= element
;
446 this->last
= element
;
447 element
->previous
= NULL
;
448 element
->next
= NULL
;
452 element_t
*old_first_element
= this->first
;
453 element
->next
= old_first_element
;
454 element
->previous
= NULL
;
455 old_first_element
->previous
= element
;
456 this->first
= element
;
462 * Implementation of linked_list_t.remove_first.
464 static status_t
remove_first(private_linked_list_t
*this, void **item
)
466 element_t
*element
= this->first
;
472 if (element
->next
!= NULL
)
474 element
->next
->previous
= NULL
;
476 this->first
= element
->next
;
480 *item
= element
->value
;
482 if (--this->count
== 0)
493 * Implementation of linked_list_t.get_first.
495 static status_t
get_first(private_linked_list_t
*this, void **item
)
497 if (this->count
== 0)
501 *item
= this->first
->value
;
506 * Implementation of linked_list_t.insert_last.
508 static void insert_last(private_linked_list_t
*this, void *item
)
510 element_t
*element
= element_create(item
);
512 if (this->count
== 0)
514 /* first entry in list */
515 this->first
= element
;
516 this->last
= element
;
517 element
->previous
= NULL
;
518 element
->next
= NULL
;
522 element_t
*old_last_element
= this->last
;
523 element
->previous
= old_last_element
;
524 element
->next
= NULL
;
525 old_last_element
->next
= element
;
526 this->last
= element
;
532 * Implementation of linked_list_t.remove_last.
534 static status_t
remove_last(private_linked_list_t
*this, void **item
)
536 element_t
*element
= this->last
;
542 if (element
->previous
!= NULL
)
544 element
->previous
->next
= NULL
;
546 this->last
= element
->previous
;
550 *item
= element
->value
;
552 if (--this->count
== 0)
563 * Implementation of linked_list_t.insert_at_position.
565 static status_t
insert_at_position (private_linked_list_t
*this,size_t position
, void *item
)
567 element_t
*current_element
;
570 if (this->count
<= position
)
575 current_element
= this->first
;
577 for (i
= 0; i
< position
;i
++)
579 current_element
= current_element
->next
;
582 if (current_element
== NULL
)
584 this->public.insert_last(&(this->public),item
);
588 element_t
*element
= element_create(item
);
589 if (current_element
->previous
== NULL
)
591 current_element
->previous
= element
;
592 element
->next
= current_element
;
593 this->first
= element
;
597 current_element
->previous
->next
= element
;
598 element
->previous
= current_element
->previous
;
599 current_element
->previous
= element
;
600 element
->next
= current_element
;
609 * Implementation of linked_list_t.remove_at_position.
611 static status_t
remove_at_position(private_linked_list_t
*this,size_t position
, void **item
)
613 iterator_t
*iterator
;
616 if (this->count
<= position
)
621 iterator
= this->public.create_iterator(&(this->public),TRUE
);
622 iterator
->iterate(iterator
, item
);
623 for (i
= 0; i
< position
; i
++)
625 if (!iterator
->iterate(iterator
, item
))
627 iterator
->destroy(iterator
);
631 iterator
->remove(iterator
);
632 iterator
->destroy(iterator
);
638 * Implementation of linked_list_t.get_at_position.
640 static status_t
get_at_position(private_linked_list_t
*this,size_t position
, void **item
)
643 iterator_t
*iterator
;
645 if (this->count
<= position
)
650 iterator
= this->public.create_iterator(&(this->public),TRUE
);
651 iterator
->iterate(iterator
, item
);
652 for (i
= 0; i
< position
; i
++)
654 if (!iterator
->iterate(iterator
, item
))
656 iterator
->destroy(iterator
);
660 iterator
->destroy(iterator
);
665 * Implementation of linked_list_t.get_last.
667 static status_t
get_last(private_linked_list_t
*this, void **item
)
669 if (this->count
== 0)
674 *item
= this->last
->value
;
680 * Implementation of linked_list_t.find_first.
682 static status_t
find_first(private_linked_list_t
*this, linked_list_match_t match
,
683 void **item
, void *d1
, void *d2
, void *d3
, void *d4
, void *d5
)
685 element_t
*current
= this->first
;
689 if (match(current
->value
, d1
, d2
, d3
, d4
, d5
))
693 *item
= current
->value
;
697 current
= current
->next
;
703 * Implementation of linked_list_t.find_last.
705 static status_t
find_last(private_linked_list_t
*this, linked_list_match_t match
,
706 void **item
, void *d1
, void *d2
, void *d3
, void *d4
, void *d5
)
708 element_t
*current
= this->last
;
712 if (match(current
->value
, d1
, d2
, d3
, d4
, d5
))
716 *item
= current
->value
;
720 current
= current
->previous
;
726 * Implementation of linked_list_t.invoke_offset.
728 static void invoke_offset(private_linked_list_t
*this, size_t offset
)
730 element_t
*current
= this->first
;
734 void (**method
)(void*) = current
->value
+ offset
;
735 (*method
)(current
->value
);
736 current
= current
->next
;
741 * Implementation of linked_list_t.invoke_function.
743 static void invoke_function(private_linked_list_t
*this, void(*fn
)(void*))
745 element_t
*current
= this->first
;
750 current
= current
->next
;
755 * Implementation of linked_list_t.clone_offset
757 static linked_list_t
*clone_offset(private_linked_list_t
*this, size_t offset
)
759 linked_list_t
*clone
= linked_list_create();
760 element_t
*current
= this->first
;
764 void* (**method
)(void*) = current
->value
+ offset
;
765 clone
->insert_last(clone
, (*method
)(current
->value
));
766 current
= current
->next
;
773 * Implementation of linked_list_t.clone_function
775 static linked_list_t
*clone_function(private_linked_list_t
*this, void* (*fn
)(void*))
777 linked_list_t
*clone
= linked_list_create();
778 element_t
*current
= this->first
;
782 clone
->insert_last(clone
, fn(current
->value
));
783 current
= current
->next
;
790 * Implementation of linked_list_t.destroy.
792 static void destroy(private_linked_list_t
*this)
795 /* Remove all list items before destroying list */
796 while (remove_first(this, &value
) == SUCCESS
)
798 /* values are not destroyed so memory leaks are possible
799 * if list is not empty when deleting */
805 * Implementation of linked_list_t.destroy_offset.
807 static void destroy_offset(private_linked_list_t
*this, size_t offset
)
809 element_t
*current
= this->first
, *next
;
813 void (**method
)(void*) = current
->value
+ offset
;
814 (*method
)(current
->value
);
815 next
= current
->next
;
823 * Implementation of linked_list_t.destroy_function.
825 static void destroy_function(private_linked_list_t
*this, void (*fn
)(void*))
827 element_t
*current
= this->first
, *next
;
832 next
= current
->next
;
840 * Implementation of linked_list_t.create_iterator.
842 static iterator_t
*create_iterator(private_linked_list_t
*linked_list
, bool forward
)
844 private_iterator_t
*this = malloc_thing(private_iterator_t
);
846 this->public.get_count
= (int (*) (iterator_t
*)) get_list_count
;
847 this->public.iterate
= (bool (*) (iterator_t
*, void **value
)) iterate
;
848 this->public.set_iterator_hook
= (void(*)(iterator_t
*, iterator_hook_t
*, void*))set_iterator_hook
;
849 this->public.insert_before
= (void (*) (iterator_t
*, void *item
)) insert_before
;
850 this->public.insert_after
= (void (*) (iterator_t
*, void *item
)) insert_after
;
851 this->public.replace
= (status_t (*) (iterator_t
*, void **, void *)) replace
;
852 this->public.remove
= (status_t (*) (iterator_t
*)) remove_
;
853 this->public.reset
= (void (*) (iterator_t
*)) iterator_reset
;
854 this->public.destroy
= (void (*) (iterator_t
*)) iterator_destroy
;
856 this->forward
= forward
;
857 this->current
= NULL
;
858 this->list
= linked_list
;
860 this->hook
= iterator_hook
;
862 return &this->public;
866 * Implementation of linked_list_t.create_iterator_locked.
868 static iterator_t
*create_iterator_locked(private_linked_list_t
*linked_list
,
869 pthread_mutex_t
*mutex
)
871 private_iterator_t
*this = (private_iterator_t
*)create_iterator(linked_list
, TRUE
);
874 pthread_mutex_lock(mutex
);
876 return &this->public;
880 * Described in header.
882 linked_list_t
*linked_list_create()
884 private_linked_list_t
*this = malloc_thing(private_linked_list_t
);
886 this->public.get_count
= (int (*) (linked_list_t
*)) get_count
;
887 this->public.create_iterator
= (iterator_t
* (*) (linked_list_t
*,bool))create_iterator
;
888 this->public.create_iterator_locked
= (iterator_t
* (*) (linked_list_t
*,pthread_mutex_t
*))create_iterator_locked
;
889 this->public.create_enumerator
= (enumerator_t
*(*)(linked_list_t
*))create_enumerator
;
890 this->public.get_first
= (status_t (*) (linked_list_t
*, void **item
))get_first
;
891 this->public.get_last
= (status_t (*) (linked_list_t
*, void **item
))get_last
;
892 this->public.find_first
= (status_t (*) (linked_list_t
*, linked_list_match_t
,void**,...))find_first
;
893 this->public.find_last
= (status_t (*) (linked_list_t
*, linked_list_match_t
,void**,...))find_last
;
894 this->public.insert_first
= (void (*) (linked_list_t
*, void *item
))insert_first
;
895 this->public.insert_last
= (void (*) (linked_list_t
*, void *item
))insert_last
;
896 this->public.remove_first
= (status_t (*) (linked_list_t
*, void **item
))remove_first
;
897 this->public.remove_last
= (status_t (*) (linked_list_t
*, void **item
))remove_last
;
898 this->public.insert_at_position
= (status_t (*) (linked_list_t
*,size_t, void *))insert_at_position
;
899 this->public.remove_at_position
= (status_t (*) (linked_list_t
*,size_t, void **))remove_at_position
;
900 this->public.get_at_position
= (status_t (*) (linked_list_t
*,size_t, void **))get_at_position
;
901 this->public.invoke_offset
= (void (*)(linked_list_t
*,size_t))invoke_offset
;
902 this->public.invoke_function
= (void (*)(linked_list_t
*,void(*)(void*)))invoke_function
;
903 this->public.clone_offset
= (linked_list_t
* (*)(linked_list_t
*,size_t))clone_offset
;
904 this->public.clone_function
= (linked_list_t
* (*)(linked_list_t
*,void*(*)(void*)))clone_function
;
905 this->public.destroy
= (void (*) (linked_list_t
*))destroy
;
906 this->public.destroy_offset
= (void (*) (linked_list_t
*,size_t))destroy_offset
;
907 this->public.destroy_function
= (void (*)(linked_list_t
*,void(*)(void*)))destroy_function
;
913 return &this->public;