diff --git a/src/lib/eina/eina_iterator.c b/src/lib/eina/eina_iterator.c index d025b6ad5b..34763f2148 100644 --- a/src/lib/eina/eina_iterator.c +++ b/src/lib/eina/eina_iterator.c @@ -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; diff --git a/src/lib/eina/eina_iterator.h b/src/lib/eina/eina_iterator.h index 7f1e94cb02..ebfd27c2cc 100644 --- a/src/lib/eina/eina_iterator.h +++ b/src/lib/eina/eina_iterator.h @@ -349,6 +349,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.