forked from enlightenment/efl
eina_iterator: add new api to have a filtered iterator
Summary: the new iterator represents the order from the elements of the original iterator, elements where the filter callback return false will be skipped. The container of this iterator is the original iterator. Test Plan: Just run `make check` there is a testcase Reviewers: cedric, jpeg, raster, herdsman Differential Revision: https://phab.enlightenment.org/D4417
This commit is contained in:
parent
36862e13ec
commit
c34e4b6312
|
@ -228,3 +228,62 @@ eina_carray_iterator_new(void** array)
|
|||
|
||||
return &it->iterator;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
Eina_Iterator iterator;
|
||||
|
||||
void *data;
|
||||
Eina_Iterator *original;
|
||||
Eina_Each_Cb cb;
|
||||
} Eina_Iterator_Filter;
|
||||
|
||||
static Eina_Bool
|
||||
eina_iterator_filter_next(Eina_Iterator_Filter *it, void **data)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!eina_iterator_next(it->original , data))
|
||||
return EINA_FALSE;
|
||||
}
|
||||
while (!it->cb(it->original, *data, it->data));
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void*
|
||||
eina_iterator_filter_get_container(Eina_Iterator_Filter *it)
|
||||
{
|
||||
return it->original;
|
||||
}
|
||||
|
||||
static void
|
||||
eina_iterator_filter_free(Eina_Iterator_Filter *it)
|
||||
{
|
||||
eina_iterator_free(it->original);
|
||||
free(it);
|
||||
}
|
||||
|
||||
EAPI Eina_Iterator*
|
||||
eina_iterator_filter_new(Eina_Iterator *iterator, Eina_Each_Cb filter, void *data)
|
||||
{
|
||||
Eina_Iterator_Filter *it;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(iterator, NULL);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(filter, NULL);
|
||||
|
||||
it = calloc(1, sizeof(Eina_Iterator_Filter));
|
||||
|
||||
it->original = iterator;
|
||||
it->data = data;
|
||||
it->cb = filter;
|
||||
|
||||
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
|
||||
|
||||
it->iterator.version = EINA_ITERATOR_VERSION;
|
||||
it->iterator.next = FUNC_ITERATOR_NEXT(eina_iterator_filter_next);
|
||||
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
|
||||
eina_iterator_filter_get_container);
|
||||
it->iterator.free = FUNC_ITERATOR_FREE(eina_iterator_filter_free);
|
||||
|
||||
return &it->iterator;
|
||||
}
|
||||
|
|
|
@ -300,6 +300,20 @@ EAPI Eina_Bool eina_iterator_unlock(Eina_Iterator *iterator) EINA_ARG_NONNULL(1)
|
|||
*/
|
||||
EAPI Eina_Iterator* eina_carray_iterator_new(void** array) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
|
||||
|
||||
/**
|
||||
* @brief Creates a new iterator which which iterates throuw all elements with are accepted by the filter callback
|
||||
*
|
||||
* @param original the iterator the use as original set
|
||||
* @param filter if the callback returns true the element from the original set is taken into the the new set.
|
||||
* @param data the data which is passed to the filter callback
|
||||
*
|
||||
* The iterator is filtered while it is beeing iterated.
|
||||
* The original iterator you pass in here is is then owned and will be freed once the the new iterator is freed.
|
||||
*
|
||||
* @since 1.19
|
||||
*/
|
||||
EAPI Eina_Iterator* eina_iterator_filter_new(Eina_Iterator *original, Eina_Each_Cb filter, void *data) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
|
||||
|
||||
/**
|
||||
* @def EINA_ITERATOR_FOREACH
|
||||
* @brief Macro to iterate over all elements easily.
|
||||
|
|
|
@ -26,6 +26,69 @@
|
|||
|
||||
#include "eina_suite.h"
|
||||
|
||||
struct Number{
|
||||
int number;
|
||||
};
|
||||
|
||||
static Eina_Bool
|
||||
_filter(const void *it EINA_UNUSED, void *data, void *fdata)
|
||||
{
|
||||
struct Number *numb = data;
|
||||
|
||||
ck_assert_ptr_eq(fdata, (void*)1);
|
||||
return numb->number % 2;
|
||||
}
|
||||
|
||||
START_TEST(eina_iterator_filter_simple)
|
||||
{
|
||||
Eina_Iterator *it, *filtered;
|
||||
Eina_Array *ea;
|
||||
|
||||
eina_init();
|
||||
|
||||
ea = eina_array_new(11);
|
||||
fail_if(!ea);
|
||||
|
||||
for(int i = 0; i <= 10; i++)
|
||||
{
|
||||
struct Number *number;
|
||||
|
||||
number = calloc(1, sizeof(struct Number));
|
||||
number->number = i;
|
||||
|
||||
eina_array_push(ea, number);
|
||||
}
|
||||
|
||||
it = eina_array_iterator_new(ea);
|
||||
filtered = eina_iterator_filter_new(it, _filter, (void*)1);
|
||||
for(int i = 1; i <= 10; i+=2)
|
||||
{
|
||||
struct Number *numb;
|
||||
Eina_Bool ret;
|
||||
|
||||
ret = eina_iterator_next(filtered, (void**)&numb);
|
||||
|
||||
fail_if(!ret);
|
||||
ck_assert_int_eq(numb->number, i);
|
||||
}
|
||||
|
||||
{
|
||||
struct Number *numb;
|
||||
Eina_Bool ret;
|
||||
|
||||
ret = eina_iterator_next(filtered, (void**)&numb);
|
||||
fail_if(ret);
|
||||
}
|
||||
|
||||
|
||||
eina_iterator_free(it);
|
||||
|
||||
eina_array_free(ea);
|
||||
|
||||
eina_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static Eina_Bool
|
||||
eina_iterator_array_check(EINA_UNUSED const Eina_Array *array,
|
||||
int *data, int *fdata)
|
||||
|
@ -529,4 +592,5 @@ eina_test_iterator(TCase *tc)
|
|||
tcase_add_test(tc, eina_iterator_list_simple);
|
||||
tcase_add_test(tc, eina_reverse_iterator_list_simple);
|
||||
tcase_add_test(tc, eina_iterator_rbtree_simple);
|
||||
tcase_add_test(tc, eina_iterator_filter_simple);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue