From b3ee881e93baeb18e867c3414f505f71a12e41bf Mon Sep 17 00:00:00 2001 From: gastal Date: Fri, 17 Feb 2012 18:52:58 +0000 Subject: [PATCH] Eina value example with user defined type. git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/eina@68082 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/examples/Makefile.am | 6 +- src/examples/eina_value_03.c | 175 +++++++++++++++++++++++++++++++++++++++++++ src/include/eina_value.h | 97 ++++++++++++++++++++++++ 3 files changed, 276 insertions(+), 2 deletions(-) create mode 100644 src/examples/eina_value_03.c diff --git a/src/examples/Makefile.am b/src/examples/Makefile.am index a82e698..66d65a3 100644 --- a/src/examples/Makefile.am +++ b/src/examples/Makefile.am @@ -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 index 0000000..7cafa3b --- /dev/null +++ b/src/examples/eina_value_03.c @@ -0,0 +1,175 @@ +#include +#include + +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); +} diff --git a/src/include/eina_value.h b/src/include/eina_value.h index 54cedbe..e6f38b6 100644 --- a/src/include/eina_value.h +++ b/src/include/eina_value.h @@ -162,6 +162,102 @@ */ /** + * @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 @@ -194,6 +290,7 @@ * 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 * * @{ */ -- 2.7.4