bu5hm4n pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=74491e8781d87b4321470bea5414a3a750a695e8

commit 74491e8781d87b4321470bea5414a3a750a695e8
Author: Marcel Hollerbach <[email protected]>
Date:   Fri Jan 10 16:35:57 2020 +0100

    eina: introduce eina_iterator_process
    
    this brings a functional-map function to the iterator implementations.
    https://en.wikipedia.org/wiki/Map_(higher-order_function)
    
    Reviewed-by: Cedric BAIL <[email protected]>
    Differential Revision: https://phab.enlightenment.org/D11062
---
 src/lib/eina/eina_iterator.c        | 59 +++++++++++++++++++++++++++++++++++++
 src/lib/eina/eina_iterator.h        | 18 +++++++++++
 src/lib/eina/eina_types.h           | 12 ++++++++
 src/tests/eina/eina_test_iterator.c | 44 +++++++++++++++++++++++++++
 4 files changed, 133 insertions(+)

diff --git a/src/lib/eina/eina_iterator.c b/src/lib/eina/eina_iterator.c
index 1043a9c6e0..26d05f4045 100644
--- a/src/lib/eina/eina_iterator.c
+++ b/src/lib/eina/eina_iterator.c
@@ -429,3 +429,62 @@ eina_iterator_filter_new(Eina_Iterator *iterator, 
Eina_Each_Cb filter, Eina_Free
 
    return &it->iterator;
 }
+
+typedef struct {
+   Eina_Iterator iterator;
+
+   void *data;
+   Eina_Iterator *original;
+   Eina_Process_Cb cb;
+   Eina_Free_Cb free;
+} Eina_Iterator_Processor;
+
+static Eina_Bool
+eina_iterator_process_next(Eina_Iterator_Processor *it, void **data)
+{
+   if (!eina_iterator_next(it->original, data))
+     return EINA_FALSE;
+
+   *data = it->cb(it->original, *data, it->data);
+
+   return EINA_TRUE;
+}
+
+static void*
+eina_iterator_process_get_container(Eina_Iterator_Processor *it)
+{
+   return it->original;
+}
+
+static void
+eina_iterator_process_free(Eina_Iterator_Processor *it)
+{
+   if (it->free)
+     it->free(it->data);
+   eina_iterator_free(it->original);
+   free(it);
+}
+
+EAPI Eina_Iterator*
+eina_iterator_processed_new(Eina_Iterator *iterator, Eina_Process_Cb process, 
Eina_Free_Cb free_cb, void *data)
+{
+   Eina_Iterator_Processor *it;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(iterator, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(process, NULL);
+
+   it = calloc(1, sizeof(Eina_Iterator_Processor));
+   it->data = data;
+   it->cb = process;
+   it->free = free_cb;
+   it->original = iterator;
+
+   EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
+
+   it->iterator.version = EINA_ITERATOR_VERSION;
+   it->iterator.next = FUNC_ITERATOR_NEXT(eina_iterator_process_next);
+   it->iterator.get_container = 
FUNC_ITERATOR_GET_CONTAINER(eina_iterator_process_get_container);
+   it->iterator.free = FUNC_ITERATOR_FREE(eina_iterator_process_free);
+
+   return &it->iterator;
+}
diff --git a/src/lib/eina/eina_iterator.h b/src/lib/eina/eina_iterator.h
index cb254c7e8e..21194d59c3 100644
--- a/src/lib/eina/eina_iterator.h
+++ b/src/lib/eina/eina_iterator.h
@@ -365,6 +365,24 @@ EAPI Eina_Iterator* eina_iterator_filter_new(Eina_Iterator 
*original, Eina_Each_
  */
 EAPI Eina_Iterator *eina_multi_iterator_internal_new(Eina_Iterator *it, ...) 
EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
 
+
+/**
+ * @brief Calls the process method on each node of iterator, producing new 
"processed"
+ * nodes and returning a new iterator which contains them.
+ *
+ * @param[in] original Iterator containing the nodes to process.
+ * @param[in] process Method to call on each node.
+ * @param[in] free_cb Method called when all nodes have been processed. It 
receives "data" as a parameter.
+ * @param[in] data Additional data passed to the process method.
+ *
+ * Processes every node in the input iterator and returns a new iterator 
containing
+ * the processed nodes. This is akin to a Map function:
+ * @see https://en.wikipedia.org/wiki/Map_(higher-order_function)
+ *
+ * @since 1.24
+ */
+EAPI Eina_Iterator* eina_iterator_processed_new(Eina_Iterator *iterator, 
Eina_Process_Cb process, Eina_Free_Cb free_cb, void *fdata) 
EINA_WARN_UNUSED_RESULT;
+
 /**
  * @def eina_multi_iterator_new
  * @brief Creates an Eina_Iterator that iterates through a series
diff --git a/src/lib/eina/eina_types.h b/src/lib/eina/eina_types.h
index c049baf4dd..ad797d3d91 100644
--- a/src/lib/eina/eina_types.h
+++ b/src/lib/eina/eina_types.h
@@ -539,6 +539,18 @@ typedef int (*Eina_Random_Cb)(const int min, const int 
max);
  */
 #define EINA_RANDOM_CB(function) ((Eina_Random_Cb)function)
 
+/**
+ * @typedef Eina_Process_Cb
+ * Method that processes some data and returns new data.
+ * It's meant to be used as a callback to process all nodes inside a container 
(See eina_iterator_processed_new, for example.)
+ */
+typedef void* (*Eina_Process_Cb)(const void *container, void *data, void 
*fdata);
+
+/**
+ * @def EINA_PROCESS_CB
+ * Macro to cast to Eina_Process.
+ */
+#define EINA_PROCESS_CB(Function) ((Eina_Process_Cb)Function)
 /**
  * @typedef Eina_Each_Cb
  * A callback type used when iterating over a container.
diff --git a/src/tests/eina/eina_test_iterator.c 
b/src/tests/eina/eina_test_iterator.c
index 28fe0dfc5b..8eb37f2488 100644
--- a/src/tests/eina/eina_test_iterator.c
+++ b/src/tests/eina/eina_test_iterator.c
@@ -654,6 +654,49 @@ EFL_START_TEST(eina_iterator_multi)
 }
 EFL_END_TEST
 
+static void*
+_return_x(const void *container EINA_UNUSED, void *data, void *fdata)
+{
+   Eina_Rectangle *rect = data;
+   ck_assert_int_eq(*((int*)fdata), 1337);
+
+   return &rect->x;
+}
+
+static void
+_free_cb(void *data)
+{
+   int *free_data = data;
+
+   *free_data = 0;
+}
+
+EFL_START_TEST(eina_iterator_process)
+{
+   Eina_Inarray *rects = eina_inarray_new(sizeof(Eina_Rectangle), 5);
+   Eina_Rectangle rect_arr[] = {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}, 
{12, 13, 14, 15}, {16, 17, 18, 19}};
+   Eina_Iterator *it;
+   int free = 1337;
+   int *a, i = 0;
+
+   eina_inarray_push(rects, &rect_arr[0]);
+   eina_inarray_push(rects, &rect_arr[1]);
+   eina_inarray_push(rects, &rect_arr[2]);
+   eina_inarray_push(rects, &rect_arr[3]);
+   eina_inarray_push(rects, &rect_arr[4]);
+
+   it = eina_iterator_processed_new(eina_inarray_iterator_new(rects), 
_return_x, _free_cb, &free);
+   EINA_ITERATOR_FOREACH(it, a)
+     {
+         ck_assert_int_eq(*a, i*4);
+         i++;
+     }
+   ck_assert_int_eq(i, 5);
+   eina_iterator_free(it);
+   ck_assert_int_eq(free, 0);
+}
+EFL_END_TEST
+
 void
 eina_test_iterator(TCase *tc)
 {
@@ -667,4 +710,5 @@ eina_test_iterator(TCase *tc)
    tcase_add_test(tc, eina_iterator_filter_free);
    tcase_add_test(tc, eina_iterator_carray_length);
    tcase_add_test(tc, eina_iterator_multi);
+   tcase_add_test(tc, eina_iterator_process);
 }

-- 


Reply via email to