forked from enlightenment/efl
Eina value example with user defined type.
SVN revision: 68082
This commit is contained in:
parent
a42425297c
commit
30d73cffd7
|
@ -42,7 +42,8 @@ SRCS = \
|
||||||
eina_model_02.c \
|
eina_model_02.c \
|
||||||
eina_model_03.c \
|
eina_model_03.c \
|
||||||
eina_value_01.c \
|
eina_value_01.c \
|
||||||
eina_value_02.c
|
eina_value_02.c \
|
||||||
|
eina_value_03.c
|
||||||
|
|
||||||
examples_PROGRAMS =
|
examples_PROGRAMS =
|
||||||
|
|
||||||
|
@ -84,7 +85,8 @@ examples_PROGRAMS += \
|
||||||
eina_model_03 \
|
eina_model_03 \
|
||||||
eina_model_04 \
|
eina_model_04 \
|
||||||
eina_value_01 \
|
eina_value_01 \
|
||||||
eina_value_02
|
eina_value_02 \
|
||||||
|
eina_value_03
|
||||||
|
|
||||||
eina_model_04_SOURCES = \
|
eina_model_04_SOURCES = \
|
||||||
eina_model_04_animal.c \
|
eina_model_04_animal.c \
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -161,6 +161,102 @@
|
||||||
* @example eina_value_02.c
|
* @example eina_value_02.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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
|
* @addtogroup Eina_Data_Types_Group Data Types
|
||||||
*
|
*
|
||||||
|
@ -194,6 +290,7 @@
|
||||||
* Examples of usage of the Eina_Value API:
|
* Examples of usage of the Eina_Value API:
|
||||||
* @li @ref eina_value_example_01_page
|
* @li @ref eina_value_example_01_page
|
||||||
* @li @ref eina_value_example_02_page
|
* @li @ref eina_value_example_02_page
|
||||||
|
* @li @ref eina_value_example_03_page
|
||||||
*
|
*
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue