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;
};

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

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

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

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

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

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

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
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
Inlined list type.
Definition: eina_inlist.h:405
EINA_INLIST_FOREACH
#define EINA_INLIST_FOREACH(list, it)
Definition: eina_inlist.h:832
eina_inlist_append
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
eina_inlist_prepend
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_remove
Eina_Inlist * eina_inlist_remove(Eina_Inlist *list, Eina_Inlist *item)
Removes node from list.
Definition: eina_inlist.c:335
eina_inlist_count
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
_Eina_Inlist::next
Eina_Inlist * next
next node
Definition: eina_inlist.h:406
EINA_INLIST
#define EINA_INLIST
Used for declaring an inlist member in a struct.
Definition: eina_inlist.h:411