implemented more flexible iterator hook API
kernel interface handles interface changes and updates address list
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
while (TRUE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (this->current == NULL)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user