The Eina_Value
object provides storage of and access to generic data, allowing you to store whatever you want in a single Eina_Value
type. It is meant for simple data types, providing uniform access and release functions for the exchange of data while preserving their types. Eina_Value
supports a number of predefined types, can be extended with additional user-provided types and can convert between differing data types including strings.
Examples of Eina_Value
usage can be found in the EFL examples git repository in the file reference/c/eina/src/eina_value.c.
Eina_Value
can handle the following common simple types:
EINA_VALUE_TYPE_UCHAR
- Unsigned charEINA_VALUE_TYPE_USHORT
- Unsigned shortEINA_VALUE_TYPE_UINT
- Unsigned intEINA_VALUE_TYPE_ULONG
- Unsigned longEINA_VALUE_TYPE_TIMESTAMP
An unsigned long variant used for timestampsEINA_VALUE_TYPE_UINT64
- Unsigned 64-bit integerEINA_VALUE_TYPE_CHAR
- CharEINA_VALUE_TYPE_SHORT
- ShortEINA_VALUE_TYPE_INT
- IntEINA_VALUE_TYPE_LONG
- LongEINA_VALUE_TYPE_INT64
- 64-bit integerEINA_VALUE_TYPE_FLOAT
- FloatEINA_VALUE_TYPE_DOUBLE
- DoubleEINA_VALUE_TYPE_STRINGSHARE
- Stringshared stringEINA_VALUE_TYPE_STRING
- StringEINA_VALUE_TYPE_TIMEVAL
- 'Struct timeval'In addition Eina_Value
has a number of specializations to handle the following aggregate types:
EINA_VALUE_TYPE_ARRAY
- Manages arrays of elements through the Eina_Value_Array
objectEINA_VALUE_TYPE_LIST
- Manages lists of elements through the Eina_Value_List
objectEINA_VALUE_TYPE_HASH
- Manages hash tables through the Eina_Value_Hash
objectEINA_VALUE_TYPE_BLOB
- Manages blobs of bytes (memory buffers) through the Eina_Value_Blob
objectEINA_VALUE_TYPE_STRUCT
: Manages user-defined compound types (structures) through the Eina_Value_Struct
objectNew values can be allocated with the eina_value_new()
function and disposed of with the eina_value_free()
function.
Eina_Value *v = eina_value_new (type);
eina_value_free (v);
The type
parameter must be one of the EINA_VALUE_TYPE_*
macros listed above.
Note that eina_value_free()
will free the memory allocated for the Eina_Value
itself and all its contents, if necessary.
If you allocate the Eina_Value
structure yourself you can configure its contents with eina_value_setup()
and free it with eina_value_flush()
.
Eina_Value v;
eina_value_setup(&v, type);
eina_value_flush(&v);
Note that eina_value_flush()
will free the content of the Eina_Value
but not the Eina_Value
structure itself.
The contents of a simple Eina_Value
can be set with eina_value_set()
and retrieved with eina_value_get()
. Note that the value of the second type
parameter must match the type used when creating the Eina_Value
.
For instance, for integers:
Eina_Value *v = eina_value_new (EINA_VALUE_TYPE_INT);
eina_value_set(v, 123);
int i;
eina_value_get(v, &i);
eina_value_free(v);
Strings are also easily handled:
Eina_Value *v = eina_value_new (EINA_VALUE_TYPE_STRING);
eina_value_set(v, "My string");
const char *str;
eina_value_get(v, &str);
eina_value_free(v);
You may copy the contents of an Eina_Value
over another one using the eina_value_copy()
function. Note that the destination Eina_Value
must exist - i.e. it will not be allocated for you - and that its contents will be replaced with a copy of the source Eina_Value
.
Eina_Value src, dst;
eina_value_setup(&src, EINA_VALUE_TYPE_INT);
eina_value_set(&src, 123);
eina_value_copy(&src, &dst);
eina_value_flush(&src);
eina_value_flush(&dst);
Two Eina_Value
s of the same type can be compared with the eina_value_compare(a, b)
function. The exact meaning of the comparison depends on the value type, but generally speaking the method returns a negative int if a<b, a positive int if a>b and 0 if both values are equal.
Eina_Value *v1 = eina_value_new(EINA_VALUE_TYPE_FLOAT);
Eina_Value *v2 = eina_value_new(EINA_VALUE_TYPE_FLOAT);
eina_value_set(v1, 7.0f);
eina_value_set(v2, 7.5f);
int comparison = eina_value_compare(v1, v2);
eina_value_free(v1);
eina_value_free(v2);
Most Eina_Value
s allow conversion from one type to another using the eina_value_convert()
function. The result of the conversion depends on the types in use. This function returns EINA_TRUE
if the conversion is successful. The conversion is typically very strict, meaning that conversion of negative values into unsigned types will fail and values which will not fit in the target type - i.e. conversions that would result in an overflow - will also fail.
Eina_Value *v_int = eina_value_new(EINA_VALUE_TYPE_INT);
Eina_Value *v_str = eina_value_new(EINA_VALUE_TYPE_STRING);
eina_value_set(v_int, 123);
eina_value_convert(v_int, v_str);
eina_value_set(v_str, "456");
eina_value_convert(v_str, v_int);
eina_value_free(v_int);
eina_value_free(v_str);
All Eina_Value
s allow for conversion into a string, and, for convenience, there is a dedicated conversion method: eina_value_to_string()
. This function allocates a new string, which you will need to free after use.
Eina_Value v;
eina_value_setup(&v, EINA_VALUE_TYPE_DOUBLE);
eina_value_set(&v, 74.5);
char *str = eina_value_to_string(&v);
free(str);
eina_value_flush(&v);
Eina_Value
supports handling collections of simple values through the common aggregate types Eina_Value_Array
, Eina_Value_List
, Eina_Value_Hash
and Eina_Value_Struct
.
All aggregate types allow the operations for simple types described above - including eina_value_free()
and eina_value_flush()
- as well as some specific methods, typically involving construction and access to particular elements within the collection.
An array is a contiguous block of memory which holds a collection of elements of the same type. Accessing and appending new elements at the end is typically very fast, but removing elements from the middle is not.
Create a new Eina_Value_Array
with eina_value_array_new(subtype, step)
, or configure an existing one with eina_value_array_setup(subtype, step)
. The subtype
parameter is the type of the Eina_Value
s that will be stored in the array. The step
parameter indicates how many elements are added to the end of the array every time it needs to be expanded, since it is typically more efficient to enlarge the array by chunks rather than element by element.
Dispose of the array or of its contents with eina_value_free()
and eina_value_flush()
respectively.
Retrieve the number of elements in an array with eina_value_array_count()
.
Remove an element with eina_value_array_remove(position)
, where the position
parameter is the zero-based index of the element to remove.
Append an element at the end of the array with eina_value_array_append()
.
Insert an element at a given position with eina_value_array_insert(position)
.
Retrieve the contents of the value at a given position with eina_value_array_get(position)
.
Set the contents of the value at a given position with eina_value_array_set(position)
.
Eina_Value *array = eina_value_array_new(EINA_VALUE_TYPE_INT, 0);
int x;
eina_value_array_append(array, 1234);
eina_value_array_get(array, 0, &x);
eina_value_free(array);
Iterate over all elements of the array with the EINA_VALUE_ARRAY_FOREACH(array, length, it, val)
macro. The array
parameter is the Eina_Value_Array
to iterate over. The length
parameter is an int variable that will receive the length of the array. The it
parameter is an int variable that will receive the position in the current iteration. The val
parameter is an Eina_Value *
that will receive the value in the array for the current iteration.
Eina_Value array;
unsigned int i, len;
Eina_Value v = EINA_VALUE_EMPTY;
EINA_VALUE_ARRAY_FOREACH(&array, len, i, &v)
{
}
A list is linked collection of Eina_Value
s in which each element contains a pointer to the next element. Insertions and deletions anywhere in the list are typically very fast, but accesses to a given position can be slow since it requires traveling through the list.
Create a new Eina_Value_List
with eina_value_list_new(subtype)
, or configure an existing one with eina_value_list_setup(subtype)
. The subtype
parameter is the type of the Eina_Value
s that will be stored in the list.
Dispose of the list or of its contents with eina_value_free()
and eina_value_flush()
respectively.
Retrieve the number of elements in a list with eina_value_list_count()
.
Remove an element with eina_value_list_remove(position)
, where the position
parameter is the zero-based index of the element to remove.
Append an element at the end of the list with eina_value_list_append()
.
Insert an element at a given position with eina_value_list_insert(position)
.
Retrieve the contents of the value at a given position with eina_value_list_get(position)
.
Set the contents of the value at a given position with eina_value_list_set(position)
.
Eina_Value *list = eina_value_list_new(EINA_VALUE_TYPE_INT);
int x;
eina_value_list_append(list, 1234);
eina_value_list_set(list, 0, 5678);
eina_value_list_get(list, 0, &x);
eina_value_free(list);
A hash table stores Einva_Value
s indexed by a string key rather than an index. Insertions, deletions and searches are typically very fast, at the cost of increased memory consumption.
Create a new Eina_Value_Hash
with eina_value_hash_new(subtype, bucket_size)
, or configure an existing one with eina_value_hash_setup(subtype, bucket_size)
. The subtype
parameter is the type of the Eina_Value
s that will be stored in the hash table. The bucket_size
parameter indicates how the table is to be expanded as new elements are added; use 0 and a sane default is chosen automatically.
Dispose of the hash table or of its contents with eina_value_free()
and eina_value_flush()
respectively.
Retrieve the number of elements in a hash table with eina_value_hash_population()
.
Remove an element with eina_value_hash_del(key)
, where the key
parameter is the string identifying the element to remove.
Retrieve the contents of the value with a given key using eina_value_hash_get(key)
.
Set the contents of the value with a given key using eina_value_hash_set(key)
. This also allows new elements to be added into the hash table.
Eina_Value *hash = eina_value_hash_new(EINA_VALUE_TYPE_INT, 0);
int x;
eina_value_hash_set(hash, "abc", 1234);
eina_value_hash_get(hash, "abc", &x);
eina_value_free(hash);
Any number of Eina_Value
s can be grouped and handled through a single Eina_Value_Struct
, just like regular structures in other languages. Upon creation the contents of the structure has to be described through an Eina_Value_Struct_Desc
object.
Create a new Eina_Value_Struct
with eina_value_struct_new(description)
, or configure an existing one with eina_value_struct_setup(description)
. The description
parameter is an object of type Eina_Value_Struct_Desc
which lists the members of the structure, among other things. Look at the Generic Value API reference for details, or this example in the EFL repository.
Dispose of the structure or its contents with eina_value_free()
and eina_value_flush()
respectively.
Retrieve the contents of any of the values in the structure with eina_value_struct_get(name)
, where the name
parameter identifies the member you want to retrieve.
Set the contents of any of the values in the structure with eina_value_struct_set(name)
, where the name
parameter identifies the member you want to set.
Beyond the above mentioned simple and aggregated Eina_Value
types provided by EFL, you can also define your own types for use anywhere you can use an Eina_Value
.
To do this, define an Eina_Value_Type
structure and use it in your calls to eina_value_new()
and eina_value_setup()
. This structure contains mainly function pointers to methods performing operations on your type such as setup, flush, copy, compare and so on.
You can find a usage example in the EFL examples repository in the file reference/c/eina/src/eina_value_custom.c.