diff options
Diffstat (limited to 'src/libstrongswan/utils/linked_list.c')
-rw-r--r-- | src/libstrongswan/utils/linked_list.c | 253 |
1 files changed, 100 insertions, 153 deletions
diff --git a/src/libstrongswan/utils/linked_list.c b/src/libstrongswan/utils/linked_list.c index 63e1bcfbf..80c4e6f9f 100644 --- a/src/libstrongswan/utils/linked_list.c +++ b/src/libstrongswan/utils/linked_list.c @@ -1,12 +1,5 @@ -/** - * @file linked_list.c - * - * @brief Implementation of linked_list_t. - * - */ - /* - * Copyright (C) 2007 Tobias Brunner + * Copyright (C) 2007-2008 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -20,6 +13,8 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: linked_list.c 3841 2008-04-18 11:48:53Z tobias $ */ #include <stdlib.h> @@ -154,9 +149,14 @@ struct private_enumerator_t { enumerator_t enumerator; /** - * next item to enumerate + * associated linked list */ - element_t *next; + private_linked_list_t *list; + + /** + * current item + */ + element_t *current; }; /** @@ -164,12 +164,23 @@ struct private_enumerator_t { */ static bool enumerate(private_enumerator_t *this, void **item) { - if (this->next == NULL) + if (!this->current) { - return FALSE; + if (!this->list->first) + { + return FALSE; + } + this->current = this->list->first; } - *item = this->next->value; - this->next = this->next->next; + else + { + if (!this->current->next) + { + return FALSE; + } + this->current = this->current->next; + } + *item = this->current->value; return TRUE; } @@ -182,7 +193,8 @@ static enumerator_t* create_enumerator(private_linked_list_t *this) enumerator->enumerator.enumerate = (void*)enumerate; enumerator->enumerator.destroy = (void*)free; - enumerator->next = this->first; + enumerator->list = this; + enumerator->current = NULL; return &enumerator->enumerator; } @@ -459,34 +471,37 @@ static void insert_first(private_linked_list_t *this, void *item) } /** - * Implementation of linked_list_t.remove_first. + * unlink an element form the list, returns following element */ -static status_t remove_first(private_linked_list_t *this, void **item) +static element_t* remove_element(private_linked_list_t *this, element_t *element) { - element_t *element = this->first; - - if (element == NULL) + element_t *next, *previous; + + next = element->next; + previous = element->previous; + free(element); + if (next) { - return NOT_FOUND; + next->previous = previous; } - if (element->next != NULL) + else { - element->next->previous = NULL; + this->last = previous; } - this->first = element->next; - - if (item != NULL) + if (previous) + { + previous->next = next; + } + else { - *item = element->value; + this->first = next; } if (--this->count == 0) { + this->first = NULL; this->last = NULL; } - - free(element); - - return SUCCESS; + return next; } /** @@ -503,6 +518,19 @@ static status_t get_first(private_linked_list_t *this, void **item) } /** + * Implementation of linked_list_t.remove_first. + */ +static status_t remove_first(private_linked_list_t *this, void **item) +{ + if (get_first(this, item) == SUCCESS) + { + remove_element(this, this->first); + return SUCCESS; + } + return NOT_FOUND; +} + +/** * Implementation of linked_list_t.insert_last. */ static void insert_last(private_linked_list_t *this, void *item) @@ -529,151 +557,69 @@ static void insert_last(private_linked_list_t *this, void *item) } /** - * Implementation of linked_list_t.remove_last. + * Implementation of linked_list_t.get_last. */ -static status_t remove_last(private_linked_list_t *this, void **item) +static status_t get_last(private_linked_list_t *this, void **item) { - element_t *element = this->last; - - if (element == NULL) + if (this->count == 0) { return NOT_FOUND; } - if (element->previous != NULL) - { - element->previous->next = NULL; - } - this->last = element->previous; - - if (item != NULL) - { - *item = element->value; - } - if (--this->count == 0) - { - this->first = NULL; - } - - free(element); - + *item = this->last->value; return SUCCESS; } /** - * Implementation of linked_list_t.insert_at_position. + * Implementation of linked_list_t.remove_last. */ -static status_t insert_at_position (private_linked_list_t *this,size_t position, void *item) +static status_t remove_last(private_linked_list_t *this, void **item) { - element_t *current_element; - int i; - - if (this->count <= position) + if (get_last(this, item) == SUCCESS) { - return INVALID_ARG; - } - - current_element = this->first; - - for (i = 0; i < position;i++) - { - current_element = current_element->next; - } - - if (current_element == NULL) - { - this->public.insert_last(&(this->public),item); + remove_element(this, this->last); return SUCCESS; } - - element_t *element = element_create(item); - if (current_element->previous == NULL) - { - current_element->previous = element; - element->next = current_element; - this->first = element; - } - else - { - current_element->previous->next = element; - element->previous = current_element->previous; - current_element->previous = element; - element->next = current_element; - } - - - this->count++; - return SUCCESS; + return NOT_FOUND; } /** - * Implementation of linked_list_t.remove_at_position. + * Implementation of linked_list_t.remove. */ -static status_t remove_at_position(private_linked_list_t *this,size_t position, void **item) +static int remove(private_linked_list_t *this, void *item, + bool (*compare)(void *,void*)) { - iterator_t *iterator; - int i; - - if (this->count <= position) - { - return INVALID_ARG; - } + element_t *current = this->first; + int removed = 0; - iterator = this->public.create_iterator(&(this->public),TRUE); - iterator->iterate(iterator, item); - for (i = 0; i < position; i++) + while (current) { - if (!iterator->iterate(iterator, item)) + if ((compare && compare(current->value, item)) || + (!compare && current->value == item)) { - iterator->destroy(iterator); - return INVALID_ARG; + removed++; + current = remove_element(this, current); } - } - iterator->remove(iterator); - iterator->destroy(iterator); - - return SUCCESS; -} - -/** - * Implementation of linked_list_t.get_at_position. - */ -static status_t get_at_position(private_linked_list_t *this,size_t position, void **item) -{ - int i; - iterator_t *iterator; - - if (this->count <= position) - { - return INVALID_ARG; - } - - iterator = this->public.create_iterator(&(this->public),TRUE); - iterator->iterate(iterator, item); - for (i = 0; i < position; i++) - { - if (!iterator->iterate(iterator, item)) + else { - iterator->destroy(iterator); - return INVALID_ARG; + current = current->next; } } - iterator->destroy(iterator); - return SUCCESS; + return removed; } /** - * Implementation of linked_list_t.get_last. + * Implementation of linked_list_t.remove_at. */ -static status_t get_last(private_linked_list_t *this, void **item) +static void remove_at(private_linked_list_t *this, private_enumerator_t *enumerator) { - if (this->count == 0) + element_t *current; + + if (enumerator->current) { - return NOT_FOUND; + current = enumerator->current; + enumerator->current = current->previous; + remove_element(this, current); } - - *item = this->last->value; - - return SUCCESS; } /** @@ -725,14 +671,15 @@ static status_t find_last(private_linked_list_t *this, linked_list_match_t match /** * Implementation of linked_list_t.invoke_offset. */ -static void invoke_offset(private_linked_list_t *this, size_t offset) +static void invoke_offset(private_linked_list_t *this, size_t offset, + void *d1, void *d2, void *d3, void *d4, void *d5) { element_t *current = this->first; while (current) { - void (**method)(void*) = current->value + offset; - (*method)(current->value); + linked_list_invoke_t *method = current->value + offset; + (*method)(current->value, d1, d2, d3, d4, d5); current = current->next; } } @@ -740,13 +687,14 @@ static void invoke_offset(private_linked_list_t *this, size_t offset) /** * Implementation of linked_list_t.invoke_function. */ -static void invoke_function(private_linked_list_t *this, void(*fn)(void*)) +static void invoke_function(private_linked_list_t *this, linked_list_invoke_t fn, + void *d1, void *d2, void *d3, void *d4, void *d5) { element_t *current = this->first; while (current) { - fn(current->value); + fn(current->value, d1, d2, d3, d4, d5); current = current->next; } } @@ -895,11 +843,10 @@ linked_list_t *linked_list_create() this->public.insert_last = (void (*) (linked_list_t *, void *item))insert_last; this->public.remove_first = (status_t (*) (linked_list_t *, void **item))remove_first; this->public.remove_last = (status_t (*) (linked_list_t *, void **item))remove_last; - this->public.insert_at_position = (status_t (*) (linked_list_t *,size_t, void *))insert_at_position; - this->public.remove_at_position = (status_t (*) (linked_list_t *,size_t, void **))remove_at_position; - this->public.get_at_position = (status_t (*) (linked_list_t *,size_t, void **))get_at_position; - this->public.invoke_offset = (void (*)(linked_list_t*,size_t))invoke_offset; - this->public.invoke_function = (void (*)(linked_list_t*,void(*)(void*)))invoke_function; + this->public.remove = (int(*)(linked_list_t*, void *item, bool (*compare)(void *,void*)))remove; + this->public.remove_at = (void(*)(linked_list_t*, enumerator_t *enumerator))remove_at; + this->public.invoke_offset = (void (*)(linked_list_t*,size_t,...))invoke_offset; + this->public.invoke_function = (void (*)(linked_list_t*,linked_list_invoke_t,...))invoke_function; this->public.clone_offset = (linked_list_t * (*)(linked_list_t*,size_t))clone_offset; this->public.clone_function = (linked_list_t * (*)(linked_list_t*,void*(*)(void*)))clone_function; this->public.destroy = (void (*) (linked_list_t *))destroy; |