An array is a data type which describes an ordered collection of values. The values are accessed by their index.
INDEX | VALUE -------------- 0 | value0 1 | value1 2 | value2 3 | value3 4 | value4 5 | value5 6 | value6 7 | value7
Eina provides 2 array types: the classic array and an inline array.
The eina_array_new()
function creates a new array. You can store strings or
objects in the created array. The function returns a new array, or if memory
allocation fails, NULL
.
The first parameter of the eina_array_new()
function defines the size of
the array allocation step. For example, if you set it to 4, the function
returns an array of 4 elements and the next time you grow the array it grows
by 4 elements. Unless you have pushed 4 elements inside, it does not grow. But
once you add the 5th element, it grows again and becomes an array of 8
elements. The allocation step feature is very useful for optimizing
performance, and it also reduces memory fragmentation by having a size that
fits the array usage. If you set the step to 0, the function sets a default
safe value.
1. Create the array:
// Strings to store in the array const char* strings[] = { "helo", "hera", "starbuck", "kat", "boomer", "hotdog", "longshot", "jammer", "crashdown", "hardball", "duck", "racetrack", "apolo", "husker", "freaker", "skulls", "bulldog", "flat top", "hammerhead", "gonzo" }; // Declaring the array (type Eina_Array) Eina_Array *array; unsigned int i; // Creating the array array = eina_array_new(20); // Inserting elements in the array for (i = 0; i < 20; i++) eina_array_push(array, strdup(strings[i]));
2. To change the allocation step, use the eina_array_step_set()
function:
sizeof()
function).In this example, the array step changes from 20 to 30.
eina_array_step_set(array, sizeof(*array), 30);
3. When no longer used, use the eina_array_free()
function to free the array. It first calls the eina_array_flush()
function and frees the memory of the pointer. It does not free the memory allocated for the elements of the array. To free them, use a while
statement with the eina_array_pop
function.
// Freeing the array elements while (eina_array_count(array)) free(eina_array_pop(array)); // Freeing the array itself eina_array_free(array);
Use the eina_array_data_set()
function. The first parameter is the array,
the second is the index of the element you want to set, and the last one is
the data. You must first get the related pointer if you need to free it, as
this function replaces the previously held data. Be careful, as there is no
array or index check. If the value is NULL
or invalid, the application can
crash.
free(eina_array_data_get(array, 0)); eina_array_data_set(array, 0, strdup(strings[3]);
Use the eina_array_push()
function. The function returns EINA_TRUE
on
success, and EINA_FALSE
on failure. The first parameter is the array to
store the element, the second one is the data you want to store. If you store
strings, remember to allocate the memory first. The example uses the
strdup
function to duplicate the string contained in strings[]
. This
function allocates the memory of the returned string, so you do not have to do
it yourself.
for (i = 0; i < 20; i++) eina_array_push(array, strdup(strings[i]));
Use the eina_array_pop()
function. It takes the array as a parameter, and
if the operation is successful, returns a pointer to the data of the removed
element.
while (eina_array_count(array)) free(eina_array_pop(array));
Use the eina_array_remove()
function:
The selector function has to return an Eina_Bool
, EINA_TRUE
if the
element stays, and EINA_FALSE
if it has to be removed.
The following example shows how to remove all the elements of the array that are longer than 5.
// Selector function Eina_Bool keep(void *data, void *gdata) { if (strlen((const char*)data) <= 5) return EINA_TRUE; return EINA_FALSE; } int remove_array() { Eina_Array *array; Eina_Array_Iterator iterator; const char *item; unsigned int i; // Creating and populating an array // Removing the undesired elements eina_array_remove(array, keep, NULL); // Flushing and freeing the array return 0; }
Use the eina_array_flush()
function. This function sets the count and
total members of an array to 0, and frees and sets its data members to
NULL
. For performance reasons, there is no array check. If the value is
NULL
or invalid, the program can crash. The only parameter of this
function is a pointer to the Eina_Array
array you want to flush.
eina_array_flush(array);
Use the eina_array_clean()
function. This function sets the counting of
members in the array to 0. It does not free any space so you have to use it
carefully. For performance reasons, there is no array check. If the value is
NULL
or invalid, the program can crash.
eina_array_clean(array);
Use the eina_array_data_get()
function with the array and the index of the
element you want to get. The function returns a pointer to the data.
// Getting the data of the first element char *mydata; mydata = eina_array_data_get(array, 0);
Use the eina_array_count()
function. The first parameter is a pointer to
the array variable returned by the eina_array_new()
function.
The function returns the number of elements.
unsigned int nb_elm; nb_elm = eina_array_count(array);
You can use various methods:
Eina_Array
iterator called ITER_NEXT
. EINA_ARRAY_ITER_NEXT()
. It takes the array to iterate as the first parameter, a counter for the current index during the iteration, and a variable of the same type as the item data and an Eina_Iterator
. To use it, declare an Eina_Iterator
, an int
counter, and, for example, a char *
item if your array contains any strings.Eina_Array_Iterator iterator; const char *item; unsigned int i; EINA_ARRAY_ITER_NEXT(array, i, item, iterator) printf("item #%d: %s\n", i, item);
eina_array_foreach()
function to iterate over the array. // Callback function static Eina_Bool elm_print(const void *container, void *data, void *fdata) { printf("%s\n", (char *)data); return EINA_TRUE; } int iterating_array() { Eina_Array *array; unsigned int i; // Creating and populating an array // Iterating over the array and calling elm_print on each element eina_array_foreach(array, elm_print, NULL); // Freeing the element data and array return 0; }
eina_array_iterator_new()
function to create an iterator for the array. NULL
or the count of the array members is less than or equal to 0, the function returns NULL
. If the memory cannot be allocated, NULL
is returned and EINA_ERROR_OUT_OF_MEMORY
is thrown. Otherwise, a valid iterator is returned. eina_array_foreach()
function. static Eina_Bool print_one(const void *container, void *data, void *fdata) { printf("%s\n", (char*)data); return EINA_TRUE; } int new_iterator() { Eina_Array *array; Eina_Iterator *it; unsigned short int i; void *uninteresting; Eina_Bool rt; // Creating and populating an array it = eina_array_iterator_new(array); it = eina_iterator_next(it, &uninteresting); eina_iterator_foreach(it, print_one, NULL); eina_iterator_free(it); return 0; }
eina_array_accessor_new()
function to get random access to the array elements. NULL
or the counting of array members is less than or equal to 0, this function returns NULL
. If the memory cannot be allocated, NULL
is returned and EINA_ERROR_OUT_OF_MEMORY
is thrown. Otherwise, a valid accessor is returned. int random_access() { Eina_Array *array; // Declaration of the array Eina_Accessor *acc; // Declaration of the accessor unsigned short int i; // Generic counter void *data; // Variable to put the data retrieved from an array element // Creating and populating an array // Creating the array accessor acc = eina_array_accessor_new(array); // Random access to the data of the array elements for(i = 1; i < 10; i += 2) { // Putting the data in the variable 'data' eina_accessor_data_get(acc, i, &data); printf("%s\n", (const char *)data); } eina_accessor_free(acc); // Freeing the accessor // Freeing the array return 0; }
An inline array is a container that stores the data itself, not the pointers to the data. This means there is no memory fragmentation, and for small data types, such as char, short, and int, it is more memory-efficient. This is because the data is stored in the cache and is faster to access. The bigger the data gets, however, the less likely it is and the less interesting it becomes.
To create an inline array, use the eina_inarray_new()
function:
sizeof(char)
is passed to the function.eina_inarray_step_set()
function.
The eina_inarray_new()
function returns a pointer to the new
Eina_Inarray
variable.
int inline_array() { Eina_Inarray *iarr; // Declare an inline array variable of the type Eina_Inarray iarr = eina_inarray_new(sizeof(char), 0); // Create an inline array of "char" eina_inarray_free(iarr); // When no longer needed, free the array memory return 0; }
Use the eina_inarray_push()
function. The first parameter is a pointer to
the array variable returned by the eina_inarray_new()
function. The second
parameter is the data you want to push to the inline array.
If everything runs fine, the function returns the index of the new element. If
something goes wrong, it returns -1
.
ch = 'a'; eina_inarray_push(iarr, &ch);
Use the eina_inarray_insert_at()
function:
eina_inarray_new()
function.The content of the pointer is copied to the given position in the inline array. All the members from the position to the end of the array are shifted towards the end. If the position is equal to the end of the array, the member is appended. If the position is bigger than the array length, the function fails.
ch = 'a'; eina_inarray_push(iarr, &ch); ch = 'b'; eina_inarray_push(iarr, &ch); ch = 'd'; eina_inarray_push(iarr, &ch); // Adding data on position 3 ch = 'c'; eina_inarray_insert_at(iarr, 2, &ch)
Use the eina_inarray_insert()
or eina_inarray_insert_sorted()
function. The only difference between these functions is that the
eina_inarray_insert_sorted()
function assumes that the array is already
sorted and consequently optimizes the insertion position by doing a binary
search.
In both functions:
eina_inarray_new()
function.Eina_Compare_Cb
callback function compares data1 and data2. data1 is the value contained in the inline array and data2 is the data you pass to the eina_inarray_insert()
or eina_inarray_insert_sorted()
function as the second parameter. If data1 is less than data2, -1 must be returned, if it is greater, 1 must be returned, and if they are equal, 0 must be returned.The following example shows how to insert a value before a greater value:
// Defining the comparison function with the position criteria Eina_Compare_Cb cmp(const void *a, const void *b) { return *(int*)a > *(int*)b; } int inline_insert() { Eina_Inarray *iarr; char ch, *ch3; int a, *b; // Creating an inline array // Adding data to the inline array a = 97; eina_inarray_push(iarr, &a); a = 98; eina_inarray_push(iarr, &a); a = 100; eina_inarray_push(iarr, &a); // Inserting data with the criteria a = 99; eina_inarray_insert_sorted(iarr, &a, cmp); eina_inarray_free(iarr); }
Use the eina_inarray_pop()
function. The only parameter is a pointer to
the array variable returned by the eina_inarray_new()
function. This
function returns the data removed from the inline array.
eina_inarray_pop(iarr);
Use the eina_inarray_remove()
function. The first parameter is a pointer
to the array variable returned by the eina_inarray_new()
function. The
second parameter is the data you want to remove from the inline array.
The eina_inarray_remove()
function finds the data and removes the matching
members from the array. The data can be an existing member of an inline array
for optimized usage. In other cases, the content is matched using the
memcmp()
function.
The eina_inarray_remove()
function returns the index of the removed
member, or -1 if failed.
iarr = eina_inarray_new(sizeof(char), 0); ch = 'a'; eina_inarray_push(iarr, &ch); // Removing data from the array eina_inarray_remove(iarr, &ch);
Use the eina_inarray_remove_at()
function. The first parameter is a
pointer to the array variable returned by the eina_inarray_new()
function.
The second parameter is the index of the element you want to remove from the
inline array.
The function returns EINA_TRUE
on success and EINA_FALSE
if something
goes wrong. The member is removed from the inline array and any members after
it are moved towards the array's head.
// Removing data from position 2 eina_inarray_remove_at(iarr, 2);
Use the eina_inarray_flush()
function. The first parameter is a pointer to
the array variable returned by the eina_inarray_new()
function. The
function removes every member from the array.
eina_inarray_flush(iarr);
Use the eina_inarray_replace_at()
function, which copies the data over the
given position:
eina_inarray_new()
function.
The function returns EINA_TRUE
on success, and EINA_FALSE
on failure.
The given pointer content is copied to the given position in the array. The
pointer is not referenced, instead its contents are copied to the member's
array using the previously defined member_size
. If the position does not
exist, the function fails.
// Replacing the member at position 3 ch = 'd'; eina_inarray_replace_at(iarr, 3, &ch);
Use the eina_inarray_sort()
function, which applies a quick sorting algorithm to the inline array:
eina_inarray_new()
function.Eina_Compare_Cb
callback comparison function, which compares data1 and data2. static int short_cmp(const void *pa, const void *pb) { const short *a = pa, *b = pb; return *a - *b; } int sorting_inline_array() { Eina_Inarray *array; int i; // Creating and populating the inline array eina_inarray_sort(array, short_cmp); eina_inarray_free(array); }
Be careful, the data given to the compare function is the pointer to the member memory itself. Do not change it.
Use the eina_inarray_search()
function that runs a linear walk looking for
the given data:
eina_inarray_new()
function.Eina_Compare_Cb
callback comparison function, which compares data1 and data2. eina_inarray_search()
function as the second parameter. If the data matches, the function must return 0, if data1 is less than data2, -1 must be returned and if it is greater, 1 must be returned.The function returns the member index, or -1 if not found.
Eina_Compare_Cb compare(const void *pa, const void *pb) { const short *a = pa, *b = pb; if (*a == *b) return EINA_TRUE; return EINA_FALSE; } int search_inline_array() { Eina_Inarray *array; int i; int elm_index; int to_search = 3; // Creating and populating the inline array elm_index = eina_inarray_search(array, &to_search, compare); eina_inarray_free(array); }
Be careful, the data given to the compare function is the pointer to the member memory itself. Do not change it.
The eina_inarray_search_sorted()
function does exactly the same as
eina_inarray_search()
, but uses a binary search for the given data.
Use the eina_inarray_count()
. The first parameter is a pointer to the
array returned by the eina_inarray_new()
function. The function returns an
unsigned int
, the number of elements.
printf("Inline array of integers with %d elements:\n", eina_inarray_count(iarr));
You can use various methods:
FOREACH
and REVERSE_FOREACH
.EINA_INARRAY_FOREACH()
macro. The first parameter is a pointer to the array variable returned by eina_inarray_new()
, and the second parameter is the variable into which the current value is put during the walk. The EINA_INARRAY_REVERSE_FOREACH()
macro does the same thing but starts from the last element. iarr = eina_inarray_new(sizeof(char), 0); int a, *b; a = 97; eina_inarray_push(iarr, &a); a = 98; eina_inarray_push(iarr, &a); a = 99; eina_inarray_push(iarr, &a); EINA_INARRAY_FOREACH(iarr, b) printf("int: %d(pointer: %p)\n", *b, b);
eina_inarray_foreach()
function, which invokes the given function on each element of the array with the given data:eina_inarray_new()
.EINA_TRUE
as long as you want to continue iterating. By returning EINA_FALSE
, you stop the iteration and make the eina_inarray_foreach()
function return EINA_FALSE
.
The eina_inarray_foreach()
function returns EINA_TRUE
if it
successfully iterates through all items of the array. Call the function for
every given data in the array. This is a safe way to iterate over an array.
static Eina_Bool array_foreach(const void *array __UNUSED__, void *p, void *user_data __UNUSED__) { short *member = p; int *i = user_data; (*p)++; (*i)++; return EINA_TRUE; } int inline_array_foreach() { Eina_Inarray *iarr; iarr = eina_inarray_new(sizeof(char), 1); int i; for (i = 0; i < numbers_count; i++) { short val = i; eina_inarray_push(iarr, &val); } i = 0; eina_inarray_foreach(iarr, array_foreach, &i); eina_inarray_free(iarr); return 0; }
Use the eina_inarray_foreach_remove()
function, which walks through the
array and, if the value matches in the callback function, removes the element:
eina_inarray_new()
function.EINA_TRUE
if the value matches, or EINA_FALSE
if it does not match.The function returns the number of removed entries or -1 if something goes wrong.
static Eina_Bool array_foreach(const void *array __UNUSED__, void *p, void *user_data __UNUSED__) { short *member = p; int *i = user_data; if (*i == *p) return EINA_TRUE; return EINA_FALSE; } int inline_array_foreach_remove() { Eina_Inarray *iarr; iarr = eina_inarray_new(sizeof(char), 1); int i; for (i = 0; i < numbers_count; i++) { short val = i; eina_inarray_push(iarr, &val); } i = 6; eina_inarray_foreach_remove(iarr, array_foreach, &i); eina_inarray_free(iarr); return 0; }