4 * @brief Generic Double Linked List
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 <pluto/constants.h>
26 #include <pluto/defs.h>
28 #include "allocator.h"
29 #include "linked_list.h"
32 typedef struct linked_list_element_s linked_list_element_t
;
36 * @brief Element of the linked_list.
38 * This element holds a pointer to the value of the list item itself.
40 struct linked_list_element_s
{
42 * value of a list item
47 * @brief Destroys a linked_list_element object
49 * @param linked_list_element_t calling object
50 * @returns SUCCESS if succeeded, FAILED otherwise
52 status_t (*destroy
) (linked_list_element_t
*this);
55 * previous list element
56 * NULL if first element in list
58 linked_list_element_t
*previous
;
61 * NULL if last element in list
63 linked_list_element_t
*next
;
67 * @brief implements function destroy of linked_list_item_t
69 static status_t
linked_list_element_destroy(linked_list_element_t
*this)
80 * @brief Creates an empty linked list object
82 * @param[in] value value of item to be set
84 * @warning only the pointer to the value is stored
86 * @return linked_list_element object
89 linked_list_element_t
*linked_list_element_create(void *value
)
91 linked_list_element_t
*this = allocator_alloc_thing(linked_list_element_t
);
98 this->destroy
= linked_list_element_destroy
;
108 * Private variables and functions of linked list
111 typedef struct private_linked_list_s private_linked_list_t
;
113 struct private_linked_list_s
{
115 * Public part of linked list
117 linked_list_t
public;
120 * number of items in the list
125 * First element in list
126 * NULL if no elements in list
128 linked_list_element_t
*first
;
130 * Last element in list
131 * NULL if no elements in list
133 linked_list_element_t
*last
;
138 * Private variables and functions of linked list iterator
141 typedef struct private_linked_list_iterator_s private_linked_list_iterator_t
;
143 struct private_linked_list_iterator_s
{
145 * Public part of linked list iterator
147 linked_list_iterator_t
public;
150 * associated linked list
152 private_linked_list_t
* list
;
155 * current element of the iterator
157 linked_list_element_t
*current
;
160 * direction of iterator
166 * Implements function has_next of linked_list_iteratr
168 bool iterator_has_next(private_linked_list_iterator_t
*this)
170 if (this->list
->count
== 0)
174 if (this->current
== NULL
)
176 this->current
= (this->forward
) ?
this->list
->first
: this->list
->last
;
181 if (this->current
->next
== NULL
)
185 this->current
= this->current
->next
;
189 if (this->current
->previous
== NULL
)
193 this->current
= this->current
->previous
;
198 * Implements function current of linked_list_iteratr
200 static status_t
iterator_current(private_linked_list_iterator_t
*this, void **value
)
206 if (this->current
== NULL
)
210 *value
= this->current
->value
;
215 * Implements function current of linked_list_iteratr
217 static status_t
iterator_reset(private_linked_list_iterator_t
*this)
223 this->current
= NULL
;
228 * Implements function destroy of linked_list_iteratr
230 static status_t
iterator_destroy(private_linked_list_iterator_t
*this)
236 allocator_free(this);
241 * @brief implements function get_count of linked_list_t
243 static status_t
get_count(private_linked_list_t
*this, int *count
)
249 *count
= this->count
;
254 static status_t
create_iterator (private_linked_list_t
*linked_list
, linked_list_iterator_t
**iterator
,bool forward
)
256 private_linked_list_iterator_t
*this = allocator_alloc_thing(private_linked_list_iterator_t
);
263 this->public.has_next
= (bool (*) (linked_list_iterator_t
*this)) iterator_has_next
;
264 this->public.current
= (status_t (*) (linked_list_iterator_t
*this, void **value
)) iterator_current
;
265 this->public.reset
= (status_t (*) (linked_list_iterator_t
*this)) iterator_reset
;
266 this->public.destroy
= (status_t (*) (linked_list_iterator_t
*this)) iterator_destroy
;
269 this->forward
= forward
;
270 this->current
= NULL
;
271 this->list
= linked_list
;
273 *iterator
= &(this->public);
280 * @brief implements function insert_first of linked_list_t
282 static status_t
insert_first(private_linked_list_t
*this, void *item
)
284 linked_list_element_t
*element
;
291 element
=(linked_list_element_t
*) linked_list_element_create(item
);
298 if (this->count
== 0)
300 /* first entry in list */
301 this->first
= element
;
302 this->last
= element
;
303 element
->previous
= NULL
;
304 element
->next
= NULL
;
308 if ((this->first
== NULL
) || (this->last
== NULL
))
310 /* should never happen */
311 element
->destroy(element
);
314 linked_list_element_t
*old_first_element
= this->first
;
315 element
->next
= old_first_element
;
316 element
->previous
= NULL
;
317 old_first_element
->previous
= element
;
318 this->first
= element
;
327 * @brief implements function remove_first of linked_list_t
329 static status_t
remove_first(private_linked_list_t
*this, void **item
)
336 if (this->count
== 0)
341 if (this->first
== NULL
)
346 linked_list_element_t
*element
= this->first
;
348 if (element
->next
!= NULL
)
350 element
->next
->previous
= NULL
;
352 this->first
= element
->next
;
354 *item
= element
->value
;
358 return (element
->destroy(element
));
362 * @brief implements function get_first of linked_list_t
364 static status_t
get_first(private_linked_list_t
*this, void **item
)
371 if (this->count
== 0)
376 if (this->first
== NULL
)
381 *item
= this->first
->value
;
387 * @brief implements function insert_last of linked_list_t
389 static status_t
insert_last(private_linked_list_t
*this, void *item
)
396 linked_list_element_t
*element
= (linked_list_element_t
*) linked_list_element_create(item
);
403 if (this->count
== 0)
405 /* first entry in list */
406 this->first
= element
;
407 this->last
= element
;
408 element
->previous
= NULL
;
409 element
->next
= NULL
;
412 if ((this->first
== NULL
) || (this->last
== NULL
))
414 /* should never happen */
415 element
->destroy(element
);
418 linked_list_element_t
*old_last_element
= this->last
;
419 element
->previous
= old_last_element
;
420 element
->next
= NULL
;
421 old_last_element
->next
= element
;
422 this->last
= element
;
431 * @brief implements function remove_last of linked_list_t
433 static status_t
remove_last(private_linked_list_t
*this, void **item
)
440 if (this->count
== 0)
445 if (this->last
== NULL
)
450 linked_list_element_t
*element
= this->last
;
452 if (element
->previous
!= NULL
)
454 element
->previous
->next
= NULL
;
456 this->last
= element
->previous
;
458 *item
= element
->value
;
462 return (element
->destroy(element
));
466 * @brief implements function get_last of linked_list_t
468 static status_t
get_last(private_linked_list_t
*this, void **item
)
475 if (this->count
== 0)
480 if (this->last
== NULL
)
485 *item
= this->last
->value
;
491 * @brief implements function insert_before of linked_list_t
493 static status_t
insert_before(private_linked_list_t
*this, private_linked_list_iterator_t
* iterator
, void *item
)
495 if ((this == NULL
) || (iterator
== NULL
))
500 if (this->count
== 0)
505 if (iterator
->current
== NULL
)
507 return (this->public.insert_first(&this->public,item
));
510 linked_list_element_t
*element
=(linked_list_element_t
*) linked_list_element_create(item
);
517 if (iterator
->current
->previous
== NULL
)
519 if (this->first
!= iterator
->current
)
521 element
->destroy(element
);
525 iterator
->current
->previous
= element
;
526 element
->next
= iterator
->current
;
527 this->first
= element
;
531 iterator
->current
->previous
->next
= element
;
532 element
->previous
= iterator
->current
->previous
;
533 iterator
->current
->previous
= element
;
534 element
->next
= iterator
->current
;
543 * @brief implements function insert_after of linked_list_t
545 static status_t
insert_after(private_linked_list_t
*this, private_linked_list_iterator_t
* iterator
, void *item
)
547 if ((this == NULL
) || (iterator
== NULL
))
552 if (this->count
== 0)
557 if (iterator
->current
== NULL
)
559 return (this->public.insert_first(&this->public,item
));
562 linked_list_element_t
*element
=(linked_list_element_t
*) linked_list_element_create(item
);
569 if (iterator
->current
->next
== NULL
)
571 if (this->last
!= iterator
->current
)
573 element
->destroy(element
);
577 iterator
->current
->next
= element
;
578 element
->previous
= iterator
->current
;
579 this->last
= element
;
583 iterator
->current
->next
->previous
= element
;
584 element
->next
= iterator
->current
->next
;
585 iterator
->current
->next
= element
;
586 element
->previous
= iterator
->current
;
594 * @brief implements function remove of linked_list_t
596 static status_t
linked_list_remove(private_linked_list_t
*this, private_linked_list_iterator_t
* iterator
)
598 linked_list_element_t
*new_current
;
600 if ((this == NULL
) || (iterator
== NULL
) || (iterator
->current
== NULL
))
605 if (this->count
== 0)
609 /* find out the new iterator position */
610 if (iterator
->current
->previous
!= NULL
)
612 new_current
= iterator
->current
->previous
;
614 else if (iterator
->current
->next
!= NULL
)
616 new_current
= iterator
->current
->next
;
623 /* now delete the entry :-) */
624 if (iterator
->current
->previous
== NULL
)
626 if (iterator
->current
->next
== NULL
)
633 iterator
->current
->next
->previous
= NULL
;
634 this->first
= iterator
->current
->next
;
637 else if (iterator
->current
->next
== NULL
)
639 iterator
->current
->previous
->next
= NULL
;
640 this->last
= iterator
->current
->previous
;
644 iterator
->current
->previous
->next
= iterator
->current
->next
;
645 iterator
->current
->next
->previous
= iterator
->current
->previous
;
649 iterator
->current
->destroy(iterator
->current
);
650 /* set the new iterator position */
651 iterator
->current
= new_current
;
656 * @brief implements function destroy of linked_list_t
658 static status_t
linked_list_destroy(private_linked_list_t
*this)
665 /* Remove all list items before destroying list */
666 while (this->count
> 0)
669 /* values are not destroyed so memory leaks are possible
670 * if list is not empty when deleting */
671 if (this->public.remove_first(&(this->public),&value
) != SUCCESS
)
673 allocator_free(this);
677 allocator_free(this);
682 * Described in header
684 linked_list_t
*linked_list_create()
686 private_linked_list_t
*this = allocator_alloc_thing(private_linked_list_t
);
688 this->public.get_count
= (status_t (*) (linked_list_t
*linked_list
, int *count
)) get_count
;
689 this->public.create_iterator
= (status_t (*) (linked_list_t
*linked_list
, linked_list_iterator_t
**iterator
,bool forward
)) create_iterator
;
690 this->public.get_first
= (status_t (*) (linked_list_t
*linked_list
, void **item
)) get_first
;
691 this->public.get_last
= (status_t (*) (linked_list_t
*linked_list
, void **item
)) get_last
;
692 this->public.insert_first
= (status_t (*) (linked_list_t
*linked_list
, void *item
)) insert_first
;
693 this->public.insert_last
= (status_t (*) (linked_list_t
*linked_list
, void *item
)) insert_last
;
694 this->public.insert_before
= (status_t (*) (linked_list_t
*linked_list
, linked_list_iterator_t
* element
, void *item
)) insert_before
;
695 this->public.insert_after
= (status_t (*) (linked_list_t
*linked_list
, linked_list_iterator_t
* element
, void *item
)) insert_after
;
696 this->public.remove
= (status_t (*) (linked_list_t
*linked_list
, linked_list_iterator_t
* element
)) linked_list_remove
;
697 this->public.remove_first
= (status_t (*) (linked_list_t
*linked_list
, void **item
)) remove_first
;
698 this->public.remove_last
= (status_t (*) (linked_list_t
*linked_list
, void **item
)) remove_last
;
699 this->public.destroy
= (status_t (*) (linked_list_t
*linked_list
)) linked_list_destroy
;
705 return (&(this->public));