diff --git a/legacy/eina/ChangeLog b/legacy/eina/ChangeLog index d7519dd907..2e904ff2cd 100644 --- a/legacy/eina/ChangeLog +++ b/legacy/eina/ChangeLog @@ -192,3 +192,4 @@ 2012-01-09 Gustavo Barbieri * Add eina_inarray data type. + * Add eina_value data type (generic value storage). diff --git a/legacy/eina/NEWS b/legacy/eina/NEWS index f29632ff35..807d61da62 100644 --- a/legacy/eina/NEWS +++ b/legacy/eina/NEWS @@ -12,6 +12,7 @@ Additions: * eina_file_map_faulted API * Xattr iterator for Eina_File : eina_file_xattr_get and eina_file_xattr_value_get API * Added eina_inarray data type + * Added eina_value data type (generic value storage) Eina 1.1.0 diff --git a/legacy/eina/src/include/Eina.h b/legacy/eina/src/include/Eina.h index dd75f2d809..92b166b2b8 100644 --- a/legacy/eina/src/include/Eina.h +++ b/legacy/eina/src/include/Eina.h @@ -188,6 +188,7 @@ extern "C" { #include "eina_refcount.h" #include "eina_mmap.h" #include "eina_xattr.h" +#include "eina_value.h" #ifdef __cplusplus } diff --git a/legacy/eina/src/include/Makefile.am b/legacy/eina/src/include/Makefile.am index baf6994445..a818d5f27a 100644 --- a/legacy/eina/src/include/Makefile.am +++ b/legacy/eina/src/include/Makefile.am @@ -62,7 +62,9 @@ eina_lock.h \ eina_prefix.h \ eina_refcount.h \ eina_mmap.h \ -eina_xattr.h +eina_xattr.h \ +eina_value.h \ +eina_inline_value.x # Will be back for developper after 1.1. # eina_object.h diff --git a/legacy/eina/src/include/eina_inarray.h b/legacy/eina/src/include/eina_inarray.h index 7468dce56f..08edb4a8a4 100644 --- a/legacy/eina/src/include/eina_inarray.h +++ b/legacy/eina/src/include/eina_inarray.h @@ -271,6 +271,26 @@ EAPI Eina_Bool eina_inarray_insert_at(Eina_Inarray *array, unsigned int position, const void *data) EINA_ARG_NONNULL(1, 3); +/** + * @brief Copy the data over the given position. + * @param array array object + * @param position where to replace the member + * @param data data to be copied at position + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * Copies the given pointer contents at the given @a position in the + * array. The pointer is not referenced, instead it's contents is + * copied to the members array using the previously defined + * @c member_size. + * + * If @a position does not exist, it will fail. + * + * @since 1.2 + */ +EAPI Eina_Bool eina_inarray_replace_at(Eina_Inarray *array, + unsigned int position, + const void *data) EINA_ARG_NONNULL(1, 3); + /** * @brief Remove member at given position * @param array array object diff --git a/legacy/eina/src/include/eina_inline_value.x b/legacy/eina/src/include/eina_inline_value.x new file mode 100644 index 0000000000..8270037083 --- /dev/null +++ b/legacy/eina/src/include/eina_inline_value.x @@ -0,0 +1,943 @@ +/* EINA - EFL data type library + * Copyright (C) 2012 ProFUSION embedded systems + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifndef EINA_INLINE_VALUE_X_ +#define EINA_INLINE_VALUE_X_ + +#include +#include "eina_stringshare.h" + +/* NOTE: most of value is implemented here for performance reasons */ + +//#define EINA_VALUE_NO_OPTIMIZE 1 +#ifdef EINA_VALUE_NO_OPTIMIZE +#define EINA_VALUE_TYPE_DEFAULT(type) (0) +#else +#define EINA_VALUE_TYPE_DEFAULT(type) \ + ((type == EINA_VALUE_TYPE_UCHAR) || \ + (type == EINA_VALUE_TYPE_USHORT) || \ + (type == EINA_VALUE_TYPE_UINT) || \ + (type == EINA_VALUE_TYPE_ULONG) || \ + (type == EINA_VALUE_TYPE_UINT64) || \ + (type == EINA_VALUE_TYPE_CHAR) || \ + (type == EINA_VALUE_TYPE_SHORT) || \ + (type == EINA_VALUE_TYPE_INT) || \ + (type == EINA_VALUE_TYPE_LONG) || \ + (type == EINA_VALUE_TYPE_INT64) || \ + (type == EINA_VALUE_TYPE_FLOAT) || \ + (type == EINA_VALUE_TYPE_DOUBLE) || \ + (type == EINA_VALUE_TYPE_STRINGSHARE) || \ + (type == EINA_VALUE_TYPE_STRING)) +#endif + +#define EINA_VALUE_TYPE_CHECK_RETURN(value) \ + EINA_SAFETY_ON_NULL_RETURN(value); \ + EINA_SAFETY_ON_FALSE_RETURN(eina_value_type_check(value->type)) + +#define EINA_VALUE_TYPE_CHECK_RETURN_VAL(value, retval) \ + EINA_SAFETY_ON_NULL_RETURN_VAL(value, retval); \ + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), retval) + +#define EINA_VALUE_TYPE_DISPATCH(type, method, no_method_err, ...) \ + do \ + { \ + if (type->method) \ + type->method(type, ##__VA_ARGS__); \ + else \ + eina_error_set(no_method_err); \ + } \ + while (0) + +#define EINA_VALUE_TYPE_DISPATCH_RETURN(value, method, no_method_err, def_ret, ...) \ + do \ + { \ + if (type->method) \ + return type->method(type, ##__VA_ARGS__); \ + eina_error_set(no_method_err); \ + return def_ret; \ + } \ + while (0) + +static inline void * +eina_value_memory_get(const Eina_Value *value) +{ + if (value->type->value_size <= 8) + return (void *)value->value.buf; + return value->value.ptr; +} + +static inline Eina_Bool +eina_value_setup(Eina_Value *value, const Eina_Value_Type *type) +{ + void *mem; + + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(type), EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(type->value_size > 0, EINA_FALSE); + + value->type = type; + + if (type->value_size <= 8) + { + mem = &value->value; + memset(mem, 0, type->value_size); + } + else + { + mem = value->value.ptr = calloc(1, type->value_size); + EINA_SAFETY_ON_NULL_RETURN_VAL(mem, EINA_FALSE); + } + + if (EINA_VALUE_TYPE_DEFAULT(type)) + { + eina_error_set(0); + return EINA_TRUE; + } + + EINA_VALUE_TYPE_DISPATCH_RETURN(type, setup, + EINA_ERROR_VALUE_FAILED, EINA_FALSE, mem); +} + +static inline void +eina_value_flush(Eina_Value *value) +{ + const Eina_Value_Type *type; + void *mem; + + EINA_VALUE_TYPE_CHECK_RETURN(value); + + type = value->type; + mem = eina_value_memory_get(value); + + if (EINA_VALUE_TYPE_DEFAULT(type)) + { + if (type == EINA_VALUE_TYPE_STRINGSHARE) + { + if (value->value.ptr) eina_stringshare_del(value->value.ptr); + } + else if (type == EINA_VALUE_TYPE_STRING) + { + if (value->value.ptr) free(value->value.ptr); + } + else if (type->value_size > 8) free(mem); + eina_error_set(0); + return; + } + + EINA_VALUE_TYPE_DISPATCH(type, flush, EINA_ERROR_VALUE_FAILED, mem); + if (type->value_size > 8) free(mem); + value->type = NULL; +} + +static inline int +eina_value_compare(const Eina_Value *a, const Eina_Value *b) +{ + const Eina_Value_Type *type; + void *pa, *pb; + + EINA_VALUE_TYPE_CHECK_RETURN_VAL(a, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(b, -1); + EINA_SAFETY_ON_FALSE_RETURN_VAL(a->type == b->type, -1); + + eina_error_set(0); + type = a->type; + pa = eina_value_memory_get(a); + pb = eina_value_memory_get(b); + +#ifndef EINA_VALUE_NO_OPTIMIZE + if (type == EINA_VALUE_TYPE_UCHAR) + { + unsigned char *ta = pa, *tb = pb; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; + } + else if (type == EINA_VALUE_TYPE_USHORT) + { + unsigned short *ta = pa, *tb = pb; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; + } + else if (type == EINA_VALUE_TYPE_UINT) + { + unsigned int *ta = pa, *tb = pb; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; + } + else if (type == EINA_VALUE_TYPE_ULONG) + { + unsigned long *ta = pa, *tb = pb; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; + } + else if (type == EINA_VALUE_TYPE_UINT64) + { + uint64_t *ta = pa, *tb = pb; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; + } + else if (type == EINA_VALUE_TYPE_CHAR) + { + char *ta = pa, *tb = pb; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; + } + else if (type == EINA_VALUE_TYPE_SHORT) + { + short *ta = pa, *tb = pb; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; + } + else if (type == EINA_VALUE_TYPE_INT) + { + int *ta = pa, *tb = pb; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; + } + else if (type == EINA_VALUE_TYPE_LONG) + { + long *ta = pa, *tb = pb; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; + } + else if (type == EINA_VALUE_TYPE_INT64) + { + int64_t *ta = pa, *tb = pb; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; + } + else if (type == EINA_VALUE_TYPE_FLOAT) + { + float *ta = pa, *tb = pb; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; + } + else if (type == EINA_VALUE_TYPE_DOUBLE) + { + double *ta = pa, *tb = pb; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; + } + else if (type == EINA_VALUE_TYPE_STRINGSHARE || + type == EINA_VALUE_TYPE_STRING) + { + const char *sa = *(const char **)pa; + const char *sb = *(const char **)pb; + if (sa == sb) + return 0; + if (sa == NULL) + return -1; + if (sb == NULL) + return 1; + return strcmp(sa, sb); + } +#endif + + EINA_VALUE_TYPE_DISPATCH_RETURN(type, compare, EINA_ERROR_VALUE_FAILED, + EINA_FALSE, pa, pb); +} + +static inline Eina_Bool +eina_value_set(Eina_Value *value, ...) +{ + va_list args; + Eina_Bool ret; + va_start(args, value); + ret = eina_value_vset(value, args); + va_end(args); + return ret; +} + +static inline Eina_Bool +eina_value_get(const Eina_Value *value, ...) +{ + va_list args; + Eina_Bool ret; + va_start(args, value); + ret = eina_value_vget(value, args); + va_end(args); + return ret; +} + +static inline Eina_Bool +eina_value_vset(Eina_Value *value, va_list args) +{ + const Eina_Value_Type *type; + void *mem; + + EINA_VALUE_TYPE_CHECK_RETURN_VAL(value, EINA_FALSE); + + type = value->type; + mem = eina_value_memory_get(value); + eina_error_set(0); +#ifndef EINA_VALUE_NO_OPTIMIZE + if (type == EINA_VALUE_TYPE_UCHAR) + { + unsigned char *tmem = mem; + *tmem = va_arg(args, unsigned int); /* promoted by va_arg */ + return EINA_TRUE; + } + else if (type == EINA_VALUE_TYPE_USHORT) + { + unsigned short *tmem = mem; + *tmem = va_arg(args, unsigned int); /* promoted by va_arg */ + return EINA_TRUE; + } + else if (type == EINA_VALUE_TYPE_UINT) + { + unsigned int *tmem = mem; + *tmem = va_arg(args, unsigned int); + return EINA_TRUE; + } + else if (type == EINA_VALUE_TYPE_ULONG) + { + unsigned long *tmem = mem; + *tmem = va_arg(args, unsigned long); + return EINA_TRUE; + } + else if (type == EINA_VALUE_TYPE_UINT64) + { + uint64_t *tmem = mem; + *tmem = va_arg(args, uint64_t); + return EINA_TRUE; + } + else if (type == EINA_VALUE_TYPE_CHAR) + { + char *tmem = mem; + *tmem = va_arg(args, int); /* promoted by va_arg */ + return EINA_TRUE; + } + else if (type == EINA_VALUE_TYPE_SHORT) + { + short *tmem = mem; + *tmem = va_arg(args, int); /* promoted by va_arg */ + return EINA_TRUE; + } + else if (type == EINA_VALUE_TYPE_INT) + { + int *tmem = mem; + *tmem = va_arg(args, int); + return EINA_TRUE; + } + else if (type == EINA_VALUE_TYPE_LONG) + { + long *tmem = mem; + *tmem = va_arg(args, long); + return EINA_TRUE; + } + else if (type == EINA_VALUE_TYPE_INT64) + { + int64_t *tmem = mem; + *tmem = va_arg(args, int64_t); + return EINA_TRUE; + } + else if (type == EINA_VALUE_TYPE_FLOAT) + { + float *tmem = mem; + *tmem = va_arg(args, double); /* promoted by va_arg */ + return EINA_TRUE; + } + else if (type == EINA_VALUE_TYPE_DOUBLE) + { + double *tmem = mem; + *tmem = va_arg(args, double); + return EINA_TRUE; + } + else if (type == EINA_VALUE_TYPE_STRINGSHARE) + { + const char *str = va_arg(args, const char *); + return eina_stringshare_replace((const char **)&value->value.ptr, str); + } + else if (type == EINA_VALUE_TYPE_STRING) + { + const char *str = va_arg(args, const char *); + free(value->value.ptr); + if (!str) + value->value.ptr = NULL; + else + { + value->value.ptr = strdup(str); + if (!value->value.ptr) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } + } + return EINA_TRUE; + } +#endif + + EINA_VALUE_TYPE_DISPATCH_RETURN(value, vset, EINA_ERROR_VALUE_FAILED, + EINA_FALSE, mem, args); +} + +static inline Eina_Bool +eina_value_vget(const Eina_Value *value, va_list args) +{ + const Eina_Value_Type *type; + const void *mem; + void *ptr; + + EINA_VALUE_TYPE_CHECK_RETURN_VAL(value, EINA_FALSE); + + type = value->type; + mem = eina_value_memory_get(value); + ptr = va_arg(args, void *); + eina_error_set(0); + if (EINA_VALUE_TYPE_DEFAULT(type)) + { + memcpy(ptr, mem, type->value_size); + return EINA_TRUE; + } + + EINA_VALUE_TYPE_DISPATCH_RETURN(value, pget, EINA_ERROR_VALUE_FAILED, + EINA_FALSE, mem, ptr); +} + +static inline Eina_Bool +eina_value_pset(Eina_Value *value, const void *ptr) +{ + const Eina_Value_Type *type; + void *mem; + + EINA_VALUE_TYPE_CHECK_RETURN_VAL(value, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(ptr, EINA_FALSE); + + type = value->type; + mem = eina_value_memory_get(value); + eina_error_set(0); + + if (EINA_VALUE_TYPE_DEFAULT(type)) + { + if (type == EINA_VALUE_TYPE_STRINGSHARE) + { + const char * const *str = ptr; + return eina_stringshare_replace((const char **)&value->value.ptr, + *str); + } + else if (type == EINA_VALUE_TYPE_STRING) + { + const char * const *str = ptr; + free(value->value.ptr); + if (!*str) + value->value.ptr = NULL; + else + { + value->value.ptr = strdup(*str); + if (!value->value.ptr) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } + } + return EINA_TRUE; + } + else + memcpy(mem, ptr, type->value_size); + return EINA_TRUE; + } + + EINA_VALUE_TYPE_DISPATCH_RETURN(value, pset, EINA_ERROR_VALUE_FAILED, + EINA_FALSE, mem, ptr); +} + +static inline Eina_Bool +eina_value_pget(const Eina_Value *value, void *ptr) +{ + const Eina_Value_Type *type; + const void *mem; + + EINA_VALUE_TYPE_CHECK_RETURN_VAL(value, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(ptr, EINA_FALSE); + + type = value->type; + mem = eina_value_memory_get(value); + eina_error_set(0); + if (EINA_VALUE_TYPE_DEFAULT(type)) + { + memcpy(ptr, mem, type->value_size); + return EINA_TRUE; + } + + EINA_VALUE_TYPE_DISPATCH_RETURN(value, pget, EINA_ERROR_VALUE_FAILED, + EINA_FALSE, mem, ptr); +} + +static inline const Eina_Value_Type * +eina_value_type_get(const Eina_Value *value) +{ + EINA_VALUE_TYPE_CHECK_RETURN_VAL(value, NULL); + return value->type; +} + +#define EINA_VALUE_TYPE_ARRAY_CHECK_RETURN_VAL(value, retval) \ + EINA_SAFETY_ON_NULL_RETURN_VAL(value, retval); \ + EINA_SAFETY_ON_FALSE_RETURN_VAL(value->type == EINA_VALUE_TYPE_ARRAY, retval) + +static inline Eina_Bool +eina_value_array_setup(Eina_Value *value, const Eina_Value_Type *subtype, unsigned int step) +{ + Eina_Value_Array desc = {subtype, step, NULL}; + if (!eina_value_setup(value, EINA_VALUE_TYPE_ARRAY)) + return EINA_FALSE; + if (!eina_value_pset(value, &desc)) + { + eina_value_flush(value); + return EINA_FALSE; + } + return EINA_TRUE; +} + +static inline unsigned int +eina_value_array_count(const Eina_Value *value) +{ + Eina_Value_Array desc; + EINA_VALUE_TYPE_ARRAY_CHECK_RETURN_VAL(value, 0); + if (!eina_value_pget(value, &desc)) + return 0; + return eina_inarray_count(desc.array); +} + +static inline Eina_Bool +eina_value_array_remove(Eina_Value *value, unsigned int position) +{ + Eina_Value_Array desc; + void *mem; + + EINA_VALUE_TYPE_ARRAY_CHECK_RETURN_VAL(value, 0); + if (!eina_value_pget(value, &desc)) + return EINA_FALSE; + + mem = eina_inarray_nth(desc.array, position); + if (!mem) + return EINA_FALSE; + + eina_value_type_flush(desc.subtype, mem); + return eina_inarray_remove_at(desc.array, position); +} + +static inline Eina_Bool +eina_value_array_vset(Eina_Value *value, unsigned int position, va_list args) +{ + Eina_Value_Array desc; + void *mem; + + EINA_VALUE_TYPE_ARRAY_CHECK_RETURN_VAL(value, 0); + if (!eina_value_pget(value, &desc)) + return EINA_FALSE; + + mem = eina_inarray_nth(desc.array, position); + if (!mem) + return EINA_FALSE; + + eina_value_type_flush(desc.subtype, mem); + + if (!eina_value_type_setup(desc.subtype, mem)) goto error_setup; + if (!eina_value_type_vset(desc.subtype, mem, args)) goto error_set; + return EINA_TRUE; + + error_set: + eina_value_type_flush(desc.subtype, mem); + error_setup: + return EINA_FALSE; +} + +static inline Eina_Bool +eina_value_array_vget(const Eina_Value *value, unsigned int position, va_list args) +{ + Eina_Value_Array desc; + const void *mem; + void *ptr; + Eina_Bool ret; + + EINA_VALUE_TYPE_ARRAY_CHECK_RETURN_VAL(value, 0); + if (!eina_value_pget(value, &desc)) + return EINA_FALSE; + + mem = eina_inarray_nth(desc.array, position); + if (!mem) + return EINA_FALSE; + + ptr = va_arg(args, void *); + ret = eina_value_type_pget(desc.subtype, mem, ptr); + return ret; +} + +static inline Eina_Bool +eina_value_array_vinsert(Eina_Value *value, unsigned int position, va_list args) +{ + Eina_Value_Array desc; + void *mem, *placeholder; + + EINA_VALUE_TYPE_ARRAY_CHECK_RETURN_VAL(value, 0); + if (!eina_value_pget(value, &desc)) + return EINA_FALSE; + + placeholder = alloca(desc.subtype->value_size); + memset(placeholder, 0, desc.subtype->value_size); + if (!eina_inarray_insert_at(desc.array, position, placeholder)) + return EINA_FALSE; + + mem = eina_inarray_nth(desc.array, position); + if (!mem) + return EINA_FALSE; + + if (!eina_value_type_setup(desc.subtype, mem)) goto error_setup; + if (!eina_value_type_vset(desc.subtype, mem, args)) goto error_set; + return EINA_TRUE; + + error_set: + eina_value_type_flush(desc.subtype, mem); + error_setup: + eina_inarray_remove_at(desc.array, position); + return EINA_FALSE; +} + +static inline Eina_Bool +eina_value_array_vappend(Eina_Value *value, va_list args) +{ + Eina_Value_Array desc; + void *mem, *placeholder; + int position; + + EINA_VALUE_TYPE_ARRAY_CHECK_RETURN_VAL(value, 0); + if (!eina_value_pget(value, &desc)) + return EINA_FALSE; + + placeholder = alloca(desc.subtype->value_size); + memset(placeholder, 0, desc.subtype->value_size); + position = eina_inarray_append(desc.array, placeholder); + if (position < 0) + return EINA_FALSE; + + mem = eina_inarray_nth(desc.array, position); + if (!mem) + return EINA_FALSE; + + if (!eina_value_type_setup(desc.subtype, mem)) goto error_setup; + if (!eina_value_type_vset(desc.subtype, mem, args)) goto error_set; + return EINA_TRUE; + + error_set: + eina_value_type_flush(desc.subtype, mem); + error_setup: + eina_inarray_remove_at(desc.array, position); + return EINA_FALSE; +} + +static inline Eina_Bool +eina_value_array_set(Eina_Value *value, unsigned int position, ...) +{ + va_list args; + Eina_Bool ret; + va_start(args, position); + ret = eina_value_array_vset(value, position, args); + va_end(args); + return ret; +} + +static inline Eina_Bool +eina_value_array_get(const Eina_Value *value, unsigned int position, ...) +{ + va_list args; + Eina_Bool ret; + va_start(args, position); + ret = eina_value_array_vget(value, position, args); + va_end(args); + return ret; +} + +static inline Eina_Bool +eina_value_array_insert(Eina_Value *value, unsigned int position, ...) +{ + va_list args; + Eina_Bool ret; + va_start(args, position); + ret = eina_value_array_vinsert(value, position, args); + va_end(args); + return ret; +} + +static inline Eina_Bool eina_value_array_append(Eina_Value *value, ...) +{ + va_list args; + Eina_Bool ret; + va_start(args, value); + ret = eina_value_array_vappend(value, args); + va_end(args); + return ret; +} + +static inline Eina_Bool +eina_value_array_pset(Eina_Value *value, unsigned int position, const void *ptr) +{ + Eina_Value_Array desc; + void *mem; + + EINA_VALUE_TYPE_ARRAY_CHECK_RETURN_VAL(value, 0); + if (!eina_value_pget(value, &desc)) + return EINA_FALSE; + + mem = eina_inarray_nth(desc.array, position); + if (!mem) + return EINA_FALSE; + + eina_value_type_flush(desc.subtype, mem); + + if (!eina_value_type_setup(desc.subtype, mem)) goto error_setup; + if (!eina_value_type_pset(desc.subtype, mem, ptr)) goto error_set; + return EINA_TRUE; + + error_set: + eina_value_type_flush(desc.subtype, mem); + error_setup: + return EINA_FALSE; +} + +static inline Eina_Bool +eina_value_array_pget(const Eina_Value *value, unsigned int position, void *ptr) +{ + Eina_Value_Array desc; + const void *mem; + Eina_Bool ret; + + EINA_VALUE_TYPE_ARRAY_CHECK_RETURN_VAL(value, 0); + if (!eina_value_pget(value, &desc)) + return EINA_FALSE; + + mem = eina_inarray_nth(desc.array, position); + if (!mem) + return EINA_FALSE; + + ret = eina_value_type_pget(desc.subtype, mem, ptr); + return ret; +} + +static inline Eina_Bool +eina_value_array_pinsert(Eina_Value *value, unsigned int position, const void *ptr) +{ + Eina_Value_Array desc; + void *mem, *placeholder; + + EINA_VALUE_TYPE_ARRAY_CHECK_RETURN_VAL(value, 0); + if (!eina_value_pget(value, &desc)) + return EINA_FALSE; + + placeholder = alloca(desc.subtype->value_size); + memset(placeholder, 0, desc.subtype->value_size); + if (!eina_inarray_insert_at(desc.array, position, placeholder)) + return EINA_FALSE; + + mem = eina_inarray_nth(desc.array, position); + if (!mem) + return EINA_FALSE; + + if (!eina_value_type_setup(desc.subtype, mem)) goto error_setup; + if (!eina_value_type_pset(desc.subtype, mem, ptr)) goto error_set; + return EINA_TRUE; + + error_set: + eina_value_type_flush(desc.subtype, mem); + error_setup: + eina_inarray_remove_at(desc.array, position); + return EINA_FALSE; +} + +static inline Eina_Bool +eina_value_array_pappend(Eina_Value *value, const void *ptr) +{ + Eina_Value_Array desc; + void *mem, *placeholder; + int position; + + EINA_VALUE_TYPE_ARRAY_CHECK_RETURN_VAL(value, 0); + if (!eina_value_pget(value, &desc)) + return EINA_FALSE; + + placeholder = alloca(desc.subtype->value_size); + memset(placeholder, 0, desc.subtype->value_size); + position = eina_inarray_append(desc.array, placeholder); + if (position < 0) + return EINA_FALSE; + + mem = eina_inarray_nth(desc.array, position); + if (!mem) + return EINA_FALSE; + + if (!eina_value_type_setup(desc.subtype, mem)) goto error_setup; + if (!eina_value_type_pset(desc.subtype, mem, ptr)) goto error_set; + return EINA_TRUE; + + error_set: + eina_value_type_flush(desc.subtype, mem); + error_setup: + eina_inarray_remove_at(desc.array, position); + return EINA_FALSE; +} + +#undef EINA_VALUE_TYPE_ARRAY_CHECK_RETURN_VAL + + +static inline Eina_Bool +eina_value_type_setup(const Eina_Value_Type *type, void *mem) +{ + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(type), EINA_FALSE); + if (!type->setup) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + return type->setup(type, mem); +} + +static inline Eina_Bool +eina_value_type_flush(const Eina_Value_Type *type, void *mem) +{ + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(type), EINA_FALSE); + if (!type->flush) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + return type->flush(type, mem); +} + +static inline Eina_Bool +eina_value_type_copy(const Eina_Value_Type *type, const void *src, void *dst) +{ + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(type), EINA_FALSE); + if (!type->copy) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + return type->copy(type, src, dst); +} + +static inline int +eina_value_type_compare(const Eina_Value_Type *type, const void *a, void *b) +{ + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(type), EINA_FALSE); + if (!type->compare) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + return type->compare(type, a, b); +} + +static inline Eina_Bool +eina_value_type_convert_to(const Eina_Value_Type *type, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(type), EINA_FALSE); + if (!type->convert_to) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + return type->convert_to(type, convert, type_mem, convert_mem); +} + +static inline Eina_Bool +eina_value_type_convert_from(const Eina_Value_Type *type, const Eina_Value_Type *convert, void *type_mem, const void *convert_mem) +{ + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(type), EINA_FALSE); + if (!type->convert_from) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + return type->convert_from(type, convert, type_mem, convert_mem); +} + +static inline Eina_Bool +eina_value_type_vset(const Eina_Value_Type *type, void *mem, va_list args) +{ + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(type), EINA_FALSE); + if (!type->vset) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + return type->vset(type, mem, args); +} + +static inline Eina_Bool +eina_value_type_pset(const Eina_Value_Type *type, void *mem, const void *ptr) +{ + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(type), EINA_FALSE); + if (!type->pset) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + return type->pset(type, mem, ptr); +} + +static inline Eina_Bool +eina_value_type_pget(const Eina_Value_Type *type, const void *mem, void *ptr) +{ + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(type), EINA_FALSE); + if (!type->pget) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + return type->pget(type, mem, ptr); +} + +#undef EINA_VALUE_TYPE_DEFAULT +#undef EINA_VALUE_TYPE_CHECK_RETURN +#undef EINA_VALUE_TYPE_CHECK_RETURN_VAL +#undef EINA_VALUE_TYPE_DISPATCH +#undef EINA_VALUE_TYPE_DISPATCH_RETURN +#endif diff --git a/legacy/eina/src/include/eina_value.h b/legacy/eina/src/include/eina_value.h new file mode 100644 index 0000000000..e5efd949dd --- /dev/null +++ b/legacy/eina/src/include/eina_value.h @@ -0,0 +1,1415 @@ +/* EINA - EFL data type library + * Copyright (C) 2012 ProFUSION embedded systems + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifndef EINA_VALUE_H_ +#define EINA_VALUE_H_ + +#include "eina_types.h" +#include "eina_fp.h" /* defines int64_t and uint64_t */ +#include "eina_inarray.h" +#include + +/** + * @addtogroup Eina_Data_Types_Group Data Types + * + * @since 1.2 + * + * @{ + */ + +/** + * @addtogroup Eina_Containers_Group Containers + * + * @{ + */ + +/** + * @defgroup Eina_Value_Group Generic Value Storage + * + * @{ + */ + + +/** + * @typedef Eina_Value + * Store generic values. + * + * @since 1.2 + */ +typedef struct _Eina_Value Eina_Value; + +/** + * @typedef Eina_Value_Type + * Describes access to the value + * + * @since 1.2 + */ +typedef struct _Eina_Value_Type Eina_Value_Type; + +/** + * @typedef Eina_Value_Union + * Union with all known values to be hold. + * + * @since 1.2 + */ +typedef union _Eina_Value_Union Eina_Value_Union; + +/** + * @union _Eina_Value_Union + * All possible values to be hold. + * + * @since 1.2 + */ +union _Eina_Value_Union +{ + unsigned char buf[8]; /**< just hold 8-bytes, more goes into ptr */ + void *ptr; /**< used as generic pointer */ + uint64_t _guarantee; /**< guarantees 8-byte alignment */ +}; + +/** + * @var EINA_VALUE_TYPE_UCHAR + * manages unsigned char type. + * + * @since 1.2 + */ +EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_UCHAR; + +/** + * @var EINA_VALUE_TYPE_USHORT + * manages unsigned short type. + * + * @since 1.2 + */ +EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_USHORT; + +/** + * @var EINA_VALUE_TYPE_UINT + * manages unsigned int type. + * + * @since 1.2 + */ +EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_UINT; + +/** + * @var EINA_VALUE_TYPE_ULONG + * manages unsigned long type. + * + * @since 1.2 + */ +EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_ULONG; + +/** + * @var EINA_VALUE_TYPE_UINT64 + * manages unsigned integer of 64 bits type. + * + * @since 1.2 + */ +EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_UINT64; + +/** + * @var EINA_VALUE_TYPE_CHAR + * manages char type. + * + * @since 1.2 + */ +EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_CHAR; + +/** + * @var EINA_VALUE_TYPE_SHORT + * manages short type. + * + * @since 1.2 + */ +EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_SHORT; + +/** + * @var EINA_VALUE_TYPE_INT + * manages int type. + * + * @since 1.2 + */ +EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_INT; + +/** + * @var EINA_VALUE_TYPE_LONG + * manages long type. + * + * @since 1.2 + */ +EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_LONG; + +/** + * @var EINA_VALUE_TYPE_INT64 + * manages integer of 64 bits type. + * + * @since 1.2 + */ +EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_INT64; + +/** + * @var EINA_VALUE_TYPE_FLOAT + * manages float type. + * + * @since 1.2 + */ +EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_FLOAT; + +/** + * @var EINA_VALUE_TYPE_DOUBLE + * manages double type. + * + * @since 1.2 + */ +EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_DOUBLE; + +/** + * @var EINA_VALUE_TYPE_STRINGSHARE + * manages stringshare type. + * + * @since 1.2 + */ +EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_STRINGSHARE; + +/** + * @var EINA_VALUE_TYPE_STRING + * manages string type. + * + * @since 1.2 + */ +EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_STRING; + + +/** + * @var EINA_VALUE_TYPE_ARRAY + * + * manages array type. The value get/set are the type of elements in + * the array, use the alternaties: + * @li eina_value_array_get() and eina_value_array_set() + * @li eina_value_array_vget() and eina_value_array_vset() + * @li eina_value_array_pget() and eina_value_array_pset() + * + * @since 1.2 + */ +EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_ARRAY; + + +/** + * @var EINA_ERROR_VALUE_FAILED + * Error identifier corresponding to value check failure. + * + * @since 1.2 + */ +EAPI extern int EINA_ERROR_VALUE_FAILED; + +/** + * @defgroup Eina_Value_Value_Group Generic Value management + * + * @{ + */ + +/** + * @struct _Eina_Value + * defines the contents of a value + * + * @since 1.2 + */ +struct _Eina_Value +{ + const Eina_Value_Type *type; /**< how to access values */ + Eina_Value_Union value; /**< to be accessed with type descriptor */ +}; + +/** + * @brief Create generic value storage. + * @param type how to manage this value. + * @return The new value or @c NULL on failure. + * + * Create a new generic value storage. The members are managed using + * the description specified by @a type. + * + * Some types may specify more operations, as an example + * #EINA_VALUE_TYPE_ARRAY uses eina_value_array_set(), + * eina_value_array_get() and so on. + * + * On failure, @c NULL is returned and #EINA_ERROR_OUT_OF_MEMORY or + * #EINA_ERROR_VALUE_FAILED is set. + * + * @note this is a helper around eina_value_setup() doing malloc for + * you. Consider using eina_value_flush() and eina_value_setup() + * to avoid memory allocations. + * + * @see eina_value_free() + * + * @since 1.2 + */ +EAPI Eina_Value *eina_value_new(const Eina_Value_Type *type) EINA_ARG_NONNULL(1) EINA_MALLOC EINA_WARN_UNUSED_RESULT; + +/** + * @brief Free value and its data. + * @param value value object + * + * @see eina_value_flush() + * + * @since 1.2 + */ +EAPI void eina_value_free(Eina_Value *value) EINA_ARG_NONNULL(1); + + +/** + * @brief Setup generic value storage. + * @param value value object + * @param type how to manage this value. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * Setups new generic value storage. The members are managed using the + * description specified by @a type. + * + * Some types may specify more operations, as an example + * #EINA_VALUE_TYPE_ARRAY uses eina_value_array_set(), + * eina_value_array_get() and so on. + * + * @note Existing memory is ignored! If it was previously set, then + * use eina_value_flush() first. + * + * On failure, #EINA_FALSE is returned and #EINA_ERROR_OUT_OF_MEMORY + * or #EINA_ERROR_VALUE_FAILED is set. + * + * @see eina_value_flush() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_setup(Eina_Value *value, + const Eina_Value_Type *type) EINA_ARG_NONNULL(1, 2); + +/** + * @brief Create generic value storage. + * @param value value object + * + * Releases all the resources associated with a generic value. The + * value must be already set with eina_value_setup() or + * eina_value_new(). + * + * After this call returns, the contents of the value are undefined, + * but the value can be reused by calling eina_value_setup() again. + * + * @see eina_value_setup() + * @see eina_value_free() + * + * @since 1.2 + */ +static inline void eina_value_flush(Eina_Value *value) EINA_ARG_NONNULL(1); + +/** + * @brief Copy generic value storage. + * @param value source value object + * @param copy destination value object + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * The @a copy object is considered internalized and its existing + * contents are ignored (just as if eina_value_flush() was called on + * it). + * + * The copy happens by calling eina_value_setup() on @a copy, followed + * by getting the contents of @a value and setting it to @a copy. + * + * @since 1.2 + */ +EAPI Eina_Bool eina_value_copy(const Eina_Value *value, + Eina_Value *copy) EINA_ARG_NONNULL(1, 2); + +/** + * @brief Compare generic value storage. + * @param a left side of comparison + * @param b right side of comparison + * @return less than zero if a < b, greater than zero if a > b, zero + * if equals + * + * @since 1.2 + */ +static inline int eina_value_compare(const Eina_Value *a, + const Eina_Value *b) EINA_ARG_NONNULL(1, 2); + +/** + * @brief Set the generic value. + * @param value source value object + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * The variable argument is dependent on chosen type. The list for + * basic types: + * + * @li EINA_VALUE_TYPE_UCHAR: unsigned char + * @li EINA_VALUE_TYPE_USHORT: unsigned short + * @li EINA_VALUE_TYPE_UINT: unsigned int + * @li EINA_VALUE_TYPE_ULONG: unsigned long + * @li EINA_VALUE_TYPE_UINT64: uint64_t + * @li EINA_VALUE_TYPE_CHAR: char + * @li EINA_VALUE_TYPE_SHORT: short + * @li EINA_VALUE_TYPE_INT: int + * @li EINA_VALUE_TYPE_LONG: long + * @li EINA_VALUE_TYPE_INT64: int64_t + * @li EINA_VALUE_TYPE_FLOAT: float + * @li EINA_VALUE_TYPE_DOUBLE: double + * @li EINA_VALUE_TYPE_STRINGSHARE: const char * + * @li EINA_VALUE_TYPE_STRING: const char * + * @li EINA_VALUE_TYPE_ARRAY: Eina_Value_Array + * + * @code + * Eina_Value *value = eina_value_new(EINA_VALUE_TYPE_INT); + * int x = 567; + * eina_value_set(value, 1234); + * eina_value_set(value, x); + * + * eina_value_flush(value); + * + * eina_value_setup(value, EINA_VALUE_TYPE_STRING); + * eina_value_set(value, "hello world!"); + * + * eina_value_free(value); + * @endcode + * + * @note for array member see eina_value_array_set() + * + * @see eina_value_get() + * @see eina_value_vset() + * @see eina_value_pset() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_set(Eina_Value *value, + ...) EINA_ARG_NONNULL(1); + +/** + * @brief Get the generic value. + * @param value source value object + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * The value is returned in the variable argument parameter, the + * actual value is type-dependent, but usually it will be what is + * stored inside the object. There shouldn't be any memory allocation, + * thus the contents should @b not be free'd. + * + * The variable argument is dependent on chosen type. The list for + * basic types: + * + * @li EINA_VALUE_TYPE_UCHAR: unsigned char* + * @li EINA_VALUE_TYPE_USHORT: unsigned short* + * @li EINA_VALUE_TYPE_UINT: unsigned int* + * @li EINA_VALUE_TYPE_ULONG: unsigned long* + * @li EINA_VALUE_TYPE_UINT64: uint64_t* + * @li EINA_VALUE_TYPE_CHAR: char* + * @li EINA_VALUE_TYPE_SHORT: short* + * @li EINA_VALUE_TYPE_INT: int* + * @li EINA_VALUE_TYPE_LONG: long* + * @li EINA_VALUE_TYPE_INT64: int64_t* + * @li EINA_VALUE_TYPE_FLOAT: float* + * @li EINA_VALUE_TYPE_DOUBLE: double* + * @li EINA_VALUE_TYPE_STRINGSHARE: const char ** + * @li EINA_VALUE_TYPE_STRING: const char ** + * @li EINA_VALUE_TYPE_ARRAY: Eina_Value_Array* + * + * @code + * Eina_Value *value = eina_value_new(EINA_VALUE_TYPE_INT); + * int x; + * const char *s; + * + * eina_value_set(value, 1234); + * eina_value_get(value, &x); + * + * eina_value_flush(value); + * + * eina_value_setup(value, EINA_VALUE_TYPE_STRING); + * eina_value_set(value, "hello world!"); + * eina_value_get(value, &s); + * + * eina_value_free(value); + * @endcode + * + * @note for array member see eina_value_array_get() + * + * @see eina_value_set() + * @see eina_value_vset() + * @see eina_value_pset() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_get(const Eina_Value *value, + ...) EINA_ARG_NONNULL(1); + +/** + * @brief Set the generic value. + * @param value source value object + * @param args variable argument + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * @note for array member see eina_value_array_vset() + * + * @see eina_value_vget() + * @see eina_value_set() + * @see eina_value_pset() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_vset(Eina_Value *value, + va_list args) EINA_ARG_NONNULL(1); + +/** + * @brief Get the generic value. + * @param value source value object + * @param args variable argument + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * The value is returned in the variable argument parameter, the + * actual value is type-dependent, but usually it will be what is + * stored inside the object. There shouldn't be any memory allocation, + * thus the contents should @b not be free'd. + * + * @note for array member see eina_value_array_vget() + * + * @see eina_value_vset() + * @see eina_value_get() + * @see eina_value_pget() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_vget(const Eina_Value *value, + va_list args) EINA_ARG_NONNULL(1); + +/** + * @brief Set the generic value from pointer. + * @param value source value object + * @param ptr pointer to specify the contents. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * The pointer type is dependent on chosen value type. The list for + * basic types: + * + * @li EINA_VALUE_TYPE_UCHAR: unsigned char* + * @li EINA_VALUE_TYPE_USHORT: unsigned short* + * @li EINA_VALUE_TYPE_UINT: unsigned int* + * @li EINA_VALUE_TYPE_ULONG: unsigned long* + * @li EINA_VALUE_TYPE_UINT64: uint64_t* + * @li EINA_VALUE_TYPE_CHAR: char* + * @li EINA_VALUE_TYPE_SHORT: short* + * @li EINA_VALUE_TYPE_INT: int* + * @li EINA_VALUE_TYPE_LONG: long* + * @li EINA_VALUE_TYPE_INT64: int64_t* + * @li EINA_VALUE_TYPE_FLOAT: float* + * @li EINA_VALUE_TYPE_DOUBLE: double* + * @li EINA_VALUE_TYPE_STRINGSHARE: const char ** + * @li EINA_VALUE_TYPE_STRING: const char ** + * @li EINA_VALUE_TYPE_ARRAY: Eina_Value_Array* + * + * @note the pointer contents are written using the size defined by + * type. It can be larger than void* or uint64_t. + * + * @code + * Eina_Value *value = eina_value_new(EINA_VALUE_TYPE_INT); + * int x = 567; + * const char *s = "hello world!"; + * + * eina_value_pset(value, &x); + * + * eina_value_flush(value); + * + * eina_value_setup(value, EINA_VALUE_TYPE_STRING); + * eina_value_pset(value, &s); + * + * eina_value_free(value); + * @endcode + * + * @note for array member see eina_value_array_pset() + * + * @see eina_value_pget() + * @see eina_value_set() + * @see eina_value_vset() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_pset(Eina_Value *value, + const void *ptr) EINA_ARG_NONNULL(1, 2); + +/** + * @brief Get the generic value to pointer. + * @param value source value object + * @param ptr pointer to receive the contents. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * The value is returned in pointer contents, the actual value is + * type-dependent, but usually it will be what is stored inside the + * object. There shouldn't be any memory allocation, thus the contents + * should @b not be free'd. + * + * The pointer type is dependent on chosen value type. The list for + * basic types: + * + * @li EINA_VALUE_TYPE_UCHAR: unsigned char* + * @li EINA_VALUE_TYPE_USHORT: unsigned short* + * @li EINA_VALUE_TYPE_UINT: unsigned int* + * @li EINA_VALUE_TYPE_ULONG: unsigned long* + * @li EINA_VALUE_TYPE_UINT64: uint64_t* + * @li EINA_VALUE_TYPE_CHAR: char* + * @li EINA_VALUE_TYPE_SHORT: short* + * @li EINA_VALUE_TYPE_INT: int* + * @li EINA_VALUE_TYPE_LONG: long* + * @li EINA_VALUE_TYPE_INT64: int64_t* + * @li EINA_VALUE_TYPE_FLOAT: float* + * @li EINA_VALUE_TYPE_DOUBLE: double* + * @li EINA_VALUE_TYPE_STRINGSHARE: const char ** + * @li EINA_VALUE_TYPE_STRING: const char ** + * @li EINA_VALUE_TYPE_ARRAY: Eina_Value_Array* + * + * @code + * Eina_Value *value = eina_value_new(EINA_VALUE_TYPE_INT); + * int x; + * const char *s; + * + * eina_value_set(value, 1234); + * eina_value_pget(value, &x); + * + * eina_value_flush(value); + * + * eina_value_setup(value, EINA_VALUE_TYPE_STRING); + * eina_value_set(value, "hello world!"); + * eina_value_pget(value, &s); + * + * eina_value_free(value); + * @endcode + * + * @note for array member see eina_value_array_get() + * + * @see eina_value_set() + * @see eina_value_vset() + * @see eina_value_pset() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_pget(const Eina_Value *value, + void *ptr) EINA_ARG_NONNULL(1, 2); + +/** + * @brief Convert one value to another type. + * @param value source value object. + * @param convert destination value object. + * @return #EINA_TRUE if converted, #EINA_FALSE otherwise. + * + * Converts one value to another trying first @a value type + * @c convert_to() function, if it did not work, try @a convert + * type @c convert_from() function. + * + * Conversion functions are type defined, the basic types can convert + * between themselves, but conversion is strict! That is, if + * converting from negative value to unsigned type, it will fail. It + * also fails on value overflow. + * + * It is recommended that all types implement at least convert to + * string, used by eina_value_to_string(). + * + * @note Both objects must be setup beforehand! + * + * @since 1.2 + */ +EAPI Eina_Bool eina_value_convert(const Eina_Value *value, + Eina_Value *convert) EINA_ARG_NONNULL(1, 2); + + +/** + * @brief Convert value to string. + * @param value value object. + * @return newly allocated memory or @c NULL on failure. + * + * @see eina_value_convert() + * @since 1.2 + */ +EAPI char *eina_value_to_string(const Eina_Value *value) EINA_ARG_NONNULL(1); + +/** + * @brief Query value type. + * @param value value object. + * @return type instance or @c NULL if type is invalid. + * + * Check if value type is valid and returns it. A type is invalid if + * it does not exist or if it is using a different version field. + * + * @see eina_value_type_check() + * + * @since 1.2 + */ +static inline const Eina_Value_Type *eina_value_type_get(const Eina_Value *value) EINA_PURE EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT; + +/** + * @} + */ + + +/** + * @defgroup Eina_Value_Array_Group Generic Value Array management + * + * @{ + */ + + +/** + * @typedef Eina_Value_Array + * Value type for #EINA_VALUE_TYPE_ARRAY + * + * @since 1.2 + */ +typedef struct _Eina_Value_Array Eina_Value_Array; + +/** + * @struct _Eina_Value_Array + * Used to store the array and its subtype. + */ +struct _Eina_Value_Array +{ + const Eina_Value_Type *subtype; /**< how to allocate and access items */ + unsigned int step; /**< how to grow the members array */ + Eina_Inarray *array; /**< the array that holds data, members are of subtype->value_size bytes. */ + }; + +/** + * @brief Create generic value storage of type array. + * @param subtype how to manage this array members. + * @param step how to grow the members array. + * @return The new value or @c NULL on failure. + * + * Create a new generic value storage of type array. The members are + * managed using the description specified by @a subtype. + * + * On failure, @c NULL is returned and #EINA_ERROR_OUT_OF_MEMORY or + * #EINA_ERROR_VALUE_FAILED is set. + * + * @note this is a helper around eina_value_array_setup() doing malloc + * for you. + * + * @see eina_value_free() + * @see eina_value_array_setup() + * + * @since 1.2 + */ +EAPI Eina_Value *eina_value_array_new(const Eina_Value_Type *subtype, + unsigned int step) EINA_ARG_NONNULL(1); + +/** + * @brief Setup generic value storage of type array. + * @param value value object + * @param subtype how to manage this array members. + * @param step how to grow the members array. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * Setups new generic value storage of type array with the given + * @a subtype. + * + * This is the same as calling eina_value_set() with + * #EINA_VALUE_TYPE_ARRAY followed by eina_value_pset() with the + * #Eina_Value_Array description configured. + * + * @note Existing memory is ignored! If it was previously set, then + * use eina_value_flush() first. + * + * On failure, #EINA_FALSE is returned and #EINA_ERROR_OUT_OF_MEMORY + * or #EINA_ERROR_VALUE_FAILED is set. + * + * @see eina_value_flush() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_array_setup(Eina_Value *value, + const Eina_Value_Type *subtype, + unsigned int step) EINA_ARG_NONNULL(1, 2); + +/** + * @brief Query number of elements in value of array type. + * @param value value object. + * @return number of child elements. + * @since 1.2 + */ +static inline unsigned int eina_value_array_count(const Eina_Value *value); + +/** + * @brief Remove element at given position in value of array type. + * @param value value object. + * @param position index of the member + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * @since 1.2 + */ +static inline Eina_Bool eina_value_array_remove(Eina_Value *value, + unsigned int position) EINA_ARG_NONNULL(1); + +/** + * @brief Set the generic value in an array member. + * @param value source value object + * @param position index of the member + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * The variable argument is dependent on chosen subtype. The list for + * basic types: + * + * @li EINA_VALUE_TYPE_UCHAR: unsigned char + * @li EINA_VALUE_TYPE_USHORT: unsigned short + * @li EINA_VALUE_TYPE_UINT: unsigned int + * @li EINA_VALUE_TYPE_ULONG: unsigned long + * @li EINA_VALUE_TYPE_UINT64: uint64_t + * @li EINA_VALUE_TYPE_CHAR: char + * @li EINA_VALUE_TYPE_SHORT: short + * @li EINA_VALUE_TYPE_INT: int + * @li EINA_VALUE_TYPE_LONG: long + * @li EINA_VALUE_TYPE_INT64: int64_t + * @li EINA_VALUE_TYPE_FLOAT: float + * @li EINA_VALUE_TYPE_DOUBLE: double + * @li EINA_VALUE_TYPE_STRINGSHARE: const char * + * @li EINA_VALUE_TYPE_STRING: const char * + * @li EINA_VALUE_TYPE_ARRAY: Eina_Value_Array + * + * @code + * Eina_Value *value = eina_value_array_new(EINA_VALUE_TYPE_INT); + * int x; + * + * eina_value_array_append(value, 1234); + * eina_value_array_set(value, 0, 5678); + * eina_value_array_get(value, 0, &x); + * eina_value_free(value); + * @endcode + * + * @see eina_value_array_get() + * @see eina_value_array_vset() + * @see eina_value_array_pset() + * @see eina_value_array_insert() + * @see eina_value_array_vinsert() + * @see eina_value_array_pinsert() + * @see eina_value_array_append() + * @see eina_value_array_vappend() + * @see eina_value_array_pappend() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_array_set(Eina_Value *value, + unsigned int position, + ...) EINA_ARG_NONNULL(1); + +/** + * @brief Get the generic value from an array member. + * @param value source value object + * @param position index of the member + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * The value is returned in the variable argument parameter, the + * actual value is type-dependent, but usually it will be what is + * stored inside the object. There shouldn't be any memory allocation, + * thus the contents should @b not be free'd. + * + * The variable argument is dependent on chosen subtype. The list for + * basic types: + * + * @li EINA_VALUE_TYPE_UCHAR: unsigned char* + * @li EINA_VALUE_TYPE_USHORT: unsigned short* + * @li EINA_VALUE_TYPE_UINT: unsigned int* + * @li EINA_VALUE_TYPE_ULONG: unsigned long* + * @li EINA_VALUE_TYPE_UINT64: uint64_t* + * @li EINA_VALUE_TYPE_CHAR: char* + * @li EINA_VALUE_TYPE_SHORT: short* + * @li EINA_VALUE_TYPE_INT: int* + * @li EINA_VALUE_TYPE_LONG: long* + * @li EINA_VALUE_TYPE_INT64: int64_t* + * @li EINA_VALUE_TYPE_FLOAT: float* + * @li EINA_VALUE_TYPE_DOUBLE: double* + * @li EINA_VALUE_TYPE_STRINGSHARE: const char ** + * @li EINA_VALUE_TYPE_STRING: const char ** + * @li EINA_VALUE_TYPE_ARRAY: Eina_Value_Array* + * + * @code + * Eina_Value *value = eina_value_array_new(EINA_VALUE_TYPE_INT); + * int x; + * + * eina_value_array_append(value, 1234); + * eina_value_array_get(value, 0, &x); + * eina_value_free(value); + * @endcode + * + * @see eina_value_array_set() + * @see eina_value_array_vset() + * @see eina_value_array_pset() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_array_get(const Eina_Value *value, + unsigned int position, + ...) EINA_ARG_NONNULL(1); + +/** + * @brief Insert the generic value in an array member position. + * @param value source value object + * @param position index of the member + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * The variable argument is dependent on chosen subtype. The list for + * basic types: + * + * @li EINA_VALUE_TYPE_UCHAR: unsigned char + * @li EINA_VALUE_TYPE_USHORT: unsigned short + * @li EINA_VALUE_TYPE_UINT: unsigned int + * @li EINA_VALUE_TYPE_ULONG: unsigned long + * @li EINA_VALUE_TYPE_UINT64: uint64_t + * @li EINA_VALUE_TYPE_CHAR: char + * @li EINA_VALUE_TYPE_SHORT: short + * @li EINA_VALUE_TYPE_INT: int + * @li EINA_VALUE_TYPE_LONG: long + * @li EINA_VALUE_TYPE_INT64: int64_t + * @li EINA_VALUE_TYPE_FLOAT: float + * @li EINA_VALUE_TYPE_DOUBLE: double + * @li EINA_VALUE_TYPE_STRINGSHARE: const char * + * @li EINA_VALUE_TYPE_STRING: const char * + * @li EINA_VALUE_TYPE_ARRAY: Eina_Value_Array + * + * @code + * Eina_Value *value = eina_value_array_new(EINA_VALUE_TYPE_INT); + * int x; + * + * eina_value_array_insert(value, 0, 1234); + * eina_value_array_get(value, 0, &x); + * eina_value_free(value); + * @endcode + * + * @see eina_value_array_set() + * @see eina_value_array_get() + * @see eina_value_array_vset() + * @see eina_value_array_pset() + * @see eina_value_array_vinsert() + * @see eina_value_array_pinsert() + * @see eina_value_array_append() + * @see eina_value_array_vappend() + * @see eina_value_array_pappend() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_array_insert(Eina_Value *value, + unsigned int position, + ...) EINA_ARG_NONNULL(1); + + +/** + * @brief Append the generic value in an array. + * @param value source value object + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * The variable argument is dependent on chosen subtype. The list for + * basic types: + * + * @li EINA_VALUE_TYPE_UCHAR: unsigned char + * @li EINA_VALUE_TYPE_USHORT: unsigned short + * @li EINA_VALUE_TYPE_UINT: unsigned int + * @li EINA_VALUE_TYPE_ULONG: unsigned long + * @li EINA_VALUE_TYPE_UINT64: uint64_t + * @li EINA_VALUE_TYPE_CHAR: char + * @li EINA_VALUE_TYPE_SHORT: short + * @li EINA_VALUE_TYPE_INT: int + * @li EINA_VALUE_TYPE_LONG: long + * @li EINA_VALUE_TYPE_INT64: int64_t + * @li EINA_VALUE_TYPE_FLOAT: float + * @li EINA_VALUE_TYPE_DOUBLE: double + * @li EINA_VALUE_TYPE_STRINGSHARE: const char * + * @li EINA_VALUE_TYPE_STRING: const char * + * @li EINA_VALUE_TYPE_ARRAY: Eina_Value_Array + * + * @code + * Eina_Value *value = eina_value_array_new(EINA_VALUE_TYPE_INT); + * int x; + * + * eina_value_array_append(value, 1234); + * eina_value_array_get(value, 0, &x); + * eina_value_free(value); + * @endcode + * + * @see eina_value_array_set() + * @see eina_value_array_get() + * @see eina_value_array_vset() + * @see eina_value_array_pset() + * @see eina_value_array_vinsert() + * @see eina_value_array_pinsert() + * @see eina_value_array_append() + * @see eina_value_array_vappend() + * @see eina_value_array_pappend() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_array_append(Eina_Value *value, + ...) EINA_ARG_NONNULL(1); + +/** + * @brief Set the generic value in an array member. + * @param value source value object + * @param position index of the member + * @param args variable argument + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * @see eina_value_array_set() + * @see eina_value_array_get() + * @see eina_value_array_pset() + * @see eina_value_array_insert() + * @see eina_value_array_vinsert() + * @see eina_value_array_pinsert() + * @see eina_value_array_append() + * @see eina_value_array_vappend() + * @see eina_value_array_pappend() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_array_vset(Eina_Value *value, + unsigned int position, + va_list args) EINA_ARG_NONNULL(1); + +/** + * @brief Get the generic value from an array member. + * @param value source value object + * @param position index of the member + * @param args variable argument + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * The value is returned in the variable argument parameter, the + * actual value is type-dependent, but usually it will be what is + * stored inside the object. There shouldn't be any memory allocation, + * thus the contents should @b not be free'd. + * + * @see eina_value_array_vset() + * @see eina_value_array_get() + * @see eina_value_array_pget() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_array_vget(const Eina_Value *value, + unsigned int position, + va_list args) EINA_ARG_NONNULL(1); +/** + * @brief Insert the generic value in an array member position. + * @param value source value object + * @param position index of the member + * @param args variable argument + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * @see eina_value_array_set() + * @see eina_value_array_get() + * @see eina_value_array_vset() + * @see eina_value_array_pset() + * @see eina_value_array_insert() + * @see eina_value_array_pinsert() + * @see eina_value_array_append() + * @see eina_value_array_vappend() + * @see eina_value_array_pappend() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_array_vinsert(Eina_Value *value, + unsigned int position, + va_list args) EINA_ARG_NONNULL(1); + +/** + * @brief Append the generic value in an array. + * @param value source value object + * @param args variable argument + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * @see eina_value_array_set() + * @see eina_value_array_get() + * @see eina_value_array_vget() + * @see eina_value_array_pset() + * @see eina_value_array_insert() + * @see eina_value_array_vinsert() + * @see eina_value_array_pinsert() + * @see eina_value_array_append() + * @see eina_value_array_pappend() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_array_vappend(Eina_Value *value, + va_list args) EINA_ARG_NONNULL(1); + + +/** + * @brief Set the generic value in an array member from pointer. + * @param value source value object + * @param position index of the member + * @param ptr pointer to specify the contents. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * The pointer type is dependent on chosen value type. The list for + * basic types: + * + * @li EINA_VALUE_TYPE_UCHAR: unsigned char* + * @li EINA_VALUE_TYPE_USHORT: unsigned short* + * @li EINA_VALUE_TYPE_UINT: unsigned int* + * @li EINA_VALUE_TYPE_ULONG: unsigned long* + * @li EINA_VALUE_TYPE_UINT64: uint64_t* + * @li EINA_VALUE_TYPE_CHAR: char* + * @li EINA_VALUE_TYPE_SHORT: short* + * @li EINA_VALUE_TYPE_INT: int* + * @li EINA_VALUE_TYPE_LONG: long* + * @li EINA_VALUE_TYPE_INT64: int64_t* + * @li EINA_VALUE_TYPE_FLOAT: float* + * @li EINA_VALUE_TYPE_DOUBLE: double* + * @li EINA_VALUE_TYPE_STRINGSHARE: const char ** + * @li EINA_VALUE_TYPE_STRING: const char ** + * @li EINA_VALUE_TYPE_ARRAY: Eina_Value_Array* + * + * @note the pointer contents are written using the size defined by + * type. It can be larger than void* or uint64_t. + * + * @code + * Eina_Value *value = eina_value_array_new(EINA_VALUE_TYPE_INT); + * int x = 1234; + * + * eina_value_array_append(value, 1234); + * eina_value_array_pset(value, 0, &x); + * eina_value_array_pget(value, 0, &x); + * eina_value_free(value); + * @endcode + * + * @see eina_value_array_set() + * @see eina_value_array_get() + * @see eina_value_array_vset() + * @see eina_value_array_insert() + * @see eina_value_array_vinsert() + * @see eina_value_array_pinsert() + * @see eina_value_array_append() + * @see eina_value_array_vappend() + * @see eina_value_array_pappend() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_array_pset(Eina_Value *value, + unsigned int position, + const void *ptr) EINA_ARG_NONNULL(1, 3); + +/** + * @brief Get the generic value to pointer from an array member. + * @param value source value object + * @param position index of the member + * @param ptr pointer to receive the contents. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * The value is returned in pointer contents, the actual value is + * type-dependent, but usually it will be what is stored inside the + * object. There shouldn't be any memory allocation, thus the contents + * should @b not be free'd. + * + * The pointer type is dependent on chosen value type. The list for + * basic types: + * + * @li EINA_VALUE_TYPE_UCHAR: unsigned char* + * @li EINA_VALUE_TYPE_USHORT: unsigned short* + * @li EINA_VALUE_TYPE_UINT: unsigned int* + * @li EINA_VALUE_TYPE_ULONG: unsigned long* + * @li EINA_VALUE_TYPE_UINT64: uint64_t* + * @li EINA_VALUE_TYPE_CHAR: char* + * @li EINA_VALUE_TYPE_SHORT: short* + * @li EINA_VALUE_TYPE_INT: int* + * @li EINA_VALUE_TYPE_LONG: long* + * @li EINA_VALUE_TYPE_INT64: int64_t* + * @li EINA_VALUE_TYPE_FLOAT: float* + * @li EINA_VALUE_TYPE_DOUBLE: double* + * @li EINA_VALUE_TYPE_STRINGSHARE: const char ** + * @li EINA_VALUE_TYPE_STRING: const char ** + * @li EINA_VALUE_TYPE_ARRAY: Eina_Value_Array* + * + * @code + * Eina_Value *value = eina_value_array_new(EINA_VALUE_TYPE_INT); + * int x; + * + * eina_value_array_append(value, 1234); + * eina_value_array_pget(value, 0, &x); + * eina_value_free(value); + * @endcode + * + * @see eina_value_array_set() + * @see eina_value_array_vset() + * @see eina_value_array_pset() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_array_pget(const Eina_Value *value, + unsigned int position, + void *ptr) EINA_ARG_NONNULL(1, 3); + +/** + * @brief Insert the generic value in an array member position from pointer. + * @param value source value object + * @param position index of the member + * @param ptr pointer to specify the contents. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * The pointer type is dependent on chosen value type. The list for + * basic types: + * + * @li EINA_VALUE_TYPE_UCHAR: unsigned char* + * @li EINA_VALUE_TYPE_USHORT: unsigned short* + * @li EINA_VALUE_TYPE_UINT: unsigned int* + * @li EINA_VALUE_TYPE_ULONG: unsigned long* + * @li EINA_VALUE_TYPE_UINT64: uint64_t* + * @li EINA_VALUE_TYPE_CHAR: char* + * @li EINA_VALUE_TYPE_SHORT: short* + * @li EINA_VALUE_TYPE_INT: int* + * @li EINA_VALUE_TYPE_LONG: long* + * @li EINA_VALUE_TYPE_INT64: int64_t* + * @li EINA_VALUE_TYPE_FLOAT: float* + * @li EINA_VALUE_TYPE_DOUBLE: double* + * @li EINA_VALUE_TYPE_STRINGSHARE: const char ** + * @li EINA_VALUE_TYPE_STRING: const char ** + * @li EINA_VALUE_TYPE_ARRAY: Eina_Value_Array* + * + * @note the pointer contents are written using the size defined by + * type. It can be larger than void* or uint64_t. + * + * @code + * Eina_Value *value = eina_value_array_new(EINA_VALUE_TYPE_INT); + * int x = 1234; + * + * eina_value_array_pinsert(value, 0, &x); + * eina_value_array_pget(value, 0, &x); + * eina_value_free(value); + * @endcode + * + * @see eina_value_array_set() + * @see eina_value_array_get() + * @see eina_value_array_vset() + * @see eina_value_array_insert() + * @see eina_value_array_vinsert() + * @see eina_value_array_pinsert() + * @see eina_value_array_append() + * @see eina_value_array_vappend() + * @see eina_value_array_pappend() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_array_pinsert(Eina_Value *value, + unsigned int position, + const void *ptr) EINA_ARG_NONNULL(1); + +/** + * @brief Append the generic value in an array from pointer. + * @param value source value object + * @param ptr pointer to specify the contents. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * + * The pointer type is dependent on chosen value type. The list for + * basic types: + * + * @li EINA_VALUE_TYPE_UCHAR: unsigned char* + * @li EINA_VALUE_TYPE_USHORT: unsigned short* + * @li EINA_VALUE_TYPE_UINT: unsigned int* + * @li EINA_VALUE_TYPE_ULONG: unsigned long* + * @li EINA_VALUE_TYPE_UINT64: uint64_t* + * @li EINA_VALUE_TYPE_CHAR: char* + * @li EINA_VALUE_TYPE_SHORT: short* + * @li EINA_VALUE_TYPE_INT: int* + * @li EINA_VALUE_TYPE_LONG: long* + * @li EINA_VALUE_TYPE_INT64: int64_t* + * @li EINA_VALUE_TYPE_FLOAT: float* + * @li EINA_VALUE_TYPE_DOUBLE: double* + * @li EINA_VALUE_TYPE_STRINGSHARE: const char ** + * @li EINA_VALUE_TYPE_STRING: const char ** + * @li EINA_VALUE_TYPE_ARRAY: Eina_Value_Array* + * + * @note the pointer contents are written using the size defined by + * type. It can be larger than void* or uint64_t. + * + * @code + * Eina_Value *value = eina_value_array_new(EINA_VALUE_TYPE_INT); + * int x = 1234; + * + * eina_value_array_pappend(value, &x); + * eina_value_array_pget(value, 0, &x); + * eina_value_free(value); + * @endcode + * + * @see eina_value_array_set() + * @see eina_value_array_get() + * @see eina_value_array_vset() + * @see eina_value_array_insert() + * @see eina_value_array_vinsert() + * @see eina_value_array_pinsert() + * @see eina_value_array_append() + * @see eina_value_array_vappend() + * @see eina_value_array_pappend() + * + * @since 1.2 + */ +static inline Eina_Bool eina_value_array_pappend(Eina_Value *value, + const void *ptr) EINA_ARG_NONNULL(1); + +/** + * @} + */ + +/** + * @defgroup Eina_Value_Type_Group Generic Value Type management + * + * @{ + */ + +/** + * @struct _Eina_Value_Type + * API to access values. + * + * @since 1.2 + */ +struct _Eina_Value_Type +{ + /** + * @def EINA_VALUE_TYPE_VERSION + * Current API version, used to validate type. + */ +#define EINA_VALUE_TYPE_VERSION (1) + unsigned int version; /**< must be #EINA_VALUE_TYPE_VERSION */ + unsigned int value_size; /**< byte size of value */ + const char *name; /**< name for debug and introspection */ + Eina_Bool (*setup)(const Eina_Value_Type *type, void *mem); /**< mem will be malloc(value_size) and should be configured */ + Eina_Bool (*flush)(const Eina_Value_Type *type, void *mem); /**< clear any values from mem */ + Eina_Bool (*copy)(const Eina_Value_Type *type, const void *src, void *dst); /**< how to copy values, both memory are @c value_size */ + int (*compare)(const Eina_Value_Type *type, const void *a, const void *b); /**< how to compare values, both memory are @c value_size */ + Eina_Bool (*convert_to)(const Eina_Value_Type *type, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem); /**< how to convert values, both memory are @c value_size */ + Eina_Bool (*convert_from)(const Eina_Value_Type *type, const Eina_Value_Type *convert, void *type_mem, const void *convert_mem); /**< how to convert values, both memory are @c value_size */ + Eina_Bool (*vset)(const Eina_Value_Type *type, void *mem, va_list args); /**< how to set memory from variable argument */ + Eina_Bool (*pset)(const Eina_Value_Type *type, void *mem, const void *ptr); /**< how to set memory from pointer */ + Eina_Bool (*pget)(const Eina_Value_Type *type, const void *mem, void *ptr); /**< how to read memory */ +}; + +/** + * @brief Query type name. + * @param type type reference. + * @return string or @c NULL if type is invalid. + * @since 1.2 + */ +EAPI const char *eina_value_type_name_get(const Eina_Value_Type *type) EINA_PURE EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT; + +/** + * @brief Check if type is valid. + * @param type type reference. + * @return #EINA_TRUE if valid, #EINA_FALSE otherwise. + * + * A type is invalid if it's NULL or if version field is not the same + * as runtime #EINA_VALUE_TYPE_VERSION. + * + * @since 1.2 + */ +EAPI Eina_Bool eina_value_type_check(const Eina_Value_Type *type) EINA_PURE EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT; + +/** + * @brief Setup memory using type descriptor. + * @param type type reference. + * @param mem memory to operate, must be of size @c type->value_size. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * @since 1.2 + */ +static inline Eina_Bool eina_value_type_setup(const Eina_Value_Type *type, void *mem); + +/** + * @brief Flush (clear) memory using type descriptor. + * @param type type reference. + * @param mem memory to operate, must be of size @c type->value_size. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * @since 1.2 + */ +static inline Eina_Bool eina_value_type_flush(const Eina_Value_Type *type, void *mem); + +/** + * @brief Copy memory using type descriptor. + * @param type type reference. + * @param src memory to operate, must be of size @c type->value_size. + * @param dst memory to operate, must be of size @c type->value_size. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * @since 1.2 + */ +static inline Eina_Bool eina_value_type_copy(const Eina_Value_Type *type, const void *src, void *dst); + +/** + * @brief Compare memory using type descriptor. + * @param type type reference. + * @param a memory to operate, must be of size @c type->value_size. + * @param b memory to operate, must be of size @c type->value_size. + * @return less than zero if a < b, greater than zero if a > b, zero if equal. + * @since 1.2 + */ +static inline int eina_value_type_compare(const Eina_Value_Type *type, const void *a, void *b); + +/** + * @brief Convert memory using type descriptor. + * @param type type reference of the source. + * @param convert type reference of the destination. + * @param type_mem memory to operate, must be of size @c type->value_size. + * @param convert_mem memory to operate, must be of size @c convert->value_size. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * @since 1.2 + */ +static inline Eina_Bool eina_value_type_convert_to(const Eina_Value_Type *type, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem); + +/** + * @brief Convert memory using type descriptor. + * @param type type reference of the destination. + * @param convert type reference of the source. + * @param type_mem memory to operate, must be of size @c type->value_size. + * @param convert_mem memory to operate, must be of size @c convert->value_size. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * @since 1.2 + */ +static inline Eina_Bool eina_value_type_convert_from(const Eina_Value_Type *type, const Eina_Value_Type *convert, void *type_mem, const void *convert_mem); + +/** + * @brief Set memory using type descriptor and variable argument. + * @param type type reference of the source. + * @param mem memory to operate, must be of size @c type->value_size. + * @param args input value. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * @since 1.2 + */ +static inline Eina_Bool eina_value_type_vset(const Eina_Value_Type *type, void *mem, va_list args); + +/** + * @brief Set memory using type descriptor and pointer. + * @param type type reference of the source. + * @param mem memory to operate, must be of size @c type->value_size. + * @param ptr pointer to input value. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * @since 1.2 + */ +static inline Eina_Bool eina_value_type_pset(const Eina_Value_Type *type, void *mem, const void *ptr); + +/** + * @brief Get memory using type descriptor. + * @param type type reference of the source. + * @param mem memory to operate, must be of size @c type->value_size. + * @param ptr pointer to output. + * @return #EINA_TRUE on success, #EINA_FALSE otherwise. + * @since 1.2 + */ +static inline Eina_Bool eina_value_type_pget(const Eina_Value_Type *type, const void *mem, void *ptr); + +/** + * @} + */ + +#include "eina_inline_value.x" + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +#endif diff --git a/legacy/eina/src/lib/eina_inarray.c b/legacy/eina/src/lib/eina_inarray.c index 9a68f699ea..8e5268852d 100644 --- a/legacy/eina/src/lib/eina_inarray.c +++ b/legacy/eina/src/lib/eina_inarray.c @@ -522,6 +522,20 @@ eina_inarray_insert_at(Eina_Inarray *array, unsigned int position, const void *d return EINA_TRUE; } +EAPI Eina_Bool +eina_inarray_replace_at(Eina_Inarray *array, unsigned int position, const void *data) +{ + unsigned char *p; + + EINA_MAGIC_CHECK_INARRAY(array, EINA_FALSE); + EINA_SAFETY_ON_TRUE_RETURN_VAL(position >= array->len, EINA_FALSE); + + p = _eina_inarray_get(array, position); + memcpy(p, data, array->member_size); + + return EINA_TRUE; +} + EAPI Eina_Bool eina_inarray_remove_at(Eina_Inarray *array, unsigned int position) { diff --git a/legacy/eina/src/lib/eina_main.c b/legacy/eina/src/lib/eina_main.c index ad8d8f4f0e..79f8a36632 100644 --- a/legacy/eina/src/lib/eina_main.c +++ b/legacy/eina/src/lib/eina_main.c @@ -68,6 +68,7 @@ #include "eina_safety_checks.h" #include "eina_inlist.h" #include "eina_inarray.h" +#include "eina_value.h" /*============================================================================* * Local * @@ -151,6 +152,7 @@ EAPI Eina_Inlist *_eina_tracking = NULL; S(simple_xml); S(file); S(prefix); + S(value); #undef S struct eina_desc_setup @@ -186,7 +188,8 @@ static const struct eina_desc_setup _eina_desc_setup[] = { S(quadtree), S(simple_xml), S(file), - S(prefix) + S(prefix), + S(value) #undef S }; static const size_t _eina_desc_setup_len = sizeof(_eina_desc_setup) / diff --git a/legacy/eina/src/lib/eina_value.c b/legacy/eina/src/lib/eina_value.c index 554f907d6d..b4fb13dfba 100644 --- a/legacy/eina/src/lib/eina_value.c +++ b/legacy/eina/src/lib/eina_value.c @@ -28,8 +28,2901 @@ # include "config.h" #endif +/* _GNU_SOURCE: asprintf() */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif #include "eina_config.h" #include "eina_private.h" +#include "eina_error.h" +#include "eina_log.h" +#include "eina_strbuf.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" +#include "eina_value.h" + +#include /* asprintf() */ +#include /* PRId64 and PRIu64 */ + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +static int _eina_value_log_dom = -1; + +#ifdef ERR +#undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_eina_value_log_dom, __VA_ARGS__) + +#ifdef DBG +#undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(_eina_value_log_dom, __VA_ARGS__) + +static const unsigned char eina_value_uchar_max = 255U; +static const char eina_value_char_max = 127; +static const char eina_value_char_min = -127 - 1; + +static const unsigned short eina_value_ushort_max = 65535U; +static const short eina_value_short_max = 32767; +static const short eina_value_short_min = -32767 - 1; + +static const unsigned int eina_value_uint_max = 4294967295U; +static const int eina_value_int_max = 2147483647; +static const int eina_value_int_min = -2147483647 - 1; + +static const uint64_t eina_value_uint64_max = 18446744073709551615ULL; +static const int64_t eina_value_int64_max = 9223372036854775807LL; +static const int64_t eina_value_int64_min = -9223372036854775807LL - 1LL; + +#if __WORDSIZE == 64 +static const unsigned long eina_value_ulong_max = 18446744073709551615ULL; +static const long eina_value_long_max = 9223372036854775807LL; +static const long eina_value_long_min = -9223372036854775807LL - 1LL; +#else +static const unsigned long eina_value_ulong_max = 4294967295U; +static const long eina_value_long_max = 2147483647; +static const long eina_value_long_min = -2147483647 - 1; +#endif + + +static Eina_Bool +_eina_value_type_uchar_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + unsigned char *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uchar_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uchar_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const unsigned char *s = src; + unsigned char *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_uchar_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const unsigned char *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_uchar_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const unsigned char v = *(const unsigned char *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_USHORT) + { + unsigned short other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT) + { + unsigned int other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_ULONG) + { + unsigned long other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v; + if (EINA_UNLIKELY(v > (unsigned char)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; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT) + { + int other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + 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), "%hhu", v); + 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; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uchar_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + unsigned char *tmem = mem; + *tmem = va_arg(args, unsigned int); /* char is promoted to int for va_arg */ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uchar_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + unsigned char *tmem = mem; + const unsigned char *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uchar_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const unsigned char *tmem = mem; + unsigned char *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_UCHAR = { + EINA_VALUE_TYPE_VERSION, + sizeof(unsigned char), + "unsigned char", + _eina_value_type_uchar_setup, + _eina_value_type_uchar_flush, + _eina_value_type_uchar_copy, + _eina_value_type_uchar_compare, + _eina_value_type_uchar_convert_to, + NULL, /* no convert from */ + _eina_value_type_uchar_vset, + _eina_value_type_uchar_pset, + _eina_value_type_uchar_pget +}; + +static Eina_Bool +_eina_value_type_ushort_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + unsigned short *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ushort_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ushort_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const unsigned short *s = src; + unsigned short *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_ushort_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const unsigned short *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_ushort_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const unsigned short v = *(const unsigned short *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v > 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; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT) + { + unsigned int other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_ULONG) + { + unsigned long other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v; + if (EINA_UNLIKELY(v > (unsigned char)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; + if (EINA_UNLIKELY(v > (unsigned short)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; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + 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), "%hu", v); + 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; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ushort_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + unsigned short *tmem = mem; + *tmem = va_arg(args, unsigned int); /* short is promoted to int for va_arg */ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ushort_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + unsigned short *tmem = mem; + const unsigned short *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ushort_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const unsigned short *tmem = mem; + unsigned short *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_USHORT = { + EINA_VALUE_TYPE_VERSION, + sizeof(unsigned short), + "unsigned short", + _eina_value_type_ushort_setup, + _eina_value_type_ushort_flush, + _eina_value_type_ushort_copy, + _eina_value_type_ushort_compare, + _eina_value_type_ushort_convert_to, + NULL, /* no convert from */ + _eina_value_type_ushort_vset, + _eina_value_type_ushort_pset, + _eina_value_type_ushort_pget +}; + +static Eina_Bool +_eina_value_type_uint_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + unsigned int *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const unsigned int *s = src; + unsigned int *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_uint_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const unsigned int *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_uint_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const unsigned int v = *(const unsigned int *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v > 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; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_ULONG) + { + unsigned long other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v; + if (EINA_UNLIKELY(v > (unsigned char)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; + if (EINA_UNLIKELY(v > (unsigned short)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; + if (EINA_UNLIKELY(v > (unsigned int)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; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + 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), "%u", v); + 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; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + unsigned int *tmem = mem; + *tmem = va_arg(args, unsigned int); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + unsigned int *tmem = mem; + const unsigned int *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const unsigned int *tmem = mem; + unsigned int *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_UINT = { + EINA_VALUE_TYPE_VERSION, + sizeof(unsigned int), + "unsigned int", + _eina_value_type_uint_setup, + _eina_value_type_uint_flush, + _eina_value_type_uint_copy, + _eina_value_type_uint_compare, + _eina_value_type_uint_convert_to, + NULL, /* no convert from */ + _eina_value_type_uint_vset, + _eina_value_type_uint_pset, + _eina_value_type_uint_pget +}; + +static Eina_Bool +_eina_value_type_ulong_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + unsigned long *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ulong_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ulong_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const unsigned long *s = src; + unsigned long *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_ulong_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const unsigned long *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_ulong_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const unsigned long v = *(const unsigned long *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v > 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; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v; + if (EINA_UNLIKELY(v > (unsigned char)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; + if (EINA_UNLIKELY(v > (unsigned short)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; + if (EINA_UNLIKELY(v > (unsigned int)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; + if (EINA_UNLIKELY(v > (unsigned long)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; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + 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), "%lu", v); + 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; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ulong_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + unsigned long *tmem = mem; + *tmem = va_arg(args, unsigned long); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ulong_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + unsigned long *tmem = mem; + const unsigned long *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_ulong_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const unsigned long *tmem = mem; + unsigned long *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_ULONG = { + EINA_VALUE_TYPE_VERSION, + sizeof(unsigned long), + "unsigned long", + _eina_value_type_ulong_setup, + _eina_value_type_ulong_flush, + _eina_value_type_ulong_copy, + _eina_value_type_ulong_compare, + _eina_value_type_ulong_convert_to, + NULL, /* no convert from */ + _eina_value_type_ulong_vset, + _eina_value_type_ulong_pset, + _eina_value_type_ulong_pget +}; + + +static Eina_Bool +_eina_value_type_uint64_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + uint64_t *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint64_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint64_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const uint64_t *s = src; + uint64_t *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_uint64_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const uint64_t *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_uint64_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const uint64_t v = *(const uint64_t *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) && + (v > 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; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v; + if (EINA_UNLIKELY(v > (unsigned char)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; + if (EINA_UNLIKELY(v > (unsigned short)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; + if (EINA_UNLIKELY(v > (unsigned int)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; + if (EINA_UNLIKELY(v > (unsigned long)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; + if (EINA_UNLIKELY(v > (uint64_t)eina_value_int64_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + 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), "%"PRIu64, v); + 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; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint64_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + uint64_t *tmem = mem; + *tmem = va_arg(args, uint64_t); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint64_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + uint64_t *tmem = mem; + const uint64_t *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_uint64_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const uint64_t *tmem = mem; + uint64_t *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_UINT64 = { + EINA_VALUE_TYPE_VERSION, + sizeof(uint64_t), + "uint64_t", + _eina_value_type_uint64_setup, + _eina_value_type_uint64_flush, + _eina_value_type_uint64_copy, + _eina_value_type_uint64_compare, + _eina_value_type_uint64_convert_to, + NULL, /* no convert from */ + _eina_value_type_uint64_vset, + _eina_value_type_uint64_pset, + _eina_value_type_uint64_pget +}; + +static Eina_Bool +_eina_value_type_char_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + char *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_char_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_char_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const char *s = src; + char *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_char_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const char *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_char_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const char v = *(const char *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v < 0)) + 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; + if (EINA_UNLIKELY(v < 0)) + 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; + if (EINA_UNLIKELY(v < 0)) + 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; + if (EINA_UNLIKELY(v < 0)) + 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; + if (EINA_UNLIKELY(v < 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; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_SHORT) + { + short other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT) + { + int other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + 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), "%hhd", v); + 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; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_char_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + char *tmem = mem; + *tmem = va_arg(args, int); /* char is promoted to int for va_arg */ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_char_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + char *tmem = mem; + const char *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_char_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const char *tmem = mem; + char *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_CHAR = { + EINA_VALUE_TYPE_VERSION, + sizeof(char), + "char", + _eina_value_type_char_setup, + _eina_value_type_char_flush, + _eina_value_type_char_copy, + _eina_value_type_char_compare, + _eina_value_type_char_convert_to, + NULL, /* no convert from */ + _eina_value_type_char_vset, + _eina_value_type_char_pset, + _eina_value_type_char_pget +}; + +static Eina_Bool +_eina_value_type_short_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + short *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_short_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_short_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const short *s = src; + short *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_short_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const short *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_short_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const short v = *(const short *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < 0)) + 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; + if (EINA_UNLIKELY(v < 0)) + 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; + if (EINA_UNLIKELY(v < 0)) + 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; + if (EINA_UNLIKELY(v < 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; + if (EINA_UNLIKELY(v < eina_value_char_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT) + { + int other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + 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), "%hd", v); + 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; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_short_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + short *tmem = mem; + *tmem = va_arg(args, int); /* short int is promoted to int for va_arg */ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_short_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + short *tmem = mem; + const short *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_short_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const short *tmem = mem; + short *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_SHORT = { + EINA_VALUE_TYPE_VERSION, + sizeof(short), + "short", + _eina_value_type_short_setup, + _eina_value_type_short_flush, + _eina_value_type_short_copy, + _eina_value_type_short_compare, + _eina_value_type_short_convert_to, + NULL, /* no convert from */ + _eina_value_type_short_vset, + _eina_value_type_short_pset, + _eina_value_type_short_pget +}; + +static Eina_Bool +_eina_value_type_int_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + int *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const int *s = src; + int *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_int_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const int *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_int_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const int v = *(const int *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < 0)) + 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; + if (EINA_UNLIKELY(v < 0)) + 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; + if (EINA_UNLIKELY(v < 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; + if (EINA_UNLIKELY(v < eina_value_char_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < eina_value_short_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + 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), "%d", v); + 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; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + int *tmem = mem; + *tmem = va_arg(args, int); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + int *tmem = mem; + const int *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const int *tmem = mem; + int *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_INT = { + EINA_VALUE_TYPE_VERSION, + sizeof(int), + "int", + _eina_value_type_int_setup, + _eina_value_type_int_flush, + _eina_value_type_int_copy, + _eina_value_type_int_compare, + _eina_value_type_int_convert_to, + NULL, /* no convert from */ + _eina_value_type_int_vset, + _eina_value_type_int_pset, + _eina_value_type_int_pget +}; + +static Eina_Bool +_eina_value_type_long_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + long *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_long_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_long_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const long *s = src; + long *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_long_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const long *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_long_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const long v = *(const long *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < 0)) + 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; + if (EINA_UNLIKELY(v < 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; + if (EINA_UNLIKELY(v < eina_value_char_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < eina_value_short_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < eina_value_int_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + 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", v); + 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; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_long_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + long *tmem = mem; + *tmem = va_arg(args, long); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_long_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + long *tmem = mem; + const long *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_long_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const long *tmem = mem; + long *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_LONG = { + EINA_VALUE_TYPE_VERSION, + sizeof(long), + "long", + _eina_value_type_long_setup, + _eina_value_type_long_flush, + _eina_value_type_long_copy, + _eina_value_type_long_compare, + _eina_value_type_long_convert_to, + NULL, /* no convert from */ + _eina_value_type_long_vset, + _eina_value_type_long_pset, + _eina_value_type_long_pget +}; + +static Eina_Bool +_eina_value_type_int64_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + int64_t *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int64_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int64_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const int64_t *s = src; + int64_t *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_int64_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const int64_t *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_int64_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const int64_t v = *(const int64_t *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) && + (v > 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; + if (EINA_UNLIKELY(v < 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; + if (EINA_UNLIKELY(v < eina_value_char_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < eina_value_short_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < eina_value_int_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < eina_value_long_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + 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), "%"PRId64, v); + 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; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int64_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + int64_t *tmem = mem; + *tmem = va_arg(args, int64_t); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int64_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + int64_t *tmem = mem; + const int64_t *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_int64_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const int64_t *tmem = mem; + int64_t *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_INT64 = { + EINA_VALUE_TYPE_VERSION, + sizeof(int64_t), + "int64_t", + _eina_value_type_int64_setup, + _eina_value_type_int64_flush, + _eina_value_type_int64_copy, + _eina_value_type_int64_compare, + _eina_value_type_int64_convert_to, + NULL, /* no convert from */ + _eina_value_type_int64_vset, + _eina_value_type_int64_pset, + _eina_value_type_int64_pget +}; + +static Eina_Bool +_eina_value_type_float_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + float *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_float_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_float_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const float *s = src; + float *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_float_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const float *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_float_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const float v = *(const float *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) && + (v > 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; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_uint64_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem = v; + if (EINA_UNLIKELY(v < eina_value_char_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < eina_value_short_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < eina_value_int_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < eina_value_long_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < eina_value_int64_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > eina_value_int64_max)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + 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), "%f", v); + 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; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_float_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + float *tmem = mem; + *tmem = va_arg(args, double); /* float is promoted to double for va_args */ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_float_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + float *tmem = mem; + const float *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_float_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const float *tmem = mem; + float *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_FLOAT = { + EINA_VALUE_TYPE_VERSION, + sizeof(float), + "float", + _eina_value_type_float_setup, + _eina_value_type_float_flush, + _eina_value_type_float_copy, + _eina_value_type_float_compare, + _eina_value_type_float_convert_to, + NULL, /* no convert from */ + _eina_value_type_float_vset, + _eina_value_type_float_pset, + _eina_value_type_float_pget +}; + +static Eina_Bool +_eina_value_type_double_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + double *tmem = mem; + *tmem = 0; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_double_flush(const Eina_Value_Type *type __UNUSED__, void *mem __UNUSED__) +{ + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_double_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const double *s = src; + double *d = dst; + *d = *s; + return EINA_TRUE; +} + +static int +_eina_value_type_double_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const double *ta = a, *tb = b; + if (*ta < *tb) + return -1; + else if (*ta > *tb) + return 1; + return 0; +} + +static Eina_Bool +_eina_value_type_double_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const double v = *(const double *)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem = v; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < 0)) + return EINA_FALSE; + if (EINA_UNLIKELY((sizeof(other_mem) != sizeof(v)) && + (v > 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; + if (EINA_UNLIKELY(v < 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; + if (EINA_UNLIKELY(v < eina_value_char_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < eina_value_short_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < eina_value_int_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + if (EINA_UNLIKELY(v < eina_value_long_min)) + return EINA_FALSE; + if (EINA_UNLIKELY(v > 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; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem = v; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem = v; + 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), "%g", (double)v); + 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; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_double_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + double *tmem = mem; + *tmem = va_arg(args, double); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_double_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + double *tmem = mem; + const double *p = ptr; + *tmem = *p; + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_double_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + const double *tmem = mem; + double *p = ptr; + *p = *tmem; + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_DOUBLE = { + EINA_VALUE_TYPE_VERSION, + sizeof(double), + "double", + _eina_value_type_double_setup, + _eina_value_type_double_flush, + _eina_value_type_double_copy, + _eina_value_type_double_compare, + _eina_value_type_double_convert_to, + NULL, /* no convert from */ + _eina_value_type_double_vset, + _eina_value_type_double_pset, + _eina_value_type_double_pget +}; + +static Eina_Bool +_eina_value_type_string_common_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + const char **tmem = mem; + *tmem = NULL; + return EINA_TRUE; +} + +static int +_eina_value_type_string_common_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const char *sa = *(const char **)a; + const char *sb = *(const char **)b; + if (sa == sb) + return 0; + if (sa == NULL) + return -1; + if (sb == NULL) + return 1; + return strcmp(sa, sb); +} + +static Eina_Bool +_eina_value_type_string_common_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const char *v = *(const char **)type_mem; + + eina_error_set(0); + + if (convert == EINA_VALUE_TYPE_UCHAR) + { + unsigned char other_mem; + if ((sscanf(v, "%hhu", &other_mem) != 1) && + (sscanf(v, "%hhx", &other_mem) != 1) && + (sscanf(v, "%hho", &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_USHORT) + { + unsigned short other_mem; + if ((sscanf(v, "%hu", &other_mem) != 1) && + (sscanf(v, "%hx", &other_mem) != 1) && + (sscanf(v, "%ho", &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT) + { + unsigned int other_mem; + if ((sscanf(v, "%u", &other_mem) != 1) && + (sscanf(v, "%x", &other_mem) != 1) && + (sscanf(v, "%o", &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_ULONG) + { + unsigned long other_mem; + if ((sscanf(v, "%lu", &other_mem) != 1) && + (sscanf(v, "%lx", &other_mem) != 1) && + (sscanf(v, "%lo", &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_UINT64) + { + uint64_t other_mem; + if ((sscanf(v, "%"SCNu64, &other_mem) != 1) && + (sscanf(v, "%"SCNx64, &other_mem) != 1) && + (sscanf(v, "%"SCNo64, &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_CHAR) + { + char other_mem; + if ((sscanf(v, "%hhd", &other_mem) != 1) && + (sscanf(v, "%hhx", &other_mem) != 1) && + (sscanf(v, "%hho", &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_SHORT) + { + short other_mem; + if ((sscanf(v, "%hd", &other_mem) != 1) && + (sscanf(v, "%hx", &other_mem) != 1) && + (sscanf(v, "%ho", &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT) + { + int other_mem; + if ((sscanf(v, "%d", &other_mem) != 1) && + (sscanf(v, "%x", &other_mem) != 1) && + (sscanf(v, "%o", &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_LONG) + { + long other_mem; + if ((sscanf(v, "%ld", &other_mem) != 1) && + (sscanf(v, "%lx", &other_mem) != 1) && + (sscanf(v, "%lo", &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_INT64) + { + int64_t other_mem; + if ((sscanf(v, "%"SCNd64, &other_mem) != 1) && + (sscanf(v, "%"SCNx64, &other_mem) != 1) && + (sscanf(v, "%"SCNo64, &other_mem) != 1)) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_FLOAT) + { + float other_mem; + if (sscanf(v, "%f", &other_mem) != 1) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_DOUBLE) + { + double other_mem; + if (sscanf(v, "%lf", &other_mem) != 1) + return EINA_FALSE; + return eina_value_type_pset(convert, convert_mem, &other_mem); + } + else if (convert == EINA_VALUE_TYPE_STRINGSHARE || + convert == EINA_VALUE_TYPE_STRING) + { + return eina_value_type_pset(convert, convert_mem, &v); + } + else + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_string_common_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + memcpy(ptr, mem, sizeof(const char *)); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_stringshare_flush(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + const char **tmem = mem; + if (*tmem) eina_stringshare_del(*tmem); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_stringshare_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const char * const*s = src; + const char **d = dst; + *d = *s; + eina_stringshare_ref(*d); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_stringshare_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + const char *str = va_arg(args, const char *); + return eina_stringshare_replace((const char **)mem, str); +} + +static Eina_Bool +_eina_value_type_stringshare_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + const char * const *str = ptr; + return eina_stringshare_replace((const char **)mem, *str); +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_STRINGSHARE = { + EINA_VALUE_TYPE_VERSION, + sizeof(const char *), + "stringshare", + _eina_value_type_string_common_setup, + _eina_value_type_stringshare_flush, + _eina_value_type_stringshare_copy, + _eina_value_type_string_common_compare, + _eina_value_type_string_common_convert_to, + NULL, /* no convert from */ + _eina_value_type_stringshare_vset, + _eina_value_type_stringshare_pset, + _eina_value_type_string_common_pget +}; + +static Eina_Bool +_eina_value_type_string_flush(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + char **tmem = mem; + if (*tmem) free(*tmem); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_string_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const char * const *s = src; + char **d = dst; + if (*s == NULL) + *d = NULL; + else + { + *d = strdup(*s); + if (*d == NULL) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } + } + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_string_vset(const Eina_Value_Type *type __UNUSED__, void *mem, va_list args) +{ + char **tmem = mem; + const char *str = va_arg(args, const char *); + free(*tmem); + if (str == NULL) + *tmem = NULL; + else + { + *tmem = strdup(str); + if (*tmem == NULL) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } + } + eina_error_set(0); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_string_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + char **tmem = mem; + const char * const *str = ptr; + free(*tmem); + if (*str == NULL) + *tmem = NULL; + else + { + *tmem = strdup(*str); + if (*tmem == NULL) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return EINA_FALSE; + } + } + eina_error_set(0); + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_STRING = { + EINA_VALUE_TYPE_VERSION, + sizeof(char *), + "string", + _eina_value_type_string_common_setup, + _eina_value_type_string_flush, + _eina_value_type_string_copy, + _eina_value_type_string_common_compare, + _eina_value_type_string_common_convert_to, + NULL, /* no convert from */ + _eina_value_type_string_vset, + _eina_value_type_string_pset, + _eina_value_type_string_common_pget +}; + + +static Eina_Bool +_eina_value_type_array_setup(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + memset(mem, 0, sizeof(Eina_Value_Array)); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_array_flush_elements(Eina_Value_Array *tmem) +{ + const Eina_Value_Type *subtype = tmem->subtype; + Eina_Bool ret = EINA_TRUE; + unsigned char sz; + char *ptr, *ptr_end; + + if (!tmem->array) return EINA_TRUE; + + sz = tmem->array->member_size; + ptr = tmem->array->members; + ptr_end = ptr + tmem->array->len * sz; + + for (; ptr < ptr_end; ptr += sz) + ret &= eina_value_type_flush(subtype, ptr); + + eina_inarray_flush(tmem->array); + return ret; +} + +static Eina_Bool +_eina_value_type_array_flush(const Eina_Value_Type *type __UNUSED__, void *mem) +{ + Eina_Value_Array *tmem = mem; + Eina_Bool ret =_eina_value_type_array_flush_elements(tmem); + + if (tmem->array) eina_inarray_free(tmem->array); + tmem->array = NULL; + tmem->subtype = NULL; + return ret; +} + +static Eina_Bool +_eina_value_type_array_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst) +{ + const Eina_Value_Type *subtype; + const Eina_Value_Array *s = src; + Eina_Value_Array *d = dst; + unsigned int count, sz; + char *placeholder, *ptr, *ptr_end; + + d->subtype = subtype = s->subtype; + d->step = s->step; + + if ((!s->array) || (!s->subtype)) + { + d->array = NULL; + return EINA_TRUE; + } + + if (!subtype->copy) + return EINA_FALSE; + + d->array = eina_inarray_new(subtype->value_size, s->step); + if (!d->array) + return EINA_FALSE; + + sz = s->array->member_size; + placeholder = alloca(sz); + memset(placeholder, 0, sz); + + count = eina_inarray_count(s->array); + ptr = s->array->members; + ptr_end = ptr + (count * sz); + + for (; ptr < ptr_end; ptr += sz) + { + int i = eina_inarray_append(d->array, placeholder); + void *imem = eina_inarray_nth(d->array, i); + if ((i < 0) || (!imem)) goto error; + if (!subtype->copy(subtype, ptr, imem)) goto error; + } + + return EINA_TRUE; + + error: + _eina_value_type_array_flush_elements(d); + return EINA_FALSE; +} + +static int +_eina_value_type_array_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b) +{ + const Eina_Value_Type *subtype; + const Eina_Value_Array *eva_a = a, *eva_b = b; + const char *a_ptr, *a_ptr_end, *b_ptr; + unsigned int count_a, count_b, count, sz; + int cmp = 0; + + if (eva_a->subtype != eva_b->subtype) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return -1; + } + + subtype = eva_a->subtype; + if (!subtype->compare) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return 0; + } + + if ((!eva_a->array) && (!eva_b->array)) + return 0; + else if (!eva_a->array) + return -1; + else if (!eva_b->array) + return 1; + + count_a = eina_inarray_count(eva_a->array); + count_b = eina_inarray_count(eva_b->array); + + if (count_a <= count_b) + count = count_a; + else + count = count_b; + + sz = eva_a->array->member_size; + + a_ptr = eva_a->array->members; + a_ptr_end = a_ptr + (count * sz); + b_ptr = eva_b->array->members; + + for (; (cmp == 0) && (a_ptr < a_ptr_end); a_ptr += sz, b_ptr += sz) + cmp = subtype->compare(subtype, a_ptr, b_ptr); + + if (cmp == 0) + { + if (count_a < count_b) + return -1; + else if (count_a > count_b) + return 1; + return 0; + } + + return cmp; +} + +static Eina_Bool +_eina_value_type_array_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem) +{ + const Eina_Value_Array *tmem = type_mem; + Eina_Bool ret = EINA_FALSE; + + if ((tmem->array) && (tmem->array->len == 1)) + { + const Eina_Value_Type *subtype = tmem->subtype; + void *imem = tmem->array->members; + + if (subtype->convert_to) + ret = subtype->convert_to(subtype, convert, imem, convert_mem); + if ((!ret) && (convert->convert_from)) + ret = convert->convert_from(convert, subtype, convert_mem, imem); + } + else if ((convert == EINA_VALUE_TYPE_STRING) || + (convert == EINA_VALUE_TYPE_STRINGSHARE)) + { + Eina_Strbuf *str = eina_strbuf_new(); + if (!tmem->array) eina_strbuf_append(str, "[]"); + else + { + const Eina_Value_Type *subtype = tmem->subtype; + unsigned char sz; + const char *ptr, *ptr_end; + Eina_Value tmp; + Eina_Bool first = EINA_TRUE; + + eina_value_setup(&tmp, EINA_VALUE_TYPE_STRING); + + eina_strbuf_append_char(str, '['); + + sz = tmem->array->member_size; + ptr = tmem->array->members; + ptr_end = ptr + tmem->array->len * sz; + for (; ptr < ptr_end; ptr += sz) + { + Eina_Bool r = EINA_FALSE; + if (subtype->convert_to) + { + r = subtype->convert_to(subtype, EINA_VALUE_TYPE_STRING, + ptr, tmp.value.buf); + if (r) + { + if (first) first = EINA_FALSE; + else eina_strbuf_append_length(str, ", ", 2); + eina_strbuf_append(str, tmp.value.ptr); + free(tmp.value.ptr); + tmp.value.ptr = NULL; + } + } + + if (!r) + { + if (first) + { + first = EINA_FALSE; + eina_strbuf_append_char(str, '?'); + } + else + eina_strbuf_append_length(str, ", ?", 3); + } + } + + eina_strbuf_append_char(str, ']'); + ptr = eina_strbuf_string_get(str); + ret = eina_value_type_pset(convert, convert_mem, &ptr); + eina_strbuf_free(str); + } + } + + if (!ret) + { + eina_error_set(EINA_ERROR_VALUE_FAILED); + return EINA_FALSE; + } + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_array_convert_from(const Eina_Value_Type *type, const Eina_Value_Type *convert, void *type_mem, const void *convert_mem) +{ + Eina_Value_Array *tmem = type_mem; + Eina_Value_Array desc = {convert, tmem->step, NULL}; + char *buf, *placeholder; + void *imem; + + if (!eina_value_type_pset(type, tmem, &desc)) + return EINA_FALSE; + + buf = alloca(convert->value_size); + if (!eina_value_type_pget(convert, convert_mem, &buf)) + return EINA_FALSE; + + placeholder = alloca(convert->value_size); + memset(placeholder, 0, convert->value_size); + + if (eina_inarray_append(tmem->array, placeholder) != 0) + return EINA_FALSE; + imem = eina_inarray_nth(tmem->array, 0); + if (!imem) + return EINA_FALSE; + + if (!eina_value_type_setup(convert, imem)) goto error_setup; + if (!eina_value_type_pset(convert, imem, &buf)) goto error_set; + return EINA_TRUE; + + error_set: + eina_value_type_flush(convert, imem); + error_setup: + eina_inarray_remove_at(tmem->array, 0); + return EINA_FALSE; +} + +static Eina_Bool +_eina_value_type_array_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr) +{ + Eina_Value_Array *tmem = mem; + const Eina_Value_Array *desc = ptr; + + if ((!tmem->subtype) && (!desc->subtype)) + return EINA_TRUE; + + if (tmem->array) + { + _eina_value_type_array_flush_elements(tmem); + eina_inarray_setup(tmem->array, desc->subtype->value_size, desc->step); + } + else + { + tmem->array = eina_inarray_new(desc->subtype->value_size, desc->step); + if (!tmem->array) + return EINA_FALSE; + } + + tmem->subtype = desc->subtype; + + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_array_vset(const Eina_Value_Type *type, void *mem, va_list args) +{ + const Eina_Value_Array desc = va_arg(args, Eina_Value_Array); + _eina_value_type_array_pset(type, mem, &desc); + return EINA_TRUE; +} + +static Eina_Bool +_eina_value_type_array_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr) +{ + memcpy(ptr, mem, sizeof(Eina_Value_Array)); + return EINA_TRUE; +} + +static const Eina_Value_Type _EINA_VALUE_TYPE_ARRAY = { + EINA_VALUE_TYPE_VERSION, + sizeof(Eina_Value_Array), + "Eina_Value_Array", + _eina_value_type_array_setup, + _eina_value_type_array_flush, + _eina_value_type_array_copy, + _eina_value_type_array_compare, + _eina_value_type_array_convert_to, + _eina_value_type_array_convert_from, + _eina_value_type_array_vset, + _eina_value_type_array_pset, + _eina_value_type_array_pget +}; + + +/** + * @endcond + */ + +static const char EINA_ERROR_VALUE_FAILED_STR[] = "Value check failed."; + +/** + * @internal + * @brief Initialize the value module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the value module of Eina. It is called + * by eina_init(). + * + * @see eina_init() + */ +Eina_Bool +eina_value_init(void) +{ + _eina_value_log_dom = eina_log_domain_register("eina_value", + EINA_LOG_COLOR_DEFAULT); + if (_eina_value_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_value"); + return EINA_FALSE; + } + + EINA_ERROR_VALUE_FAILED = eina_error_msg_static_register( + EINA_ERROR_VALUE_FAILED_STR); + + EINA_VALUE_TYPE_UCHAR = &_EINA_VALUE_TYPE_UCHAR; + EINA_VALUE_TYPE_USHORT = &_EINA_VALUE_TYPE_USHORT; + EINA_VALUE_TYPE_UINT = &_EINA_VALUE_TYPE_UINT; + EINA_VALUE_TYPE_ULONG = &_EINA_VALUE_TYPE_ULONG; + EINA_VALUE_TYPE_UINT64 = &_EINA_VALUE_TYPE_UINT64; + EINA_VALUE_TYPE_CHAR = &_EINA_VALUE_TYPE_CHAR; + EINA_VALUE_TYPE_SHORT = &_EINA_VALUE_TYPE_SHORT; + EINA_VALUE_TYPE_INT = &_EINA_VALUE_TYPE_INT; + EINA_VALUE_TYPE_LONG = &_EINA_VALUE_TYPE_LONG; + EINA_VALUE_TYPE_INT64 = &_EINA_VALUE_TYPE_INT64; + EINA_VALUE_TYPE_FLOAT = &_EINA_VALUE_TYPE_FLOAT; + EINA_VALUE_TYPE_DOUBLE = &_EINA_VALUE_TYPE_DOUBLE; + EINA_VALUE_TYPE_STRINGSHARE = &_EINA_VALUE_TYPE_STRINGSHARE; + EINA_VALUE_TYPE_STRING = &_EINA_VALUE_TYPE_STRING; + EINA_VALUE_TYPE_ARRAY = &_EINA_VALUE_TYPE_ARRAY; + + return EINA_TRUE; +} + +/** + * @internal + * @brief Shut down the value module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the value module set up by + * eina_value_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_value_shutdown(void) +{ + eina_log_domain_unregister(_eina_value_log_dom); + _eina_value_log_dom = -1; + return EINA_TRUE; +} /*============================================================================* * Global * @@ -39,9 +2932,163 @@ * API * *============================================================================*/ +EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_UCHAR; + +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_UCHAR = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_USHORT = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_UINT = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_ULONG = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_UINT64 = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_CHAR = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_SHORT = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_INT = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_LONG = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_INT64 = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_FLOAT = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_DOUBLE = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_STRINGSHARE = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_STRING = NULL; +EAPI const Eina_Value_Type *EINA_VALUE_TYPE_ARRAY = NULL; + +EAPI Eina_Error EINA_ERROR_VALUE_FAILED = 0; + EAPI const unsigned int eina_prime_table[] = { 17, 31, 61, 127, 257, 509, 1021, 2053, 4093, 8191, 16381, 32771, 65537, 131071, 262147, 524287, 1048573, 2097143, 4194301, 8388617, 16777213 }; + +EAPI Eina_Value * +eina_value_new(const Eina_Value_Type *type) +{ + Eina_Value *value = malloc(sizeof(Eina_Value)); + if (!value) + { + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + return NULL; + } + if (!eina_value_setup(value, type)) + { + free(value); + return NULL; + } + return value; +} + +EAPI void +eina_value_free(Eina_Value *value) +{ + EINA_SAFETY_ON_NULL_RETURN(value); + eina_value_flush(value); + free(value); +} + + +EAPI Eina_Bool +eina_value_copy(const Eina_Value *value, Eina_Value *copy) +{ + const Eina_Value_Type *type; + const void *src; + void *dst; + Eina_Bool ret; + + EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), + EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(copy, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(value->type->copy, EINA_FALSE); + + type = value->type; + if (!eina_value_setup(copy, type)) + return EINA_FALSE; + + src = eina_value_memory_get(value); + dst = eina_value_memory_get(copy); + ret = type->copy(type, src, dst); + if (!ret) + eina_value_flush(copy); + + return ret; +} + +EAPI Eina_Bool +eina_value_convert(const Eina_Value *value, Eina_Value *convert) +{ + Eina_Bool ret = EINA_FALSE; + const Eina_Value_Type *type, *convert_type; + const void *type_mem; + void *convert_mem; + + EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(convert, EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), + EINA_FALSE); + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(convert->type), + EINA_FALSE); + + type = value->type; + convert_type = convert->type; + + type_mem = eina_value_memory_get(value); + convert_mem = eina_value_memory_get(convert); + + if (type->convert_to) + ret = type->convert_to(type, convert_type, type_mem, convert_mem); + + if ((!ret) && (convert_type->convert_from)) + ret = convert_type->convert_from(convert_type, type, convert_mem, + type_mem); + + return ret; +} + +EAPI char * +eina_value_to_string(const Eina_Value *value) +{ + Eina_Value tmp; + + EINA_SAFETY_ON_NULL_RETURN_VAL(value, NULL); + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(value->type), NULL); + + if (!eina_value_setup(&tmp, EINA_VALUE_TYPE_STRING)) + return NULL; + if (!eina_value_convert(value, &tmp)) + return NULL; + + return tmp.value.ptr; /* steal value */ +} + +EAPI Eina_Value * +eina_value_array_new(const Eina_Value_Type *subtype, unsigned int step) +{ + Eina_Value *value; + + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(subtype), EINA_FALSE); + + value = calloc(1, sizeof(Eina_Value)); + if (!value) + return NULL; + + if (!eina_value_array_setup(value, subtype, step)) + { + free(value); + return NULL; + } + + return value; +} + +EAPI Eina_Bool +eina_value_type_check(const Eina_Value_Type *type) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE); + return type->version == EINA_VALUE_TYPE_VERSION; +} + +EAPI const char * +eina_value_type_name_get(const Eina_Value_Type *type) +{ + EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(type), NULL); + return type->name; +} diff --git a/legacy/eina/src/tests/Makefile.am b/legacy/eina/src/tests/Makefile.am index 5f81cb412b..fdaf04108e 100644 --- a/legacy/eina/src/tests/Makefile.am +++ b/legacy/eina/src/tests/Makefile.am @@ -65,7 +65,8 @@ eina_test_tiler.c \ eina_test_strbuf.c \ eina_test_str.c \ eina_test_quadtree.c \ -eina_test_simple_xml_parser.c +eina_test_simple_xml_parser.c \ +eina_test_value.c eina_suite_LDADD = @CHECK_LIBS@ $(top_builddir)/src/lib/libeina.la -lm diff --git a/legacy/eina/src/tests/eina_suite.c b/legacy/eina/src/tests/eina_suite.c index 85dd6c8eac..648a717613 100644 --- a/legacy/eina/src/tests/eina_suite.c +++ b/legacy/eina/src/tests/eina_suite.c @@ -67,6 +67,7 @@ static const Eina_Test_Case etc[] = { { "QuadTree", eina_test_quadtree }, { "Sched", eina_test_sched }, { "Simple Xml Parser", eina_test_simple_xml_parser}, + { "Value", eina_test_value }, { NULL, NULL } }; diff --git a/legacy/eina/src/tests/eina_suite.h b/legacy/eina/src/tests/eina_suite.h index b72c524843..6eaaec7178 100644 --- a/legacy/eina/src/tests/eina_suite.h +++ b/legacy/eina/src/tests/eina_suite.h @@ -55,5 +55,6 @@ void eina_test_quadtree(TCase *tc); void eina_test_fp(TCase *tc); void eina_test_sched(TCase *tc); void eina_test_simple_xml_parser(TCase *tc); +void eina_test_value(TCase *tc); #endif /* EINA_SUITE_H_ */ diff --git a/legacy/eina/src/tests/eina_test_value.c b/legacy/eina/src/tests/eina_test_value.c new file mode 100644 index 0000000000..458f874ed0 --- /dev/null +++ b/legacy/eina/src/tests/eina_test_value.c @@ -0,0 +1,1037 @@ +/* EINA - EFL data type library + * Copyright (C) 2012 ProFUSION embedded systems + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "eina_suite.h" +#include "Eina.h" + +#define FP_ERR (0.0000001) +#define CHECK_FP(a, b) ((a - b) < FP_ERR) + +START_TEST(eina_value_test_simple) +{ + Eina_Value *value; + char c; + short s; + int i; + long l; + int64_t i64; + unsigned char uc; + unsigned short us; + unsigned int ui; + unsigned long ul; + uint64_t u64; + float f; + double d; + + eina_init(); + + value = eina_value_new(EINA_VALUE_TYPE_CHAR); + fail_unless(value != NULL); + fail_unless(eina_value_set(value, 'x')); + fail_unless(eina_value_get(value, &c)); + fail_unless(c == 'x'); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_SHORT)); + fail_unless(eina_value_set(value, 300)); + fail_unless(eina_value_get(value, &s)); + fail_unless(s == 300); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_INT)); + fail_unless(eina_value_set(value, -12345)); + fail_unless(eina_value_get(value, &i)); + fail_unless(i == -12345); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_LONG)); + fail_unless(eina_value_set(value, 0xb33f)); + fail_unless(eina_value_get(value, &l)); + fail_unless(l == 0xb33f); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_INT64)); + fail_unless(eina_value_set(value, 0x0011223344556677)); + fail_unless(eina_value_get(value, &i64)); + fail_unless(i64 == 0x0011223344556677); + eina_value_flush(value); + + /* unsigned: */ + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_UCHAR)); + fail_unless(eina_value_set(value, 200)); + fail_unless(eina_value_get(value, &uc)); + fail_unless(uc == 200); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_USHORT)); + fail_unless(eina_value_set(value, 65535)); + fail_unless(eina_value_get(value, &us)); + fail_unless(us == 65535); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_UINT)); + fail_unless(eina_value_set(value, 4000000000U)); + fail_unless(eina_value_get(value, &ui)); + fail_unless(ui == 4000000000U); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_ULONG)); + fail_unless(eina_value_set(value, 3000000001U)); + fail_unless(eina_value_get(value, &ul)); + fail_unless(ul == 3000000001U); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_UINT64)); + fail_unless(eina_value_set(value, 0x1122334455667788)); + fail_unless(eina_value_get(value, &u64)); + fail_unless(u64 == 0x1122334455667788); + eina_value_flush(value); + + /* floating point */ + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_FLOAT)); + fail_unless(eina_value_set(value, 0.1234)); + fail_unless(eina_value_get(value, &f)); + fail_unless(CHECK_FP(0.1234, f)); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_DOUBLE)); + fail_unless(eina_value_set(value, 34567.8)); + fail_unless(eina_value_get(value, &d)); + fail_unless(CHECK_FP(34567.8, d)); + eina_value_flush(value); + + eina_value_free(value); + eina_shutdown(); +} +END_TEST + +START_TEST(eina_value_test_compare) +{ + Eina_Value *a, *b; + + eina_init(); + + a = eina_value_new(EINA_VALUE_TYPE_CHAR); + fail_unless(a != NULL); + b = eina_value_new(EINA_VALUE_TYPE_CHAR); + fail_unless(b != NULL); + + fail_unless(eina_value_set(a, 123)); + fail_unless(eina_value_set(b, 123)); + fail_unless(eina_value_compare(a, b) == 0); + fail_unless(eina_value_set(a, -10)); + fail_unless(eina_value_set(b, 123)); + fail_unless(eina_value_compare(a, b) < 0); + fail_unless(eina_value_set(a, 123)); + fail_unless(eina_value_set(b, 10)); + fail_unless(eina_value_compare(a, b) > 0); + eina_value_flush(a); + eina_value_flush(b); + + fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_SHORT)); + fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_SHORT)); + fail_unless(eina_value_set(a, 1230)); + fail_unless(eina_value_set(b, 1230)); + fail_unless(eina_value_compare(a, b) == 0); + fail_unless(eina_value_set(a, -100)); + fail_unless(eina_value_set(b, 1230)); + fail_unless(eina_value_compare(a, b) < 0); + fail_unless(eina_value_set(a, 1230)); + fail_unless(eina_value_set(b, -100)); + fail_unless(eina_value_compare(a, b) > 0); + eina_value_flush(a); + eina_value_flush(b); + + fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_INT)); + fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_INT)); + fail_unless(eina_value_set(a, 300000)); + fail_unless(eina_value_set(b, 300000)); + fail_unless(eina_value_compare(a, b) == 0); + fail_unless(eina_value_set(a, -100)); + fail_unless(eina_value_set(b, 300000)); + fail_unless(eina_value_compare(a, b) < 0); + fail_unless(eina_value_set(a, 300000)); + fail_unless(eina_value_set(b, -100)); + fail_unless(eina_value_compare(a, b) > 0); + eina_value_flush(a); + eina_value_flush(b); + + fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_LONG)); + fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_LONG)); + fail_unless(eina_value_set(a, 300000L)); + fail_unless(eina_value_set(b, 300000L)); + fail_unless(eina_value_compare(a, b) == 0); + fail_unless(eina_value_set(a, -100L)); + fail_unless(eina_value_set(b, 300000L)); + fail_unless(eina_value_compare(a, b) < 0); + fail_unless(eina_value_set(a, 300000L)); + fail_unless(eina_value_set(b, -100L)); + fail_unless(eina_value_compare(a, b) > 0); + eina_value_flush(a); + eina_value_flush(b); + + fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_INT64)); + fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_INT64)); + fail_unless(eina_value_set(a, (int64_t)800000)); + fail_unless(eina_value_set(b, (int64_t)800000)); + fail_unless(eina_value_compare(a, b) == 0); + fail_unless(eina_value_set(a, (int64_t)-100)); + fail_unless(eina_value_set(b, (int64_t)8000000)); + fail_unless(eina_value_compare(a, b) < 0); + fail_unless(eina_value_set(a, (int64_t)8000000)); + fail_unless(eina_value_set(b, (int64_t)-100)); + fail_unless(eina_value_compare(a, b) > 0); + eina_value_flush(a); + eina_value_flush(b); + + fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_UCHAR)); + fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_UCHAR)); + fail_unless(eina_value_set(a, 123)); + fail_unless(eina_value_set(b, 123)); + fail_unless(eina_value_compare(a, b) == 0); + fail_unless(eina_value_set(a, 10)); + fail_unless(eina_value_set(b, 123)); + fail_unless(eina_value_compare(a, b) < 0); + fail_unless(eina_value_set(a, 123)); + fail_unless(eina_value_set(b, 10)); + fail_unless(eina_value_compare(a, b) > 0); + eina_value_flush(a); + eina_value_flush(b); + + fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_USHORT)); + fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_USHORT)); + fail_unless(eina_value_set(a, 1230)); + fail_unless(eina_value_set(b, 1230)); + fail_unless(eina_value_compare(a, b) == 0); + fail_unless(eina_value_set(a, 100)); + fail_unless(eina_value_set(b, 1230)); + fail_unless(eina_value_compare(a, b) < 0); + fail_unless(eina_value_set(a, 1230)); + fail_unless(eina_value_set(b, 100)); + fail_unless(eina_value_compare(a, b) > 0); + eina_value_flush(a); + eina_value_flush(b); + + fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_UINT)); + fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_UINT)); + fail_unless(eina_value_set(a, 300000)); + fail_unless(eina_value_set(b, 300000)); + fail_unless(eina_value_compare(a, b) == 0); + fail_unless(eina_value_set(a, 100)); + fail_unless(eina_value_set(b, 300000)); + fail_unless(eina_value_compare(a, b) < 0); + fail_unless(eina_value_set(a, 300000)); + fail_unless(eina_value_set(b, 100)); + fail_unless(eina_value_compare(a, b) > 0); + eina_value_flush(a); + eina_value_flush(b); + + fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_ULONG)); + fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_ULONG)); + fail_unless(eina_value_set(a, 300000UL)); + fail_unless(eina_value_set(b, 300000UL)); + fail_unless(eina_value_compare(a, b) == 0); + fail_unless(eina_value_set(a, 100UL)); + fail_unless(eina_value_set(b, 300000UL)); + fail_unless(eina_value_compare(a, b) < 0); + fail_unless(eina_value_set(a, 300000UL)); + fail_unless(eina_value_set(b, 100UL)); + fail_unless(eina_value_compare(a, b) > 0); + eina_value_flush(a); + eina_value_flush(b); + + fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_UINT64)); + fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_UINT64)); + fail_unless(eina_value_set(a, (uint64_t)8000000)); + fail_unless(eina_value_set(b, (uint64_t)8000000)); + fail_unless(eina_value_compare(a, b) == 0); + fail_unless(eina_value_set(a, (uint64_t)100)); + fail_unless(eina_value_set(b, (uint64_t)8000000)); + fail_unless(eina_value_compare(a, b) < 0); + fail_unless(eina_value_set(a, (uint64_t)8000000)); + fail_unless(eina_value_set(b, (uint64_t)100)); + fail_unless(eina_value_compare(a, b) > 0); + eina_value_flush(a); + eina_value_flush(b); + + fail_unless(eina_value_setup(a, EINA_VALUE_TYPE_STRING)); + fail_unless(eina_value_setup(b, EINA_VALUE_TYPE_STRING)); + fail_unless(eina_value_set(a, "aaa")); + fail_unless(eina_value_set(b, "aaa")); + fail_unless(eina_value_compare(a, b) == 0); + fail_unless(eina_value_set(a, "abc")); + fail_unless(eina_value_set(b, "acd")); + fail_unless(eina_value_compare(a, b) < 0); + fail_unless(eina_value_set(a, "acd")); + fail_unless(eina_value_set(b, "abc")); + fail_unless(eina_value_compare(a, b) > 0); + eina_value_flush(a); + eina_value_flush(b); + + fail_unless(eina_value_array_setup(a, EINA_VALUE_TYPE_CHAR, 0)); + fail_unless(eina_value_array_setup(b, EINA_VALUE_TYPE_CHAR, 0)); + fail_unless(eina_value_compare(a, b) == 0); + + fail_unless(eina_value_array_append(a, 1)); + fail_unless(eina_value_array_append(a, 2)); + fail_unless(eina_value_array_append(a, 3)); + + fail_unless(eina_value_array_append(b, 1)); + fail_unless(eina_value_array_append(b, 2)); + fail_unless(eina_value_array_append(b, 3)); + + fail_unless(eina_value_compare(a, b) == 0); + + fail_unless(eina_value_array_set(a, 0, 0)); + fail_unless(eina_value_compare(a, b) < 0); + + fail_unless(eina_value_array_set(a, 0, 10)); + fail_unless(eina_value_compare(a, b) > 0); + + fail_unless(eina_value_array_set(a, 0, 1)); + + fail_unless(eina_value_array_set(b, 0, 0)); + fail_unless(eina_value_compare(a, b) > 0); + + fail_unless(eina_value_array_set(b, 0, 10)); + fail_unless(eina_value_compare(a, b) < 0); + + fail_unless(eina_value_array_set(b, 0, 1)); + fail_unless(eina_value_compare(a, b) == 0); + + /* bigger arrays are greater */ + fail_unless(eina_value_array_append(b, 0)); + fail_unless(eina_value_compare(a, b) < 0); + + fail_unless(eina_value_array_append(a, 0)); + fail_unless(eina_value_array_append(a, 0)); + fail_unless(eina_value_compare(a, b) > 0); + + /* bigger arrays are greater, unless an element says otherwise */ + fail_unless(eina_value_array_set(b, 0, 10)); + fail_unless(eina_value_compare(a, b) < 0); + + eina_value_free(a); + eina_value_free(b); + eina_shutdown(); +} +END_TEST + +START_TEST(eina_value_test_string) +{ + Eina_Value *value; + const char *s; + + eina_init(); + + value = eina_value_new(EINA_VALUE_TYPE_STRING); + fail_unless(value != NULL); + fail_unless(eina_value_set(value, "hello world!")); + fail_unless(eina_value_get(value, &s)); + fail_unless(strcmp(s, "hello world!") == 0); + + fail_unless(eina_value_set(value, "eina-value")); + fail_unless(eina_value_get(value, &s)); + fail_unless(strcmp(s, "eina-value") == 0); + + eina_value_flush(value); + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_STRING)); + + fail_unless(eina_value_set(value, "profusion")); + fail_unless(eina_value_get(value, &s)); + fail_unless(strcmp(s, "profusion") == 0); + + eina_value_free(value); + eina_shutdown(); +} +END_TEST + +START_TEST(eina_value_test_pvariant) +{ + Eina_Value *value; + char c, in_c; + short s, in_s; + int i, in_i; + long l, in_l; + int64_t i64, in_i64; + unsigned char uc, in_uc; + unsigned short us, in_us; + unsigned int ui, in_ui; + unsigned long ul, in_ul; + uint64_t u64, in_u64; + float f, in_f; + double d, in_d; + const char *str, *in_str; + + eina_init(); + + value = eina_value_new(EINA_VALUE_TYPE_CHAR); + fail_unless(value != NULL); + in_c = 'x'; + fail_unless(eina_value_pset(value, &in_c)); + fail_unless(eina_value_pget(value, &c)); + fail_unless(c == 'x'); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_SHORT)); + in_s = 300; + fail_unless(eina_value_pset(value, &in_s)); + fail_unless(eina_value_pget(value, &s)); + fail_unless(s == 300); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_INT)); + in_i = -12345; + fail_unless(eina_value_pset(value, &in_i)); + fail_unless(eina_value_pget(value, &i)); + fail_unless(i == -12345); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_LONG)); + in_l = 0xb33f; + fail_unless(eina_value_pset(value, &in_l)); + fail_unless(eina_value_pget(value, &l)); + fail_unless(l == 0xb33f); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_INT64)); + in_i64 = 0x0011223344556677; + fail_unless(eina_value_pset(value, &in_i64)); + fail_unless(eina_value_pget(value, &i64)); + fail_unless(i64 == 0x0011223344556677); + eina_value_flush(value); + + /* unsigned: */ + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_UCHAR)); + in_uc = 200; + fail_unless(eina_value_pset(value, &in_uc)); + fail_unless(eina_value_pget(value, &uc)); + fail_unless(uc == 200); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_USHORT)); + in_us = 65535; + fail_unless(eina_value_pset(value, &in_us)); + fail_unless(eina_value_pget(value, &us)); + fail_unless(us == 65535); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_UINT)); + in_ui = 4000000000U; + fail_unless(eina_value_pset(value, &in_ui)); + fail_unless(eina_value_pget(value, &ui)); + fail_unless(ui == 4000000000U); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_ULONG)); + in_ul = 3000000001U; + fail_unless(eina_value_pset(value, &in_ul)); + fail_unless(eina_value_pget(value, &ul)); + fail_unless(ul == 3000000001U); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_UINT64)); + in_u64 = 0x1122334455667788; + fail_unless(eina_value_pset(value, &in_u64)); + fail_unless(eina_value_pget(value, &u64)); + fail_unless(u64 == 0x1122334455667788); + eina_value_flush(value); + + /* floating point */ + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_FLOAT)); + in_f = 0.1234; + fail_unless(eina_value_pset(value, &in_f)); + fail_unless(eina_value_pget(value, &f)); + fail_unless(CHECK_FP(0.1234, f)); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_DOUBLE)); + in_d = 34567.8; + fail_unless(eina_value_pset(value, &in_d)); + fail_unless(eina_value_pget(value, &d)); + fail_unless(CHECK_FP(34567.8, d)); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_STRING)); + in_str = "hello world!"; + fail_unless(eina_value_pset(value, &in_str)); + fail_unless(eina_value_pget(value, &str)); + fail_unless(strcmp(str, "hello world!") == 0); + + in_str = "eina-value"; + fail_unless(eina_value_pset(value, &in_str)); + fail_unless(eina_value_pget(value, &str)); + fail_unless(strcmp(str, "eina-value") == 0); + + eina_value_flush(value); + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_STRING)); + + in_str = "profusion"; + fail_unless(eina_value_pset(value, &in_str)); + fail_unless(eina_value_pget(value, &str)); + fail_unless(strcmp(str, "profusion") == 0); + + eina_value_free(value); + eina_shutdown(); +} +END_TEST + +START_TEST(eina_value_test_to_string) +{ + Eina_Value *value; + char c, in_c; + short s, in_s; + int i, in_i; + long l, in_l; + int64_t i64, in_i64; + unsigned char uc, in_uc; + unsigned short us, in_us; + unsigned int ui, in_ui; + unsigned long ul, in_ul; + uint64_t u64, in_u64; + float f, in_f; + double d, in_d; + const char *str, *in_str; + char *out; + char buf[256]; + + eina_init(); + + value = eina_value_new(EINA_VALUE_TYPE_CHAR); + fail_unless(value != NULL); + in_c = 'x'; + fail_unless(eina_value_pset(value, &in_c)); + fail_unless(eina_value_pget(value, &c)); + fail_unless(c == 'x'); + snprintf(buf, sizeof(buf), "%hhd", in_c); + out = eina_value_to_string(value); + fail_unless(out != NULL); + fail_unless(strcmp(buf, out) == 0); + free(out); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_SHORT)); + in_s = 300; + fail_unless(eina_value_pset(value, &in_s)); + fail_unless(eina_value_pget(value, &s)); + fail_unless(s == 300); + snprintf(buf, sizeof(buf), "%hd", in_s); + out = eina_value_to_string(value); + fail_unless(out != NULL); + fail_unless(strcmp(buf, out) == 0); + free(out); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_INT)); + in_i = -12345; + fail_unless(eina_value_pset(value, &in_i)); + fail_unless(eina_value_pget(value, &i)); + fail_unless(i == -12345); + snprintf(buf, sizeof(buf), "%d", in_i); + out = eina_value_to_string(value); + fail_unless(out != NULL); + fail_unless(strcmp(buf, out) == 0); + free(out); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_LONG)); + in_l = 0xb33f; + fail_unless(eina_value_pset(value, &in_l)); + fail_unless(eina_value_pget(value, &l)); + fail_unless(l == 0xb33f); + snprintf(buf, sizeof(buf), "%ld", in_l); + out = eina_value_to_string(value); + fail_unless(out != NULL); + fail_unless(strcmp(buf, out) == 0); + free(out); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_INT64)); + in_i64 = 0x0011223344556677; + fail_unless(eina_value_pset(value, &in_i64)); + fail_unless(eina_value_pget(value, &i64)); + fail_unless(i64 == 0x0011223344556677); + snprintf(buf, sizeof(buf), "%"PRId64, in_i64); + out = eina_value_to_string(value); + fail_unless(out != NULL); + fail_unless(strcmp(buf, out) == 0); + free(out); + eina_value_flush(value); + + /* unsigned: */ + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_UCHAR)); + in_uc = 200; + fail_unless(eina_value_pset(value, &in_uc)); + fail_unless(eina_value_pget(value, &uc)); + fail_unless(uc == 200); + snprintf(buf, sizeof(buf), "%hhu", in_uc); + out = eina_value_to_string(value); + fail_unless(out != NULL); + fail_unless(strcmp(buf, out) == 0); + free(out); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_USHORT)); + in_us = 65535; + fail_unless(eina_value_pset(value, &in_us)); + fail_unless(eina_value_pget(value, &us)); + fail_unless(us == 65535); + snprintf(buf, sizeof(buf), "%hu", in_us); + out = eina_value_to_string(value); + fail_unless(out != NULL); + fail_unless(strcmp(buf, out) == 0); + free(out); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_UINT)); + in_ui = 4000000000U; + fail_unless(eina_value_pset(value, &in_ui)); + fail_unless(eina_value_pget(value, &ui)); + fail_unless(ui == 4000000000U); + snprintf(buf, sizeof(buf), "%u", in_ui); + out = eina_value_to_string(value); + fail_unless(out != NULL); + fail_unless(strcmp(buf, out) == 0); + free(out); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_ULONG)); + in_ul = 3000000001U; + fail_unless(eina_value_pset(value, &in_ul)); + fail_unless(eina_value_pget(value, &ul)); + fail_unless(ul == 3000000001U); + snprintf(buf, sizeof(buf), "%lu", in_ul); + out = eina_value_to_string(value); + fail_unless(out != NULL); + fail_unless(strcmp(buf, out) == 0); + free(out); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_UINT64)); + in_u64 = 0x1122334455667788; + fail_unless(eina_value_pset(value, &in_u64)); + fail_unless(eina_value_pget(value, &u64)); + fail_unless(u64 == 0x1122334455667788); + snprintf(buf, sizeof(buf), "%"PRIu64, in_u64); + out = eina_value_to_string(value); + fail_unless(out != NULL); + fail_unless(strcmp(buf, out) == 0); + free(out); + eina_value_flush(value); + + /* floating point */ + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_FLOAT)); + in_f = 0.1234; + fail_unless(eina_value_pset(value, &in_f)); + fail_unless(eina_value_pget(value, &f)); + fail_unless(CHECK_FP(0.1234, f)); + snprintf(buf, sizeof(buf), "%g", in_f); + out = eina_value_to_string(value); + fail_unless(out != NULL); + fail_unless(strncmp(buf, out, 6) == 0); /* stupid float... */ + free(out); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_DOUBLE)); + in_d = 34567.8; + fail_unless(eina_value_pset(value, &in_d)); + fail_unless(eina_value_pget(value, &d)); + fail_unless(CHECK_FP(34567.8, d)); + snprintf(buf, sizeof(buf), "%g", in_d); + out = eina_value_to_string(value); + fail_unless(out != NULL); + fail_unless(strncmp(buf, out, 7) == 0); /* stupid double... */ + free(out); + eina_value_flush(value); + + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_STRING)); + in_str = "hello world!"; + fail_unless(eina_value_pset(value, &in_str)); + fail_unless(eina_value_pget(value, &str)); + fail_unless(strcmp(str, "hello world!") == 0); + out = eina_value_to_string(value); + fail_unless(out != NULL); + fail_unless(strcmp(in_str, out) == 0); + free(out); + + in_str = "eina-value"; + fail_unless(eina_value_pset(value, &in_str)); + fail_unless(eina_value_pget(value, &str)); + fail_unless(strcmp(str, "eina-value") == 0); + out = eina_value_to_string(value); + fail_unless(out != NULL); + fail_unless(strcmp(in_str, out) == 0); + free(out); + + eina_value_flush(value); + fail_unless(eina_value_setup(value, EINA_VALUE_TYPE_STRING)); + + in_str = "profusion"; + fail_unless(eina_value_pset(value, &in_str)); + fail_unless(eina_value_pget(value, &str)); + fail_unless(strcmp(str, "profusion") == 0); + out = eina_value_to_string(value); + fail_unless(out != NULL); + fail_unless(strcmp(in_str, out) == 0); + free(out); + + eina_value_free(value); + eina_shutdown(); +} +END_TEST + +START_TEST(eina_value_test_convert_char) +{ + Eina_Value *value, conv; + char c; + short s; + int i; + long l; + int64_t i64; + unsigned char uc; + unsigned short us; + unsigned int ui; + unsigned long ul; + uint64_t u64; + float f; + double d; + const char *str; + + eina_init(); + + value = eina_value_new(EINA_VALUE_TYPE_CHAR); + fail_unless(value != NULL); + + fail_unless(eina_value_set(value, 123)); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_UCHAR)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &uc)); + fail_unless(uc == 123); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_USHORT)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &us)); + fail_unless(us == 123); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_UINT)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &ui)); + fail_unless(ui == 123); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_ULONG)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &ul)); + fail_unless(ul == 123); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_UINT64)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &u64)); + fail_unless(u64 == 123); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_CHAR)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &c)); + fail_unless(c == 123); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_SHORT)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &s)); + fail_unless(s == 123); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_INT)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &i)); + fail_unless(i == 123); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_LONG)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &l)); + fail_unless(l == 123); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_INT64)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &i64)); + fail_unless(i64 == 123); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_FLOAT)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &f)); + fail_unless(CHECK_FP(f, 123)); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_DOUBLE)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &d)); + fail_unless(CHECK_FP(d, 123)); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_STRING)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &str)); + fail_unless(str != NULL); + fail_unless(strcmp(str, "123") == 0); + eina_value_flush(&conv); + + /* negative tests */ + fail_unless(eina_value_set(value, -123)); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_UCHAR)); + fail_if(eina_value_convert(value, &conv)); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_USHORT)); + fail_if(eina_value_convert(value, &conv)); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_UINT)); + fail_if(eina_value_convert(value, &conv)); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_ULONG)); + fail_if(eina_value_convert(value, &conv)); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_UINT64)); + fail_if(eina_value_convert(value, &conv)); + eina_value_flush(&conv); + + eina_value_free(value); + eina_shutdown(); +} +END_TEST + +START_TEST(eina_value_test_convert_uchar) +{ + Eina_Value *value, conv; + char c; + short s; + int i; + long l; + int64_t i64; + unsigned char uc; + unsigned short us; + unsigned int ui; + unsigned long ul; + uint64_t u64; + float f; + double d; + const char *str; + + eina_init(); + + value = eina_value_new(EINA_VALUE_TYPE_UCHAR); + fail_unless(value != NULL); + + fail_unless(eina_value_set(value, 31)); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_UCHAR)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &uc)); + fail_unless(uc == 31); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_USHORT)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &us)); + fail_unless(us == 31); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_UINT)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &ui)); + fail_unless(ui == 31); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_ULONG)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &ul)); + fail_unless(ul == 31); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_UINT64)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &u64)); + fail_unless(u64 == 31); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_CHAR)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &c)); + fail_unless(c == 31); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_SHORT)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &s)); + fail_unless(s == 31); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_INT)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &i)); + fail_unless(i == 31); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_LONG)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &l)); + fail_unless(l == 31); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_INT64)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &i64)); + fail_unless(i64 == 31); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_FLOAT)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &f)); + fail_unless(CHECK_FP(f, 31)); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_DOUBLE)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &d)); + fail_unless(CHECK_FP(d, 31)); + eina_value_flush(&conv); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_STRING)); + fail_unless(eina_value_convert(value, &conv)); + fail_unless(eina_value_get(&conv, &str)); + fail_unless(str != NULL); + fail_unless(strcmp(str, "31") == 0); + eina_value_flush(&conv); + + /* negative tests */ + fail_unless(eina_value_set(value, 200)); + + fail_unless(eina_value_setup(&conv, EINA_VALUE_TYPE_CHAR)); + fail_if(eina_value_convert(value, &conv)); + eina_value_flush(&conv); + + eina_value_free(value); + eina_shutdown(); +} +END_TEST + + +START_TEST(eina_value_test_array) +{ + Eina_Value *value; + char c; + char buf[1024]; + char *str; + + eina_init(); + + value = eina_value_array_new(EINA_VALUE_TYPE_CHAR, 0); + fail_unless(value != NULL); + + fail_unless(eina_value_array_append(value, 'k')); + fail_unless(eina_value_array_append(value, '-')); + fail_unless(eina_value_array_append(value, 's')); + + fail_unless(eina_value_array_get(value, 0, &c)); + fail_unless(c == 'k'); + fail_unless(eina_value_array_get(value, 1, &c)); + fail_unless(c == '-'); + fail_unless(eina_value_array_get(value, 2, &c)); + fail_unless(c == 's'); + + fail_unless(eina_value_array_insert(value, 0, '!')); + fail_unless(eina_value_array_get(value, 0, &c)); + fail_unless(c == '!'); + fail_unless(eina_value_array_get(value, 1, &c)); + fail_unless(c == 'k'); + fail_unless(eina_value_array_get(value, 2, &c)); + fail_unless(c == '-'); + fail_unless(eina_value_array_get(value, 3, &c)); + fail_unless(c == 's'); + + fail_unless(eina_value_array_set(value, 0, '*')); + fail_unless(eina_value_array_get(value, 0, &c)); + fail_unless(c == '*'); + fail_unless(eina_value_array_get(value, 1, &c)); + fail_unless(c == 'k'); + fail_unless(eina_value_array_get(value, 2, &c)); + fail_unless(c == '-'); + fail_unless(eina_value_array_get(value, 3, &c)); + fail_unless(c == 's'); + + snprintf(buf, sizeof(buf), "[%hhd, %hhd, %hhd, %hhd]", + '*', 'k', '-', 's'); + + str = eina_value_to_string(value); + fail_unless(str != NULL); + fail_unless(strcmp(str, buf) == 0); + free(str); + + eina_value_flush(value); + fail_unless(eina_value_array_setup(value, EINA_VALUE_TYPE_STRINGSHARE, 2)); + + fail_unless(eina_value_array_append(value, "Enlightenment.org")); + fail_unless(eina_value_array_append(value, "X11")); + fail_unless(eina_value_array_append(value, "Pants")); + fail_unless(eina_value_array_append(value, "on!!!")); + fail_unless(eina_value_array_append(value, "k-s")); + + str = eina_value_to_string(value); + fail_unless(str != NULL); + fail_unless(strcmp(str, "[Enlightenment.org, X11, Pants, on!!!, k-s]") == 0); + free(str); + + eina_value_free(value); + eina_shutdown(); +} +END_TEST + +void +eina_test_value(TCase *tc) +{ + tcase_add_test(tc, eina_value_test_simple); + tcase_add_test(tc, eina_value_test_string); + tcase_add_test(tc, eina_value_test_pvariant); + tcase_add_test(tc, eina_value_test_compare); + tcase_add_test(tc, eina_value_test_to_string); + tcase_add_test(tc, eina_value_test_convert_char); + tcase_add_test(tc, eina_value_test_convert_uchar); + // TODO: other converters... + tcase_add_test(tc, eina_value_test_array); +}