aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstrongswan
diff options
context:
space:
mode:
authorMartin Willi <martin@strongswan.org>2007-06-15 13:23:18 +0000
committerMartin Willi <martin@strongswan.org>2007-06-15 13:23:18 +0000
commit08a8f4496ff58c74631da1b7145145d9e9b56ccc (patch)
tree83007743fbc4ee1a583aaf2d762149c076da7019 /src/libstrongswan
parent02b3ec0a10482feabdf1017f1693deeabbfcb245 (diff)
downloadstrongswan-08a8f4496ff58c74631da1b7145145d9e9b56ccc.tar.bz2
strongswan-08a8f4496ff58c74631da1b7145145d9e9b56ccc.tar.xz
implemented more flexible iterator hook API
kernel interface handles interface changes and updates address list
Diffstat (limited to 'src/libstrongswan')
-rw-r--r--src/libstrongswan/utils/iterator.h42
-rw-r--r--src/libstrongswan/utils/linked_list.c59
2 files changed, 68 insertions, 33 deletions
diff --git a/src/libstrongswan/utils/iterator.h b/src/libstrongswan/utils/iterator.h
index 02a15c534..b4ff85bfb 100644
--- a/src/libstrongswan/utils/iterator.h
+++ b/src/libstrongswan/utils/iterator.h
@@ -26,15 +26,46 @@
#include <library.h>
+typedef enum hook_result_t hook_result_t;
+
+/**
+ * @brief Return value of an iterator hook.
+ *
+ * Returning HOOK_AGAIN is useful to "inject" additional elements in an
+ * iteration, HOOK_NEXT is the normal iterator behavior, and HOOK_SKIP may
+ * be used to filter elements out.
+ *
+ * @ingroup utils
+ */
+enum hook_result_t {
+
+ /**
+ * A value was placed in out, hook is called again with the same "in"
+ */
+ HOOK_AGAIN,
+
+ /**
+ * A value was placed in out, hook is called again with next "in" (if any)
+ */
+ HOOK_NEXT,
+
+ /**
+ * No value in out, call again with next "in" (if any)
+ */
+ HOOK_SKIP,
+};
+
/**
* @brief Iterator hook function prototype.
*
* @param param user supplied parameter
* @param in the value the hook receives from the iterator
* @param out the value supplied as a result to the iterator
- * @return TRUE to return "out", FALSE to skip this value
+ * @return a hook_result_t
+ *
+ * @ingroup utils
*/
-typedef bool (iterator_hook_t)(void *param, void *in, void **out);
+typedef hook_result_t (iterator_hook_t)(void *param, void *in, void **out);
typedef struct iterator_t iterator_t;
@@ -45,8 +76,6 @@ typedef struct iterator_t iterator_t;
* iterator_t defines an interface for iterating over collections.
* It allows searching, deleting, updating and inserting.
*
- * Thanks to JMP for iterator lessons :-)
- *
* @b Constructors:
* - via linked_list_t.create_iterator, or
* - any other class which supports the iterator_t interface
@@ -84,8 +113,11 @@ struct iterator_t {
* Sometimes it is useful to hook in an iterator. The hook function is
* called before any successful return of iterate(). It takes the
* iterator value, may manipulate it (or the references object), and returns
- * the value that the iterate() function returns.
+ * the value that the iterate() function returns. Depending on the hook
+ * return value, the hook is called again, called with next, or skipped.
* A value of NULL deactivates the iterator hook.
+ * If an iterator is hooked, only the iterate() method is valid,
+ * all other methods behave undefined.
*
* @param this calling object
* @param hook iterator hook which manipulates the iterated value
diff --git a/src/libstrongswan/utils/linked_list.c b/src/libstrongswan/utils/linked_list.c
index de043a02e..de52ea46a 100644
--- a/src/libstrongswan/utils/linked_list.c
+++ b/src/libstrongswan/utils/linked_list.c
@@ -151,10 +151,10 @@ static int get_list_count(private_iterator_t *this)
/**
* default iterator hook which does nothing
*/
-static bool iterator_hook(void *param, void *in, void **out)
+static hook_result_t iterator_hook(void *param, void *in, void **out)
{
*out = in;
- return TRUE;
+ return HOOK_NEXT;
}
/**
@@ -180,40 +180,43 @@ static void set_iterator_hook(private_iterator_t *this, iterator_hook_t *hook,
*/
static bool iterate(private_iterator_t *this, void** value)
{
- if (this->list->count == 0)
- {
- return FALSE;
- }
- if (this->current == NULL)
+ while (TRUE)
{
- this->current = (this->forward) ? this->list->first : this->list->last;
- if (!this->hook(this->hook_param, this->current->value, value))
+ if (this->forward)
{
- return iterate(this, value);
+ this->current = this->current ? this->current->next : this->list->first;
}
- return TRUE;
- }
- if (this->forward)
- {
- if (this->current->next == NULL)
+ else
+ {
+ this->current = this->current ? this->current->previous : this->list->last;
+ }
+
+ if (this->current == NULL)
{
return FALSE;
}
- this->current = this->current->next;
- if (!this->hook(this->hook_param, this->current->value, value))
+
+ switch (this->hook(this->hook_param, this->current->value, value))
{
- return iterate(this, value);
+ case HOOK_AGAIN:
+ /* rewind */
+ if (this->forward)
+ {
+ this->current = this->current->previous;
+ }
+ else
+ {
+ this->current = this->current->next;
+ }
+ break;
+ case HOOK_NEXT:
+ /* normal iteration */
+ break;
+ case HOOK_SKIP:
+ /* advance */
+ continue;
}
- return TRUE;
- }
- if (this->current->previous == NULL)
- {
- return FALSE;
- }
- this->current = this->current->previous;
- if (!this->hook(this->hook_param, this->current->value, value))
- {
- return iterate(this, value);
+ break;
}
return TRUE;
}