Add merge function to list data type.

SVN revision: 36922
This commit is contained in:
Cedric BAIL 2008-10-21 11:28:38 +00:00
parent 0eb2aaab4d
commit 1950725606
3 changed files with 214 additions and 5 deletions

View 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);

View 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 *
@ -1291,6 +1286,147 @@ eina_list_sort(Eina_List *list, unsigned int size, Eina_Compare_Cb func)
return 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.
*

View 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);
}