Eina Generic Values in C#

The Eina namespace provides data types and useful tools which are not available in plain C. The C# runtime though, already provides most of Eina's functionality so you will rarely need to use it. The Eina Programming Guides are still useful for those EFL methods which use Eina types as parameters or return types.

The Eina.Value class 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/csharp/eina/src/eina_value.cs.

WARNING
NOTE The C# bindings are currently in BETA state
They should only be used for experimenting and NOT for any product development.
The source code for the tutorials is subject to change in the future.
NOTE

Value Types

Eina.Value can handle the following common simple types (found inside the Eina.ValueType enum):

Eina.ValueType C# type Content
SByte sbyte Signed char (8-bit integer)
Byte byte Unsigned char (8-bit integer)
Short short Signed short (16-bit integer)
UShort ushort Unsigned short (16-bit integer)
Int32 int Signed integer (32-bit)
UInt32 uint Unsigned integer (32-bit)
Long, Int64 long Signed long (64-bit integer)
ULong, UInt64 ulong Unsigned long (64-bit integer)
Float float Single precision (32-bit) floating point
Double double Double precision (64-bit) floating point
String string Unicode text string

In addition, Eina.Value supports the following aggregate types:

Eina.ValueType Content
Array Manages arrays of elements
List Manages lists of elements
Hash Manages hash tables

Simple Values

Creating Simple Values

New values can be allocated with the standard new() operator passing in the desired type as an Eina.ValueType:

var int_val = new Eina.Value(Eina.ValueType.Int32);

When the int_val variable goes out of scope any memory allocated internally by the Eina.Value will be freed as expected.

Changing the Type of Simple Values

The type of an Eina.Value can be changed at any time using Setup() and passing in the desired new type:

var val = new Eina.Value(Eina.ValueType.Int32);
val.Setup(Eina.ValueType.Float);

The content of the Eina.Value will be destroyed, but not the Eina.Value variable.

Accessing the Content of Simple Values

The contents of a simple Eina.Value can be set with Set() and retrieved with Get(). Note that the types provided must match the type used when creating the Eina.Value.

For instance, for integers:

var val = new Eina.Value(Eina.ValueType.Int32);
val.Set(123);
 
int i;
val.Get(out i);

Strings are also easily handled:

var val = new Eina.Value(Eina.ValueType.String);
val.Set("My string");
 
string str;
val.Get(out str);

Copying the Content of a Value

Eina.Values are referenced types, which means that when you make a copy of an Eina.Value variable, the underlying value is not copied: both variables point to the same value.

var src = new Eina.Value(Eina.ValueType.Int32);
src.Set(100);
var dst = src;
src.Set(200);
// Now both src and dst contain the integer 200

If you need to create a separate Eina.Value variable containing the same value, use new and initialize it:

var src = new Eina.Value(Eina.ValueType.Int32);
src.Set(100);
var dst = new Eina.Value(src);
src.Set(200);
// Now src=200 and dst=100

Comparing Two Values

Two Eina.Values of the same type can be compared with the standard operators , ==, != and >. The exact meaning of the comparison depends on the value type.

var v1 = new Eina. Value(Eina.ValueType.Float);
var v2 = new Eina. Value(Eina.ValueType.Float);
v1.Set(7.0f);
v2.Set(7.5f);
if (v1 > v2) { ... }

The internal method v1.Compare(v2) is also available. The exact meaning of the comparison depends again on the value type. The method returns: a negative integer if v1 < v2, a positive integer if v1 > v2 and 0 if both values are equal.

Converting Between Values

Most Eina.Values allow conversion from one type to another using the ConvertTo() function. The result of the conversion depends on the types in use. This function returns 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.

var v1 = new Eina.Value(Eina.ValueType.Int);
var v2 = new Eina.Value(Eina.ValueType.Float);
v1.Set(7);
v1.ConvertTo(v2);
Console.WriteLine(v2);

The above code should output 7.0000 on the screen because v2 is a floating type.

Converting to Strings

All Eina.Values allow for conversion into a string, and, for convenience, there is a dedicated conversion method: ToString().

var v1 = new Eina.Value(Eina.ValueType.Int);
v1.Set(7);
string str = v1.ToString();

Implicit Conversions

For convenience, implicit conversion operators also exist between an Eina.Value and the actual stored type, so operations like these are possible:

Eina.Value int_val = 123;
Eina.Value str_val = "My string";
int i = int_val;
string str = str_val;

These conversions allow directly providing native values to EFL methods expecting an Eina.Value, for example.

NOTE: As with all implicit conversions, use with caution to make sure the compiler is actually choosing the types you expect.

Aggregate Values

Eina.Value supports handling collections of simple values through the aggregate types Eina.ValueType.Array, Eina.ValueType.List and Eina.ValueType.Hash.

All aggregate types allow the operations for simple types described above 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 beginning or the middle is not.

Create a new array with new(Eina.ValueType.Array, subtype, step), or re-configure an existing one with Setup(Eina.ValueType.Array, subtype, step). The subtype parameter is the type of the Eina.Values 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. Its default value is 0 meaning that EFL will choose a value for you.

var varray = new Eina.Value(Eina.ValueType.Array, Eina.ValueType.Int32);

Retrieve the number of elements in an array with Count().

int count = varray.Count();

Append an element at the end of the array with Append().

varray.Append(100);
varray.Append(200);

Retrieve or set the contents of the value at a given position with the [] operator.

varray[1] = 100;
int old_val = varray[1];

Retrieve the type of the elements of an array (the subtype) with GetValueSubType():

Eina.ValueType subtype = varray.GetValueSubType();

NOTE: Elements cannot be removed from an array as of now, due to limitations in the current C# bindings.

Lists

A list is a linked collection of Eina.Values in which each element contains a pointer to the next element. Insertions and deletions anywhere in the list are typically very fast, but accessing a given position can be slow since it requires traveling through the list.

Create a new list with new(Eina.ValueType.Array, subtype), or configure an existing one with Setup(subtype). The subtype parameter is the type of the Eina.Values that will be stored in the list.

var vlist = new Eina.Value(Eina.ValueType.List, Eina.ValueType.Int32);

Retrieve the number of elements in a list with Count().

int count = vlist.Count();

Append an element at the end of the list with Append().

vlist.Append(100);
vlist.Append(200);

NOTE: Elements can only be added at the end as of now, due to limitations in the current C# bindings.

Retrieve or set the contents of the value at a given position with the [] operator.

vlist[1] = 100;
int old_val = vlist[1];

Retrieve the type of the elements of a list (the subtype) with GetValueSubType():

Eina.ValueType subtype = vlist.GetValueSubType();

NOTE: Elements cannot be removed from a list as of now, due to limitations in the current C# bindings.

Hash Tables

A hash table stores Eina.Values indexed by a string key rather than an integer. Insertions, deletions and searches are typically very fast, at the cost of increased memory consumption.

NOTE: Implementation of Hash tables inside Eina.Values is not complete at this moment.

Create a new hash table with new(Eina.ValueType.Hash, subtype, bucket_size), or configure an existing one with Setup(subtype, bucket_size). The subtype parameter is the type of the Eina.Values 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 will be chosen automatically.

var vhash = new (Eina.ValueType.Hash, Eina.ValueType.Int32);

Retrieve the number of elements in a hash table with Count().

int count = vhash.Count();

Further Reading

Eina Value example
Miscellaneous usage example for the Eina.Value type.
Generic Value API
Reference Guide for the Generic Value API (in C).