eina: add eina_multi_iterator_new.
authorCedric BAIL <cedric@osg.samsung.com>
Fri, 16 Nov 2018 01:42:27 +0000 (17:42 -0800)
committerHermet Park <hermetpark@gmail.com>
Wed, 5 Dec 2018 05:37:06 +0000 (14:37 +0900)
This will return an Iterator that will walk over a serie of iterator.
This technicaly take ownership of the iterator it is walking over and
destroy as it goes and doesn't need them anymore.

Reviewed-by: Vitor Sousa da Silva <vitorsousa@expertisesolutions.com.br>
Differential Revision: https://phab.enlightenment.org/D7286

src/lib/eina/eina_iterator.c
src/lib/eina/eina_iterator.h

index d025b6a..34763f2 100644 (file)
@@ -29,6 +29,8 @@
 #include "eina_safety_checks.h"
 #include "eina_iterator.h"
 
+#include "eina_list.h"
+
 /*============================================================================*
  *                                  Local                                     *
  *============================================================================*/
@@ -290,6 +292,83 @@ eina_carray_length_iterator_new(void** array, unsigned int step, unsigned int le
    return &it->iterator;
 }
 
+typedef struct _Eina_Iterator_Multi Eina_Multi_Iterator;
+
+struct _Eina_Iterator_Multi
+{
+   Eina_Iterator iterator;
+
+   Eina_List *iterators;
+};
+
+static Eina_Bool
+eina_multi_iterator_next(Eina_Multi_Iterator *it, void **data)
+{
+   Eina_Bool r;
+
+   if (!it->iterators)
+     return EINA_FALSE;
+
+   // Search for an iterator that do have some data
+   while (!eina_iterator_next(eina_list_data_get(it->iterators), data))
+     {
+        eina_iterator_free(eina_list_data_get(it->iterators));
+        it->iterators = eina_list_remove_list(it->iterators, it->iterators);
+
+        if (!it->iterators) return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
+static void**
+eina_multi_iterator_get_container(Eina_Multi_Iterator *it)
+{
+   if (!it->iterators) return NULL;
+   return eina_iterator_container_get(eina_list_data_get(it->iterators));
+}
+
+static void
+eina_multi_iterator_free(Eina_Multi_Iterator *it)
+{
+   Eina_Iterator *itc;
+
+   EINA_LIST_FREE(it->iterators, itc)
+     eina_iterator_free(itc);
+   free(it);
+}
+
+EAPI Eina_Iterator *
+eina_multi_iterator_internal_new(Eina_Iterator *itc, ...)
+{
+   Eina_Multi_Iterator *it;
+   va_list args;
+
+   it = calloc(1, sizeof (Eina_Multi_Iterator));
+   if (!it) return NULL;
+
+   EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
+
+   it->iterators = eina_list_append(it->iterators, itc);
+
+   va_start(args, itc);
+
+   while ((itc = (Eina_Iterator *) va_arg(args, Eina_Iterator *)))
+     {
+        it->iterators = eina_list_append(it->iterators, itc);
+     }
+
+   va_end(args);
+
+   it->iterator.version = EINA_ITERATOR_VERSION;
+   it->iterator.next = FUNC_ITERATOR_NEXT(eina_multi_iterator_next);
+   it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
+      eina_multi_iterator_get_container);
+   it->iterator.free = FUNC_ITERATOR_FREE(eina_multi_iterator_free);
+
+   return &it->iterator;
+}
+
 typedef struct {
    Eina_Iterator iterator;
 
index 7f1e94c..ebfd27c 100644 (file)
@@ -350,6 +350,39 @@ EAPI Eina_Iterator *eina_carray_length_iterator_new(void** array, unsigned int s
 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;
 
 /**
+ * @brief Creates an Eina_Iterator that iterates through a serie
+ * of Eina_Iterator.
+ *
+ * @param[in] it The first Eina_Iterator to iterate over
+ * @return The iterator that will walk all the other iterator
+ *
+ * Eina_Iterator* iterator = eina_multi_iterator_new(it1, it2, it3, NULL);
+ *
+ * @note The returned array will destroy iterator given to it once they are not
+ * necessary anymore. Taking ownership of those iterator.
+ *
+ * @since 1.22
+ */
+EAPI Eina_Iterator *eina_multi_iterator_internal_new(Eina_Iterator *it, ...) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
+
+/**
+ * @def eina_multi_iterator_new
+ * @brief Creates an Eina_Iterator that iterates through a serie
+ * of Eina_Iterator.
+ *
+ * @param[in] it The first Eina_Iterator to iterate over
+ * @return The iterator that will walk all the other iterator
+ *
+ * Eina_Iterator* iterator = eina_multi_iterator_new(it1, it2, it3);
+ *
+ * @note The returned array will destroy iterator given to it once they are not
+ * necessary anymore. Taking ownership of those iterator.
+ *
+ * @since 1.22
+ */
+#define eina_multi_iterator_new(It, ...) eina_multi_iterator_internal_new(It, ##__VA_ARGS__, NULL)
+
+/**
  * @def EINA_ITERATOR_FOREACH
  * @brief Definition for the macro to iterate over all elements easily.
  *