Sorting Eina_List elements

If you don't know how to create lists see Adding elements to Eina_List.

#include <stdio.h>
#include <string.h>
#include <Eina.h>
int
main(int argc, char **argv)
{
(void)argc;
(void)argv;
Eina_List *list = NULL, *other_list = NULL;
Eina_List *l;
void *data;
int cmp_result;
Eina_Compare_Cb cmp_func = (Eina_Compare_Cb)strcmp;
eina_init();
list = eina_list_append(list, "starbuck");
list = eina_list_append(list, "appolo");
list = eina_list_append(list, "boomer");
Eina.h
Eina Utility library.
eina_list_append
EINA_API Eina_List * eina_list_append(Eina_List *list, const void *data)
Appends the given data to the given linked list.
Definition eina_list.c:584
Eina_List
struct _Eina_List Eina_List
Type for a generic double linked list.
Definition eina_list.h:304
eina_init
EINA_API int eina_init(void)
Initializes the Eina library.
Definition eina_main.c:291
Eina_Compare_Cb
int(* Eina_Compare_Cb)(const void *data1, const void *data2)
Function used in functions using sorting.
Definition eina_types.h:548

This is the code we have already seen to create a list. Now if we need to search the list we can do it like this:

data = eina_list_search_unsorted(list, cmp_func, "boomer");
l = eina_list_search_unsorted_list(list, cmp_func, "boomer");
if (l->data != data)
return 1;
eina_list_search_unsorted
EINA_API void * eina_list_search_unsorted(const Eina_List *list, Eina_Compare_Cb func, const void *data)
Returns node data if it is in the unsorted list.
Definition eina_list.c:1565
eina_list_search_unsorted_list
EINA_API Eina_List * eina_list_search_unsorted_list(const Eina_List *list, Eina_Compare_Cb func, const void *data)
Returns node if data is in the unsorted list.
Definition eina_list.c:1549
_Eina_List::data
void * data
Pointer to list element payload.
Definition eina_list.h:319

However if searching the list multiple times it probably is better to sort the list since the sorted_search functions are much faster:

list = eina_list_sort(list, 0, cmp_func);
data = eina_list_search_sorted(list, cmp_func, "starbuck");
l = eina_list_search_sorted_list(list, cmp_func, "starbuck");
if (l->data != data)
return 1;
eina_list_search_sorted
EINA_API void * eina_list_search_sorted(const Eina_List *list, Eina_Compare_Cb func, const void *data)
Returns node data if it is in the sorted list.
Definition eina_list.c:1541
eina_list_sort
EINA_API Eina_List * eina_list_sort(Eina_List *list, unsigned int limit, Eina_Compare_Cb func)
Sorts a list according to the ordering func will return.
Definition eina_list.c:1112
eina_list_search_sorted_list
EINA_API Eina_List * eina_list_search_sorted_list(const Eina_List *list, Eina_Compare_Cb func, const void *data)
Returns node if data is in the sorted list.
Definition eina_list.c:1522

Once the list is sorted it's not a good idea to use append/prepend functions since that would add the element in the wrong place, instead elements should be added with eina_list_sorted_insert():

list = eina_list_sorted_insert(list, cmp_func, "helo");
eina_list_sorted_insert
EINA_API Eina_List * eina_list_sorted_insert(Eina_List *list, Eina_Compare_Cb func, const void *data)
Inserts a new node into a sorted list.
Definition eina_list.c:757

A noteworthy use case is adding an element to a list only if it doesn't exist already, this can accomplished by searching for the element that is closest to what is being added, and if that doesn't match add:

l = eina_list_search_sorted_near_list(list, cmp_func, "hera", &cmp_result);
if (cmp_result > 0)
list = eina_list_prepend_relative_list(list, "hera", l);
else if (cmp_result < 0)
list = eina_list_append_relative_list(list, "hera", l);
eina_list_search_sorted_near_list
EINA_API Eina_List * eina_list_search_sorted_near_list(const Eina_List *list, Eina_Compare_Cb func, const void *data, int *result_cmp)
Returns node nearest to data from the sorted list.
Definition eina_list.c:1439
eina_list_append_relative_list
EINA_API Eina_List * eina_list_append_relative_list(Eina_List *list, const void *data, Eina_List *relative)
Appends a list node to a linked list after the specified member.
Definition eina_list.c:670
eina_list_prepend_relative_list
EINA_API Eina_List * eina_list_prepend_relative_list(Eina_List *list, const void *data, Eina_List *relative)
Prepends a list node to a linked list before the specified member.
Definition eina_list.c:724

Note
  eina_list_search_sorted_near_list() will tell you not only the nearest node to what was searched for but how it compares to your term, this way it is easy to know if you have to add before or after that node.

It is sometimes useful to get a portion of the list as another list, here we take every element that comes after "boomer" and split it into "other_list":

l = eina_list_search_sorted_list(list, cmp_func, "boomer");
list = eina_list_split_list(list, l, &other_list);
eina_list_split_list
EINA_API Eina_List * eina_list_split_list(Eina_List *list, Eina_List *relative, Eina_List **right)
Splits a list into 2 lists.
Definition eina_list.c:1316

It is also possible to add entire lists of elements using eina_list_sorted_merge():

other_list = eina_list_sort(other_list, 0, cmp_func);
list = eina_list_sorted_merge(list, other_list, cmp_func);
eina_list_sorted_merge
EINA_API Eina_List * eina_list_sorted_merge(Eina_List *left, Eina_List *right, Eina_Compare_Cb func)
Merges two sorted list according to the ordering func will return.
Definition eina_list.c:1362

And as always release memory and shutdown eina before ending:

eina_list_free(list);
eina_shutdown();
return 0;
}
eina_list_free
EINA_API Eina_List * eina_list_free(Eina_List *list)
Frees an entire list and all the nodes, ignoring the data contained.
Definition eina_list.c:823
eina_shutdown
EINA_API int eina_shutdown(void)
Shuts down the Eina library.
Definition eina_main.c:379

The full source code can be found on the examples folder on the eina_list_02.c file.