Compare commits

...

8 Commits

Author SHA1 Message Date
Jérémy Zurcher 813cfcf08f add EAPI void eina_list_filter_map_reduce(…)
- filter then map then reduce
2013-06-13 15:54:59 +02:00
Jérémy Zurcher 587077ef4b eina_list_reduce: 3 arg NONNULL 2013-06-13 15:06:03 +02:00
Jérémy Zurcher 6d2c2d3929 eina_list map reduce: reduce code 2013-06-13 15:04:06 +02:00
Jérémy Zurcher 041c4f41df add EAPI Eina_List* eina_list_reduce(Eina_List *list, Eina_Reduce_Cb func, void *acc)
- apply the reduce function on the list nodes
- typedef void (*Eina_Reduce_Cb)(const void *data, void *acc)
2013-06-13 14:59:26 +02:00
Jérémy Zurcher 53c02a31ac add EAPI eina_list_map(Eina_List *list, Eina_Map_Cb func)
- eina_list_map applies func on each node of list
- typedef void (*Eina_Map_Cb)(const void *data);
2013-06-13 14:23:08 +02:00
Jérémy Zurcher d874570568 add EAPI eina_list_filter(Eina_List *list, Eina_Filter_Cb func)
- eina_list_filter returns a new list
- typedef Eina_Bool (*Eina_Filter_Cb)(const void *data);
- returns EINA_TRUE if satisfies the predicate
2013-06-12 17:52:06 +02:00
Jérémy Zurcher ab9bb6a2a8 eina_test_list: format 2013-06-12 17:24:22 +02:00
Jérémy Zurcher 0d9a4e5717 add EAPI eina_list_remove_duplicates(Eina_List *list, Eina_Bool keep_first)
it compares data pointers, keeps only the first or the last of each
2013-06-12 17:08:40 +02:00
4 changed files with 417 additions and 3 deletions

View File

@ -751,6 +751,64 @@ eina_list_remove_list(Eina_List *list, Eina_List *remove_list)
return return_l;
}
EAPI Eina_List *
eina_list_remove_duplicates(Eina_List *list, Eina_Bool keep_first)
{
Eina_List *itr1, *itr2, *itr3;
if (!list)
return NULL;
EINA_MAGIC_CHECK_LIST(list, NULL);
if (keep_first)
{
itr1 = list;
while (itr1)
{
itr2 = itr1->next;
while (itr2)
{
itr3 = itr2->next;
if (itr1->data == itr2->data)
{
list = eina_list_remove_list(list, itr2);
}
itr2 = itr3;
}
itr1 = itr1->next;
}
}
else
{
itr1 = list->accounting->last;
while (itr1)
{
itr2 = itr1->prev;
while (itr2)
{
itr3 = itr2->prev;
if (itr1->data == itr2->data)
{
list = eina_list_remove_list(list, itr2);
}
itr2 = itr3;
}
itr1 = itr1->prev;
}
}
return list;
}
EAPI Eina_List *
eina_list_free(Eina_List *list)
{
@ -1095,6 +1153,93 @@ eina_list_sort(Eina_List *list, unsigned int limit, Eina_Compare_Cb func)
return list;
}
EAPI Eina_List *
eina_list_filter(Eina_List *list, Eina_Filter_Cb func)
{
const Eina_List *l;
Eina_List *lfiltered;
void *data;
if (!list)
return NULL;
EINA_MAGIC_CHECK_LIST(list, NULL);
if (func == NULL)
return eina_list_clone(list);
lfiltered = NULL;
EINA_LIST_FOREACH(list, l, data)
{
if (func(data) == EINA_TRUE)
lfiltered = eina_list_append(lfiltered, data);
}
return lfiltered;
}
EAPI Eina_List *
eina_list_map(Eina_List *list, Eina_Map_Cb func)
{
const Eina_List *l;
void *data;
if (!list)
return NULL;
EINA_MAGIC_CHECK_LIST(list, NULL);
if (func)
EINA_LIST_FOREACH(list, l, data)
func(data);
return list;
}
EAPI Eina_List *
eina_list_reduce(Eina_List *list, Eina_Reduce_Cb func, void *acc)
{
const Eina_List *l;
void *data;
if (!list)
return NULL;
EINA_MAGIC_CHECK_LIST(list, NULL);
if (func)
EINA_LIST_FOREACH(list, l, data)
func(data, acc);
return list;
}
EAPI void
eina_list_filter_map_reduce(Eina_List *list,
Eina_Filter_Cb filter,
Eina_Map_Cb map,
Eina_Reduce_Cb reduce, void *acc)
{
const Eina_List *l;
void *data;
if (!list)
return;
EINA_MAGIC_CHECK_LIST(list);
EINA_LIST_FOREACH(list, l, data)
{
if ((filter == NULL) || (filter(data) == EINA_TRUE))
{
if (map)
map(data);
if (reduce)
reduce(data, acc);
}
}
}
EAPI Eina_List *
eina_list_shuffle(Eina_List *list, Eina_Random_Cb func)
{

View File

@ -619,6 +619,25 @@ EAPI Eina_List *eina_list_remove(Eina_List *list, const void *data) E
EAPI Eina_List *eina_list_remove_list(Eina_List *list, Eina_List *remove_list) EINA_ARG_NONNULL(2) EINA_WARN_UNUSED_RESULT;
/**
* @brief Remove duplicated list nodes.
*
* @param list The given linked list.
* @param keep_first Keep the first or last occurence
* @return A list pointer.
*
* This function removes multiple node occurences that have the same data.
* It keeps the first or last occurence depending of @p keep_first.
* If @p list is @c NULL, @c NULL is returned, otherwise a new list pointer
* that should be used in place of the one passed to this function.
*
* @since 1.8
*
* @warning @p list must be a pointer to the first element of the list.
*/
EAPI Eina_List *eina_list_remove_duplicates(Eina_List *list, Eina_Bool keep_first) EINA_WARN_UNUSED_RESULT;
/**
* @brief Move the specified data to the head of the list.
*
@ -920,6 +939,68 @@ EAPI Eina_List *eina_list_clone(const Eina_List *list) EINA_WARN_UNUS
EAPI Eina_List *eina_list_sort(Eina_List *list, unsigned int limit, Eina_Compare_Cb func) EINA_ARG_NONNULL(3) EINA_WARN_UNUSED_RESULT;
/**
* @brief filter (clone some) the elements in the list in exactly same order.
*
* @param list The list to filter.
* @param func The filter function.
* @return The new list.
*
* This function clone in order the elements in @p list that satisfy the
* filter @p func. This filter function @p func must return @c EINA_TRUE if the
* element is to be cloned. If @p list is @c NULL, this functon returns @c NULL.
* If @p func is @c NULL, this functon calls @see eina_list_clone().
* This returns a new list.
*
* @since 1.8
*
* @warning @p list must be a pointer to the first element of the list.
*/
EAPI Eina_List *eina_list_filter(Eina_List *list, Eina_Filter_Cb func) EINA_WARN_UNUSED_RESULT;
/**
* @brief Apply a function on all nodes of list
*
* @param list The list to apply function on.
* @param func The function to apply on nodes.
* @return The same list.
* @since 1.8
*
* @warning @p list must be a pointer to the first element of the list.
*/
EAPI Eina_List *eina_list_map(Eina_List *list, Eina_Map_Cb func) EINA_WARN_UNUSED_RESULT;
/**
* @brief Apply a reduce function on all nodes of list
*
* @param list The list to reduce.
* @param func The reduce function to apply on nodes.
* @param acc The pointer to the accumulator of the reduce function.
* @return The same list.
* @since 1.8
*
* @warning @p list must be a pointer to the first element of the list.
*/
EAPI Eina_List *eina_list_reduce(Eina_List *list, Eina_Reduce_Cb func, void *acc) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(3);
/**
* @brief Apply a filter, then a map then a reduce function on all nodes of list
*
* @param list The list to filter, map then reduce.
* @param filter The filter function.
* @param map The reduce function to apply on nodes.
* @param reduce The reduce function to apply on nodes.
* @param acc The pointer to the accumulator of the reduce function.
* @since 1.8
*
* @see eina_list_filter()
* @see eina_list_map()
* @see eina_list_reduce()
*
* @warning @p list must be a pointer to the first element of the list.
*/
EAPI void eina_list_filter_map_reduce(Eina_List *list, Eina_Filter_Cb filter, Eina_Map_Cb map, Eina_Reduce_Cb reduce, void *acc) EINA_ARG_NONNULL(5);
/**
* @brief Shuffle list.
*

View File

@ -333,6 +333,44 @@ typedef int (*Eina_Compare_Cb)(const void *data1, const void *data2);
*/
#define EINA_COMPARE_CB(function) ((Eina_Compare_Cb)function)
/**
* @typedef Eina_Filter_Cb
* Function used in filtering functions.
* It returns EINA_TRUE only if @p data satisfies the predicate thus
* is not to be filtered.
*/
typedef Eina_Bool (*Eina_Filter_Cb)(const void *data);
/**
* @def EINA_FILTER_CB
* Macro to cast to Eina_Filter_Cb.
*/
#define EINA_FILTER_CB(function) ((Eina_Filter_Cb)function)
/**
* @typedef Eina_Map_Cb
* Function to be applied on nodes.
*/
typedef void (*Eina_Map_Cb)(const void *data);
/**
* @def EINA_MAP_CB
* Macro to cast to Eina_Map_Cb.
*/
#define EINA_MAP_CB(function) ((Eina_Map_Cb)function)
/**
* @typedef Eina_Reduce_Cb
* Function to be applied on nodes.
*/
typedef void (*Eina_Reduce_Cb)(const void *data, void *acc);
/**
* @def EINA_REDUCE_CB
* Macro to cast to Eina_Reduce_Cb.
*/
#define EINA_REDUCE_CB(function) ((Eina_Reduce_Cb)function)
/**
* @typedef Eina_Random_Cb
* Function used in shuffling functions. An integer betwen min and max

View File

@ -400,14 +400,14 @@ START_TEST(eina_test_shuffle)
eina_init();
for(i = 0; i < SHUFFLE_SZ; i++)
for (i = 0; i < SHUFFLE_SZ; i++)
{
n[i] = i;
rand_count[i] = 0;
list = eina_list_append(list, &n[i]);
}
for(i = 0; i < SHUFFLE_N; i++)
for (i = 0; i < SHUFFLE_N; i++)
{
list = eina_list_shuffle(list, NULL);
p = eina_list_nth(list, SHUFFLE_SZ/2);
@ -425,7 +425,7 @@ START_TEST(eina_test_shuffle)
}
d = SHUFFLE_SZ/(float)(SHUFFLE_N);
for(i = 0; i < SHUFFLE_SZ; i++)
for (i = 0; i < SHUFFLE_SZ; i++)
{
fail_if(rand_count[i]*d > 1.20f);
fail_if(rand_count[i]*d < 0.80f);
@ -435,6 +435,154 @@ START_TEST(eina_test_shuffle)
}
END_TEST
START_TEST(eina_test_remove_duplicates)
{
int i;
int *p;
int data[] = { 0, 1, 2, 3, 4, 5, 6 };
int result1[] = { 0, 1, 2, 3, 4, 5, 6 };
int result2[] = {2, 3, 4, 1, 6, 5, 0};
Eina_List *list = NULL;
eina_init();
list = eina_list_append(list, &data[0]);
list = eina_list_append(list, &data[1]);
list = eina_list_append(list, &data[1]);
list = eina_list_append(list, &data[2]);
list = eina_list_append(list, &data[3]);
list = eina_list_append(list, &data[4]);
list = eina_list_append(list, &data[1]);
list = eina_list_append(list, &data[5]);
list = eina_list_append(list, &data[6]);
list = eina_list_append(list, &data[5]);
list = eina_list_append(list, &data[0]);
list = eina_list_append(list, &data[0]);
fail_if(eina_list_count(list) != 12);
list = eina_list_remove_duplicates(list, EINA_TRUE);
fail_if(eina_list_count(list) != 7);
for (i = 0; i < 7; i++)
{
p = eina_list_nth(list, i);
fail_if(*p != result1[i]);
}
list = eina_list_free(list);
list = eina_list_append(list, &data[0]);
list = eina_list_append(list, &data[1]);
list = eina_list_append(list, &data[1]);
list = eina_list_append(list, &data[2]);
list = eina_list_append(list, &data[3]);
list = eina_list_append(list, &data[4]);
list = eina_list_append(list, &data[1]);
list = eina_list_append(list, &data[5]);
list = eina_list_append(list, &data[6]);
list = eina_list_append(list, &data[5]);
list = eina_list_append(list, &data[0]);
list = eina_list_append(list, &data[0]);
fail_if(eina_list_count(list) != 12);
list = eina_list_remove_duplicates(list, EINA_FALSE);
fail_if(eina_list_count(list) != 7);
for (i = 0; i < 7; i++)
{
p = eina_list_nth(list, i);
fail_if(*p != result2[i]);
}
list = eina_list_free(list);
eina_shutdown();
}
END_TEST
static Eina_Bool filter_cb(int *data)
{
return ( (*data < 81) ? EINA_TRUE : EINA_FALSE );
}
static void map_cb(int *data)
{
*data = *data * 3;
}
static void reduce_cb(int *data, int *acc)
{
*acc += (*data * 3);
}
START_TEST(eina_test_filter_map_reduce)
{
int i;
int *p;
int sum;
int data[] = { 6, 9, 93, 42, 1, 7, 9, 81, 1664, 1337 };
int result1[] = { 6, 9, 42, 1, 7, 9 };
int result2[] = { 18, 27, 126, 3, 21, 27 };
Eina_List *list = NULL;
Eina_List *l = NULL;
eina_init();
for (i = 0; i < 10; i++)
list = eina_list_append(list, &data[i]);
l = eina_list_filter(list, NULL);
fail_if(eina_list_count(list) != 10);
for (i = 0; i < 10; i++)
{
p = eina_list_nth(l, i);
fail_if(*p != data[i]);
}
l = eina_list_free(l);
l = eina_list_filter(list, EINA_FILTER_CB(filter_cb));
fail_if(eina_list_count(l) != 6);
for (i = 0; i < 6; i++)
{
p = eina_list_nth(l, i);
fail_if(*p != result1[i]);
}
l = eina_list_map(l, EINA_MAP_CB(map_cb));
fail_if(eina_list_count(l) != 6);
for (i = 0; i < 6; i++)
{
p = eina_list_nth(l, i);
fail_if(*p != result2[i]);
}
sum = 0;
l = eina_list_reduce(l, EINA_REDUCE_CB(reduce_cb), &sum);
fail_if(sum != 666);
l = eina_list_free(l);
sum = 0;
l = eina_list_clone(list);
eina_list_filter_map_reduce(l,
EINA_FILTER_CB(filter_cb),
EINA_MAP_CB(map_cb),
EINA_REDUCE_CB(reduce_cb), &sum);
l = eina_list_free(l);
fail_if(sum != 864);
sum = 0;
l = eina_list_clone(list);
eina_list_filter_map_reduce(l,
NULL,
EINA_MAP_CB(map_cb),
EINA_REDUCE_CB(reduce_cb), &sum);
l = eina_list_free(l);
fail_if(sum != 32301);
list = eina_list_free(list);
eina_shutdown();
}
END_TEST
void
eina_test_list(TCase *tc)
{
@ -443,4 +591,6 @@ eina_test_list(TCase *tc)
tcase_add_test(tc, eina_test_sorted_insert);
tcase_add_test(tc, eina_test_list_split);
tcase_add_test(tc, eina_test_shuffle);
tcase_add_test(tc, eina_test_remove_duplicates);
tcase_add_test(tc, eina_test_filter_map_reduce);
}