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);
* 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 *
}
/**
+ * @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.
}
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);
}