From a125108ebe848b9f9e1aac0e19ae524c1df053e4 Mon Sep 17 00:00:00 2001 From: Gustavo Sverzut Barbieri Date: Thu, 12 Jan 2012 01:31:21 +0000 Subject: [PATCH] eina_value: add struct timeval. may be useful for esskyuehl. SVN revision: 67106 --- legacy/eina/src/include/eina_value.h | 7 + legacy/eina/src/lib/eina_value.c | 204 ++++++++++++++++++++++++ legacy/eina/src/tests/eina_test_value.c | 79 +++++++++ 3 files changed, 290 insertions(+) diff --git a/legacy/eina/src/include/eina_value.h b/legacy/eina/src/include/eina_value.h index 6a4c217afd..e3aef99d77 100644 --- a/legacy/eina/src/include/eina_value.h +++ b/legacy/eina/src/include/eina_value.h @@ -236,6 +236,13 @@ EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_LIST; */ EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_HASH; +/** + * @var EINA_VALUE_TYPE_TIMEVAL + * manages 'struct timeval' type + * @since 1.2 + */ +EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_TIMEVAL; + /** * @var EINA_ERROR_VALUE_FAILED diff --git a/legacy/eina/src/lib/eina_value.c b/legacy/eina/src/lib/eina_value.c index 22b28c57c7..0da6600b4a 100644 --- a/legacy/eina/src/lib/eina_value.c +++ b/legacy/eina/src/lib/eina_value.c @@ -47,6 +47,7 @@ void *alloca (size_t); #include /* asprintf() */ #include /* PRId64 and PRIu64 */ +#include /* struct timeval */ #include "eina_config.h" #include "eina_private.h" @@ -3327,6 +3328,207 @@ static const Eina_Value_Type _EINA_VALUE_TYPE_HASH = { _eina_value_type_hash_pget }; +static Eina_Bool +_eina_value_type_timeval_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + memset(mem, 0, sizeof(struct timeval)); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_timeval_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_timeval_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const struct timeval *s = src; + struct timeval *d = dst; + *d = *s; + return EINA_TRUE; +} + +static inline struct timeval _eina_value_type_timeval_fix(const struct timeval *input) +{ + struct timeval ret = *input; + if (EINA_UNLIKELY(ret.tv_usec < 0)) + { + ret.tv_sec -= 1; + ret.tv_usec += 1e6; + } + return ret; +} + +static int +_eina_value_type_timeval_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + struct timeval va = _eina_value_type_timeval_fix(a); + struct timeval vb = _eina_value_type_timeval_fix(b); + if (timercmp(&va, &vb, <)) + return -1; + else if (timercmp(&va, &vb, >)) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_timeval_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + struct timeval v = _eina_value_type_timeval_fix(type_mem); + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v.tv_sec; + if (EINA_UNLIKELY(v.tv_sec < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v.tv_sec > eina_value_uchar_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_USHORT) + { + unsigned short other_mem = v.tv_sec; + if (EINA_UNLIKELY(v.tv_sec < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v.tv_sec > eina_value_ushort_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT) + { + unsigned int other_mem = v.tv_sec; + if (EINA_UNLIKELY(v.tv_sec < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v.tv_sec > eina_value_uint_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_ULONG) + { + unsigned long other_mem = v.tv_sec; + if (EINA_UNLIKELY(v.tv_sec < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) && + ((unsigned long)v.tv_sec > eina_value_ulong_max))) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem = v.tv_sec; + if (EINA_UNLIKELY(v.tv_sec < 0)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v.tv_sec; + if (EINA_UNLIKELY(v.tv_sec < eina_value_char_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v.tv_sec > eina_value_char_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_SHORT) + { + short other_mem = v.tv_sec; + if (EINA_UNLIKELY(v.tv_sec < eina_value_short_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v.tv_sec > eina_value_short_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT) + { + int other_mem = v.tv_sec; + if (EINA_UNLIKELY(v.tv_sec < eina_value_int_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v.tv_sec > eina_value_int_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem = v.tv_sec; + if (EINA_UNLIKELY(v.tv_sec < eina_value_long_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v.tv_sec > eina_value_long_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v.tv_sec; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = (float)v.tv_sec + (float)v.tv_usec / 1.0e6; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = (double)v.tv_sec + (double)v.tv_usec / 1.0e6; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_STRINGSHARE || + convert == EINA_VALUE_TYPE_STRING) + { + const char *other_mem; + char buf[64]; + snprintf(buf, sizeof(buf), "%ld.%06ld", v.tv_sec, v.tv_usec); + other_mem = buf; /* required due &buf == buf */ + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } +} + +static Eina_Bool +_eina_value_type_timeval_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + struct timeval *tmem = mem; + *tmem = _eina_value_type_timeval_fix(ptr); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_timeval_vset(const Eina_Value_Type *type, void *mem, va_list args) +{ + const struct timeval desc = va_arg(args, struct timeval); + _eina_value_type_timeval_pset(type, mem, &desc); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_timeval_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + memcpy(ptr, mem, sizeof(struct timeval)); + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_TIMEVAL = { + EINA_VALUE_TYPE_VERSION, + sizeof(struct timeval), + "struct timeval", + _eina_value_type_timeval_setup, + _eina_value_type_timeval_flush, + _eina_value_type_timeval_copy, + _eina_value_type_timeval_compare, + _eina_value_type_timeval_convert_to, + NULL, /* no convert from */ + _eina_value_type_timeval_vset, + _eina_value_type_timeval_pset, + _eina_value_type_timeval_pget +}; + /* keep all basic types inlined in an array so we can compare if it's * a basic type using pointer arithmetic. * @@ -3587,6 +3789,7 @@ eina_value_init(void) EINA_VALUE_TYPE_ARRAY = &_EINA_VALUE_TYPE_ARRAY; EINA_VALUE_TYPE_LIST = &_EINA_VALUE_TYPE_LIST; EINA_VALUE_TYPE_HASH = &_EINA_VALUE_TYPE_HASH; + EINA_VALUE_TYPE_TIMEVAL = &_EINA_VALUE_TYPE_TIMEVAL; return EINA_TRUE; } @@ -3638,6 +3841,7 @@ EAPI const Eina_Value_Type *EINA_VALUE_TYPE_STRING = NULL; EAPI const Eina_Value_Type *EINA_VALUE_TYPE_ARRAY = NULL; EAPI const Eina_Value_Type *EINA_VALUE_TYPE_LIST = NULL; EAPI const Eina_Value_Type *EINA_VALUE_TYPE_HASH = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_TIMEVAL = NULL; EAPI Eina_Error EINA_ERROR_VALUE_FAILED = 0; diff --git a/legacy/eina/src/tests/eina_test_value.c b/legacy/eina/src/tests/eina_test_value.c index 5688365bc4..ab8567e2c5 100644 --- a/legacy/eina/src/tests/eina_test_value.c +++ b/legacy/eina/src/tests/eina_test_value.c @@ -1307,6 +1307,84 @@ START_TEST(eina_value_test_hash) } END_TEST + +START_TEST(eina_value_test_timeval) +{ + Eina_Value *value, other; + struct timeval itv, otv; + char c; + char *str; + + eina_init(); + + value = eina_value_new(EINA_VALUE_TYPE_TIMEVAL); + fail_unless(value != NULL); + + itv.tv_sec = 1; + itv.tv_usec = 123; + fail_unless(eina_value_set(value, itv)); + fail_unless(eina_value_get(value, &otv)); + fail_unless(memcmp(&itv, &otv, sizeof(struct timeval)) == 0); + + itv.tv_sec = 3; + itv.tv_usec = -1; + fail_unless(eina_value_set(value, itv)); + fail_unless(eina_value_get(value, &otv)); + itv.tv_sec = 2; + itv.tv_usec = 999999; + fail_unless(memcmp(&itv, &otv, sizeof(struct timeval)) == 0); + + fail_unless(eina_value_setup(&other, EINA_VALUE_TYPE_CHAR)); + fail_unless(eina_value_convert(value, &other)); + fail_unless(eina_value_get(&other, &c)); + fail_unless(c == 2); + eina_value_flush(&other); + + itv.tv_sec = 12345; + itv.tv_usec = 6789; + fail_unless(eina_value_set(value, itv)); + str = eina_value_to_string(value); + fail_unless(str != NULL); + fail_unless(strcmp(str, "12345.006789") == 0); + free(str); + + fail_unless(eina_value_setup(&other, EINA_VALUE_TYPE_TIMEVAL)); + fail_unless(eina_value_set(&other, itv)); + fail_unless(eina_value_compare(value, &other) == 0); + + itv.tv_sec++; + fail_unless(eina_value_set(&other, itv)); + fail_unless(eina_value_compare(value, &other) < 0); + + itv.tv_sec -= 2; + fail_unless(eina_value_set(&other, itv)); + fail_unless(eina_value_compare(value, &other) > 0); + + itv.tv_sec++; + fail_unless(eina_value_set(&other, itv)); + fail_unless(eina_value_compare(value, &other) == 0); + + itv.tv_usec++; + fail_unless(eina_value_set(&other, itv)); + fail_unless(eina_value_compare(value, &other) < 0); + + itv.tv_usec -= 2; + fail_unless(eina_value_set(&other, itv)); + fail_unless(eina_value_compare(value, &other) > 0); + + itv.tv_usec++; + fail_unless(eina_value_set(&other, itv)); + fail_unless(eina_value_compare(value, &other) == 0); + + + eina_value_flush(&other); + + + eina_value_free(value); + eina_shutdown(); +} +END_TEST + void eina_test_value(TCase *tc) { @@ -1321,4 +1399,5 @@ eina_test_value(TCase *tc) tcase_add_test(tc, eina_value_test_array); tcase_add_test(tc, eina_value_test_list); tcase_add_test(tc, eina_value_test_hash); + tcase_add_test(tc, eina_value_test_timeval); }