summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Hollerbach <marcel-hollerbach@t-online.de>2016-11-20 15:24:26 +0100
committerMarcel Hollerbach <marcel-hollerbach@t-online.de>2016-11-21 12:13:02 +0100
commitc34e4b6312e8f1ff6bb67bac93d79061d1bcb728 (patch)
tree6e08ac95fa3d86b3f9c8b49a51ec83c14b17538b
parent36862e13ecf0d2737904ba7919977e76789b75e2 (diff)
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
-rw-r--r--src/lib/eina/eina_iterator.c59
-rw-r--r--src/lib/eina/eina_iterator.h14
-rw-r--r--src/tests/eina/eina_test_iterator.c64
3 files changed, 137 insertions, 0 deletions
diff --git a/src/lib/eina/eina_iterator.c b/src/lib/eina/eina_iterator.c
index 5d621816b9..ba64bf2437 100644
--- a/src/lib/eina/eina_iterator.c
+++ b/src/lib/eina/eina_iterator.c
@@ -228,3 +228,62 @@ eina_carray_iterator_new(void** array)
228 228
229 return &it->iterator; 229 return &it->iterator;
230} 230}
231
232typedef struct {
233 Eina_Iterator iterator;
234
235 void *data;
236 Eina_Iterator *original;
237 Eina_Each_Cb cb;
238} Eina_Iterator_Filter;
239
240static Eina_Bool
241eina_iterator_filter_next(Eina_Iterator_Filter *it, void **data)
242{
243 do
244 {
245 if (!eina_iterator_next(it->original , data))
246 return EINA_FALSE;
247 }
248 while (!it->cb(it->original, *data, it->data));
249
250 return EINA_TRUE;
251}
252
253static void*
254eina_iterator_filter_get_container(Eina_Iterator_Filter *it)
255{
256 return it->original;
257}
258
259static void
260eina_iterator_filter_free(Eina_Iterator_Filter *it)
261{
262 eina_iterator_free(it->original);
263 free(it);
264}
265
266EAPI Eina_Iterator*
267eina_iterator_filter_new(Eina_Iterator *iterator, Eina_Each_Cb filter, void *data)
268{
269 Eina_Iterator_Filter *it;
270
271 EINA_SAFETY_ON_NULL_RETURN_VAL(iterator, NULL);
272 EINA_SAFETY_ON_NULL_RETURN_VAL(filter, NULL);
273
274 it = calloc(1, sizeof(Eina_Iterator_Filter));
275
276 it->original = iterator;
277 it->data = data;
278 it->cb = filter;
279
280 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
281
282 it->iterator.version = EINA_ITERATOR_VERSION;
283 it->iterator.next = FUNC_ITERATOR_NEXT(eina_iterator_filter_next);
284 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
285 eina_iterator_filter_get_container);
286 it->iterator.free = FUNC_ITERATOR_FREE(eina_iterator_filter_free);
287
288 return &it->iterator;
289}
diff --git a/src/lib/eina/eina_iterator.h b/src/lib/eina/eina_iterator.h
index 275e928a9b..304af32d5e 100644
--- a/src/lib/eina/eina_iterator.h
+++ b/src/lib/eina/eina_iterator.h
@@ -301,6 +301,20 @@ EAPI Eina_Bool eina_iterator_unlock(Eina_Iterator *iterator) EINA_ARG_NONNULL(1)
301EAPI Eina_Iterator* eina_carray_iterator_new(void** array) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT; 301EAPI Eina_Iterator* eina_carray_iterator_new(void** array) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
302 302
303/** 303/**
304 * @brief Creates a new iterator which which iterates throuw all elements with are accepted by the filter callback
305 *
306 * @param original the iterator the use as original set
307 * @param filter if the callback returns true the element from the original set is taken into the the new set.
308 * @param data the data which is passed to the filter callback
309 *
310 * The iterator is filtered while it is beeing iterated.
311 * The original iterator you pass in here is is then owned and will be freed once the the new iterator is freed.
312 *
313 * @since 1.19
314 */
315EAPI Eina_Iterator* eina_iterator_filter_new(Eina_Iterator *original, Eina_Each_Cb filter, void *data) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
316
317/**
304 * @def EINA_ITERATOR_FOREACH 318 * @def EINA_ITERATOR_FOREACH
305 * @brief Macro to iterate over all elements easily. 319 * @brief Macro to iterate over all elements easily.
306 * 320 *
diff --git a/src/tests/eina/eina_test_iterator.c b/src/tests/eina/eina_test_iterator.c
index 463861ef5d..ea695efc36 100644
--- a/src/tests/eina/eina_test_iterator.c
+++ b/src/tests/eina/eina_test_iterator.c
@@ -26,6 +26,69 @@
26 26
27#include "eina_suite.h" 27#include "eina_suite.h"
28 28
29struct Number{
30 int number;
31};
32
33static Eina_Bool
34_filter(const void *it EINA_UNUSED, void *data, void *fdata)
35{
36 struct Number *numb = data;
37
38 ck_assert_ptr_eq(fdata, (void*)1);
39 return numb->number % 2;
40}
41
42START_TEST(eina_iterator_filter_simple)
43{
44 Eina_Iterator *it, *filtered;
45 Eina_Array *ea;
46
47 eina_init();
48
49 ea = eina_array_new(11);
50 fail_if(!ea);
51
52 for(int i = 0; i <= 10; i++)
53 {
54 struct Number *number;
55
56 number = calloc(1, sizeof(struct Number));
57 number->number = i;
58
59 eina_array_push(ea, number);
60 }
61
62 it = eina_array_iterator_new(ea);
63 filtered = eina_iterator_filter_new(it, _filter, (void*)1);
64 for(int i = 1; i <= 10; i+=2)
65 {
66 struct Number *numb;
67 Eina_Bool ret;
68
69 ret = eina_iterator_next(filtered, (void**)&numb);
70
71 fail_if(!ret);
72 ck_assert_int_eq(numb->number, i);
73 }
74
75 {
76 struct Number *numb;
77 Eina_Bool ret;
78
79 ret = eina_iterator_next(filtered, (void**)&numb);
80 fail_if(ret);
81 }
82
83
84 eina_iterator_free(it);
85
86 eina_array_free(ea);
87
88 eina_shutdown();
89}
90END_TEST
91
29static Eina_Bool 92static Eina_Bool
30eina_iterator_array_check(EINA_UNUSED const Eina_Array *array, 93eina_iterator_array_check(EINA_UNUSED const Eina_Array *array,
31 int *data, int *fdata) 94 int *data, int *fdata)
@@ -529,4 +592,5 @@ eina_test_iterator(TCase *tc)
529 tcase_add_test(tc, eina_iterator_list_simple); 592 tcase_add_test(tc, eina_iterator_list_simple);
530 tcase_add_test(tc, eina_reverse_iterator_list_simple); 593 tcase_add_test(tc, eina_reverse_iterator_list_simple);
531 tcase_add_test(tc, eina_iterator_rbtree_simple); 594 tcase_add_test(tc, eina_iterator_rbtree_simple);
595 tcase_add_test(tc, eina_iterator_filter_simple);
532} 596}