summaryrefslogtreecommitdiff
path: root/src/libstrongswan/utils/linked_list.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/utils/linked_list.c')
-rw-r--r--src/libstrongswan/utils/linked_list.c253
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;