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.invoke_offset.
682 static void invoke_offset(private_linked_list_t
*this, size_t offset
)
684 element_t
*current
= this->first
;
688 void (**method
)(void*) = current
->value
+ offset
;
689 (*method
)(current
->value
);
690 current
= current
->next
;
695 * Implementation of linked_list_t.invoke_function.
697 static void invoke_function(private_linked_list_t
*this, void(*fn
)(void*))
699 element_t
*current
= this->first
;
704 current
= current
->next
;
709 * Implementation of linked_list_t.clone_offset
711 static linked_list_t
*clone_offset(private_linked_list_t
*this, size_t offset
)
713 linked_list_t
*clone
= linked_list_create();
714 element_t
*current
= this->first
;
718 void* (**method
)(void*) = current
->value
+ offset
;
719 clone
->insert_last(clone
, (*method
)(current
->value
));
720 current
= current
->next
;
727 * Implementation of linked_list_t.clone_function
729 static linked_list_t
*clone_function(private_linked_list_t
*this, void* (*fn
)(void*))
731 linked_list_t
*clone
= linked_list_create();
732 element_t
*current
= this->first
;
736 clone
->insert_last(clone
, fn(current
->value
));
737 current
= current
->next
;
744 * Implementation of linked_list_t.destroy.
746 static void destroy(private_linked_list_t
*this)
749 /* Remove all list items before destroying list */
750 while (remove_first(this, &value
) == SUCCESS
)
752 /* values are not destroyed so memory leaks are possible
753 * if list is not empty when deleting */
759 * Implementation of linked_list_t.destroy_offset.
761 static void destroy_offset(private_linked_list_t
*this, size_t offset
)
763 element_t
*current
= this->first
, *next
;
767 void (**method
)(void*) = current
->value
+ offset
;
768 (*method
)(current
->value
);
769 next
= current
->next
;
777 * Implementation of linked_list_t.destroy_function.
779 static void destroy_function(private_linked_list_t
*this, void (*fn
)(void*))
781 element_t
*current
= this->first
, *next
;
786 next
= current
->next
;
794 * Implementation of linked_list_t.create_iterator.
796 static iterator_t
*create_iterator(private_linked_list_t
*linked_list
, bool forward
)
798 private_iterator_t
*this = malloc_thing(private_iterator_t
);
800 this->public.get_count
= (int (*) (iterator_t
*)) get_list_count
;
801 this->public.iterate
= (bool (*) (iterator_t
*, void **value
)) iterate
;
802 this->public.set_iterator_hook
= (void(*)(iterator_t
*, iterator_hook_t
*, void*))set_iterator_hook
;
803 this->public.insert_before
= (void (*) (iterator_t
*, void *item
)) insert_before
;
804 this->public.insert_after
= (void (*) (iterator_t
*, void *item
)) insert_after
;
805 this->public.replace
= (status_t (*) (iterator_t
*, void **, void *)) replace
;
806 this->public.remove
= (status_t (*) (iterator_t
*)) remove_
;
807 this->public.reset
= (void (*) (iterator_t
*)) iterator_reset
;
808 this->public.destroy
= (void (*) (iterator_t
*)) iterator_destroy
;
810 this->forward
= forward
;
811 this->current
= NULL
;
812 this->list
= linked_list
;
814 this->hook
= iterator_hook
;
816 return &this->public;
820 * Implementation of linked_list_t.create_iterator_locked.
822 static iterator_t
*create_iterator_locked(private_linked_list_t
*linked_list
,
823 pthread_mutex_t
*mutex
)
825 private_iterator_t
*this = (private_iterator_t
*)create_iterator(linked_list
, TRUE
);
828 pthread_mutex_lock(mutex
);
830 return &this->public;
834 * Described in header.
836 linked_list_t
*linked_list_create()
838 private_linked_list_t
*this = malloc_thing(private_linked_list_t
);
840 this->public.get_count
= (int (*) (linked_list_t
*)) get_count
;
841 this->public.create_iterator
= (iterator_t
* (*) (linked_list_t
*,bool))create_iterator
;
842 this->public.create_iterator_locked
= (iterator_t
* (*) (linked_list_t
*,pthread_mutex_t
*))create_iterator_locked
;
843 this->public.create_enumerator
= (enumerator_t
*(*)(linked_list_t
*))create_enumerator
;
844 this->public.get_first
= (status_t (*) (linked_list_t
*, void **item
))get_first
;
845 this->public.get_last
= (status_t (*) (linked_list_t
*, void **item
))get_last
;
846 this->public.insert_first
= (void (*) (linked_list_t
*, void *item
))insert_first
;
847 this->public.insert_last
= (void (*) (linked_list_t
*, void *item
))insert_last
;
848 this->public.remove_first
= (status_t (*) (linked_list_t
*, void **item
))remove_first
;
849 this->public.remove_last
= (status_t (*) (linked_list_t
*, void **item
))remove_last
;
850 this->public.insert_at_position
= (status_t (*) (linked_list_t
*,size_t, void *))insert_at_position
;
851 this->public.remove_at_position
= (status_t (*) (linked_list_t
*,size_t, void **))remove_at_position
;
852 this->public.get_at_position
= (status_t (*) (linked_list_t
*,size_t, void **))get_at_position
;
853 this->public.invoke_offset
= (void (*)(linked_list_t
*,size_t))invoke_offset
;
854 this->public.invoke_function
= (void (*)(linked_list_t
*,void(*)(void*)))invoke_function
;
855 this->public.clone_offset
= (linked_list_t
* (*)(linked_list_t
*,size_t))clone_offset
;
856 this->public.clone_function
= (linked_list_t
* (*)(linked_list_t
*,void*(*)(void*)))clone_function
;
857 this->public.destroy
= (void (*) (linked_list_t
*))destroy
;
858 this->public.destroy_offset
= (void (*) (linked_list_t
*,size_t))destroy_offset
;
859 this->public.destroy_function
= (void (*)(linked_list_t
*,void(*)(void*)))destroy_function
;
865 return &this->public;