4 * @brief Implementation of linked_list_t.
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 #include "linked_list.h"
29 typedef struct linked_list_element_t linked_list_element_t
;
32 * @brief Element in a linked list.
34 * This element holds a pointer to the value it represents.
36 struct linked_list_element_t
{
39 * Value of a list item.
44 * Previous list element.
46 * NULL if first element in list.
48 linked_list_element_t
*previous
;
53 * NULL if last element in list.
55 linked_list_element_t
*next
;
58 * Destroys a linked_list_element object.
60 * @param linked_list_element_t calling object
62 void (*destroy
) (linked_list_element_t
*this);
66 * Implementation of linked_list_element_t.destroy.
68 static void linked_list_element_destroy(linked_list_element_t
*this)
74 * @brief Creates an empty linked list object.
76 * @warning Only the pointer to the value is stored.
78 * @param[in] value value of item to be set
79 * @return linked_list_element_t object
82 linked_list_element_t
*linked_list_element_create(void *value
)
84 linked_list_element_t
*this = malloc_thing(linked_list_element_t
);
86 this->destroy
= linked_list_element_destroy
;
96 typedef struct private_linked_list_t private_linked_list_t
;
99 * Private data of a linked_list_t object.
102 struct private_linked_list_t
{
104 * Public part of linked list.
106 linked_list_t
public;
109 * Number of items in the list.
114 * First element in list.
115 * NULL if no elements in list.
117 linked_list_element_t
*first
;
120 * Last element in list.
121 * NULL if no elements in list.
123 linked_list_element_t
*last
;
127 typedef struct private_iterator_t private_iterator_t
;
130 * Private variables and functions of linked list iterator.
132 struct private_iterator_t
{
134 * Public part of linked list iterator.
139 * Associated linked list.
141 private_linked_list_t
* list
;
144 * Current element of the iterator.
146 linked_list_element_t
*current
;
149 * Direction of iterator.
155 * Implementation of iterator_t.has_next.
157 static bool iterate(private_iterator_t
*this, void** value
)
159 if (this->list
->count
== 0)
163 if (this->current
== NULL
)
165 this->current
= (this->forward
) ? this->list
->first
: this->list
->last
;
166 *value
= this->current
->value
;
171 if (this->current
->next
== NULL
)
175 this->current
= this->current
->next
;
176 *value
= this->current
->value
;
180 if (this->current
->previous
== NULL
)
184 this->current
= this->current
->previous
;
185 *value
= this->current
->value
;
190 * Implementation of iterator_t.has_next.
192 static bool iterator_has_next(private_iterator_t
*this)
194 if (this->list
->count
== 0)
198 if (this->current
== NULL
)
200 this->current
= (this->forward
) ? this->list
->first
: this->list
->last
;
205 if (this->current
->next
== NULL
)
209 this->current
= this->current
->next
;
213 if (this->current
->previous
== NULL
)
217 this->current
= this->current
->previous
;
222 * Implementation of iterator_t.current.
224 static status_t
iterator_current(private_iterator_t
*this, void **value
)
226 if (this->current
== NULL
)
230 *value
= this->current
->value
;
235 * Implementation of iterator_t.reset.
237 static void iterator_reset(private_iterator_t
*this)
239 this->current
= NULL
;
243 * Implementation of iterator_t.remove.
245 static status_t
remove(private_iterator_t
*this)
247 linked_list_element_t
*new_current
;
249 if (this->current
== NULL
)
254 if (this->list
->count
== 0)
258 /* find out the new iterator position */
259 if (this->current
->previous
!= NULL
)
261 new_current
= this->current
->previous
;
263 else if (this->current
->next
!= NULL
)
265 new_current
= this->current
->next
;
272 /* now delete the entry :-) */
273 if (this->current
->previous
== NULL
)
275 if (this->current
->next
== NULL
)
277 this->list
->first
= NULL
;
278 this->list
->last
= NULL
;
282 this->current
->next
->previous
= NULL
;
283 this->list
->first
= this->current
->next
;
286 else if (this->current
->next
== NULL
)
288 this->current
->previous
->next
= NULL
;
289 this->list
->last
= this->current
->previous
;
293 this->current
->previous
->next
= this->current
->next
;
294 this->current
->next
->previous
= this->current
->previous
;
298 this->current
->destroy(this->current
);
299 /* set the new iterator position */
300 this->current
= new_current
;
305 * Implementation of iterator_t.insert_before.
307 static void insert_before(private_iterator_t
* iterator
, void *item
)
309 if (iterator
->current
== NULL
)
311 iterator
->list
->public.insert_first(&(iterator
->list
->public), item
);
314 linked_list_element_t
*element
=(linked_list_element_t
*) linked_list_element_create(item
);
316 if (iterator
->current
->previous
== NULL
)
318 iterator
->current
->previous
= element
;
319 element
->next
= iterator
->current
;
320 iterator
->list
->first
= element
;
324 iterator
->current
->previous
->next
= element
;
325 element
->previous
= iterator
->current
->previous
;
326 iterator
->current
->previous
= element
;
327 element
->next
= iterator
->current
;
330 iterator
->list
->count
++;
334 * Implementation of iterator_t.replace.
336 static status_t
replace (private_iterator_t
*this, void **old_item
, void *new_item
)
338 if (this->current
== NULL
)
342 if (old_item
!= NULL
)
344 *old_item
= this->current
->value
;
346 this->current
->value
= new_item
;
352 * Implementation of iterator_t.insert_after.
354 static void insert_after(private_iterator_t
* iterator
, void *item
)
356 if (iterator
->current
== NULL
)
358 iterator
->list
->public.insert_first(&(iterator
->list
->public),item
);
362 linked_list_element_t
*element
=(linked_list_element_t
*) linked_list_element_create(item
);
364 if (iterator
->current
->next
== NULL
)
366 iterator
->current
->next
= element
;
367 element
->previous
= iterator
->current
;
368 iterator
->list
->last
= element
;
372 iterator
->current
->next
->previous
= element
;
373 element
->next
= iterator
->current
->next
;
374 iterator
->current
->next
= element
;
375 element
->previous
= iterator
->current
;
377 iterator
->list
->count
++;
381 * Implementation of iterator_t.destroy.
383 static void iterator_destroy(private_iterator_t
*this)
389 * Implementation of linked_list_t.get_count.
391 static int get_count(private_linked_list_t
*this)
397 * Implementation of linked_list_t.call_on_items.
399 static void call_on_items(private_linked_list_t
*this, void(*func
)(void*))
401 iterator_t
*iterator
;
404 iterator
= this->public.create_iterator(&(this->public),TRUE
);
406 while (iterator
->has_next(iterator
))
408 iterator
->current(iterator
, &item
);
411 iterator
->destroy(iterator
);
415 * Implementation of linked_list_t.insert_first.
417 static void insert_first(private_linked_list_t
*this, void *item
)
419 linked_list_element_t
*element
;
421 element
=(linked_list_element_t
*) linked_list_element_create(item
);
423 if (this->count
== 0)
425 /* first entry in list */
426 this->first
= element
;
427 this->last
= element
;
428 element
->previous
= NULL
;
429 element
->next
= NULL
;
433 linked_list_element_t
*old_first_element
= this->first
;
434 element
->next
= old_first_element
;
435 element
->previous
= NULL
;
436 old_first_element
->previous
= element
;
437 this->first
= element
;
444 * Implementation of linked_list_t.remove_first.
446 static status_t
remove_first(private_linked_list_t
*this, void **item
)
448 if (this->count
== 0)
453 linked_list_element_t
*element
= this->first
;
455 if (element
->next
!= NULL
)
457 element
->next
->previous
= NULL
;
459 this->first
= element
->next
;
463 *item
= element
->value
;
468 element
->destroy(element
);
474 * Implementation of linked_list_t.get_first.
476 static status_t
get_first(private_linked_list_t
*this, void **item
)
478 if (this->count
== 0)
483 *item
= this->first
->value
;
489 * Implementation of linked_list_t.insert_last.
491 static void insert_last(private_linked_list_t
*this, void *item
)
493 linked_list_element_t
*element
= (linked_list_element_t
*) linked_list_element_create(item
);
495 if (this->count
== 0)
497 /* first entry in list */
498 this->first
= element
;
499 this->last
= element
;
500 element
->previous
= NULL
;
501 element
->next
= NULL
;
506 linked_list_element_t
*old_last_element
= this->last
;
507 element
->previous
= old_last_element
;
508 element
->next
= NULL
;
509 old_last_element
->next
= element
;
510 this->last
= element
;
517 * Implementation of linked_list_t.remove_last.
519 static status_t
remove_last(private_linked_list_t
*this, void **item
)
521 if (this->count
== 0)
526 linked_list_element_t
*element
= this->last
;
528 if (element
->previous
!= NULL
)
530 element
->previous
->next
= NULL
;
532 this->last
= element
->previous
;
536 *item
= element
->value
;
541 element
->destroy(element
);
547 * Implementation of linked_list_t.insert_at_position.
549 static status_t
insert_at_position (private_linked_list_t
*this,size_t position
, void *item
)
551 linked_list_element_t
*current_element
;
554 if (this->count
<= position
)
559 current_element
= this->first
;
561 for (i
= 0; i
< position
;i
++)
563 current_element
= current_element
->next
;
566 if (current_element
== NULL
)
568 this->public.insert_last(&(this->public),item
);
572 linked_list_element_t
*element
=(linked_list_element_t
*) linked_list_element_create(item
);
575 if (current_element
->previous
== NULL
)
577 current_element
->previous
= element
;
578 element
->next
= current_element
;
579 this->first
= element
;
583 current_element
->previous
->next
= element
;
584 element
->previous
= current_element
->previous
;
585 current_element
->previous
= element
;
586 element
->next
= current_element
;
595 * Implementation of linked_list_t.remove_at_position.
597 static status_t
remove_at_position (private_linked_list_t
*this,size_t position
, void **item
)
599 iterator_t
*iterator
;
602 if (this->count
<= position
)
607 iterator
= this->public.create_iterator(&(this->public),TRUE
);
609 iterator
->has_next(iterator
);
610 for (i
= 0; i
< position
;i
++)
612 iterator
->has_next(iterator
);
614 iterator
->current(iterator
,item
);
615 iterator
->remove(iterator
);
616 iterator
->destroy(iterator
);
622 * Implementation of linked_list_t.get_at_position.
624 static status_t
get_at_position (private_linked_list_t
*this,size_t position
, void **item
)
627 iterator_t
*iterator
;
629 if (this->count
<= position
)
634 iterator
= this->public.create_iterator(&(this->public),TRUE
);
636 iterator
->has_next(iterator
);
637 for (i
= 0; i
< position
;i
++)
639 iterator
->has_next(iterator
);
641 status
= iterator
->current(iterator
,item
);
642 iterator
->destroy(iterator
);
647 * Implementation of linked_list_t.get_last.
649 static status_t
get_last(private_linked_list_t
*this, void **item
)
651 if (this->count
== 0)
656 *item
= this->last
->value
;
662 * Implementation of linked_list_t.create_iterator.
664 static iterator_t
*create_iterator (private_linked_list_t
*linked_list
,bool forward
)
666 private_iterator_t
*this = malloc_thing(private_iterator_t
);
668 this->public.iterate
= (bool (*) (iterator_t
*this, void **value
)) iterate
;
669 this->public.has_next
= (bool (*) (iterator_t
*this)) iterator_has_next
;
670 this->public.current
= (status_t (*) (iterator_t
*this, void **value
)) iterator_current
;
671 this->public.insert_before
= (void (*) (iterator_t
*this, void *item
)) insert_before
;
672 this->public.insert_after
= (void (*) (iterator_t
*this, void *item
)) insert_after
;
673 this->public.replace
= (status_t (*) (iterator_t
*, void **, void *)) replace
;
674 this->public.remove
= (status_t (*) (iterator_t
*this)) remove
;
675 this->public.reset
= (void (*) (iterator_t
*this)) iterator_reset
;
676 this->public.destroy
= (void (*) (iterator_t
*this)) iterator_destroy
;
678 this->forward
= forward
;
679 this->current
= NULL
;
680 this->list
= linked_list
;
682 return &(this->public);
686 * Implementation of linked_list_t.destroy.
688 static void linked_list_destroy(private_linked_list_t
*this)
691 /* Remove all list items before destroying list */
692 while (this->public.remove_first(&(this->public),&value
) != NOT_FOUND
)
694 /* values are not destroyed so memory leaks are possible
695 * if list is not empty when deleting */
701 * Described in header.
703 linked_list_t
*linked_list_create()
705 private_linked_list_t
*this = malloc_thing(private_linked_list_t
);
707 this->public.get_count
= (int (*) (linked_list_t
*)) get_count
;
708 this->public.create_iterator
= (iterator_t
* (*) (linked_list_t
*,bool )) create_iterator
;
709 this->public.call_on_items
= (void (*) (linked_list_t
*, void(*func
)(void*)))call_on_items
;
710 this->public.get_first
= (status_t (*) (linked_list_t
*, void **item
)) get_first
;
711 this->public.get_last
= (status_t (*) (linked_list_t
*, void **item
)) get_last
;
712 this->public.insert_first
= (void (*) (linked_list_t
*, void *item
)) insert_first
;
713 this->public.insert_last
= (void (*) (linked_list_t
*, void *item
)) insert_last
;
714 this->public.remove_first
= (status_t (*) (linked_list_t
*, void **item
)) remove_first
;
715 this->public.remove_last
= (status_t (*) (linked_list_t
*, void **item
)) remove_last
;
716 this->public.insert_at_position
=(status_t (*) (linked_list_t
*,size_t, void *)) insert_at_position
;
717 this->public.remove_at_position
=(status_t (*) (linked_list_t
*,size_t, void **)) remove_at_position
;
718 this->public.get_at_position
=(status_t (*) (linked_list_t
*,size_t, void **)) get_at_position
;
720 this->public.destroy
= (void (*) (linked_list_t
*)) linked_list_destroy
;
726 return (&(this->public));