eina: Add detailed description and some examples to Eina_Inlist.
SVN revision: 60310
After Width: | Height: | Size: 8.7 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 7.6 KiB |
After Width: | Height: | Size: 9.9 KiB |
After Width: | Height: | Size: 25 KiB |
|
@ -20,7 +20,10 @@ SRCS = \
|
||||||
eina_list_01.c \
|
eina_list_01.c \
|
||||||
eina_list_02.c \
|
eina_list_02.c \
|
||||||
eina_list_03.c \
|
eina_list_03.c \
|
||||||
eina_list_04.c
|
eina_list_04.c \
|
||||||
|
eina_inlist_01.c \
|
||||||
|
eina_inlist_02.c \
|
||||||
|
eina_inlist_03.c
|
||||||
|
|
||||||
pkglib_PROGRAMS =
|
pkglib_PROGRAMS =
|
||||||
|
|
||||||
|
@ -40,6 +43,9 @@ pkglib_PROGRAMS += \
|
||||||
eina_list_01 \
|
eina_list_01 \
|
||||||
eina_list_02 \
|
eina_list_02 \
|
||||||
eina_list_03 \
|
eina_list_03 \
|
||||||
eina_list_04
|
eina_list_04 \
|
||||||
|
eina_inlist_01 \
|
||||||
|
eina_inlist_02 \
|
||||||
|
eina_inlist_03
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
// Compile with:
|
||||||
|
// gcc -g `pkg-config --cflags --libs eina` eina_inlist_01.c -o eina_inlist_01
|
||||||
|
#include <Eina.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
struct my_struct {
|
||||||
|
EINA_INLIST;
|
||||||
|
int a, b;
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
sort_cb(const void *d1, const void *d2)
|
||||||
|
{
|
||||||
|
const Eina_Inlist *l1, *l2;
|
||||||
|
const struct my_struct *x1, *x2;
|
||||||
|
|
||||||
|
l1 = d1;
|
||||||
|
l2 = d2;
|
||||||
|
|
||||||
|
x1 = EINA_INLIST_CONTAINER_GET(l1, struct my_struct);
|
||||||
|
x2 = EINA_INLIST_CONTAINER_GET(l2, struct my_struct);
|
||||||
|
|
||||||
|
return x1->a - x2->a;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
struct my_struct *d, *cur;
|
||||||
|
Eina_Inlist *list, *itr, *tmp;
|
||||||
|
|
||||||
|
eina_init();
|
||||||
|
|
||||||
|
d = malloc(sizeof(*d));
|
||||||
|
d->a = 1;
|
||||||
|
d->b = 10;
|
||||||
|
list = eina_inlist_append(NULL, EINA_INLIST_GET(d));
|
||||||
|
|
||||||
|
d = malloc(sizeof(*d));
|
||||||
|
d->a = 2;
|
||||||
|
d->b = 20;
|
||||||
|
list = eina_inlist_append(list, EINA_INLIST_GET(d));
|
||||||
|
|
||||||
|
d = malloc(sizeof(*d));
|
||||||
|
d->a = 3;
|
||||||
|
d->b = 30;
|
||||||
|
list = eina_inlist_prepend(list, EINA_INLIST_GET(d));
|
||||||
|
|
||||||
|
printf("list=%p\n", list);
|
||||||
|
EINA_INLIST_FOREACH(list, cur)
|
||||||
|
printf("\ta=%d, b=%d\n", cur->a, cur->b);
|
||||||
|
|
||||||
|
list = eina_inlist_promote(list, EINA_INLIST_GET(d));
|
||||||
|
|
||||||
|
d = malloc(sizeof(*d));
|
||||||
|
d->a = 4;
|
||||||
|
d->b = 40;
|
||||||
|
list = eina_inlist_append_relative(list, EINA_INLIST_GET(d), list);
|
||||||
|
|
||||||
|
list = eina_inlist_demote(list, EINA_INLIST_GET(d));
|
||||||
|
|
||||||
|
list = eina_inlist_sort(list, sort_cb);
|
||||||
|
|
||||||
|
printf("list after sort=%p\n", list);
|
||||||
|
EINA_INLIST_FOREACH(list, cur)
|
||||||
|
printf("\ta=%d, b=%d\n", cur->a, cur->b);
|
||||||
|
|
||||||
|
tmp = eina_inlist_find(list, EINA_INLIST_GET(d));
|
||||||
|
if (tmp)
|
||||||
|
cur = EINA_INLIST_CONTAINER_GET(tmp, struct my_struct);
|
||||||
|
else
|
||||||
|
cur = NULL;
|
||||||
|
|
||||||
|
if (d != cur)
|
||||||
|
printf("wrong node! cur=%p\n", cur);
|
||||||
|
|
||||||
|
list = eina_inlist_remove(list, EINA_INLIST_GET(d));
|
||||||
|
free(d);
|
||||||
|
printf("list=%p\n", list);
|
||||||
|
for (itr = list; itr != NULL; itr = itr->next)
|
||||||
|
{
|
||||||
|
cur = EINA_INLIST_CONTAINER_GET(itr, struct my_struct);
|
||||||
|
printf("\ta=%d, b=%d\n", cur->a, cur->b);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (list)
|
||||||
|
{
|
||||||
|
Eina_Inlist *aux = list;
|
||||||
|
list = eina_inlist_remove(list, list);
|
||||||
|
free(aux);
|
||||||
|
}
|
||||||
|
|
||||||
|
eina_shutdown();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
// Compile with:
|
||||||
|
// gcc -g `pkg-config --cflags --libs eina` eina_inlist_01.c -o eina_inlist_01
|
||||||
|
#include <Eina.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
struct my_struct {
|
||||||
|
EINA_INLIST;
|
||||||
|
int a, b;
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
struct my_struct *d, *cur;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
Eina_Inlist *inlist = NULL;
|
||||||
|
Eina_List *list = NULL, *l_itr, *l_next;
|
||||||
|
|
||||||
|
eina_init();
|
||||||
|
|
||||||
|
for (i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
d = malloc(sizeof(*d));
|
||||||
|
d->a = i;
|
||||||
|
d->b = i * 10;
|
||||||
|
inlist = eina_inlist_append(inlist, EINA_INLIST_GET(d));
|
||||||
|
if ((i % 2) == 0)
|
||||||
|
list = eina_list_prepend(list, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("inlist=%p\n", inlist);
|
||||||
|
EINA_INLIST_FOREACH(inlist, cur)
|
||||||
|
printf("\ta=%d, b=%d\n", cur->a, cur->b);
|
||||||
|
|
||||||
|
printf("list=%p\n", list);
|
||||||
|
EINA_LIST_FOREACH(list, l_itr, cur)
|
||||||
|
printf("\ta=%d, b=%d\n", cur->a, cur->b);
|
||||||
|
|
||||||
|
printf("inlist count=%d\n", eina_inlist_count(inlist));
|
||||||
|
printf("list count=%d\n\n", eina_list_count(list));
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH_SAFE(list, l_itr, l_next, cur)
|
||||||
|
{
|
||||||
|
if ((cur->a % 3) == 0)
|
||||||
|
list = eina_list_remove_list(list, l_itr);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("inlist count=%d\n", eina_inlist_count(inlist));
|
||||||
|
printf("list count=%d\n\n", eina_list_count(list));
|
||||||
|
|
||||||
|
eina_list_free(list);
|
||||||
|
|
||||||
|
while (inlist)
|
||||||
|
{
|
||||||
|
Eina_Inlist *aux = inlist;
|
||||||
|
inlist = eina_inlist_remove(inlist, inlist);
|
||||||
|
free(aux);
|
||||||
|
}
|
||||||
|
|
||||||
|
eina_shutdown();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
// Compile with:
|
||||||
|
// gcc -g `pkg-config --cflags --libs eina` eina_inlist_01.c -o eina_inlist_01
|
||||||
|
#include <Eina.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
struct my_struct {
|
||||||
|
EINA_INLIST;
|
||||||
|
Eina_Inlist even;
|
||||||
|
int a, b;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EVEN_INLIST_GET(Inlist) (& ((Inlist)->even))
|
||||||
|
|
||||||
|
#define EVEN_INLIST_CONTAINER_GET(ptr, type) \
|
||||||
|
((type *)((char *)ptr - offsetof(type, even)))
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
struct my_struct *d, *cur;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
Eina_Inlist *list = NULL, *list_even = NULL, *itr;
|
||||||
|
|
||||||
|
eina_init();
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("list=%p\n", list);
|
||||||
|
EINA_INLIST_FOREACH(list, cur)
|
||||||
|
printf("\ta=%d, b=%d\n", cur->a, cur->b);
|
||||||
|
|
||||||
|
printf("list_even=%p\n", list_even);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("list count=%d\n", eina_inlist_count(list));
|
||||||
|
printf("list_even count=%d\n\n", eina_inlist_count(list_even));
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
while (list)
|
||||||
|
{
|
||||||
|
Eina_Inlist *aux = list;
|
||||||
|
list = eina_inlist_remove(list, list);
|
||||||
|
free(aux);
|
||||||
|
}
|
||||||
|
|
||||||
|
eina_shutdown();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -24,6 +24,260 @@
|
||||||
#include "eina_accessor.h"
|
#include "eina_accessor.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page inlist_01_example_page Eina_Inlist basic usage
|
||||||
|
* @dontinclude eina_inlist_01.c
|
||||||
|
*
|
||||||
|
* To see the full source for this example, click here: @ref
|
||||||
|
* eina_inlist_01_c
|
||||||
|
*
|
||||||
|
* As explained before, inline lists mean its nodes pointers are part of same
|
||||||
|
* memory block/blob. This is done by using the macro @ref EINA_INLIST inside the
|
||||||
|
* data structure that will be used:
|
||||||
|
*
|
||||||
|
* @skip struct
|
||||||
|
* @until };
|
||||||
|
*
|
||||||
|
* The resulting node representing this struct can be exemplified by the
|
||||||
|
* following picture:
|
||||||
|
*
|
||||||
|
* @image html eina_inlist-node_eg1-my-struct.png
|
||||||
|
* @image rtf eina_inlist-node_eg1-my-struct.png
|
||||||
|
*
|
||||||
|
* Let's define a comparison function that will be used later during the
|
||||||
|
* sorting of the list:
|
||||||
|
*
|
||||||
|
* @skip int
|
||||||
|
* @until }
|
||||||
|
*
|
||||||
|
* The @ref Eina_Inlist can be used exactly the same way as @ref Eina_List when
|
||||||
|
* appending, prepend and removing items. But since we already have the node
|
||||||
|
* pointers inside the structure, they need to be retrieved with the macro @ref
|
||||||
|
* EINA_INLIST_GET :
|
||||||
|
*
|
||||||
|
* @skip malloc
|
||||||
|
* @until append
|
||||||
|
*
|
||||||
|
* Notice that @ref eina_inlist_append always receives the head of the list as
|
||||||
|
* first argument, and its return value should be used as the list pointer
|
||||||
|
* (head):
|
||||||
|
*
|
||||||
|
* @skip malloc
|
||||||
|
* @until append
|
||||||
|
*
|
||||||
|
* After appending 3 items, the list now should look similar to this:
|
||||||
|
*
|
||||||
|
* @image html eina_inlist-node_eg1-inlist.png
|
||||||
|
* @image rtf eina_inlist-node_eg1-inlist.png
|
||||||
|
*
|
||||||
|
* The macro @ref EINA_INLIST_FOREACH can be used to iterate over the list:
|
||||||
|
*
|
||||||
|
* @skip printf
|
||||||
|
* @until cur->a
|
||||||
|
*
|
||||||
|
* @ref eina_inlist_promote(), @ref eina_inlist_demote(), @ref
|
||||||
|
* eina_inlist_append_relative() and similar functions all work in the same way
|
||||||
|
* as the @ref Eina_List :
|
||||||
|
*
|
||||||
|
* @skip eina_inlist_promote
|
||||||
|
* @until eina_inlist_demote
|
||||||
|
*
|
||||||
|
* Now let's use the @c sort_cb function declared above to sort our list:
|
||||||
|
*
|
||||||
|
* @skipline eina_inlist_sort
|
||||||
|
*
|
||||||
|
* Removing an element from the inlist is also similar to @ref Eina_List :
|
||||||
|
*
|
||||||
|
* @skip inlist_remove
|
||||||
|
* @until free
|
||||||
|
*
|
||||||
|
* Another way of walking through the inlist.
|
||||||
|
*
|
||||||
|
* @skip for
|
||||||
|
* @until }
|
||||||
|
*
|
||||||
|
* Notice that in the previous piece of code, since we only have the pointers to
|
||||||
|
* the inlist nodes, we have to use the @ref EINA_INLIST_CONTAINER_GET macro
|
||||||
|
* that will return the pointer to the entire structure. Of course, in this case
|
||||||
|
* it is the same as the list pointer, since the @ref EINA_INLIST macro was used
|
||||||
|
* in the beginning of the structure.
|
||||||
|
*
|
||||||
|
* Now to finish this example, lets delete this list:
|
||||||
|
*
|
||||||
|
* @skip while
|
||||||
|
* @until }
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page inlist_02_example_page Eina_Inlist advanced usage - lists and inlists
|
||||||
|
* @dontinclude eina_inlist_02.c
|
||||||
|
*
|
||||||
|
* This example describes the usage of @ref Eina_Inlist mixed with @ref
|
||||||
|
* Eina_List . We create and add elements to an inlist, and the even members
|
||||||
|
* are also added to a normal list. Later we remove the elements divisible by 3
|
||||||
|
* from this normal list.
|
||||||
|
*
|
||||||
|
* The struct that is going to be used is the same used in @ref
|
||||||
|
* inlist_01_example_page , since we still need the @ref EINA_INLIST macro to
|
||||||
|
* declare the inlist node info:
|
||||||
|
*
|
||||||
|
* @skip struct
|
||||||
|
* @until };
|
||||||
|
*
|
||||||
|
* The resulting node representing this struct can be exemplified by the
|
||||||
|
* following picture:
|
||||||
|
*
|
||||||
|
* @image html eina_inlist-node_eg2-my-struct.png
|
||||||
|
* @image rtf eina_inlist-node_eg2-my-struct.png
|
||||||
|
*
|
||||||
|
* Now we need some pointers and auxiliar variables that will help us iterate on
|
||||||
|
* the lists:
|
||||||
|
*
|
||||||
|
* @skip struct
|
||||||
|
* @until l_next;
|
||||||
|
*
|
||||||
|
* Allocating 100 elements and putting them into an inlist, and the even
|
||||||
|
* elements also go to the normal list:
|
||||||
|
*
|
||||||
|
* @skip for
|
||||||
|
* @until }
|
||||||
|
*
|
||||||
|
* After this point, what we have are two distinct lists that share some
|
||||||
|
* elements. The first list (inlist) is defined by the pointers inside the
|
||||||
|
* elements data structure, while the second list (normal list) has its own node
|
||||||
|
* data structure that is kept outside of the elements.
|
||||||
|
*
|
||||||
|
* The two lists, sharing some elements, can be represented by the following
|
||||||
|
* picture:
|
||||||
|
*
|
||||||
|
* <img src="eina_inlist-node_eg2-list-inlist.png" width="100%"/>
|
||||||
|
* @image rtf eina_inlist-node_eg2-list-inlist.png
|
||||||
|
*
|
||||||
|
* Accessing both lists is done normally, as if they didn't have any elements in
|
||||||
|
* common:
|
||||||
|
*
|
||||||
|
* @skip printf
|
||||||
|
* @until eina_list_count
|
||||||
|
*
|
||||||
|
* We can remove elements from the normal list, but we just don't free them
|
||||||
|
* because they are still stored in the inlist:
|
||||||
|
*
|
||||||
|
* @skip EINA_LIST_FOREACH_SAFE
|
||||||
|
* @until eina_list_count
|
||||||
|
*
|
||||||
|
* To finish this example, we want to free both lists, we can't just free all
|
||||||
|
* elements on the second list (normal list) because they are still being used
|
||||||
|
* in the inlist. So we first discard the normal list without freeing its
|
||||||
|
* elements, then we free all elements in the inlist (that contains all elements
|
||||||
|
* allocated until now):
|
||||||
|
*
|
||||||
|
* @skip eina_list_free
|
||||||
|
* @until }
|
||||||
|
*
|
||||||
|
* Here is the full source code for this example: @ref eina_inlist_02_c
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page inlist_03_example_page Eina_Inlist advanced usage - multi-inlists
|
||||||
|
* @dontinclude eina_inlist_03.c
|
||||||
|
*
|
||||||
|
* 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 @ref
|
||||||
|
* EINA_INLIST, and adding another member @c even that is of type @ref
|
||||||
|
* Eina_Inlist too:
|
||||||
|
*
|
||||||
|
* @skip struct
|
||||||
|
* @until };
|
||||||
|
*
|
||||||
|
* The representation for this struct is:
|
||||||
|
*
|
||||||
|
* @image html eina_inlist-node_eg3-my-struct.png
|
||||||
|
* @image rtf eina_inlist-node_eg3-my-struct.png
|
||||||
|
*
|
||||||
|
* And we will define some convenience macros that are equivalent to @ref
|
||||||
|
* EINA_INLIST_GET and @ref EINA_INLIST_CONTAINER_GET :
|
||||||
|
*
|
||||||
|
* @skip define
|
||||||
|
* @until offsetof
|
||||||
|
*
|
||||||
|
* We need two pointers, one for each list, and a pointer that will be used as
|
||||||
|
* an iterator:
|
||||||
|
*
|
||||||
|
* @skipline Eina_Inlist
|
||||||
|
*
|
||||||
|
* Now we allocate and add to the first list every number from 0 to 99. These
|
||||||
|
* nodes data also have the @ref Eina_Inlist node info for the second list (@c
|
||||||
|
* even). We will use them to add just the even numbers to the second list, the
|
||||||
|
* @c list_even. Also notice that we are using our macro @c EVEN_INLIST_GET to
|
||||||
|
* get the pointer to the even list node info:
|
||||||
|
*
|
||||||
|
* @skip for
|
||||||
|
* @until }
|
||||||
|
*
|
||||||
|
* And the resulting lists will be as follow:
|
||||||
|
*
|
||||||
|
* <img src="eina_inlist-node_eg3-two-inlists.png" width="100%"/>
|
||||||
|
* @image rtf eina_inlist-node_eg3-two-inlists.png
|
||||||
|
*
|
||||||
|
* For the first list, we can use the macro @ref EINA_INLIST_FOREACH to iterate
|
||||||
|
* over its elements:
|
||||||
|
*
|
||||||
|
* @skip FOREACH
|
||||||
|
* @until printf
|
||||||
|
*
|
||||||
|
* But for the second list, we have to do it manually. Of course we could create
|
||||||
|
* a similar macro to @ref 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:
|
||||||
|
*
|
||||||
|
* @skip for
|
||||||
|
* @until }
|
||||||
|
*
|
||||||
|
* Let's just check that the two lists have the expected number of elements:
|
||||||
|
*
|
||||||
|
* @skip list count
|
||||||
|
* @until list_even count
|
||||||
|
*
|
||||||
|
* And removing the numbers divisible by 3 only from the second list:
|
||||||
|
*
|
||||||
|
* @skip itr
|
||||||
|
* @until list_even count
|
||||||
|
*
|
||||||
|
* 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:
|
||||||
|
*
|
||||||
|
* @skip while
|
||||||
|
* @until free
|
||||||
|
*
|
||||||
|
* To see the full source code for this example, click here: @ref
|
||||||
|
* eina_inlist_03_c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page eina_inlist_01_c eina_inlist_01.c
|
||||||
|
* @include eina_inlist_01.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page eina_inlist_02_c eina_inlist_02.c
|
||||||
|
* @include eina_inlist_02.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @page eina_inlist_03_c eina_inlist_03.c
|
||||||
|
* @include eina_inlist_03.c
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup Eina_Inline_List_Group Inline List
|
* @addtogroup Eina_Inline_List_Group Inline List
|
||||||
*
|
*
|
||||||
|
@ -31,10 +285,14 @@
|
||||||
*
|
*
|
||||||
* Inline lists mean its nodes pointers are part of same memory as
|
* Inline lists mean its nodes pointers are part of same memory as
|
||||||
* data. This has the benefit of fragmenting memory less and avoiding
|
* data. This has the benefit of fragmenting memory less and avoiding
|
||||||
* @c node->data indirection, but has the drawback of elements only
|
* @c node->data indirection, but has the drawback of higher cost for some
|
||||||
* being able to be part of one single inlist at same time. But it is
|
* common operations like count and sort.
|
||||||
* possible to have inlist nodes to be part of regular lists created
|
*
|
||||||
* with eina_list_append() or eina_list_prepend().
|
* It is possible to have inlist nodes to be part of regular lists, created with
|
||||||
|
* @ref eina_list_append() or @ref eina_list_prepend(). It's also possible to
|
||||||
|
* have a structure with two inlist pointers, thus be part of two different
|
||||||
|
* inlists at the same time, but the current convenience macros provided won't
|
||||||
|
* work for both of them. Consult @ref inlist_advanced for more info.
|
||||||
*
|
*
|
||||||
* Inline lists have their purposes, but if you don't know what those purposes are, go with
|
* Inline lists have their purposes, but if you don't know what those purposes are, go with
|
||||||
* regular lists instead.
|
* regular lists instead.
|
||||||
|
@ -46,61 +304,62 @@
|
||||||
* This lets the compiler to do type checking and let the programmer know
|
* This lets the compiler to do type checking and let the programmer know
|
||||||
* exactly what type this list is.
|
* exactly what type this list is.
|
||||||
*
|
*
|
||||||
* @code
|
* A simple example demonstrating the basic usage of an inlist can be found
|
||||||
* #include <Eina.h>
|
* here: @ref inlist_01_example_page
|
||||||
* #include <stdio.h>
|
|
||||||
*
|
*
|
||||||
* int
|
* @section inlist_algo Algorithm
|
||||||
* main(void)
|
|
||||||
* {
|
|
||||||
* struct my_struct {
|
|
||||||
* EINA_INLIST;
|
|
||||||
* int a, b;
|
|
||||||
* } *d, *cur;
|
|
||||||
* Eina_Inlist *list, *itr;
|
|
||||||
*
|
*
|
||||||
* eina_init();
|
* The basic structure can be represented by the following picture:
|
||||||
*
|
*
|
||||||
* d = malloc(sizeof(*d));
|
* @image html eina_inlist-node.png
|
||||||
* d->a = 1;
|
* @image rtf eina_inlist-node.png
|
||||||
* d->b = 10;
|
|
||||||
* list = eina_inlist_append(NULL, EINA_INLIST_GET(d));
|
|
||||||
*
|
*
|
||||||
* d = malloc(sizeof(*d));
|
* One data structure will also have the node information, with three pointers:
|
||||||
* d->a = 2;
|
* @a prev, @a next and @a last. The @a last pointer is just valid for the first
|
||||||
* d->b = 20;
|
* element (the list head), otherwise each insertion in the list would have to
|
||||||
* list = eina_inlist_append(list, EINA_INLIST_GET(d));
|
* be done updating every node with the correct pointer. This means that it's
|
||||||
|
* always very important to keep a pointer to the first element of the list,
|
||||||
|
* since it is the only one that has the correct information to allow a proper
|
||||||
|
* O(1) append to the list.
|
||||||
*
|
*
|
||||||
* d = malloc(sizeof(*d));
|
* @section inlist_perf Performance
|
||||||
* d->a = 3;
|
|
||||||
* d->b = 30;
|
|
||||||
* list = eina_inlist_prepend(list, EINA_INLIST_GET(d));
|
|
||||||
*
|
*
|
||||||
* printf("list=%p\n", list);
|
* Due to the nature of the inlist, there's no accounting information, and no
|
||||||
* EINA_INLIST_FOREACH(list, cur)
|
* easy access to the last element from each list node. This means that @ref
|
||||||
* printf("\ta=%d, b=%d\n", cur->a, cur->b);
|
* eina_inlist_count() is order-N, while @ref eina_list_count() is order-1 (constant
|
||||||
|
* time).
|
||||||
*
|
*
|
||||||
* list = eina_inlist_remove(list, EINA_INLIST_GET(d));
|
* For the same reasons, @ref eina_inlist_sort() is slower than @ref
|
||||||
* free(d);
|
* eina_list_sort() . If the list is intended to have faster access, be
|
||||||
* printf("list=%p\n", list);
|
* sorted/merged frequently, or needs to have other complex operations, consider
|
||||||
* for (itr = list; itr != NULL; itr = itr->next)
|
* using @ref Eina_List instead.
|
||||||
* {
|
|
||||||
* cur = EINA_INLIST_CONTAINER_GET(itr, struct my_struct);
|
|
||||||
* printf("\ta=%d, b=%d\n", cur->a, cur->b);
|
|
||||||
* }
|
|
||||||
*
|
*
|
||||||
* while (list)
|
* @section inlist_advanced Advanced Usage
|
||||||
* {
|
|
||||||
* Eina_Inlist *aux = list;
|
|
||||||
* list = eina_inlist_remove(list, list);
|
|
||||||
* free(aux);
|
|
||||||
* }
|
|
||||||
*
|
*
|
||||||
* eina_shutdown();
|
* The basic usage considers a struct that will have the user data, and also
|
||||||
|
* have an inlist node information (prev, next and last pointers) created with
|
||||||
|
* @ref EINA_INLIST during the struct declaration. This allows one to use the
|
||||||
|
* convenience macros @ref EINA_INLIST_GET(), @ref EINA_INLIST_CONTAINER_GET(),
|
||||||
|
* @ref EINA_INLIST_FOREACH() and so. This happens because the @ref EINA_INLIST
|
||||||
|
* macro declares a struct member with the name @a __inlist, and all the other
|
||||||
|
* macros assume that this struct member has this name.
|
||||||
*
|
*
|
||||||
* return 0;
|
* It may be the case that someone needs to have some inlist nodes added to a
|
||||||
* }
|
* @ref Eina_List too. If this happens, the inlist nodes can be added to the
|
||||||
* @endcode
|
* @ref Eina_List without any problems. This example demonstrates this case:
|
||||||
|
* @ref inlist_02_example_page
|
||||||
|
*
|
||||||
|
* It's also possible to have some data that is part of two different inlists.
|
||||||
|
* If this is the case, then it won't be possible to use the convenience macros
|
||||||
|
* to both of the lists. It will be necessary to create a new set of macros that
|
||||||
|
* will allow access to the second list node info. An example for this usage can
|
||||||
|
* be found here:
|
||||||
|
* @ref inlist_03_example_page
|
||||||
|
*
|
||||||
|
* List of examples:
|
||||||
|
* @li @ref inlist_01_example_page
|
||||||
|
* @li @ref inlist_02_example_page
|
||||||
|
* @li @ref inlist_03_example_page
|
||||||
*
|
*
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|