Eina value example with user defined type.
authorgastal <gastal@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Fri, 17 Feb 2012 18:52:58 +0000 (18:52 +0000)
committergastal <gastal@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Fri, 17 Feb 2012 18:52:58 +0000 (18:52 +0000)
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/eina@68082 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

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

index a82e698..66d65a3 100644 (file)
@@ -42,7 +42,8 @@ SRCS = \
        eina_model_02.c \
        eina_model_03.c \
        eina_value_01.c \
-       eina_value_02.c
+       eina_value_02.c \
+       eina_value_03.c
 
 examples_PROGRAMS =
 
@@ -84,7 +85,8 @@ examples_PROGRAMS += \
        eina_model_03 \
        eina_model_04 \
        eina_value_01 \
-       eina_value_02
+       eina_value_02 \
+       eina_value_03
 
 eina_model_04_SOURCES = \
        eina_model_04_animal.c \
diff --git a/src/examples/eina_value_03.c b/src/examples/eina_value_03.c
new file mode 100644 (file)
index 0000000..7cafa3b
--- /dev/null
@@ -0,0 +1,175 @@
+#include <Eina.h>
+#include <sys/time.h>
+
+static Eina_Bool
+_tz_setup(const Eina_Value_Type *type, void *mem)
+{
+   memset(mem, 0, type->value_size);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_tz_flush(const Eina_Value_Type *type, void *mem)
+{
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_tz_copy(const Eina_Value_Type *type, const void *src, void * dst)
+{
+   struct timezone *tzsrc = src;
+   struct timezone *tzdst = dst;
+   *tzdst = *tzsrc;
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_tz_compare(const Eina_Value_Type *type, const void *a, const void *b)
+{
+   struct timezone tza = *(struct timezone*)a;
+   struct timezone tzb = *(struct timezone*)b;
+
+   if (tza.tz_minuteswest < tzb.tz_minuteswest)
+     return -1;
+   else if (tza.tz_minuteswest > tzb.tz_minuteswest)
+     return 1;
+   return 0;
+}
+
+static Eina_Bool
+_tz_pset(const Eina_Value_Type *type, void *mem, const void *ptr)
+{
+   *(struct timezone*)mem = *(struct timezone*)ptr;
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_tz_vset(const Eina_Value_Type *type, void *mem, va_list args)
+{
+   const struct timezone tz = va_arg(args, struct timezone);
+   return _tz_pset(type, mem, &tz);
+}
+
+static Eina_Bool
+_tz_pget(const Eina_Value_Type *type, const void *mem, void *ptr)
+{
+   memcpy(ptr, mem, type->value_size);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_tz_convert_to(const Eina_Value_Type *type, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
+{
+   struct timezone v = *(struct timezone*)type_mem;
+
+   eina_error_set(0);
+
+   if (convert == EINA_VALUE_TYPE_UCHAR)
+     {
+        unsigned char other_mem = v.tz_minuteswest;
+        return eina_value_type_pset(convert, convert_mem, &other_mem);
+     }
+   else if (convert == EINA_VALUE_TYPE_USHORT)
+     {
+        unsigned short other_mem = v.tz_minuteswest;
+        return eina_value_type_pset(convert, convert_mem, &other_mem);
+     }
+   else if (convert == EINA_VALUE_TYPE_UINT)
+     {
+        unsigned int other_mem = v.tz_minuteswest;
+        return eina_value_type_pset(convert, convert_mem, &other_mem);
+     }
+   else if ((convert == EINA_VALUE_TYPE_ULONG) || (convert == EINA_VALUE_TYPE_TIMESTAMP))
+     {
+        unsigned long other_mem = v.tz_minuteswest;
+        return eina_value_type_pset(convert, convert_mem, &other_mem);
+     }
+   else if (convert == EINA_VALUE_TYPE_UINT64)
+     {
+        uint64_t other_mem = v.tz_minuteswest;
+        return eina_value_type_pset(convert, convert_mem, &other_mem);
+     }
+   else if (convert == EINA_VALUE_TYPE_CHAR)
+     {
+        char other_mem = v.tz_minuteswest;
+        return eina_value_type_pset(convert, convert_mem, &other_mem);
+     }
+   else if (convert == EINA_VALUE_TYPE_SHORT)
+     {
+        short other_mem = v.tz_minuteswest;
+        return eina_value_type_pset(convert, convert_mem, &other_mem);
+     }
+   else if (convert == EINA_VALUE_TYPE_INT)
+     {
+        int other_mem = v.tz_minuteswest;
+        return eina_value_type_pset(convert, convert_mem, &other_mem);
+     }
+   else if (convert == EINA_VALUE_TYPE_LONG)
+     {
+        long other_mem = v.tz_minuteswest;
+        return eina_value_type_pset(convert, convert_mem, &other_mem);
+     }
+   else if (convert == EINA_VALUE_TYPE_INT64)
+     {
+        int64_t other_mem = v.tz_minuteswest;
+        return eina_value_type_pset(convert, convert_mem, &other_mem);
+     }
+   else if (convert == EINA_VALUE_TYPE_FLOAT)
+     return eina_value_type_pset(convert, convert_mem, &v.tz_minuteswest);
+   else if (convert == EINA_VALUE_TYPE_DOUBLE)
+     return eina_value_type_pset(convert, convert_mem, &v.tz_minuteswest);
+   else if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
+            convert == EINA_VALUE_TYPE_STRING)
+     {
+        const char *other_mem;
+        char buf[64];
+        snprintf(buf, sizeof(buf), "%d", v.tz_minuteswest);
+        other_mem = buf; /* required due &buf == buf */
+        return eina_value_type_pset(convert, convert_mem, &other_mem);
+     }
+
+   eina_error_set(EINA_ERROR_VALUE_FAILED);
+   return EINA_FALSE;
+}
+
+static Eina_Value_Type TZ_TYPE = {
+   EINA_VALUE_TYPE_VERSION,
+   sizeof(struct timezone),
+   "struct timezone",
+   _tz_setup,
+   _tz_flush,
+   _tz_copy,
+   _tz_compare,
+   _tz_convert_to,
+   NULL, //No convert from
+   _tz_vset,
+   _tz_pset,
+   _tz_pget
+};
+
+int main(int argc, char **argv)
+{
+   Eina_Value vtv, vtz;
+   struct timeval tv;
+   struct timezone tz;
+   char *s;
+
+   eina_init();
+
+   eina_value_setup(&vtv, EINA_VALUE_TYPE_TIMEVAL);
+   eina_value_setup(&vtz, &TZ_TYPE);
+
+   gettimeofday(&tv, &tz);
+   eina_value_set(&vtv, tv);
+   eina_value_set(&vtz, tz);
+
+   s = eina_value_to_string(&vtv);
+   printf("time: %s\n", s);
+   free(s);
+   s = eina_value_to_string(&vtz);
+   printf("timezone: %s\n", s);
+   free(s);
+
+   eina_value_flush(&vtz);
+   eina_value_flush(&vtv);
+}
index 54cedbe..e6f38b6 100644 (file)
  */
 
 /**
+ * @page eina_value_example_03_page Eina value custom type example
+ * @dontinclude eina_value_03.c
+ *
+ * For this example we'll be creating our own custom type of eina value. Eina
+ * value can already store struct timeval(man gettimeofday for more information)
+ * but it has no type to store struct timezone, so that's what this example will
+ * do.
+ * @note struct timezone is actually obsolete, so using it in real world
+ * programs is probably not a good idea, but this is an example so, bear with
+ * us.
+ *
+ * To create our own custom eina value type we need to define functions to
+ * do the following operations on it:
+ * @li Setup
+ * @li Flush
+ * @li Copy
+ * @li Compare
+ * @li Set
+ * @li Get
+ * @li Conversion
+ *
+ * Most of this functions are very simple, so let's look at them, starting with
+ * setup which only clear the memory so that we can be certain we won't be using
+ * stale data:
+ * @until }
+ *
+ * Now the flush function, which is even simpler, it does nothing, that's
+ * because there is nothing we need to do, all the necessary steps are taken by
+ * eina value itself:
+ * @until }
+ *
+ * Our next function, copy, is a bit more interesting, but not much, it just
+ * casts our void pointers to struct timezone pointers and does the copy:
+ * @until }
+ * @note By now you might be wondering why our functions receive void pointers
+ * instead of pointers to struct timezone, and this is a good point. The reason
+ * for this is that eina value doesn't know anything about our type so it must
+ * use a generic void pointer, casting that pointer into a proper value is the
+ * job of the implementor of the new type.
+ *
+ * Next we have the comparison function, which compares the @c tz_minuteswest
+ * field of struct timezone, we don't compare @c tz_dsttime because that field
+ * is not used in linux:
+ * @until }
+ *
+ * Next we have setting, this however requires not one but rather two functions,
+ * the reason for this is because to be able to receive arguments of any type
+ * eina value uses @ref https://wikipedia.org/wiki/Variadic_functions "variadic
+ * functions", so we need a function to get the argument from a va_list and
+ * another to actually to the setting.
+ *
+ * Lets first look at the pset function which sets the received value to a
+ * pointer:
+ * @until }
+ *
+ * Next we have the vset function which get the argument from the va_list and
+ * passes it to the pset function:
+ * @until }
+ *
+ * And now the function to get the value, a very simple copying of the value to
+ * the given pointer:
+ * @until }
+ *
+ * And finally our conversion function, this is our longest and most interesting
+ * one. For numeric type we simply assign the value of @c tz_minuteswest to the
+ * new type and call a set function using it:
+ * @until EINA_VALUE_TYPE_DOUBLE
+ * @until return
+ * @note It would be a good idea to add checks for over and underflow for these
+ * types and return #EINA_FALSE in thoses cases, we omit this here for brevity.
+ *
+ * For string types we use @c snprintf() to format our @c tz_minuteswest field
+ * and put it in a string(again @c tz_dsttime is ignored because it's not used):
+ * @until }
+ *
+ * Finally we handle any other types by returning an error in that case:
+ * @until }
+ *
+ * Now that we have all the functions, we can populate an @c Eina_Value_Type to
+ * later use it with @c eina_value_setup():
+ * @until }
+ *
+ * We can now finally use our new TZ_TYPE with eina value, so lets conclude our
+ * example by practicing that by setting its value and printing it:
+ * @until }
+ *
+ * For the full source code see @ref eina_value_03_c.
+ */
+
+/**
+ * @page eina_value_03_c eina_value_03.c
+ * @include eina_value_03.c
+ * @example eina_value_03.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
+ * @li @ref eina_value_example_03_page
  *
  * @{
  */