Add merge function to list data type.
authorcedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 21 Oct 2008 11:28:38 +0000 (11:28 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 21 Oct 2008 11:28:38 +0000 (11:28 +0000)
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/eina@36922 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/include/eina_list.h
src/lib/eina_list.c
src/tests/eina_test_list.c

index 1b1cce2..e61e5e6 100644 (file)
@@ -96,6 +96,9 @@ 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, unsigned int size, Eina_Compare_Cb func);
+EAPI Eina_List *eina_list_merge (Eina_List *left, Eina_List *right);
+EAPI Eina_List *eina_list_sorted_merge(Eina_List *left, Eina_List *right, Eina_Compare_Cb func);
+
 
 static inline Eina_List *eina_list_last (const Eina_List *list);
 static inline Eina_List *eina_list_next (const Eina_List *list);
index ab0dce1..c6ca443 100644 (file)
@@ -1217,11 +1217,6 @@ eina_list_reverse(Eina_List *list)
  * extern Eina_List *list;
  *
  * list = eina_list_sort(list, eina_list_count(list), sort_cb);
- * if (eina_error_get())
- *   {
- *     fprintf(stderr, "ERROR: Memory is low. List Sorting failed.\n");
- *     exit(-1);
- *   }
  * @endcode
  */
 EAPI Eina_List *
@@ -1292,6 +1287,147 @@ eina_list_sort(Eina_List *list, unsigned int size, Eina_Compare_Cb func)
 }
 
 /**
+ * @brief Merge two list.
+ *
+ * @param left Head list to merge.
+ * @param right Tail list to merge.
+ * @return A new merged list.
+ *
+ * This function put right at the end of left and return the head.
+ *
+ * Both left and right does not exist anymore after the merge.
+ *
+ */
+EAPI Eina_List *
+eina_list_merge(Eina_List *left, Eina_List *right)
+{
+   if (!left) return right;
+   if (!right) return left;
+
+   left->accounting->last->next = right;
+   right->prev = left->accounting->last;
+
+   left->accounting->last = right->accounting->last;
+   left->accounting->count += right->accounting->count;
+
+   _eina_list_mempool_accounting_free(right->accounting);
+
+   while (right)
+     {
+       right->accounting = left->accounting;
+       right = right->next;
+     }
+
+   return left;
+}
+
+/**
+ * @brief Merge two sorted list according to the ordering func will return.
+ *
+ * @param left First list to merge.
+ * @param right Second list to merge.
+ * @param func A function pointer that can handle comparing the list data
+ * nodes.
+ * @return A new sorted list.
+ *
+ * This function compare the head of @p left and @p right, and choose the
+ * smallest one to be head of the returned list. It will continue this process
+ * for all entry of both list.
+ *
+ * Both left and right does not exist anymore after the merge.
+ * If @p func is NULL, it will return NULL.
+ *
+ * Example:
+ * @code
+ * int
+ * sort_cb(void *d1, void *d2)
+ * {
+ *   const char *txt = NULL;
+ *    const char *txt2 = NULL;
+ *
+ *    if(!d1) return(1);
+ *    if(!d2) return(-1);
+ *
+ *    return(strcmp((const char*)d1, (const char*)d2));
+ * }
+ * extern Eina_List *sorted1;
+ * extern Eina_List *sorted2;
+ *
+ * list = eina_list_sorted_merge(sorted1, sorted2, sort_cb);
+ * @endcode
+ */
+EAPI Eina_List *
+eina_list_sorted_merge(Eina_List *left, Eina_List *right, Eina_Compare_Cb func)
+{
+   Eina_List *ret;
+   Eina_List *current;
+
+   if (!left) return right;
+   if (!right) return left;
+   if (!func) return NULL;
+
+   if (func(left->data, right->data) < 0)
+     {
+       ret = left;
+       current = left;
+       left = left->next;
+       ret->accounting->count += right->accounting->count;
+
+       _eina_list_mempool_accounting_free(right->accounting);
+     }
+   else
+     {
+       ret = right;
+       current = right;
+       right = right->next;
+       ret->accounting->count += left->accounting->count;
+
+       _eina_list_mempool_accounting_free(left->accounting);
+     }
+
+   while (left && right)
+     {
+       if (func(left->data, right->data) < 0)
+         {
+            current->next = left;
+            left->prev = current;
+            left = left->next;
+         }
+       else
+         {
+            current->next = right;
+            right->prev = current;
+            right = right->next;
+         }
+
+       current = current->next;
+       current->accounting = ret->accounting;
+     }
+
+   if (left)
+     {
+       current->next = left;
+       left->prev = current;
+     }
+
+   if (right)
+     {
+       current->next = right;
+       right->prev = current;
+     }
+
+   while (current->next)
+     {
+       current->accounting = ret->accounting;
+       current = current->next;
+     }
+
+   ret->accounting->last = current;
+
+   return ret;
+}
+
+/**
  * @brief Returned a new iterator asociated to a list.
  *
  * @param list The list.
index e6a6565..190ef8a 100644 (file)
@@ -188,8 +188,78 @@ START_TEST(eina_test_simple)
 }
 END_TEST
 
+START_TEST(eina_test_merge)
+{
+   Eina_List *l1;
+   Eina_List *l2;
+   Eina_List *l3;
+   Eina_List *l4;
+   Eina_List *l5;
+   int data[] = { 6, 9, 42, 1, 7, 9, 81, 1664, 1337, 3, 21, 10, 0, 5, 2008 };
+   int *prev;
+   int *current;
+   int i;
+
+   eina_list_init();
+
+   l1 = eina_list_append(NULL, &data[0]);
+   l1 = eina_list_append(l1, &data[1]);
+   l1 = eina_list_append(l1, &data[2]);
+
+   l2 = eina_list_append(NULL, &data[3]);
+   l2 = eina_list_append(l2, &data[4]);
+   l2 = eina_list_append(l2, &data[5]);
+
+   l3 = eina_list_append(NULL, &data[6]);
+   l3 = eina_list_append(l3, &data[7]);
+   l3 = eina_list_append(l3, &data[8]);
+
+   l4 = eina_list_append(NULL, &data[9]);
+   l4 = eina_list_append(l4, &data[10]);
+   l4 = eina_list_append(l4, &data[11]);
+
+   l5 = eina_list_append(NULL, &data[12]);
+   l5 = eina_list_append(l5, &data[13]);
+   l5 = eina_list_append(l5, &data[14]);
+
+   l1 = eina_list_merge(l1, l2);
+   fail_if(l1 == NULL);
+   fail_if(eina_list_count(l1) != 6);
+   for (i = 0; i < 6; ++i)
+     fail_if(eina_list_nth(l1, i) != &data[i]);
+
+   l1 = eina_list_sort(l1, -1, eina_int_cmp);
+   l3 = eina_list_sort(l3, -1, eina_int_cmp);
+   l4 = eina_list_sort(l4, -1, eina_int_cmp);
+   l5 = eina_list_sort(l5, -1, eina_int_cmp);
+
+   l1 = eina_list_sorted_merge(l1, l3, eina_int_cmp);
+   fail_if(l1 == NULL);
+   fail_if(eina_list_count(l1) != 9);
+
+   l1 = eina_list_sorted_merge(l1, l4, eina_int_cmp);
+   fail_if(l1 == NULL);
+   fail_if(eina_list_count(l1) != 12);
+
+   l1 = eina_list_sorted_merge(l1, l5, eina_int_cmp);
+   fail_if(l1 == NULL);
+   fail_if(eina_list_count(l1) != 15);
+
+   prev = eina_list_data_get(l1);
+   for (i = 1; i < eina_list_count(l1); ++i)
+     {
+       current = eina_list_nth(l1, i);
+       fail_if (*prev > *current);
+       prev = current;
+     }
+
+   eina_list_shutdown();
+}
+END_TEST
+
 void
 eina_test_list(TCase *tc)
 {
    tcase_add_test(tc, eina_test_simple);
+   tcase_add_test(tc, eina_test_merge);
 }