Documented example of eina_value struct usage.
authorJonas M. Gastal <jgastal@profusion.mobi>
Fri, 17 Feb 2012 13:24:05 +0000 (13:24 +0000)
committerJonas M. Gastal <jgastal@profusion.mobi>
Fri, 17 Feb 2012 13:24:05 +0000 (13:24 +0000)
SVN revision: 68072

legacy/eina/src/examples/Makefile.am
legacy/eina/src/examples/eina_value_02.c [new file with mode: 0644]
legacy/eina/src/include/eina_value.h

index ea0ae14..a82e698 100644 (file)
@@ -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 (file)
index 0000000..b6ab114
--- /dev/null
@@ -0,0 +1,97 @@
+#include <Eina.h>
+
+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();
+}
index f792541..54cedbe 100644 (file)
  */
 
 /**
+ * @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
  *
  * @since 1.2
  *
  * Examples of usage of the Eina_Value API:
  * @li @ref eina_value_example_01_page
+ * @li @ref eina_value_example_02_page
  *
  * @{
  */