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 "linked_list.h"
27 #include <utils/allocator.h>
30 typedef struct linked_list_element_t linked_list_element_t
;
33 * @brief Element of the linked_list.
35 * This element holds a pointer to the value of the list item itself.
37 struct linked_list_element_t
{
39 * value of a list item
44 * @brief Destroys a linked_list_element object
46 * @param linked_list_element_t calling object
47 * @returns SUCCESS if succeeded, FAILED otherwise
49 status_t (*destroy
) (linked_list_element_t
*this);
52 * previous list element
53 * NULL if first element in list
55 linked_list_element_t
*previous
;
58 * NULL if last element in list
60 linked_list_element_t
*next
;
64 * @brief implements function destroy of linked_list_item_t
66 static status_t
linked_list_element_destroy(linked_list_element_t
*this)
77 * @brief Creates an empty linked list object
79 * @param[in] value value of item to be set
81 * @warning only the pointer to the value is stored
83 * @return linked_list_element object
86 linked_list_element_t
*linked_list_element_create(void *value
)
88 linked_list_element_t
*this = allocator_alloc_thing(linked_list_element_t
);
95 this->destroy
= linked_list_element_destroy
;
105 * Private variables and functions of linked list
108 typedef struct private_linked_list_t private_linked_list_t
;
110 struct private_linked_list_t
{
112 * Public part of linked list
114 linked_list_t
public;
117 * number of items in the list
122 * First element in list
123 * NULL if no elements in list
125 linked_list_element_t
*first
;
127 * Last element in list
128 * NULL if no elements in list
130 linked_list_element_t
*last
;
135 * Private variables and functions of linked list iterator
138 typedef struct private_linked_list_iterator_t private_linked_list_iterator_t
;
140 struct private_linked_list_iterator_t
{
142 * Public part of linked list iterator
144 linked_list_iterator_t
public;
147 * associated linked list
149 private_linked_list_t
* list
;
152 * current element of the iterator
154 linked_list_element_t
*current
;
157 * direction of iterator
163 * Implements function has_next of linked_list_iteratr
165 bool iterator_has_next(private_linked_list_iterator_t
*this)
167 if (this->list
->count
== 0)
171 if (this->current
== NULL
)
173 this->current
= (this->forward
) ?
this->list
->first
: this->list
->last
;
178 if (this->current
->next
== NULL
)
182 this->current
= this->current
->next
;
186 if (this->current
->previous
== NULL
)
190 this->current
= this->current
->previous
;
195 * Implements function current of linked_list_iteratr
197 static status_t
iterator_current(private_linked_list_iterator_t
*this, void **value
)
203 if (this->current
== NULL
)
207 *value
= this->current
->value
;
212 * Implements function current of linked_list_iteratr
214 static status_t
iterator_reset(private_linked_list_iterator_t
*this)
220 this->current
= NULL
;
225 * Implements function destroy of linked_list_iteratr
227 static status_t
iterator_destroy(private_linked_list_iterator_t
*this)
233 allocator_free(this);
238 * @brief implements function get_count of linked_list_t
240 static int get_count(private_linked_list_t
*this)
247 * @brief implements function insert_first of linked_list_t
249 static status_t
insert_first(private_linked_list_t
*this, void *item
)
251 linked_list_element_t
*element
;
258 element
=(linked_list_element_t
*) linked_list_element_create(item
);
265 if (this->count
== 0)
267 /* first entry in list */
268 this->first
= element
;
269 this->last
= element
;
270 element
->previous
= NULL
;
271 element
->next
= NULL
;
275 if ((this->first
== NULL
) || (this->last
== NULL
))
277 /* should never happen */
278 element
->destroy(element
);
281 linked_list_element_t
*old_first_element
= this->first
;
282 element
->next
= old_first_element
;
283 element
->previous
= NULL
;
284 old_first_element
->previous
= element
;
285 this->first
= element
;
294 * @brief implements function remove_first of linked_list_t
296 static status_t
remove_first(private_linked_list_t
*this, void **item
)
303 if (this->count
== 0)
308 if (this->first
== NULL
)
313 linked_list_element_t
*element
= this->first
;
315 if (element
->next
!= NULL
)
317 element
->next
->previous
= NULL
;
319 this->first
= element
->next
;
321 *item
= element
->value
;
325 return (element
->destroy(element
));
329 * @brief implements function get_first of linked_list_t
331 static status_t
get_first(private_linked_list_t
*this, void **item
)
338 if (this->count
== 0)
343 if (this->first
== NULL
)
348 *item
= this->first
->value
;
354 * @brief implements function insert_last of linked_list_t
356 static status_t
insert_last(private_linked_list_t
*this, void *item
)
363 linked_list_element_t
*element
= (linked_list_element_t
*) linked_list_element_create(item
);
370 if (this->count
== 0)
372 /* first entry in list */
373 this->first
= element
;
374 this->last
= element
;
375 element
->previous
= NULL
;
376 element
->next
= NULL
;
379 if ((this->first
== NULL
) || (this->last
== NULL
))
381 /* should never happen */
382 element
->destroy(element
);
385 linked_list_element_t
*old_last_element
= this->last
;
386 element
->previous
= old_last_element
;
387 element
->next
= NULL
;
388 old_last_element
->next
= element
;
389 this->last
= element
;
398 * @brief implements function remove_last of linked_list_t
400 static status_t
remove_last(private_linked_list_t
*this, void **item
)
407 if (this->count
== 0)
412 if (this->last
== NULL
)
417 linked_list_element_t
*element
= this->last
;
419 if (element
->previous
!= NULL
)
421 element
->previous
->next
= NULL
;
423 this->last
= element
->previous
;
425 *item
= element
->value
;
429 return (element
->destroy(element
));
433 * @brief implements function get_last of linked_list_t
435 static status_t
get_last(private_linked_list_t
*this, void **item
)
442 if (this->count
== 0)
447 if (this->last
== NULL
)
452 *item
= this->last
->value
;
458 * @brief implements function insert_before of linked_list_t
460 static status_t
insert_before(private_linked_list_iterator_t
* iterator
, void *item
)
462 if (iterator
->current
== NULL
)
464 return (iterator
->list
->public.insert_first(&(iterator
->list
->public), item
));
467 linked_list_element_t
*element
=(linked_list_element_t
*) linked_list_element_create(item
);
474 if (iterator
->current
->previous
== NULL
)
476 if (iterator
->list
->first
!= iterator
->current
)
478 element
->destroy(element
);
482 iterator
->current
->previous
= element
;
483 element
->next
= iterator
->current
;
484 iterator
->list
->first
= element
;
488 iterator
->current
->previous
->next
= element
;
489 element
->previous
= iterator
->current
->previous
;
490 iterator
->current
->previous
= element
;
491 element
->next
= iterator
->current
;
494 iterator
->list
->count
++;
500 * @brief implements function insert_after of linked_list_t
502 static status_t
insert_after(private_linked_list_iterator_t
* iterator
, void *item
)
504 if (iterator
->current
== NULL
)
506 return (iterator
->list
->public.insert_first(&(iterator
->list
->public),item
));
509 linked_list_element_t
*element
=(linked_list_element_t
*) linked_list_element_create(item
);
516 if (iterator
->current
->next
== NULL
)
518 if (iterator
->list
->last
!= iterator
->current
)
520 element
->destroy(element
);
524 iterator
->current
->next
= element
;
525 element
->previous
= iterator
->current
;
526 iterator
->list
->last
= element
;
530 iterator
->current
->next
->previous
= element
;
531 element
->next
= iterator
->current
->next
;
532 iterator
->current
->next
= element
;
533 element
->previous
= iterator
->current
;
536 iterator
->list
->count
++;
540 static status_t
create_iterator (private_linked_list_t
*linked_list
, linked_list_iterator_t
**iterator
,bool forward
)
542 private_linked_list_iterator_t
*this = allocator_alloc_thing(private_linked_list_iterator_t
);
549 this->public.has_next
= (bool (*) (linked_list_iterator_t
*this)) iterator_has_next
;
550 this->public.current
= (status_t (*) (linked_list_iterator_t
*this, void **value
)) iterator_current
;
551 this->public.insert_before
= (status_t (*) (linked_list_iterator_t
*this, void *item
)) insert_before
;
552 this->public.insert_after
= (status_t (*) (linked_list_iterator_t
*this, void *item
)) insert_after
;
553 this->public.reset
= (status_t (*) (linked_list_iterator_t
*this)) iterator_reset
;
554 this->public.destroy
= (status_t (*) (linked_list_iterator_t
*this)) iterator_destroy
;
557 this->forward
= forward
;
558 this->current
= NULL
;
559 this->list
= linked_list
;
561 *iterator
= &(this->public);
567 * @brief implements function remove of linked_list_t
569 static status_t
linked_list_remove(private_linked_list_t
*this, private_linked_list_iterator_t
* iterator
)
571 linked_list_element_t
*new_current
;
573 if ((this == NULL
) || (iterator
== NULL
) || (iterator
->current
== NULL
))
578 if (this->count
== 0)
582 /* find out the new iterator position */
583 if (iterator
->current
->previous
!= NULL
)
585 new_current
= iterator
->current
->previous
;
587 else if (iterator
->current
->next
!= NULL
)
589 new_current
= iterator
->current
->next
;
596 /* now delete the entry :-) */
597 if (iterator
->current
->previous
== NULL
)
599 if (iterator
->current
->next
== NULL
)
606 iterator
->current
->next
->previous
= NULL
;
607 this->first
= iterator
->current
->next
;
610 else if (iterator
->current
->next
== NULL
)
612 iterator
->current
->previous
->next
= NULL
;
613 this->last
= iterator
->current
->previous
;
617 iterator
->current
->previous
->next
= iterator
->current
->next
;
618 iterator
->current
->next
->previous
= iterator
->current
->previous
;
622 iterator
->current
->destroy(iterator
->current
);
623 /* set the new iterator position */
624 iterator
->current
= new_current
;
629 * @brief implements function destroy of linked_list_t
631 static status_t
linked_list_destroy(private_linked_list_t
*this)
638 /* Remove all list items before destroying list */
639 while (this->count
> 0)
642 /* values are not destroyed so memory leaks are possible
643 * if list is not empty when deleting */
644 if (this->public.remove_first(&(this->public),&value
) != SUCCESS
)
646 allocator_free(this);
650 allocator_free(this);
655 * Described in header
657 linked_list_t
*linked_list_create()
659 private_linked_list_t
*this = allocator_alloc_thing(private_linked_list_t
);
661 this->public.get_count
= (int (*) (linked_list_t
*linked_list
)) get_count
;
662 this->public.create_iterator
= (status_t (*) (linked_list_t
*linked_list
, linked_list_iterator_t
**iterator
,bool forward
)) create_iterator
;
663 this->public.get_first
= (status_t (*) (linked_list_t
*linked_list
, void **item
)) get_first
;
664 this->public.get_last
= (status_t (*) (linked_list_t
*linked_list
, void **item
)) get_last
;
665 this->public.insert_first
= (status_t (*) (linked_list_t
*linked_list
, void *item
)) insert_first
;
666 this->public.insert_last
= (status_t (*) (linked_list_t
*linked_list
, void *item
)) insert_last
;
667 this->public.remove
= (status_t (*) (linked_list_t
*linked_list
, linked_list_iterator_t
* element
)) linked_list_remove
;
668 this->public.remove_first
= (status_t (*) (linked_list_t
*linked_list
, void **item
)) remove_first
;
669 this->public.remove_last
= (status_t (*) (linked_list_t
*linked_list
, void **item
)) remove_last
;
670 this->public.destroy
= (status_t (*) (linked_list_t
*linked_list
)) linked_list_destroy
;
676 return (&(this->public));