Eina_Inlist advanced usage - multi-inlists

This example describes the usage of multiple inlists storing the same data. It means that some data may appear in more than one inlist at the same time. We will demonstrate this by creating an inlist with 100 numbers, and adding the odd numbers to the second inlist, then remove the numbers divisible by 3 from the second list.

To accomplish this, it is necessary to have two inlist pointers in the struct that is going to be stored. We are using the default inlist member EINA_INLIST, and adding another member `even` that is of type Eina_Inlist too:

struct my_struct {
EINA_INLIST;
Eina_Inlist even;
int a, b;
};
EINA_INLIST
#define EINA_INLIST
Used for declaring an inlist member in a struct.
Definition eina_inlist.h:411
Eina_Inlist
struct _Eina_Inlist Eina_Inlist
Inlined list type.
Definition eina_inlist.h:391

The representation for this struct is:

And we will define some convenience macros that are equivalent to EINA_INLIST_GET and EINA_INLIST_CONTAINER_GET :

#define EVEN_INLIST_GET(Inlist) (& ((Inlist)->even))
#define EVEN_INLIST_CONTAINER_GET(ptr, type) \
((type *)((char *)ptr - offsetof(type, even)))

We need two pointers, one for each list, and a pointer that will be used as an iterator:

Eina_Inlist *list = NULL, *list_even = NULL, *itr;

Now we allocate and add to the first list every number from 0 to 99. These nodes data also have the Eina_Inlist node info for the second list (`even`). We will use them to add just the even numbers to the second list, the `list_even`. Also notice that we are using our macro `EVEN_INLIST_GET` to get the pointer to the even list node info:

for (i = 0; i < 100; i++)
{
d = malloc(sizeof(*d));
d->a = i;
d->b = i * 10;
list = eina_inlist_append(list, EINA_INLIST_GET(d));
if ((i % 2) == 0)
list_even = eina_inlist_prepend(list_even, EVEN_INLIST_GET(d));
}
eina_inlist_prepend
EINA_API Eina_Inlist * eina_inlist_prepend(Eina_Inlist *list, Eina_Inlist *new_l)
Adds a new node to beginning of list.
Definition eina_inlist.c:254
EINA_INLIST_GET
#define EINA_INLIST_GET(Inlist)
Utility macro to get the inlist object of a struct.
Definition eina_inlist.h:413
eina_inlist_append
EINA_API Eina_Inlist * eina_inlist_append(Eina_Inlist *list, Eina_Inlist *new_l)
Adds a new node to end of a list.
Definition eina_inlist.c:227

And the resulting lists will be as follow:

For the first list, we can use the macro EINA_INLIST_FOREACH to iterate over its elements:

EINA_INLIST_FOREACH(list, cur)
printf("\ta=%d, b=%d\n", cur->a, cur->b);
EINA_INLIST_FOREACH
#define EINA_INLIST_FOREACH(list, it)
Definition eina_inlist.h:832

But for the second list, we have to do it manually. Of course we could create a similar macro to EINA_INLIST_FOREACH, but since this macro is more complex than the other two and we are using it only once, it's better to just do it manually:

for (itr = list_even; itr != NULL; itr = itr->next)
{
cur = EVEN_INLIST_CONTAINER_GET(itr, struct my_struct);
printf("\ta=%d, b=%d\n", cur->a, cur->b);
}

Let's just check that the two lists have the expected number of elements:

printf("list count=%d\n", eina_inlist_count(list));
printf("list_even count=%d\n\n", eina_inlist_count(list_even));
eina_inlist_count
EINA_API unsigned int eina_inlist_count(const Eina_Inlist *list)
Gets the count of the number of items in a list.
Definition eina_inlist.c:448

And removing the numbers divisible by 3 only from the second list:

itr = list_even;
while (itr)
{
Eina_Inlist *next = itr->next;
cur = EVEN_INLIST_CONTAINER_GET(itr, struct my_struct);
if ((cur->a % 3) == 0)
list_even = eina_inlist_remove(list_even, itr);
itr = next;
}
printf("list count=%d\n", eina_inlist_count(list));
printf("list_even count=%d\n\n", eina_inlist_count(list_even));
eina_inlist_remove
EINA_API Eina_Inlist * eina_inlist_remove(Eina_Inlist *list, Eina_Inlist *item)
Removes node from list.
Definition eina_inlist.c:335

Now that we don't need the two lists anymore, we can just free all the items. Since all of the allocated data was put into the first list, and both lists are made of pointers to inside the data structures, we can free only the first list (that contains all the elements) and the second list will be gone with it:

while (list)
{
struct my_struct *aux = EINA_INLIST_CONTAINER_GET(list,
struct my_struct);
list = eina_inlist_remove(list, list);
free(aux);
EINA_INLIST_CONTAINER_GET
#define EINA_INLIST_CONTAINER_GET(ptr, type)
Utility macro to get the container object of an inlist.
Definition eina_inlist.h:415

To see the full source code for this example, click here: eina_inlist_03.c Eina_Inlist advanced usage - multi-inlists source