forked from enlightenment/efl
Add merge function to list data type.
SVN revision: 36922
This commit is contained in:
parent
0eb2aaab4d
commit
1950725606
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue