From 712ec600121f23a413ce8e328f3b0d21e0b35e6a Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Thu, 8 Dec 2016 19:53:22 +0100 Subject: [PATCH] eina: add free cb to eina_iterator_filter_new if you allocate memory for the data param data you can free it in this callback. --- src/lib/eina/eina_iterator.c | 6 ++++- src/lib/eina/eina_iterator.h | 3 ++- src/tests/eina/eina_test_iterator.c | 44 ++++++++++++++++++++++++++++++++++++- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/lib/eina/eina_iterator.c b/src/lib/eina/eina_iterator.c index ba64bf2..4a4e281 100644 --- a/src/lib/eina/eina_iterator.c +++ b/src/lib/eina/eina_iterator.c @@ -235,6 +235,7 @@ typedef struct { void *data; Eina_Iterator *original; Eina_Each_Cb cb; + Eina_Free_Cb free; } Eina_Iterator_Filter; static Eina_Bool @@ -259,12 +260,14 @@ eina_iterator_filter_get_container(Eina_Iterator_Filter *it) static void eina_iterator_filter_free(Eina_Iterator_Filter *it) { + if (it->free) + it->free(it->data); 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_new(Eina_Iterator *iterator, Eina_Each_Cb filter, Eina_Free_Cb free_cb, void *data) { Eina_Iterator_Filter *it; @@ -276,6 +279,7 @@ eina_iterator_filter_new(Eina_Iterator *iterator, Eina_Each_Cb filter, void *dat it->original = iterator; it->data = data; it->cb = filter; + it->free = free_cb; EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); diff --git a/src/lib/eina/eina_iterator.h b/src/lib/eina/eina_iterator.h index 304af32..fadf1df 100644 --- a/src/lib/eina/eina_iterator.h +++ b/src/lib/eina/eina_iterator.h @@ -305,6 +305,7 @@ EAPI Eina_Iterator* eina_carray_iterator_new(void** array) EINA_ARG_NONNULL(1) E * * @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 free_cb when the iterator is gone this callback will be called with data as argument * @param data the data which is passed to the filter callback * * The iterator is filtered while it is beeing iterated. @@ -312,7 +313,7 @@ EAPI Eina_Iterator* eina_carray_iterator_new(void** array) EINA_ARG_NONNULL(1) E * * @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; +EAPI Eina_Iterator* eina_iterator_filter_new(Eina_Iterator *original, Eina_Each_Cb filter, Eina_Free_Cb free_cb, void *data) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT; /** * @def EINA_ITERATOR_FOREACH diff --git a/src/tests/eina/eina_test_iterator.c b/src/tests/eina/eina_test_iterator.c index ea695ef..2066269 100644 --- a/src/tests/eina/eina_test_iterator.c +++ b/src/tests/eina/eina_test_iterator.c @@ -60,7 +60,7 @@ START_TEST(eina_iterator_filter_simple) } it = eina_array_iterator_new(ea); - filtered = eina_iterator_filter_new(it, _filter, (void*)1); + filtered = eina_iterator_filter_new(it, _filter, NULL, (void*)1); for(int i = 1; i <= 10; i+=2) { struct Number *numb; @@ -89,6 +89,47 @@ START_TEST(eina_iterator_filter_simple) } END_TEST +struct Free_test { + Eina_Bool got_freed; +}; + +static Eina_Bool +_filter_free(const void *it EINA_UNUSED, void *data EINA_UNUSED, void *fdata EINA_UNUSED) +{ + return EINA_TRUE; +} + +static void +_free(void *data) +{ + struct Free_test *test = data; + test->got_freed = EINA_TRUE; +} + +START_TEST(eina_iterator_filter_free) +{ + Eina_Iterator *it, *filtered; + Eina_Array *ea; + struct Free_test *data; + eina_init(); + + data = calloc(1, sizeof(struct Free_test)); + ea = eina_array_new(11); + fail_if(!ea); + + it = eina_array_iterator_new(ea); + filtered = eina_iterator_filter_new(it, _filter_free, _free, data); + eina_iterator_free(filtered); + + eina_array_free(ea); + + ck_assert_int_ne(data->got_freed, 0); + + free(data); + + eina_shutdown(); +} +END_TEST static Eina_Bool eina_iterator_array_check(EINA_UNUSED const Eina_Array *array, int *data, int *fdata) @@ -593,4 +634,5 @@ eina_test_iterator(TCase *tc) 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); + tcase_add_test(tc, eina_iterator_filter_free); } -- 2.7.4