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 void* (*hook
)(void*);
139 * Implementation of iterator_t.get_count.
141 static int get_list_count(private_iterator_t
*this)
143 return this->list
->count
;
147 * default iterator hook which does nothing
149 static void *iterator_hook(void *value
)
155 * Implementation of iterator_t.set_iterator_hook.
157 static void set_iterator_hook(private_iterator_t
*this, void*(*hook
)(void*))
161 this->hook
= iterator_hook
;
170 * Implementation of iterator_t.iterate.
172 static bool iterate(private_iterator_t
*this, void** value
)
174 if (this->list
->count
== 0)
178 if (this->current
== NULL
)
180 this->current
= (this->forward
) ?
this->list
->first
: this->list
->last
;
181 *value
= this->hook(this->current
->value
);
186 if (this->current
->next
== NULL
)
190 this->current
= this->current
->next
;
191 *value
= this->hook(this->current
->value
);
195 if (this->current
->previous
== NULL
)
199 this->current
= this->current
->previous
;
200 *value
= this->hook(this->current
->value
);
205 * Implementation of iterator_t.reset.
207 static void iterator_reset(private_iterator_t
*this)
209 this->current
= NULL
;
213 * Implementation of iterator_t.remove.
215 static status_t
remove_(private_iterator_t
*this)
217 element_t
*new_current
;
219 if (this->current
== NULL
)
224 if (this->list
->count
== 0)
228 /* find out the new iterator position */
229 if (this->current
->previous
!= NULL
)
231 new_current
= this->current
->previous
;
238 /* now delete the entry :-) */
239 if (this->current
->previous
== NULL
)
241 if (this->current
->next
== NULL
)
243 this->list
->first
= NULL
;
244 this->list
->last
= NULL
;
248 this->current
->next
->previous
= NULL
;
249 this->list
->first
= this->current
->next
;
252 else if (this->current
->next
== NULL
)
254 this->current
->previous
->next
= NULL
;
255 this->list
->last
= this->current
->previous
;
259 this->current
->previous
->next
= this->current
->next
;
260 this->current
->next
->previous
= this->current
->previous
;
265 /* set the new iterator position */
266 this->current
= new_current
;
271 * Implementation of iterator_t.insert_before.
273 static void insert_before(private_iterator_t
* iterator
, void *item
)
275 if (iterator
->current
== NULL
)
277 iterator
->list
->public.insert_first(&(iterator
->list
->public), item
);
280 element_t
*element
= element_create(item
);
281 if (iterator
->current
->previous
== NULL
)
283 iterator
->current
->previous
= element
;
284 element
->next
= iterator
->current
;
285 iterator
->list
->first
= element
;
289 iterator
->current
->previous
->next
= element
;
290 element
->previous
= iterator
->current
->previous
;
291 iterator
->current
->previous
= element
;
292 element
->next
= iterator
->current
;
294 iterator
->list
->count
++;
298 * Implementation of iterator_t.replace.
300 static status_t
replace(private_iterator_t
*this, void **old_item
, void *new_item
)
302 if (this->current
== NULL
)
306 if (old_item
!= NULL
)
308 *old_item
= this->current
->value
;
310 this->current
->value
= new_item
;
316 * Implementation of iterator_t.insert_after.
318 static void insert_after(private_iterator_t
*iterator
, void *item
)
320 if (iterator
->current
== NULL
)
322 iterator
->list
->public.insert_first(&(iterator
->list
->public),item
);
326 element_t
*element
= element_create(item
);
327 if (iterator
->current
->next
== NULL
)
329 iterator
->current
->next
= element
;
330 element
->previous
= iterator
->current
;
331 iterator
->list
->last
= element
;
335 iterator
->current
->next
->previous
= element
;
336 element
->next
= iterator
->current
->next
;
337 iterator
->current
->next
= element
;
338 element
->previous
= iterator
->current
;
340 iterator
->list
->count
++;
344 * Implementation of iterator_t.destroy.
346 static void iterator_destroy(private_iterator_t
*this)
350 pthread_mutex_unlock(this->mutex
);
356 * Implementation of linked_list_t.get_count.
358 static int get_count(private_linked_list_t
*this)
364 * Implementation of linked_list_t.insert_first.
366 static void insert_first(private_linked_list_t
*this, void *item
)
370 element
= element_create(item
);
371 if (this->count
== 0)
373 /* first entry in list */
374 this->first
= element
;
375 this->last
= element
;
376 element
->previous
= NULL
;
377 element
->next
= NULL
;
381 element_t
*old_first_element
= this->first
;
382 element
->next
= old_first_element
;
383 element
->previous
= NULL
;
384 old_first_element
->previous
= element
;
385 this->first
= element
;
391 * Implementation of linked_list_t.remove_first.
393 static status_t
remove_first(private_linked_list_t
*this, void **item
)
395 element_t
*element
= this->first
;
401 if (element
->next
!= NULL
)
403 element
->next
->previous
= NULL
;
405 this->first
= element
->next
;
409 *item
= element
->value
;
411 if (--this->count
== 0)
422 * Implementation of linked_list_t.get_first.
424 static status_t
get_first(private_linked_list_t
*this, void **item
)
426 if (this->count
== 0)
430 *item
= this->first
->value
;
435 * Implementation of linked_list_t.insert_last.
437 static void insert_last(private_linked_list_t
*this, void *item
)
439 element_t
*element
= element_create(item
);
441 if (this->count
== 0)
443 /* first entry in list */
444 this->first
= element
;
445 this->last
= element
;
446 element
->previous
= NULL
;
447 element
->next
= NULL
;
451 element_t
*old_last_element
= this->last
;
452 element
->previous
= old_last_element
;
453 element
->next
= NULL
;
454 old_last_element
->next
= element
;
455 this->last
= element
;
461 * Implementation of linked_list_t.remove_last.
463 static status_t
remove_last(private_linked_list_t
*this, void **item
)
465 element_t
*element
= this->last
;
471 if (element
->previous
!= NULL
)
473 element
->previous
->next
= NULL
;
475 this->last
= element
->previous
;
479 *item
= element
->value
;
481 if (--this->count
== 0)
492 * Implementation of linked_list_t.insert_at_position.
494 static status_t
insert_at_position (private_linked_list_t
*this,size_t position
, void *item
)
496 element_t
*current_element
;
499 if (this->count
<= position
)
504 current_element
= this->first
;
506 for (i
= 0; i
< position
;i
++)
508 current_element
= current_element
->next
;
511 if (current_element
== NULL
)
513 this->public.insert_last(&(this->public),item
);
517 element_t
*element
= element_create(item
);
518 if (current_element
->previous
== NULL
)
520 current_element
->previous
= element
;
521 element
->next
= current_element
;
522 this->first
= element
;
526 current_element
->previous
->next
= element
;
527 element
->previous
= current_element
->previous
;
528 current_element
->previous
= element
;
529 element
->next
= current_element
;
538 * Implementation of linked_list_t.remove_at_position.
540 static status_t
remove_at_position(private_linked_list_t
*this,size_t position
, void **item
)
542 iterator_t
*iterator
;
545 if (this->count
<= position
)
550 iterator
= this->public.create_iterator(&(this->public),TRUE
);
551 iterator
->iterate(iterator
, item
);
552 for (i
= 0; i
< position
; i
++)
554 if (!iterator
->iterate(iterator
, item
))
556 iterator
->destroy(iterator
);
560 iterator
->remove(iterator
);
561 iterator
->destroy(iterator
);
567 * Implementation of linked_list_t.get_at_position.
569 static status_t
get_at_position(private_linked_list_t
*this,size_t position
, void **item
)
572 iterator_t
*iterator
;
574 if (this->count
<= position
)
579 iterator
= this->public.create_iterator(&(this->public),TRUE
);
580 iterator
->iterate(iterator
, item
);
581 for (i
= 0; i
< position
; i
++)
583 if (!iterator
->iterate(iterator
, item
))
585 iterator
->destroy(iterator
);
589 iterator
->destroy(iterator
);
594 * Implementation of linked_list_t.get_last.
596 static status_t
get_last(private_linked_list_t
*this, void **item
)
598 if (this->count
== 0)
603 *item
= this->last
->value
;
609 * Implementation of linked_list_t.invoke.
611 static void invoke(private_linked_list_t
*this, size_t offset
)
613 element_t
*current
= this->first
;
617 void (**method
)(void*) = current
->value
+ offset
;
618 (*method
)(current
->value
);
619 current
= current
->next
;
624 * Implementation of linked_list_t.destroy.
626 static void destroy(private_linked_list_t
*this)
629 /* Remove all list items before destroying list */
630 while (this->public.remove_first(&(this->public), &value
) == SUCCESS
)
632 /* values are not destroyed so memory leaks are possible
633 * if list is not empty when deleting */
639 * Implementation of linked_list_t.destroy_offset.
641 static void destroy_offset(private_linked_list_t
*this, size_t offset
)
643 element_t
*current
= this->first
, *next
;
647 void (**method
)(void*) = current
->value
+ offset
;
648 (*method
)(current
->value
);
649 next
= current
->next
;
657 * Implementation of linked_list_t.destroy_function.
659 static void destroy_function(private_linked_list_t
*this, void (*fn
)(void*))
661 element_t
*current
= this->first
, *next
;
666 next
= current
->next
;
674 * Implementation of linked_list_t.create_iterator.
676 static iterator_t
*create_iterator(private_linked_list_t
*linked_list
, bool forward
)
678 private_iterator_t
*this = malloc_thing(private_iterator_t
);
680 this->public.get_count
= (int (*) (iterator_t
*)) get_list_count
;
681 this->public.iterate
= (bool (*) (iterator_t
*, void **value
)) iterate
;
682 this->public.set_iterator_hook
= (void(*)(iterator_t
*, void*(*)(void*)))set_iterator_hook
;
683 this->public.insert_before
= (void (*) (iterator_t
*, void *item
)) insert_before
;
684 this->public.insert_after
= (void (*) (iterator_t
*, void *item
)) insert_after
;
685 this->public.replace
= (status_t (*) (iterator_t
*, void **, void *)) replace
;
686 this->public.remove
= (status_t (*) (iterator_t
*)) remove_
;
687 this->public.reset
= (void (*) (iterator_t
*)) iterator_reset
;
688 this->public.destroy
= (void (*) (iterator_t
*)) iterator_destroy
;
690 this->forward
= forward
;
691 this->current
= NULL
;
692 this->list
= linked_list
;
694 this->hook
= iterator_hook
;
696 return &this->public;
700 * Implementation of linked_list_t.create_iterator_locked.
702 static iterator_t
*create_iterator_locked(private_linked_list_t
*linked_list
,
703 pthread_mutex_t
*mutex
)
705 private_iterator_t
*this = (private_iterator_t
*)create_iterator(linked_list
, TRUE
);
708 pthread_mutex_lock(mutex
);
710 return &this->public;
714 * Described in header.
716 linked_list_t
*linked_list_create()
718 private_linked_list_t
*this = malloc_thing(private_linked_list_t
);
720 this->public.get_count
= (int (*) (linked_list_t
*)) get_count
;
721 this->public.create_iterator
= (iterator_t
* (*) (linked_list_t
*,bool))create_iterator
;
722 this->public.create_iterator_locked
= (iterator_t
* (*) (linked_list_t
*,pthread_mutex_t
*))create_iterator_locked
;
723 this->public.get_first
= (status_t (*) (linked_list_t
*, void **item
))get_first
;
724 this->public.get_last
= (status_t (*) (linked_list_t
*, void **item
))get_last
;
725 this->public.insert_first
= (void (*) (linked_list_t
*, void *item
))insert_first
;
726 this->public.insert_last
= (void (*) (linked_list_t
*, void *item
))insert_last
;
727 this->public.remove_first
= (status_t (*) (linked_list_t
*, void **item
))remove_first
;
728 this->public.remove_last
= (status_t (*) (linked_list_t
*, void **item
))remove_last
;
729 this->public.insert_at_position
= (status_t (*) (linked_list_t
*,size_t, void *))insert_at_position
;
730 this->public.remove_at_position
= (status_t (*) (linked_list_t
*,size_t, void **))remove_at_position
;
731 this->public.get_at_position
= (status_t (*) (linked_list_t
*,size_t, void **))get_at_position
;
732 this->public.invoke
= (void (*)(linked_list_t
*,size_t))invoke
;
733 this->public.destroy
= (void (*) (linked_list_t
*))destroy
;
734 this->public.destroy_offset
= (void (*) (linked_list_t
*,size_t))destroy_offset
;
735 this->public.destroy_function
= (void (*)(linked_list_t
*,void(*)(void*)))destroy_function
;
741 return &this->public;