diff options
author | Martin Willi <martin@strongswan.org> | 2007-06-15 13:23:18 +0000 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2007-06-15 13:23:18 +0000 |
commit | 08a8f4496ff58c74631da1b7145145d9e9b56ccc (patch) | |
tree | 83007743fbc4ee1a583aaf2d762149c076da7019 /src/libstrongswan | |
parent | 02b3ec0a10482feabdf1017f1693deeabbfcb245 (diff) | |
download | strongswan-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.h | 42 | ||||
-rw-r--r-- | src/libstrongswan/utils/linked_list.c | 59 |
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; } |