diff --git a/legacy/eina/src/examples/Makefile.am b/legacy/eina/src/examples/Makefile.am index ea0ae14adf..a82e698449 100644 --- a/legacy/eina/src/examples/Makefile.am +++ b/legacy/eina/src/examples/Makefile.am @@ -41,7 +41,8 @@ SRCS = \ eina_model_01.c \ eina_model_02.c \ eina_model_03.c \ - eina_value_01.c + eina_value_01.c \ + eina_value_02.c examples_PROGRAMS = @@ -82,7 +83,8 @@ examples_PROGRAMS += \ eina_model_02 \ eina_model_03 \ eina_model_04 \ - eina_value_01 + eina_value_01 \ + eina_value_02 eina_model_04_SOURCES = \ eina_model_04_animal.c \ diff --git a/legacy/eina/src/examples/eina_value_02.c b/legacy/eina/src/examples/eina_value_02.c new file mode 100644 index 0000000000..b6ab1146a9 --- /dev/null +++ b/legacy/eina/src/examples/eina_value_02.c @@ -0,0 +1,97 @@ +#include + +static Eina_Value_Struct_Desc *V1_DESC = NULL; +static Eina_Value_Struct_Desc *V2_DESC = NULL; + +void value_init(void) +{ + typedef struct _My_Struct_V1 { + int param1; + char param2; + } My_Struct_V1; + + + static Eina_Value_Struct_Member v1_members[] = { + // no eina_value_type as they are not constant initializers, see below. + EINA_VALUE_STRUCT_MEMBER(NULL, My_Struct_V1, param1), + EINA_VALUE_STRUCT_MEMBER(NULL, My_Struct_V1, param2) + }; + v1_members[0].type = EINA_VALUE_TYPE_INT; + v1_members[1].type = EINA_VALUE_TYPE_CHAR; + static Eina_Value_Struct_Desc v1_desc = { + EINA_VALUE_STRUCT_DESC_VERSION, + NULL, // no special operations + v1_members, + EINA_C_ARRAY_LENGTH(v1_members), + sizeof(My_Struct_V1) + }; + V1_DESC = &v1_desc; + + typedef struct _My_Struct_V2 { + int param1; + char param2; + int param3; + } My_Struct_V2; + static Eina_Value_Struct_Member v2_members[] = { + // no eina_value_type as they are not constant initializers, see below. + EINA_VALUE_STRUCT_MEMBER(NULL, My_Struct_V2, param1), + EINA_VALUE_STRUCT_MEMBER(NULL, My_Struct_V2, param2), + EINA_VALUE_STRUCT_MEMBER(NULL, My_Struct_V2, param3) + }; + v2_members[0].type = EINA_VALUE_TYPE_INT; + v2_members[1].type = EINA_VALUE_TYPE_CHAR; + v2_members[2].type = EINA_VALUE_TYPE_INT; + static Eina_Value_Struct_Desc v2_desc = { + EINA_VALUE_STRUCT_DESC_VERSION, + NULL, // no special operations + v2_members, + EINA_C_ARRAY_LENGTH(v2_members), + sizeof(My_Struct_V2) + }; + V2_DESC = &v2_desc; +} + +void rand_init(Eina_Value *v) +{ + if (v->type != EINA_VALUE_TYPE_STRUCT) + return; + + eina_value_struct_set(v, "param1", rand()); + eina_value_struct_set(v, "param2", rand() % 256); + eina_value_struct_set(v, "param3", rand()); +} + +void my_struct_use(Eina_Value *params) +{ + int p1, p3; + char p2; + + eina_value_struct_get(params, "param1", &p1); + eina_value_struct_get(params, "param2", &p2); + printf("param1: %d\nparam2: %c\n", p1, p2); + + if (eina_value_struct_get(params, "param3", &p3)) + printf("param3: %d\n", p3); +} + +int main(int argc, char **argv) +{ + Eina_Value *v1, *v2; + + eina_init(); + value_init(); + srand(time(NULL)); + + v1 = eina_value_struct_new(V1_DESC); + v2 = eina_value_struct_new(V2_DESC); + + rand_init(v1); + my_struct_use(v1); + + rand_init(v2); + my_struct_use(v2); + + eina_value_free(v1); + eina_value_free(v2); + eina_shutdown(); +} diff --git a/legacy/eina/src/include/eina_value.h b/legacy/eina/src/include/eina_value.h index f7925414b5..54cedbe532 100644 --- a/legacy/eina/src/include/eina_value.h +++ b/legacy/eina/src/include/eina_value.h @@ -92,6 +92,75 @@ * @example eina_value_01.c */ +/** + * @page eina_value_example_02_page Eina_Value struct usage + * @dontinclude eina_value_02.c + * + * This example will examine a hypothetical situation in which we had a + * structure(which represented parameters) with two fields, and then need to add + * a third field to our structure. If using structs directly we'd need to + * rewrite every piece of code that touches the struct, by using eina value, and + * thus having the compiler not even know the struct, we can reduce the amount + * of changes needed and retain interoperability between the old and new format. + * + * Our example will start with a function that creates descriptions of both of + * our structs for eina value usage. The first step is to create a struct and + * describe its members: + * @until v1_members[1] + * @note We can't pass the types of the members to EINA_VALUE_STRUCT_MEMBER + * macro because they are not constant initializers. + * + * So far it should be pretty easy to understand, we said @c My_Struct_V1 has + * two members, one of type @c int and another of type @c char. We now create + * the description of the actual struct, again nothing overly complex, we signal + * which version of EINA_VALUE_STRUCT we're using, we declare no special + * operations, our members and our size: + * @until V1_DESC + * + * We now repeat the process for the second version of our struct, the only + * difference is the addition of a third parameter of type @c int : + * @until V2_DESC + * @until } + * + * We'll now look at a function that sets the values of our structs. For + * simplicity's sake we initialize it we random values, a real world case would + * read these values from a file, a database or even from the network. The + * fundamental detail here is that this function works for both V1 and V2 + * structs, this is because setting a parameter that a struct that doesn't have + * does nothing without throwing any errors: + * @until } + * @note While using eina_value_struct_set() with an in-existing parameter + * causes no error, it does return #EINA_FALSE, to notify it was not possible + * to set the value. This could be used to determine that we're handling a V1 + * struct and take some action based on that. + * + * The next thing is to do is see what a function that uses the values of the + * struct looks like. We'll again be very simplistic in our usage, we'll just + * print the values, but a real world case, might send these values to another + * process use them to open a network/database connection or anything else. + * Since all versions of the struct have @c param1 and @c param2 we'll + * unconditionally use them: + * @until printf + * + * The next step is to conditionally use @c param3, which can fortunately be + * done in the same step in which we get it's value: + * @until } + * + * There we've now got functions that can both populate and use values from both + * our structs, so now let's actually use them in our main function by creating + * a struct of each type, initializing them and them using them: + * @until } + * + * This concludes our example. For the full source code see @ref + * eina_value_02_c. + */ + +/** + * @page eina_value_02_c eina_value_02.c + * @include eina_value_02.c + * @example eina_value_02.c + */ + /** * @addtogroup Eina_Data_Types_Group Data Types * @@ -124,6 +193,7 @@ * * Examples of usage of the Eina_Value API: * @li @ref eina_value_example_01_page + * @li @ref eina_value_example_02_page * * @{ */