From 95f3d712d80623ff8386736bcdc92af43ae2bb20 Mon Sep 17 00:00:00 2001 From: barbieri Date: Thu, 6 Aug 2009 18:35:53 +0000 Subject: [PATCH] smarter eina_list_merge(), more tests. 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: http://svn.enlightenment.org/svn/e/trunk/eina@41622 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/lib/eina_list.c | 39 +++++++++++++++++++++++++++++++++------ src/tests/eina_test_list.c | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 64 insertions(+), 13 deletions(-) diff --git a/src/lib/eina_list.c b/src/lib/eina_list.c index 80febb3..0f2b57a 100644 --- a/src/lib/eina_list.c +++ b/src/lib/eina_list.c @@ -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; diff --git a/src/tests/eina_test_list.c b/src/tests/eina_test_list.c index 190ef8a..1714336 100644 --- a/src/tests/eina_test_list.c +++ b/src/tests/eina_test_list.c @@ -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); -- 2.7.4