smarter eina_list_merge(), more tests.
authorbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 6 Aug 2009 18:35:53 +0000 (18:35 +0000)
committerbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 6 Aug 2009 18:35:53 +0000 (18:35 +0000)
eina_list_merge() now fixes the smallest list segment, not always the
right. Before if we joined a list 1 to 1000 segments we'd fix all the
1000 instead of the single at left.

Tests to make sure both code paths are being executed.

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/eina@41622 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

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

index 80febb3..0f2b57a 100644 (file)
@@ -1512,25 +1512,52 @@ eina_list_sort(Eina_List *list, unsigned int size, Eina_Compare_Cb func)
  *
  * Both left and right does not exist anymore after the merge.
  *
+ * @note merge cost is O(n), being @b n the size of the smallest
+ * list. This is due the need to fix accounting of that segment,
+ * making count and last access O(1).
  */
 EAPI Eina_List *
 eina_list_merge(Eina_List *left, Eina_List *right)
 {
+   unsigned int n_left, n_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;
+   n_left = left->accounting->count;
+   n_right = right->accounting->count;
+
+   if (n_left >= n_right)
+     {
+       Eina_List *itr = right;
+       left->accounting->last = right->accounting->last;
+       left->accounting->count += n_right;
 
-   _eina_list_mempool_accounting_free(right->accounting);
+       _eina_list_mempool_accounting_free(right->accounting);
 
-   while (right)
+       do
+         {
+            itr->accounting = left->accounting;
+            itr = itr->next;
+         }
+       while (itr);
+     }
+   else
      {
-       right->accounting = left->accounting;
-       right = right->next;
+       Eina_List *itr = left->accounting->last;
+       right->accounting->count += n_left;
+
+       _eina_list_mempool_accounting_free(left->accounting);
+
+       do
+         {
+            itr->accounting = right->accounting;
+            itr = itr->prev;
+         }
+       while (itr);
      }
 
    return left;
index 190ef8a..1714336 100644 (file)
@@ -205,10 +205,40 @@ START_TEST(eina_test_merge)
    l1 = eina_list_append(NULL, &data[0]);
    l1 = eina_list_append(l1, &data[1]);
    l1 = eina_list_append(l1, &data[2]);
+   l1 = eina_list_append(l1, &data[3]);
+   fail_if(l1 == NULL);
+
+   l2 = eina_list_append(NULL, &data[4]);
+   l2 = eina_list_append(l2, &data[5]);
+   fail_if(l2 == NULL);
+
+   l1 = eina_list_merge(l1, l2);
+   fail_if(l1 == NULL);
+   fail_if(eina_list_count(l1) != 6);
+   for (i = 0, l2 = l1; ((l2 != NULL) && (i < 6)); ++i, l2 = l2->next)
+     fail_if(l2->data != &data[i]);
+   fail_if(i != 6);
+   fail_if(l2 != NULL);
+
+   eina_list_free(l1);
+
+   l1 = eina_list_append(NULL, &data[0]);
+   l1 = eina_list_append(l1, &data[1]);
+   fail_if(l1 == NULL);
 
-   l2 = eina_list_append(NULL, &data[3]);
+   l2 = eina_list_append(NULL, &data[2]);
+   l2 = eina_list_append(l2, &data[3]);
    l2 = eina_list_append(l2, &data[4]);
    l2 = eina_list_append(l2, &data[5]);
+   fail_if(l2 == NULL);
+
+   l1 = eina_list_merge(l1, l2);
+   fail_if(l1 == NULL);
+   fail_if(eina_list_count(l1) != 6);
+   for (i = 0, l2 = l1; ((l2 != NULL) && (i < 6)); ++i, l2 = l2->next)
+     fail_if(l2->data != &data[i]);
+   fail_if(i != 6);
+   fail_if(l2 != NULL);
 
    l3 = eina_list_append(NULL, &data[6]);
    l3 = eina_list_append(l3, &data[7]);
@@ -222,12 +252,6 @@ START_TEST(eina_test_merge)
    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);