# Generic Value #

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](https://git.enlightenment.org/enlightenment/examples/) in the file [reference/c/eina/src/eina_value.c](https://git.enlightenment.org/enlightenment/examples/src/branch/master/reference/c/eina/src/eina_value.c).

## Value Types ##

``Eina_Value`` can handle the following common *simple* types:

* ``EINA_VALUE_TYPE_UCHAR`` - Unsigned char * ``EINA_VALUE_TYPE_USHORT`` - Unsigned short * ``EINA_VALUE_TYPE_UINT`` - Unsigned int * ``EINA_VALUE_TYPE_ULONG`` - Unsigned long * ``EINA_VALUE_TYPE_TIMESTAMP`` An unsigned long variant used for timestamps * ``EINA_VALUE_TYPE_UINT64`` - Unsigned 64-bit integer * ``EINA_VALUE_TYPE_CHAR`` - Char * ``EINA_VALUE_TYPE_SHORT`` - Short * ``EINA_VALUE_TYPE_INT`` - Int * ``EINA_VALUE_TYPE_LONG`` - Long * ``EINA_VALUE_TYPE_INT64`` - 64-bit integer * ``EINA_VALUE_TYPE_FLOAT`` - Float * ``EINA_VALUE_TYPE_DOUBLE`` - Double * ``EINA_VALUE_TYPE_STRINGSHARE`` - Stringshared string * ``EINA_VALUE_TYPE_STRING`` - String * ``EINA_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`` object * ``EINA_VALUE_TYPE_LIST`` - Manages lists of elements through the ``Eina_Value_List`` object * ``EINA_VALUE_TYPE_HASH`` - Manages hash tables through the ``Eina_Value_Hash`` object * ``EINA_VALUE_TYPE_BLOB`` - Manages blobs of bytes (memory buffers) through the ``Eina_Value_Blob`` object * ``EINA_VALUE_TYPE_STRUCT``: Manages user-defined compound types (structures) through the ``Eina_Value_Struct`` object

## Simple Values ##

### Creating and Destroying Simple Values ###

New values can be allocated with the ``eina_value_new()`` function and disposed of with the ``eina_value_free()`` function.

```c 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.

### Managing the Content of Simple Values ###

If you allocate the ``Eina_Value`` structure yourself you can configure its contents with ``eina_value_setup()`` and free it with ``eina_value_flush()``.

```c 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.

### Accessing the Content of Simple Values ###

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:

```c 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:

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

### Copying the Content of a Value ###

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``.

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

### Comparing Two Values ###

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.

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

### Converting Between Values ###

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.

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

### Converting to Strings ###

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.

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

## Aggregate Values ##

``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.

### Arrays ###

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)``.

```c 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.

```c Eina_Value array; unsigned int i, len; Eina_Value v = EINA_VALUE_EMPTY;

EINA_VALUE_ARRAY_FOREACH(&array, len, i, &v)

{
}

```

### Lists ###

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)``.

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

### Hash Tables ###

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.

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

### Structures ###

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](https://www.enlightenment.org/develop/legacy/api/c/start#group__Eina__Value__Group.html) reference for details, or [this example in the EFL repository](https://git.enlightenment.org/enlightenment/examples/src/branch/master/reference/c/eina/src/eina_value.c).

*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.

## Custom Value Types ##

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](https://git.enlightenment.org/enlightenment/examples/) in the file [reference/c/eina/src/eina_value_custom.c](https://git.enlightenment.org/enlightenment/examples/src/branch/master/reference/c/eina/src/eina_value_custom.c).

## Further Reading ##

[Generic Value API](https://www.enlightenment.org/develop/legacy/api/c/start#group__Eina__Value__Group.html) : A reference for the Generic Value API.

[Eina Value Example](https://git.enlightenment.org/enlightenment/examples/src/branch/master/reference/c/eina/src/eina_value.c) : An example use of the Generic Value API.

[Eina Value Custom Example](https://git.enlightenment.org/enlightenment/examples/src/branch/master/reference/c/eina/src/eina_value_custom.c) : An example of using custom types with the Generic Value API.