Add iterator/accessor to eina list.
authorcedric <cedric>
Wed, 13 Aug 2008 09:19:34 +0000 (09:19 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 13 Aug 2008 09:19:34 +0000 (09:19 +0000)
Change list size type to unsigned int.

git-svn-id: http://svn.enlightenment.org/svn/e/trunk/e17/proto/eina@35454 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/include/eina_inline_list.x
src/include/eina_list.h
src/lib/eina_list.c
src/tests/eina_bench_array.c
src/tests/eina_test_accessor.c
src/tests/eina_test_iterator.c

index 71feb4e..d8e4012 100644 (file)
@@ -47,7 +47,7 @@ eina_list_data(const Eina_List *list)
    return list->data;
 }
 
-static inline int
+static inline unsigned int
 eina_list_count(const Eina_List *list)
 {
    if (!list) return 0;
index 9efd9d7..9d07647 100644 (file)
@@ -22,6 +22,8 @@
 #include <stdlib.h>
 
 #include "eina_types.h"
+#include "eina_iterator.h"
+#include "eina_accessor.h"
 
 /**
  * @defgroup List_Group List
@@ -41,7 +43,7 @@ struct _Eina_List /** A linked list node */
 struct _Eina_List_Accounting
 {
    Eina_List *last;
-   int        count;
+   unsigned int count;
 };
 
 
@@ -60,16 +62,21 @@ EAPI Eina_List *eina_list_promote_list (Eina_List *list, Eina_List *move_list);
 EAPI void *eina_list_find(const Eina_List *list, const void *data);
 EAPI Eina_List *eina_list_find_list (const Eina_List *list, const void *data);
 EAPI Eina_List *eina_list_free (Eina_List *list);
-EAPI void *eina_list_nth(const Eina_List *list, int n);
-EAPI Eina_List *eina_list_nth_list (const Eina_List *list, int n);
+EAPI void *eina_list_nth(const Eina_List *list, unsigned int n);
+EAPI Eina_List *eina_list_nth_list (const Eina_List *list, unsigned int n);
 EAPI Eina_List *eina_list_reverse (Eina_List *list);
-EAPI Eina_List *eina_list_sort (Eina_List *list, int size, int(*func)(void*,void*));
+EAPI Eina_List *eina_list_sort (Eina_List *list, unsigned int size, int(*func)(void*,void*));
 
 static inline Eina_List *eina_list_last (const Eina_List *list);
 static inline Eina_List *eina_list_next (const Eina_List *list);
 static inline Eina_List *eina_list_prev (const Eina_List *list);
 static inline void *eina_list_data(const Eina_List *list);
-static inline int eina_list_count(const Eina_List *list);
+static inline unsigned int eina_list_count(const Eina_List *list);
+
+EAPI Eina_Iterator *eina_list_iterator_new(const Eina_List *list);
+EAPI Eina_Accessor *eina_list_accessor_new(const Eina_List *list);
+
+#define EINA_LIST_ITER_NEXT(list, l, data) for (l = list, data = eina_list_data(l); l; l = eina_list_next(l), data = eina_list_data(l))
 
 /** @} */
 #include "eina_inline_list.x"
index 553cf1e..b1f700c 100644 (file)
 /*============================================================================*
  *                                  Local                                     * 
  *============================================================================*/
+typedef struct _Eina_Iterator_List Eina_Iterator_List;
+typedef struct _Eina_Accessor_List Eina_Accessor_List;
+
+struct _Eina_Iterator_List
+{
+   Eina_Iterator iterator;
+
+   const Eina_List *head;
+   const Eina_List *current;
+};
+
+struct _Eina_Accessor_List
+{
+   Eina_Accessor accessor;
+
+   const Eina_List *head;
+   const Eina_List *current;
+
+   unsigned int index;
+};
+
 static inline Eina_List_Accounting*
 _eina_list_mempool_accounting_new(__UNUSED__ Eina_List *list)
 {
@@ -139,6 +160,108 @@ static Eina_Mempool2 _eina_list_accounting_mempool =
 };
 #endif
 
+static Eina_Bool
+eina_list_iterator_next(Eina_Iterator_List *it, void **data)
+{
+   if (it->current == NULL) return EINA_FALSE;
+   if (data) *data = eina_list_data(it->current);
+
+   it->current = eina_list_next(it->current);
+
+   return EINA_TRUE;
+}
+
+static Eina_List *
+eina_list_iterator_get_container(Eina_Iterator_List *it)
+{
+   return (Eina_List *) it->head;
+}
+
+static void
+eina_list_iterator_free(Eina_Iterator_List *it)
+{
+   free(it);
+}
+
+static Eina_Bool
+eina_list_accessor_get_at(Eina_Accessor_List *it, unsigned int index, void **data)
+{
+   const Eina_List *over;
+   unsigned int middle;
+   unsigned int i;
+
+   if (index > eina_list_count(it->head)) return EINA_FALSE;
+
+   if (it->index == index)
+     {
+       over = it->current;
+     }
+   else if (index > it->index)
+     {
+       /* After current position. */
+       middle = ((eina_list_count(it->head) - it->index) >> 1) + it->index;
+
+       if (index > middle)
+         {
+            /* Go backward from the end. */
+            for (i = eina_list_count(it->head) - 1, over = eina_list_last(it->head);
+                 i > index && over != NULL;
+                 --i, over = eina_list_prev(over))
+              ;
+         }
+       else
+         {
+            /* Go forward from current. */
+            for (i = it->index, over = it->current;
+                 i < index && over != NULL;
+                 ++i, over = eina_list_next(over))
+              ;
+         }
+     }
+   else
+     {
+       /* Before current position. */
+       middle = it->index >> 1;
+
+       if (index > middle)
+         {
+            /* Go backward from current. */
+            for (i = it->index, over = it->current;
+                 i > index && over != NULL;
+                 --i, over = eina_list_prev(over))
+              ;
+         }
+       else
+         {
+            /* Go forward from start. */
+            for (i = 0, over = it->head;
+                 i < index && over != NULL;
+                 ++i, over = eina_list_next(over))
+              ;
+         }
+     }
+
+   if (over == NULL) return EINA_FALSE;
+
+   it->current = over;
+   it->index = index;
+
+   if (data) *data = eina_list_data(it->current);
+   return EINA_TRUE;
+}
+
+static Eina_List *
+eina_list_accessor_get_container(Eina_Accessor_List *it)
+{
+   return (Eina_List *) it->head;
+}
+
+static void
+eina_list_accessor_free(Eina_Accessor_List *it)
+{
+   free(it);
+}
+
 /*============================================================================*
  *                                 Global                                     *
  *============================================================================*/
@@ -589,7 +712,7 @@ eina_list_promote_list(Eina_List *list, Eina_List *move_list)
 EAPI void *
 eina_list_find(const Eina_List *list, const void *data)
 {
-   if (eina_list_find_list(list, data)) return data;
+   if (eina_list_find_list(list, data)) return (void*) data;
    return NULL;
 }
 
@@ -789,7 +912,7 @@ static inline void *eina_list_data(const Eina_List *list);
  * @endcode
  * @ingroup Eina_List_General_Group
  */
-static inline int eina_list_count(const Eina_List *list);
+static inline unsigned int eina_list_count(const Eina_List *list);
 
 /**
  * Get the nth member's data pointer in a list
@@ -814,10 +937,10 @@ static inline int eina_list_count(const Eina_List *list);
  * @ingroup Eina_List_Find_Group
  */
 EAPI void *
-eina_list_nth(const Eina_List *list, int n)
+eina_list_nth(const Eina_List *list, unsigned int n)
 {
    Eina_List *l;
-   
+
    l = eina_list_nth_list(list, n);
    return l ? l->data : NULL;
 }
@@ -845,14 +968,13 @@ eina_list_nth(const Eina_List *list, int n)
  * @ingroup Eina_List_Find_Group
  */
 EAPI Eina_List *
-eina_list_nth_list(const Eina_List *list, int n)
+eina_list_nth_list(const Eina_List *list, unsigned int n)
 {
-   int i;
    const Eina_List *l;
+   unsigned int i;
 
    /* check for non-existing nodes */
-   if ((!list) || (n < 0) ||
-       (n > (list->accounting->count - 1)))
+   if ((!list) || (n > (list->accounting->count - 1)))
      return NULL;
 
    /* if the node is in the 2nd half of the list, search from the end
@@ -960,7 +1082,7 @@ eina_list_reverse(Eina_List *list)
  * @ingroup Eina_List_Ordering_Group
  */
 EAPI Eina_List *
-eina_list_sort(Eina_List *list, int size, int (*func)(void *, void *))
+eina_list_sort(Eina_List *list, unsigned int size, int (*func)(void *, void *))
 {
    Eina_List*   last;
    unsigned int        list_number;
@@ -970,7 +1092,7 @@ eina_list_sort(Eina_List *list, int size, int (*func)(void *, void *))
    if (!list || !func) return NULL;
 
    /* if the caller specified an invalid size, sort the whole list */
-   if ((size <= 0) ||
+   if ((size == 0) ||
        (size > list->accounting->count))
      size = list->accounting->count;
 
@@ -1060,3 +1182,53 @@ eina_list_sort(Eina_List *list, int size, int (*func)(void *, void *))
    list->accounting->last = last;
    return list;
 }
+
+EAPI Eina_Iterator *
+eina_list_iterator_new(const Eina_List *list)
+{
+   Eina_Iterator_List *it;
+
+   if (!list) return NULL;
+
+   eina_error_set(0);
+   it = calloc(1, sizeof (Eina_Iterator_List));
+   if (!it) {
+      eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
+      return NULL;
+   }
+
+   it->head = list;
+   it->current = list;
+
+   it->iterator.next = FUNC_ITERATOR_NEXT(eina_list_iterator_next);
+   it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(eina_list_iterator_get_container);
+   it->iterator.free = FUNC_ITERATOR_FREE(eina_list_iterator_free);
+
+   return &it->iterator;
+}
+
+EAPI Eina_Accessor *
+eina_list_accessor_new(const Eina_List *list)
+{
+   Eina_Accessor_List *it;
+
+   if (!list) return NULL;
+
+   eina_error_set(0);
+   it = calloc(1, sizeof (Eina_Accessor_List));
+   if (!it) {
+      eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
+      return NULL;
+   }
+
+   it->head = list;
+   it->current = list;
+   it->index = 0;
+
+   it->accessor.get_at = FUNC_ACCESSOR_GET_AT(eina_list_accessor_get_at);
+   it->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER(eina_list_accessor_get_container);
+   it->accessor.free = FUNC_ACCESSOR_FREE(eina_list_accessor_free);
+
+   return &it->accessor;
+}
+
index 2e73e03..390d266 100644 (file)
@@ -234,6 +234,73 @@ eina_bench_list_4evas_render(int request)
 }
 
 static void
+eina_bench_list_4evas_render_iterator(int request)
+{
+   Eina_List *list = NULL;
+   Eina_List *tmp;
+   Eina_Bench_Object *ebo;
+   Eina_Iterator *it;
+   int i;
+   int j;
+
+   eina_list_init();
+
+   for (i = 0; i < 1000; ++i)
+     {
+       for (j = 0; j < request; ++j)
+         {
+            ebo = malloc(sizeof (Eina_Bench_Object));
+            if (!ebo) continue ;
+
+            ebo->keep = rand() < (RAND_MAX / 2) ? EINA_TRUE : EINA_FALSE;
+
+            list = eina_list_prepend(list, ebo);
+         }
+
+       if (i == 500)
+         {
+            while (list)
+              {
+                 free(eina_list_data(list));
+                 list = eina_list_remove_list(list, list);
+              }
+         }
+       else
+         {
+            if (i % 30 == 0)
+              {
+                 tmp = list;
+                 while (tmp)
+                   {
+                      Eina_List *reminder = tmp;
+
+                      ebo = eina_list_data(reminder);
+                      tmp = eina_list_next(tmp);
+
+                      if (ebo->keep == EINA_FALSE)
+                        {
+                           list = eina_list_remove_list(list, reminder);
+                           free(ebo);
+                        }
+                   }
+              }
+         }
+
+       it = eina_list_iterator_new(list);
+       eina_iterator_foreach(it, EINA_EACH(eina_iterator_ebo_rand), NULL);
+       eina_iterator_free(it);
+     }
+
+   while (list)
+     {
+       free(eina_list_data(list));
+       list = eina_list_remove_list(list, list);
+     }
+
+   eina_list_shutdown();
+}
+
+static void
 eina_bench_inlist_4evas_render(int request)
 {
    Eina_Inlist *head = NULL;
@@ -362,6 +429,7 @@ void eina_bench_array(Eina_Bench *bench)
    eina_bench_register(bench, "array-inline", EINA_BENCH(eina_bench_array_4evas_render_inline), 200, 4000, 100);
    eina_bench_register(bench, "array-iterator", EINA_BENCH(eina_bench_array_4evas_render_iterator), 200, 4000, 100);
    eina_bench_register(bench, "list", EINA_BENCH(eina_bench_list_4evas_render), 200, 4000, 100);
+   eina_bench_register(bench, "list-iterator", EINA_BENCH(eina_bench_list_4evas_render_iterator), 200, 4000, 100);
    eina_bench_register(bench, "inlist", EINA_BENCH(eina_bench_inlist_4evas_render), 200, 4000, 100);
    eina_bench_register(bench, "inlist-iterator", EINA_BENCH(eina_bench_inlist_4evas_render_iterator), 200, 4000, 100);
 }
index 1df3aa5..c0656bf 100644 (file)
@@ -25,6 +25,7 @@
 #include "eina_suite.h"
 #include "eina_array.h"
 #include "eina_inlist.h"
+#include "eina_list.h"
 #include "eina_private.h"
 
 static Eina_Bool
@@ -164,10 +165,75 @@ START_TEST(eina_accessor_inlist_simple)
 }
 END_TEST
 
+static Eina_Bool
+eina_iterator_list_data_check(__UNUSED__ const Eina_List *list, int *data, int *fdata)
+{
+   switch (*fdata)
+     {
+      case 0: fail_if(*data != 9); break;
+      case 1: fail_if(*data != 6); break;
+     }
+
+   (*fdata)++;
+
+   return EINA_TRUE;
+}
+
+START_TEST(eina_accessor_list_simple)
+{
+   Eina_List *list = NULL;
+   Eina_Accessor *it;
+   int data[] = { 6, 9, 42, 1, 7, 1337, 81, 1664 };
+   int *j;
+   int i = 0;
+
+   eina_list_init();
+
+   list = eina_list_append(list, &data[0]);
+   fail_if(list == NULL);
+
+   list = eina_list_prepend(list, &data[1]);
+   fail_if(list == NULL);
+
+   list = eina_list_append(list, &data[2]);
+   fail_if(list == NULL);
+
+   list = eina_list_append(list, &data[3]);
+   fail_if(list == NULL);
+
+   list = eina_list_prepend(list, &data[4]);
+   fail_if(list == NULL);
+
+   list = eina_list_append(list, &data[5]);
+   fail_if(list == NULL);
+
+   list = eina_list_prepend(list, &data[6]);
+   fail_if(list == NULL);
+
+   it = eina_list_accessor_new(list);
+   fail_if(!it);
+
+   eina_accessor_over(it, EINA_EACH(eina_iterator_list_data_check), 2, 4, &i);
+
+   fail_if(eina_accessor_data_get(it, 5, (void**) &j) != EINA_TRUE);
+   fail_if(*j != 1);
+   fail_if(eina_accessor_data_get(it, 3, (void**) &j) != EINA_TRUE);
+   fail_if(*j != 6);
+   fail_if(eina_accessor_data_get(it, 3, (void**) &j) != EINA_TRUE);
+   fail_if(*j != 6);
+   fail_if(eina_accessor_data_get(it, 1, (void**) &j) != EINA_TRUE);
+   fail_if(*j != 7);
+   fail_if(eina_accessor_data_get(it, 5, (void**) &j) != EINA_TRUE);
+   fail_if(*j != 1);
+
+   eina_accessor_free(it);
+}
+END_TEST
 
 void
 eina_test_accessor(TCase *tc)
 {
    tcase_add_test(tc, eina_accessor_array_simple);
    tcase_add_test(tc, eina_accessor_inlist_simple);
+   tcase_add_test(tc, eina_accessor_list_simple);
 }
index 4315969..9392c56 100644 (file)
@@ -26,6 +26,7 @@
 #include "eina_array.h"
 #include "eina_hash.h"
 #include "eina_inlist.h"
+#include "eina_list.h"
 #include "eina_private.h"
 
 static Eina_Bool
@@ -212,10 +213,68 @@ START_TEST(eina_iterator_inlist_simple)
 }
 END_TEST
 
+static Eina_Bool
+eina_iterator_list_data_check(__UNUSED__ const Eina_List *list, int *data, int *fdata)
+{
+   switch (*fdata)
+     {
+      case 0: fail_if(*data != 81); break;
+      case 1: fail_if(*data != 7); break;
+      case 2: fail_if(*data != 9); break;
+      case 3: fail_if(*data != 6); break;
+      case 4: fail_if(*data != 42); break;
+      case 5: fail_if(*data != 1); break;
+      case 6: fail_if(*data != 1337); break;
+     }
+
+   (*fdata)++;
+
+   return EINA_TRUE;
+}
+
+START_TEST(eina_iterator_list_simple)
+{
+   Eina_List *list = NULL;
+   Eina_Iterator *it;
+   int data[] = { 6, 9, 42, 1, 7, 1337, 81, 1664 };
+   int i = 0;
+
+   eina_list_init();
+
+   list = eina_list_append(list, &data[0]);
+   fail_if(list == NULL);
+
+   list = eina_list_prepend(list, &data[1]);
+   fail_if(list == NULL);
+
+   list = eina_list_append(list, &data[2]);
+   fail_if(list == NULL);
+
+   list = eina_list_append(list, &data[3]);
+   fail_if(list == NULL);
+
+   list = eina_list_prepend(list, &data[4]);
+   fail_if(list == NULL);
+
+   list = eina_list_append(list, &data[5]);
+   fail_if(list == NULL);
+
+   list = eina_list_prepend(list, &data[6]);
+   fail_if(list == NULL);
+
+   it = eina_list_iterator_new(list);
+   fail_if(!it);
+
+   eina_iterator_foreach(it, EINA_EACH(eina_iterator_list_data_check), &i);
+   eina_iterator_free(it);
+}
+END_TEST
+
 void
 eina_test_iterator(TCase *tc)
 {
    tcase_add_test(tc, eina_iterator_array_simple);
    tcase_add_test(tc, eina_iterator_hash_simple);
    tcase_add_test(tc, eina_iterator_inlist_simple);
+   tcase_add_test(tc, eina_iterator_list_simple);
 }