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 {
int a, b;
};
#define EINA_INLIST
Used for declaring an inlist member in a struct.
Definition: eina_inlist.h:411
Inlined list type.
Definition: eina_inlist.h:405

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;
if ((i % 2) == 0)
list_even = eina_inlist_prepend(list_even, EVEN_INLIST_GET(d));
}
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
#define EINA_INLIST_GET(Inlist)
Utility macro to get the inlist object of a struct.
Definition: eina_inlist.h:413
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:

printf("\ta=%d, b=%d\n", cur->a, cur->b);
#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_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_API Eina_Inlist * eina_inlist_remove(Eina_Inlist *list, Eina_Inlist *item)
Removes node from list.
Definition: eina_inlist.c:335
Eina_Inlist * next
next node
Definition: eina_inlist.h:406

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