*
* 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;
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]);
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);