forked from enlightenment/efl
eina_value: add struct type.
efficient storage with named access, can specify compare, alloc, free and other operations for even better management. no changelog/news as this is under eina_value, all new for 1.2 release. SVN revision: 67155
This commit is contained in:
parent
32392d38f8
commit
b1feb2fe8c
|
@ -944,14 +944,14 @@ eina_value_list_vset(Eina_Value *value, unsigned int position, va_list args)
|
|||
static inline Eina_Bool
|
||||
eina_value_list_vget(const Eina_Value *value, unsigned int position, va_list args)
|
||||
{
|
||||
Eina_Value_List *desc;
|
||||
const Eina_Value_List *desc;
|
||||
const Eina_List *node;
|
||||
const void *mem;
|
||||
void *ptr;
|
||||
Eina_Bool ret;
|
||||
|
||||
EINA_VALUE_TYPE_LIST_CHECK_RETURN_VAL(value, 0);
|
||||
desc = (Eina_Value_List *)eina_value_memory_get(value);
|
||||
desc = (const Eina_Value_List *)eina_value_memory_get(value);
|
||||
if (!desc)
|
||||
return EINA_FALSE;
|
||||
|
||||
|
@ -1120,13 +1120,13 @@ eina_value_list_pset(Eina_Value *value, unsigned int position, const void *ptr)
|
|||
static inline Eina_Bool
|
||||
eina_value_list_pget(const Eina_Value *value, unsigned int position, void *ptr)
|
||||
{
|
||||
Eina_Value_List *desc;
|
||||
const Eina_Value_List *desc;
|
||||
const Eina_List *node;
|
||||
const void *mem;
|
||||
Eina_Bool ret;
|
||||
|
||||
EINA_VALUE_TYPE_LIST_CHECK_RETURN_VAL(value, 0);
|
||||
desc = (Eina_Value_List *)eina_value_memory_get(value);
|
||||
desc = (const Eina_Value_List *)eina_value_memory_get(value);
|
||||
if (!desc)
|
||||
return EINA_FALSE;
|
||||
|
||||
|
@ -1316,14 +1316,14 @@ eina_value_hash_vset(Eina_Value *value, const char *key, va_list args)
|
|||
static inline Eina_Bool
|
||||
eina_value_hash_vget(const Eina_Value *value, const char *key, va_list args)
|
||||
{
|
||||
Eina_Value_Hash *desc;
|
||||
const Eina_Value_Hash *desc;
|
||||
const void *mem;
|
||||
void *ptr;
|
||||
Eina_Bool ret;
|
||||
|
||||
EINA_VALUE_TYPE_HASH_CHECK_RETURN_VAL(value, EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
|
||||
desc = (Eina_Value_Hash *)eina_value_memory_get(value);
|
||||
desc = (const Eina_Value_Hash *)eina_value_memory_get(value);
|
||||
if (!desc)
|
||||
return EINA_FALSE;
|
||||
|
||||
|
@ -1403,13 +1403,13 @@ eina_value_hash_pset(Eina_Value *value, const char *key, const void *ptr)
|
|||
static inline Eina_Bool
|
||||
eina_value_hash_pget(const Eina_Value *value, const char *key, void *ptr)
|
||||
{
|
||||
Eina_Value_Hash *desc;
|
||||
const Eina_Value_Hash *desc;
|
||||
const void *mem;
|
||||
Eina_Bool ret;
|
||||
|
||||
EINA_VALUE_TYPE_HASH_CHECK_RETURN_VAL(value, 0);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
|
||||
desc = (Eina_Value_Hash *)eina_value_memory_get(value);
|
||||
desc = (const Eina_Value_Hash *)eina_value_memory_get(value);
|
||||
if (!desc)
|
||||
return EINA_FALSE;
|
||||
|
||||
|
@ -1422,6 +1422,172 @@ eina_value_hash_pget(const Eina_Value *value, const char *key, void *ptr)
|
|||
}
|
||||
#undef EINA_VALUE_TYPE_HASH_CHECK_RETURN_VAL
|
||||
|
||||
#define EINA_VALUE_TYPE_STRUCT_CHECK_RETURN_VAL(value, retval) \
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(value, retval); \
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(value->type == EINA_VALUE_TYPE_STRUCT, retval)
|
||||
|
||||
/**
|
||||
* @brief Find member of struct
|
||||
* @since 1.2
|
||||
* @internal
|
||||
*/
|
||||
EAPI const Eina_Value_Struct_Member *eina_value_struct_member_find(const Eina_Value_Struct *st, const char *name) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT;
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_value_struct_setup(Eina_Value *value, const Eina_Value_Struct_Desc *sdesc)
|
||||
{
|
||||
Eina_Value_Struct desc = {sdesc, NULL};
|
||||
if (!eina_value_setup(value, EINA_VALUE_TYPE_STRUCT))
|
||||
return EINA_FALSE;
|
||||
if (!eina_value_pset(value, &desc))
|
||||
{
|
||||
eina_value_flush(value);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
eina_value_struct_member_memory_get(const Eina_Value_Struct *st, const Eina_Value_Struct_Member *member)
|
||||
{
|
||||
unsigned char *base = (unsigned char *)st->memory;
|
||||
if (!base) return NULL;
|
||||
return base + member->offset;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_value_struct_vset(Eina_Value *value, const char *name, va_list args)
|
||||
{
|
||||
const Eina_Value_Struct_Member *member;
|
||||
Eina_Value_Struct *st;
|
||||
void *mem;
|
||||
|
||||
EINA_VALUE_TYPE_STRUCT_CHECK_RETURN_VAL(value, EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
|
||||
st = (Eina_Value_Struct *)eina_value_memory_get(value);
|
||||
if (!st)
|
||||
return EINA_FALSE;
|
||||
member = eina_value_struct_member_find(st, name);
|
||||
if (!member)
|
||||
return EINA_FALSE;
|
||||
mem = eina_value_struct_member_memory_get(st, member);
|
||||
if (!mem)
|
||||
return EINA_FALSE;
|
||||
|
||||
eina_value_type_flush(member->type, mem);
|
||||
if (!eina_value_type_setup(member->type, mem)) goto error_setup;
|
||||
if (!eina_value_type_vset(member->type, mem, args)) goto error_set;
|
||||
return EINA_TRUE;
|
||||
|
||||
error_set:
|
||||
eina_value_type_flush(member->type, mem);
|
||||
error_setup:
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_value_struct_vget(const Eina_Value *value, const char *name, va_list args)
|
||||
{
|
||||
const Eina_Value_Struct_Member *member;
|
||||
const Eina_Value_Struct *st;
|
||||
const void *mem;
|
||||
void *ptr;
|
||||
Eina_Bool ret;
|
||||
|
||||
EINA_VALUE_TYPE_STRUCT_CHECK_RETURN_VAL(value, EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
|
||||
st = (const Eina_Value_Struct *)eina_value_memory_get(value);
|
||||
if (!st)
|
||||
return EINA_FALSE;
|
||||
member = eina_value_struct_member_find(st, name);
|
||||
if (!member)
|
||||
return EINA_FALSE;
|
||||
mem = eina_value_struct_member_memory_get(st, member);
|
||||
if (!mem)
|
||||
return EINA_FALSE;
|
||||
|
||||
ptr = va_arg(args, void *);
|
||||
ret = eina_value_type_pget(member->type, mem, ptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_value_struct_set(Eina_Value *value, const char *name, ...)
|
||||
{
|
||||
va_list args;
|
||||
Eina_Bool ret;
|
||||
va_start(args, name);
|
||||
ret = eina_value_struct_vset(value, name, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_value_struct_get(const Eina_Value *value, const char *name, ...)
|
||||
{
|
||||
va_list args;
|
||||
Eina_Bool ret;
|
||||
va_start(args, name);
|
||||
ret = eina_value_struct_vget(value, name, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_value_struct_pset(Eina_Value *value, const char *name, const void *ptr)
|
||||
{
|
||||
const Eina_Value_Struct_Member *member;
|
||||
Eina_Value_Struct *st;
|
||||
void *mem;
|
||||
|
||||
EINA_VALUE_TYPE_STRUCT_CHECK_RETURN_VAL(value, 0);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
|
||||
st = (Eina_Value_Struct *)eina_value_memory_get(value);
|
||||
if (!st)
|
||||
return EINA_FALSE;
|
||||
member = eina_value_struct_member_find(st, name);
|
||||
if (!member)
|
||||
return EINA_FALSE;
|
||||
mem = eina_value_struct_member_memory_get(st, member);
|
||||
if (!mem)
|
||||
return EINA_FALSE;
|
||||
|
||||
eina_value_type_flush(member->type, mem);
|
||||
if (!eina_value_type_setup(member->type, mem)) goto error_setup;
|
||||
if (!eina_value_type_pset(member->type, mem, ptr)) goto error_set;
|
||||
return EINA_TRUE;
|
||||
|
||||
error_set:
|
||||
eina_value_type_flush(member->type, mem);
|
||||
error_setup:
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_value_struct_pget(const Eina_Value *value, const char *name, void *ptr)
|
||||
{
|
||||
const Eina_Value_Struct_Member *member;
|
||||
const Eina_Value_Struct *st;
|
||||
const void *mem;
|
||||
Eina_Bool ret;
|
||||
|
||||
EINA_VALUE_TYPE_STRUCT_CHECK_RETURN_VAL(value, 0);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
|
||||
st = (const Eina_Value_Struct *)eina_value_memory_get(value);
|
||||
if (!st)
|
||||
return EINA_FALSE;
|
||||
member = eina_value_struct_member_find(st, name);
|
||||
if (!member)
|
||||
return EINA_FALSE;
|
||||
mem = eina_value_struct_member_memory_get(st, member);
|
||||
if (!mem)
|
||||
return EINA_FALSE;
|
||||
|
||||
ret = eina_value_type_pget(member->type, mem, ptr);
|
||||
return ret;
|
||||
}
|
||||
#undef EINA_VALUE_TYPE_STRUCT_CHECK_RETURN_VAL
|
||||
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_value_type_setup(const Eina_Value_Type *type, void *mem)
|
||||
|
@ -1460,7 +1626,7 @@ eina_value_type_copy(const Eina_Value_Type *type, const void *src, void *dst)
|
|||
}
|
||||
|
||||
static inline int
|
||||
eina_value_type_compare(const Eina_Value_Type *type, const void *a, void *b)
|
||||
eina_value_type_compare(const Eina_Value_Type *type, const void *a, const void *b)
|
||||
{
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(type), EINA_FALSE);
|
||||
if (!type->compare)
|
||||
|
|
|
@ -301,6 +301,28 @@ EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_TIMEVAL;
|
|||
*/
|
||||
EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_BLOB;
|
||||
|
||||
/**
|
||||
* @var EINA_VALUE_TYPE_STRUCT
|
||||
*
|
||||
* manages struct type. Use the value get/set for structs:
|
||||
* @li eina_value_struct_get() and eina_value_struct_set()
|
||||
* @li eina_value_struct_vget() and eina_value_struct_vset()
|
||||
* @li eina_value_struct_pget() and eina_value_struct_pset()
|
||||
*
|
||||
* eina_value_set() takes an #Eina_Value_Struct where just @c desc is
|
||||
* used. If there is an @c memory, it will be adopted and its contents
|
||||
* must be properly configurable as @c desc expects. eina_value_pset()
|
||||
* takes a pointer to an #Eina_Value_Struct. For your convenience, use
|
||||
* eina_value_struct_setup().
|
||||
*
|
||||
* eina_value_get() and eina_value_pget() takes a pointer to
|
||||
* #Eina_Value_Struct, it's an exact copy of the current structure in
|
||||
* use by value, no copies are done.
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_STRUCT;
|
||||
|
||||
/**
|
||||
* @var EINA_ERROR_VALUE_FAILED
|
||||
* Error identifier corresponding to value check failure.
|
||||
|
@ -464,6 +486,7 @@ static inline int eina_value_compare(const Eina_Value *a,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct
|
||||
*
|
||||
* @code
|
||||
* Eina_Value *value = eina_value_new(EINA_VALUE_TYPE_INT);
|
||||
|
@ -524,6 +547,7 @@ static inline Eina_Bool eina_value_set(Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash*
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @code
|
||||
* Eina_Value *value = eina_value_new(EINA_VALUE_TYPE_INT);
|
||||
|
@ -626,6 +650,7 @@ static inline Eina_Bool eina_value_vget(const Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash*
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @note the pointer contents are written using the size defined by
|
||||
* type. It can be larger than void* or uint64_t.
|
||||
|
@ -691,6 +716,7 @@ static inline Eina_Bool eina_value_pset(Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash*
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
*
|
||||
* @code
|
||||
* Eina_Value *value = eina_value_new(EINA_VALUE_TYPE_INT);
|
||||
|
@ -898,6 +924,7 @@ static inline Eina_Bool eina_value_array_remove(Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct
|
||||
*
|
||||
* @code
|
||||
* Eina_Value *value = eina_value_array_new(EINA_VALUE_TYPE_INT, 0);
|
||||
|
@ -958,6 +985,7 @@ static inline Eina_Bool eina_value_array_set(Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash*
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @code
|
||||
* Eina_Value *value = eina_value_array_new(EINA_VALUE_TYPE_INT, 0);
|
||||
|
@ -1006,6 +1034,7 @@ static inline Eina_Bool eina_value_array_get(const Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct
|
||||
*
|
||||
* @code
|
||||
* Eina_Value *value = eina_value_array_new(EINA_VALUE_TYPE_INT, 0);
|
||||
|
@ -1060,6 +1089,7 @@ static inline Eina_Bool eina_value_array_insert(Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct
|
||||
*
|
||||
* @code
|
||||
* Eina_Value *value = eina_value_array_new(EINA_VALUE_TYPE_INT, 0);
|
||||
|
@ -1200,6 +1230,7 @@ static inline Eina_Bool eina_value_array_vappend(Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash*
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @note the pointer contents are written using the size defined by
|
||||
* type. It can be larger than void* or uint64_t.
|
||||
|
@ -1264,6 +1295,7 @@ static inline Eina_Bool eina_value_array_pset(Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash*
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @code
|
||||
* Eina_Value *value = eina_value_array_new(EINA_VALUE_TYPE_INT, 0);
|
||||
|
@ -1313,6 +1345,7 @@ static inline Eina_Bool eina_value_array_pget(const Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash*
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @note the pointer contents are written using the size defined by
|
||||
* type. It can be larger than void* or uint64_t.
|
||||
|
@ -1370,6 +1403,7 @@ static inline Eina_Bool eina_value_array_pinsert(Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash*
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @note the pointer contents are written using the size defined by
|
||||
* type. It can be larger than void* or uint64_t.
|
||||
|
@ -1520,6 +1554,7 @@ static inline Eina_Bool eina_value_list_remove(Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct
|
||||
*
|
||||
* @code
|
||||
* Eina_Value *value = eina_value_list_new(EINA_VALUE_TYPE_INT);
|
||||
|
@ -1579,6 +1614,7 @@ static inline Eina_Bool eina_value_list_set(Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash*
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @code
|
||||
* Eina_Value *value = eina_value_list_new(EINA_VALUE_TYPE_INT);
|
||||
|
@ -1626,6 +1662,7 @@ static inline Eina_Bool eina_value_list_get(const Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct
|
||||
*
|
||||
* @code
|
||||
* Eina_Value *value = eina_value_list_new(EINA_VALUE_TYPE_INT);
|
||||
|
@ -1679,6 +1716,7 @@ static inline Eina_Bool eina_value_list_insert(Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct
|
||||
*
|
||||
* @code
|
||||
* Eina_Value *value = eina_value_list_new(EINA_VALUE_TYPE_INT);
|
||||
|
@ -1818,6 +1856,7 @@ static inline Eina_Bool eina_value_list_vappend(Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash*
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @note the pointer contents are written using the size defined by
|
||||
* type. It can be larger than void* or uint64_t.
|
||||
|
@ -1881,6 +1920,7 @@ static inline Eina_Bool eina_value_list_pset(Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash*
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @code
|
||||
* Eina_Value *value = eina_value_list_new(EINA_VALUE_TYPE_INT);
|
||||
|
@ -1929,6 +1969,7 @@ static inline Eina_Bool eina_value_list_pget(const Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash*
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @note the pointer contents are written using the size defined by
|
||||
* type. It can be larger than void* or uint64_t.
|
||||
|
@ -1985,6 +2026,7 @@ static inline Eina_Bool eina_value_list_pinsert(Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash*
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @note the pointer contents are written using the size defined by
|
||||
* type. It can be larger than void* or uint64_t.
|
||||
|
@ -2118,7 +2160,7 @@ static inline Eina_Bool eina_value_hash_del(Eina_Value *value,
|
|||
* @param key key to find the member
|
||||
* @return #EINA_TRUE on success, #EINA_FALSE otherwise.
|
||||
*
|
||||
* The variable argument is dependent on chosen subtype. The hash for
|
||||
* The variable argument is dependent on chosen subtype. The list for
|
||||
* basic types:
|
||||
*
|
||||
* @li EINA_VALUE_TYPE_UCHAR: unsigned char
|
||||
|
@ -2138,6 +2180,7 @@ static inline Eina_Bool eina_value_hash_del(Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @code
|
||||
* Eina_Value *value = eina_value_hash_new(EINA_VALUE_TYPE_INT, 0);
|
||||
|
@ -2170,7 +2213,7 @@ static inline Eina_Bool eina_value_hash_set(Eina_Value *value,
|
|||
* stored inside the object. There shouldn't be any memory allocation,
|
||||
* thus the contents should @b not be freed.
|
||||
*
|
||||
* The variable argument is dependent on chosen subtype. The hash for
|
||||
* The variable argument is dependent on chosen subtype. The list for
|
||||
* basic types:
|
||||
*
|
||||
* @li EINA_VALUE_TYPE_UCHAR: unsigned char*
|
||||
|
@ -2190,6 +2233,7 @@ static inline Eina_Bool eina_value_hash_set(Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash*
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @code
|
||||
* Eina_Value *value = eina_value_hash_new(EINA_VALUE_TYPE_INT, 0);
|
||||
|
@ -2255,7 +2299,7 @@ static inline Eina_Bool eina_value_hash_vget(const Eina_Value *value,
|
|||
* @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 hash for
|
||||
* The pointer type is dependent on chosen value type. The list for
|
||||
* basic types:
|
||||
*
|
||||
* @li EINA_VALUE_TYPE_UCHAR: unsigned char*
|
||||
|
@ -2275,6 +2319,7 @@ static inline Eina_Bool eina_value_hash_vget(const Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash*
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @note the pointer contents are written using the size defined by
|
||||
* type. It can be larger than void* or uint64_t.
|
||||
|
@ -2310,7 +2355,7 @@ static inline Eina_Bool eina_value_hash_pset(Eina_Value *value,
|
|||
* object. There shouldn't be any memory allocation, thus the contents
|
||||
* should @b not be freed.
|
||||
*
|
||||
* The pointer type is dependent on chosen value type. The hash for
|
||||
* The pointer type is dependent on chosen value type. The list for
|
||||
* basic types:
|
||||
*
|
||||
* @li EINA_VALUE_TYPE_UCHAR: unsigned char*
|
||||
|
@ -2330,6 +2375,7 @@ static inline Eina_Bool eina_value_hash_pset(Eina_Value *value,
|
|||
* @li EINA_VALUE_TYPE_HASH: Eina_Value_Hash*
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @code
|
||||
* Eina_Value *value = eina_value_hash_new(EINA_VALUE_TYPE_INT, 0);
|
||||
|
@ -2414,6 +2460,475 @@ struct _Eina_Value_Blob
|
|||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup Eina_Value_Struct_Group Generic Value Struct management
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef Eina_Value_Struct_Operations
|
||||
* How to manage struct. Any @c NULL callback is ignored.
|
||||
* @since 1.2
|
||||
*/
|
||||
typedef struct _Eina_Value_Struct_Operations Eina_Value_Struct_Operations;
|
||||
|
||||
/**
|
||||
* @typedef Eina_Value_Struct_Member
|
||||
* Describes a single member of struct.
|
||||
* @since 1.2
|
||||
*/
|
||||
typedef struct _Eina_Value_Struct_Member Eina_Value_Struct_Member;
|
||||
|
||||
/**
|
||||
* @typedef Eina_Value_Struct_Desc
|
||||
* Describes the struct by listing its size, members and operations.
|
||||
* @since 1.2
|
||||
*/
|
||||
typedef struct _Eina_Value_Struct_Desc Eina_Value_Struct_Desc;
|
||||
|
||||
/**
|
||||
* @typedef Eina_Value_Struct
|
||||
* @since 1.2
|
||||
*/
|
||||
typedef struct _Eina_Value_Struct Eina_Value_Struct;
|
||||
|
||||
/**
|
||||
* @struct _Eina_Value_Struct_Operations
|
||||
* How to manage struct. Any @c NULL callback is ignored.
|
||||
* @since 1.2
|
||||
*/
|
||||
struct _Eina_Value_Struct_Operations
|
||||
{
|
||||
#define EINA_VALUE_STRUCT_OPERATIONS_VERSION (1)
|
||||
unsigned int version; /**< must be EINA_VALUE_STRUCT_OPERATIONS_VERSION */
|
||||
void *(*alloc)(const Eina_Value_Struct_Operations *ops, const Eina_Value_Struct_Desc *desc);
|
||||
void (*free)(const Eina_Value_Struct_Operations *ops, const Eina_Value_Struct_Desc *desc, void *memory);
|
||||
void *(*copy)(const Eina_Value_Struct_Operations *ops, const Eina_Value_Struct_Desc *desc, const void *memory);
|
||||
int (*compare)(const Eina_Value_Struct_Operations *ops, const Eina_Value_Struct_Desc *desc, const void *data1, const void *data2);
|
||||
const Eina_Value_Struct_Member *(*find_member)(const Eina_Value_Struct_Operations *ops, const Eina_Value_Struct_Desc *desc, const char *name); /**< replace the function to find description for member. For huge structures consider using binary search, stringshared, hash or gperf. The default function does linear search using strcmp(). */
|
||||
};
|
||||
|
||||
/**
|
||||
* @var EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH
|
||||
*
|
||||
* Assumes @c members is sorted by name and applies binary search for
|
||||
* names.
|
||||
*
|
||||
* Ideally the @c member_count field is set to speed it up.
|
||||
*
|
||||
* No other methods are set (alloc, free, copy, compare), then it uses
|
||||
* the default operations.
|
||||
*/
|
||||
EAPI extern const Eina_Value_Struct_Operations *EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH;
|
||||
|
||||
/**
|
||||
* @var EINA_VALUE_STRUCT_OPERATIONS_STRINGSHARE
|
||||
*
|
||||
* Assumes @c members name are stringshared and can be compared for
|
||||
* equality without using its contents (simple pointer comparison).
|
||||
*
|
||||
* Ideally the search @c name will be stringshared as well, but it
|
||||
* will do a second loop with a forced stringshare if it did not find
|
||||
* the member.
|
||||
*
|
||||
* No other methods are set (alloc, free, copy, compare), then it uses
|
||||
* the default operations.
|
||||
*/
|
||||
EAPI extern const Eina_Value_Struct_Operations *EINA_VALUE_STRUCT_OPERATIONS_STRINGSHARE;
|
||||
|
||||
/**
|
||||
* @struct _Eina_Value_Struct_Member
|
||||
* @since 1.2
|
||||
*/
|
||||
struct _Eina_Value_Struct_Member
|
||||
{
|
||||
const char *name;
|
||||
const Eina_Value_Type *type;
|
||||
unsigned int offset;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct _Eina_Value_Struct_Desc
|
||||
* @since 1.2
|
||||
*/
|
||||
struct _Eina_Value_Struct_Desc
|
||||
{
|
||||
#define EINA_VALUE_STRUCT_DESC_VERSION (1)
|
||||
unsigned int version; /**< must be EINA_VALUE_STRUCT_DESC_VERSION */
|
||||
const Eina_Value_Struct_Operations *ops; /**< operations, if @c NULL defaults will be used. You may use operations to optimize member lookup using binary search or gperf hash. */
|
||||
const Eina_Value_Struct_Member *members; /**< array of member descriptions, if @c member_count is zero, then it must be @c NULL terminated. */
|
||||
unsigned int member_count; /**< if > 0, specifies number of members. If zero then @c members must be NULL terminated. */
|
||||
unsigned int size; /**< byte size to allocate, may be bigger than sum of members */
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct _Eina_Value_Struct
|
||||
* @since 1.2
|
||||
*/
|
||||
struct _Eina_Value_Struct
|
||||
{
|
||||
const Eina_Value_Struct_Desc *desc;
|
||||
void *memory;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Create generic value storage of type struct.
|
||||
* @param desc how to manage this struct members.
|
||||
* @return The new value or @c NULL on failure.
|
||||
*
|
||||
* Create a new generic value storage of type struct. The members are
|
||||
* managed using the description specified by @a desc.
|
||||
*
|
||||
* On failure, @c NULL is returned and #EINA_ERROR_OUT_OF_MEMORY or
|
||||
* #EINA_ERROR_VALUE_FAILED is set.
|
||||
*
|
||||
* @note this creates from mempool and then uses
|
||||
* eina_value_struct_setup().
|
||||
*
|
||||
* @see eina_value_free()
|
||||
* @see eina_value_struct_setup()
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
EAPI Eina_Value *eina_value_struct_new(const Eina_Value_Struct_Desc *desc) EINA_ARG_NONNULL(1);
|
||||
|
||||
/**
|
||||
* @brief Initialize generic value storage of type struct.
|
||||
* @param value value object
|
||||
* @param desc how to manage this struct members.
|
||||
* @return #EINA_TRUE on success, #EINA_FALSE otherwise.
|
||||
*
|
||||
* Initializes new generic value storage of type struct with the given
|
||||
* @a desc.
|
||||
*
|
||||
* This is the same as calling eina_value_set() with
|
||||
* #EINA_VALUE_TYPE_STRUCT followed by eina_value_pset() with the
|
||||
* #Eina_Value_Struct description configured.
|
||||
*
|
||||
* @note Existing contents are ignored! If the value was previously used, 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_struct_setup(Eina_Value *value,
|
||||
const Eina_Value_Struct_Desc *desc) EINA_ARG_NONNULL(1, 2);
|
||||
|
||||
/**
|
||||
* @brief Set the generic value in an struct member.
|
||||
* @param value source value object
|
||||
* @param name name to find the member
|
||||
* @return #EINA_TRUE on success, #EINA_FALSE otherwise.
|
||||
*
|
||||
* The variable argument is dependent on chosen member 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_HASH: Eina_Value_Hash
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @code
|
||||
* struct myst {
|
||||
* int i;
|
||||
* char c;
|
||||
* };
|
||||
* const Eina_Value_Struct_Member myst_members[] = {
|
||||
* {"i", EINA_VALUE_TYPE_INT, 0},
|
||||
* {"c", EINA_VALUE_TYPE_CHAR, 4},
|
||||
* {NULL, NULL, 0}
|
||||
* };
|
||||
* const Eina_Value_Struct_Desc myst_desc = {
|
||||
* EINA_VALUE_STRUCT_DESC_VERSION,
|
||||
* NULL, myst_members, 2, sizeof(struct myst)
|
||||
* };
|
||||
* Eina_Value *value = eina_value_struct_new(&my_desc);
|
||||
* int x;
|
||||
* char y;
|
||||
*
|
||||
* eina_value_struct_set(value, "i", 5678);
|
||||
* eina_value_struct_get(value, "i", &x);
|
||||
* eina_value_struct_set(value, "c", 0xf);
|
||||
* eina_value_struct_get(value, "c", &y);
|
||||
* eina_value_free(value);
|
||||
* @endcode
|
||||
*
|
||||
* @see eina_value_struct_get()
|
||||
* @see eina_value_struct_vset()
|
||||
* @see eina_value_struct_pset()
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
static inline Eina_Bool eina_value_struct_set(Eina_Value *value,
|
||||
const char *name,
|
||||
...) EINA_ARG_NONNULL(1);
|
||||
|
||||
/**
|
||||
* @brief Get the generic value from an struct member.
|
||||
* @param value source value object
|
||||
* @param name name to find 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 freed.
|
||||
*
|
||||
* The variable argument is dependent on chosen member 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_HASH: Eina_Value_Hash*
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @code
|
||||
* struct myst {
|
||||
* int i;
|
||||
* char c;
|
||||
* };
|
||||
* const Eina_Value_Struct_Member myst_members[] = {
|
||||
* {"i", EINA_VALUE_TYPE_INT, 0},
|
||||
* {"c", EINA_VALUE_TYPE_CHAR, 4},
|
||||
* {NULL, NULL, 0}
|
||||
* };
|
||||
* const Eina_Value_Struct_Desc myst_desc = {
|
||||
* EINA_VALUE_STRUCT_DESC_VERSION,
|
||||
* NULL, myst_members, 2, sizeof(struct myst)
|
||||
* };
|
||||
* Eina_Value *value = eina_value_struct_new(&my_desc);
|
||||
* int x;
|
||||
* char y;
|
||||
*
|
||||
* eina_value_struct_set(value, "i", 5678);
|
||||
* eina_value_struct_get(value, "i", &x);
|
||||
* eina_value_struct_set(value, "c", 0xf);
|
||||
* eina_value_struct_get(value, "c", &y);
|
||||
* eina_value_free(value);
|
||||
* @endcode
|
||||
*
|
||||
* @see eina_value_struct_set()
|
||||
* @see eina_value_struct_vset()
|
||||
* @see eina_value_struct_pset()
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
static inline Eina_Bool eina_value_struct_get(const Eina_Value *value,
|
||||
const char *name,
|
||||
...) EINA_ARG_NONNULL(1);
|
||||
|
||||
/**
|
||||
* @brief Set the generic value in an struct member.
|
||||
* @param value source value object
|
||||
* @param name name to find the member
|
||||
* @param args variable argument
|
||||
* @return #EINA_TRUE on success, #EINA_FALSE otherwise.
|
||||
* @see eina_value_struct_set()
|
||||
* @see eina_value_struct_get()
|
||||
* @see eina_value_struct_pset()
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
static inline Eina_Bool eina_value_struct_vset(Eina_Value *value,
|
||||
const char *name,
|
||||
va_list args) EINA_ARG_NONNULL(1);
|
||||
|
||||
/**
|
||||
* @brief Get the generic value from an struct member.
|
||||
* @param value source value object
|
||||
* @param name name to find 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 freed.
|
||||
*
|
||||
* @see eina_value_struct_vset()
|
||||
* @see eina_value_struct_get()
|
||||
* @see eina_value_struct_pget()
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
static inline Eina_Bool eina_value_struct_vget(const Eina_Value *value,
|
||||
const char *name,
|
||||
va_list args) EINA_ARG_NONNULL(1);
|
||||
|
||||
/**
|
||||
* @brief Set the generic value in an struct member from pointer.
|
||||
* @param value source value object
|
||||
* @param name name to find 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_HASH: Eina_Value_Hash*
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @note the pointer contents are written using the size defined by
|
||||
* type. It can be larger than void* or uint64_t.
|
||||
*
|
||||
* @code
|
||||
* struct myst {
|
||||
* int i;
|
||||
* char c;
|
||||
* };
|
||||
* const Eina_Value_Struct_Member myst_members[] = {
|
||||
* {"i", EINA_VALUE_TYPE_INT, 0},
|
||||
* {"c", EINA_VALUE_TYPE_CHAR, 4},
|
||||
* {NULL, NULL, 0}
|
||||
* };
|
||||
* const Eina_Value_Struct_Desc myst_desc = {
|
||||
* EINA_VALUE_STRUCT_DESC_VERSION,
|
||||
* NULL, myst_members, 2, sizeof(struct myst)
|
||||
* };
|
||||
* Eina_Value *value = eina_value_struct_new(&my_desc);
|
||||
* int x = 5678;
|
||||
* char y = 0xf;
|
||||
*
|
||||
* eina_value_struct_pset(value, "i", &);
|
||||
* eina_value_struct_pget(value, "i", &x);
|
||||
* eina_value_struct_pset(value, "c", &y);
|
||||
* eina_value_struct_pget(value, "c", &y);
|
||||
* eina_value_free(value);
|
||||
* @endcode
|
||||
*
|
||||
* @see eina_value_struct_set()
|
||||
* @see eina_value_struct_get()
|
||||
* @see eina_value_struct_vset()
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
static inline Eina_Bool eina_value_struct_pset(Eina_Value *value,
|
||||
const char *name,
|
||||
const void *ptr) EINA_ARG_NONNULL(1, 3);
|
||||
|
||||
/**
|
||||
* @brief Get the generic value to pointer from an struct member.
|
||||
* @param value source value object
|
||||
* @param name name to find 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 freed.
|
||||
*
|
||||
* 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_HASH: Eina_Value_Hash*
|
||||
* @li EINA_VALUE_TYPE_TIMEVAL: struct timeval*
|
||||
* @li EINA_VALUE_TYPE_BLOB: Eina_Value_Blob*
|
||||
* @li EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct*
|
||||
*
|
||||
* @code
|
||||
* struct myst {
|
||||
* int i;
|
||||
* char c;
|
||||
* };
|
||||
* const Eina_Value_Struct_Member myst_members[] = {
|
||||
* {"i", EINA_VALUE_TYPE_INT, 0},
|
||||
* {"c", EINA_VALUE_TYPE_CHAR, 4},
|
||||
* {NULL, NULL, 0}
|
||||
* };
|
||||
* const Eina_Value_Struct_Desc myst_desc = {
|
||||
* EINA_VALUE_STRUCT_DESC_VERSION,
|
||||
* NULL, myst_members, 2, sizeof(struct myst)
|
||||
* };
|
||||
* Eina_Value *value = eina_value_struct_new(&my_desc);
|
||||
* int x = 5678;
|
||||
* char y = 0xf;
|
||||
*
|
||||
* eina_value_struct_pset(value, "i", &);
|
||||
* eina_value_struct_pget(value, "i", &x);
|
||||
* eina_value_struct_pset(value, "c", &y);
|
||||
* eina_value_struct_pget(value, "c", &y);
|
||||
* eina_value_free(value);
|
||||
* @endcode
|
||||
*
|
||||
* @see eina_value_struct_set()
|
||||
* @see eina_value_struct_vset()
|
||||
* @see eina_value_struct_pset()
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
static inline Eina_Bool eina_value_struct_pget(const Eina_Value *value,
|
||||
const char *name,
|
||||
void *ptr) EINA_ARG_NONNULL(1, 3);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup Eina_Value_Type_Group Generic Value Type management
|
||||
*
|
||||
|
@ -2503,7 +3018,7 @@ static inline Eina_Bool eina_value_type_copy(const Eina_Value_Type *type, const
|
|||
* @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);
|
||||
static inline int eina_value_type_compare(const Eina_Value_Type *type, const void *a, const void *b);
|
||||
|
||||
/**
|
||||
* @brief Convert memory using type descriptor.
|
||||
|
|
|
@ -3819,6 +3819,497 @@ static const Eina_Value_Type _EINA_VALUE_TYPE_BLOB = {
|
|||
_eina_value_type_blob_pget
|
||||
};
|
||||
|
||||
static int
|
||||
_eina_value_struct_operations_binsearch_cmp(const void *pa, const void *pb)
|
||||
{
|
||||
const Eina_Value_Struct_Member *a = pa, *b = pb;
|
||||
return strcmp(a->name, b->name);
|
||||
}
|
||||
|
||||
static const Eina_Value_Struct_Member *
|
||||
_eina_value_struct_operations_binsearch_find_member(const Eina_Value_Struct_Operations *ops __UNUSED__, const Eina_Value_Struct_Desc *desc, const char *name)
|
||||
{
|
||||
unsigned int count = desc->member_count;
|
||||
Eina_Value_Struct_Member search;
|
||||
if (count == 0)
|
||||
{
|
||||
const Eina_Value_Struct_Member *itr = desc->members;
|
||||
for (; itr->name != NULL; itr++)
|
||||
count++;
|
||||
}
|
||||
|
||||
search.name = name;
|
||||
return bsearch(&search, desc->members, count,
|
||||
sizeof(Eina_Value_Struct_Member),
|
||||
_eina_value_struct_operations_binsearch_cmp);
|
||||
}
|
||||
|
||||
static Eina_Value_Struct_Operations _EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH = {
|
||||
EINA_VALUE_STRUCT_OPERATIONS_VERSION,
|
||||
NULL, /* default alloc */
|
||||
NULL, /* default free */
|
||||
NULL, /* default copy */
|
||||
NULL, /* default compare */
|
||||
_eina_value_struct_operations_binsearch_find_member
|
||||
};
|
||||
|
||||
static const Eina_Value_Struct_Member *
|
||||
_eina_value_struct_operations_stringshare_find_member(const Eina_Value_Struct_Operations *ops __UNUSED__, const Eina_Value_Struct_Desc *desc, const char *name)
|
||||
{
|
||||
const Eina_Value_Struct_Member *itr = desc->members;
|
||||
|
||||
/* assumes name is stringshared.
|
||||
*
|
||||
* we do this because it's the recommended usage pattern, moreover
|
||||
* we expect to find the member, as users shouldn't look for
|
||||
* non-existent members!
|
||||
*/
|
||||
if (desc->member_count > 0)
|
||||
{
|
||||
const Eina_Value_Struct_Member *itr_end = itr + desc->member_count;
|
||||
for (; itr < itr_end; itr++)
|
||||
if (itr->name == name)
|
||||
return itr;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; itr->name != NULL; itr++)
|
||||
if (itr->name == name)
|
||||
return itr;
|
||||
}
|
||||
|
||||
name = eina_stringshare_add(name);
|
||||
eina_stringshare_del(name); /* we'll not use the contents, this is fine */
|
||||
/* stringshare and look again */
|
||||
if (desc->member_count > 0)
|
||||
{
|
||||
const Eina_Value_Struct_Member *itr_end = itr + desc->member_count;
|
||||
for (; itr < itr_end; itr++)
|
||||
if (itr->name == name)
|
||||
return itr;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; itr->name != NULL; itr++)
|
||||
if (itr->name == name)
|
||||
return itr;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Eina_Value_Struct_Operations _EINA_VALUE_STRUCT_OPERATIONS_STRINGSHARE = {
|
||||
EINA_VALUE_STRUCT_OPERATIONS_VERSION,
|
||||
NULL, /* default alloc */
|
||||
NULL, /* default free */
|
||||
NULL, /* default copy */
|
||||
NULL, /* default compare */
|
||||
_eina_value_struct_operations_stringshare_find_member
|
||||
};
|
||||
|
||||
static inline const Eina_Value_Struct_Operations *
|
||||
_eina_value_type_struct_ops_get(const Eina_Value_Struct *st)
|
||||
{
|
||||
if (!st) return NULL;
|
||||
if (!st->desc) return NULL;
|
||||
if (!st->desc->ops) return NULL;
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL
|
||||
(st->desc->ops->version == EINA_VALUE_STRUCT_OPERATIONS_VERSION, NULL);
|
||||
return st->desc->ops;
|
||||
}
|
||||
|
||||
EAPI const Eina_Value_Struct_Member *
|
||||
eina_value_struct_member_find(const Eina_Value_Struct *st, const char *name)
|
||||
{
|
||||
const Eina_Value_Struct_Operations *ops;
|
||||
const Eina_Value_Struct_Member *itr;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(st->desc, NULL);
|
||||
|
||||
ops = _eina_value_type_struct_ops_get(st);
|
||||
if ((ops) && (ops->find_member))
|
||||
return ops->find_member(ops, st->desc, name);
|
||||
|
||||
itr = st->desc->members;
|
||||
if (st->desc->member_count)
|
||||
{
|
||||
const Eina_Value_Struct_Member *itr_end = itr + st->desc->member_count;
|
||||
for (; itr < itr_end; itr++)
|
||||
{
|
||||
if (strcmp(name, itr->name) == 0)
|
||||
return itr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; itr->name != NULL; itr++)
|
||||
{
|
||||
if (strcmp(name, itr->name) == 0)
|
||||
return itr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_eina_value_type_struct_setup(const Eina_Value_Type *type __UNUSED__, void *mem)
|
||||
{
|
||||
memset(mem, 0, sizeof(Eina_Value_Struct));
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_eina_value_type_struct_flush_member(const Eina_Value_Struct_Member *member, Eina_Value_Struct *st)
|
||||
{
|
||||
unsigned char *base = st->memory;
|
||||
return eina_value_type_flush(member->type, base + member->offset);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_eina_value_type_struct_flush(const Eina_Value_Type *type __UNUSED__, void *mem)
|
||||
{
|
||||
const Eina_Value_Struct_Operations *ops;
|
||||
const Eina_Value_Struct_Member *itr;
|
||||
Eina_Value_Struct *tmem = mem;
|
||||
Eina_Bool ret = EINA_TRUE;
|
||||
|
||||
itr = tmem->desc->members;
|
||||
if (tmem->desc->member_count > 0)
|
||||
{
|
||||
const Eina_Value_Struct_Member *itr_end;
|
||||
itr_end = itr + tmem->desc->member_count;
|
||||
for (; itr < itr_end; itr++)
|
||||
ret &= _eina_value_type_struct_flush_member(itr, tmem);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; itr->name != NULL; itr++)
|
||||
ret &= _eina_value_type_struct_flush_member(itr, tmem);
|
||||
}
|
||||
|
||||
ops = _eina_value_type_struct_ops_get(mem);
|
||||
if ((ops) && (ops->free))
|
||||
ops->free(ops, tmem->desc, tmem->memory);
|
||||
else
|
||||
free(tmem->memory);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_eina_value_type_struct_copy_member(const Eina_Value_Struct_Member *member, const Eina_Value_Struct *s, Eina_Value_Struct *d)
|
||||
{
|
||||
const unsigned char *base_s = s->memory;
|
||||
unsigned char *base_d = d->memory;
|
||||
return eina_value_type_copy(member->type,
|
||||
base_s + member->offset,
|
||||
base_d + member->offset);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_eina_value_type_struct_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst)
|
||||
{
|
||||
const Eina_Value_Struct_Operations *ops;
|
||||
const Eina_Value_Struct_Member *itr;
|
||||
const Eina_Value_Struct *s = src;
|
||||
Eina_Value_Struct *d = dst;
|
||||
|
||||
*d = *s;
|
||||
|
||||
ops = _eina_value_type_struct_ops_get(src);
|
||||
if ((ops) && (ops->copy))
|
||||
{
|
||||
d->memory = ops->copy(ops, s->desc, s->memory);
|
||||
if (d->memory == NULL)
|
||||
return EINA_FALSE;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
d->memory = malloc(s->desc->size);
|
||||
if (!d->memory)
|
||||
{
|
||||
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
itr = s->desc->members;
|
||||
if (s->desc->member_count > 0)
|
||||
{
|
||||
const Eina_Value_Struct_Member *itr_end = itr + s->desc->member_count;
|
||||
for (; itr < itr_end; itr++)
|
||||
if (!_eina_value_type_struct_copy_member(itr, s, d))
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; itr->name != NULL; itr++)
|
||||
if (!_eina_value_type_struct_copy_member(itr, s, d))
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
return EINA_TRUE;
|
||||
|
||||
error:
|
||||
itr--;
|
||||
for (; itr >= s->desc->members; itr--)
|
||||
_eina_value_type_struct_flush_member(itr, d);
|
||||
free(d->memory);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline int
|
||||
_eina_value_type_struct_compare_member(const Eina_Value_Struct_Member *member, const Eina_Value_Struct *ta, const Eina_Value_Struct *tb)
|
||||
{
|
||||
const unsigned char *base_a = ta->memory;
|
||||
const unsigned char *base_b = tb->memory;
|
||||
return eina_value_type_compare(member->type,
|
||||
base_a + member->offset,
|
||||
base_b + member->offset);
|
||||
}
|
||||
|
||||
static int
|
||||
_eina_value_type_struct_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b)
|
||||
{
|
||||
const Eina_Value_Struct_Operations *ops = _eina_value_type_struct_ops_get(a);
|
||||
const Eina_Value_Struct *ta = a, *tb = b;
|
||||
const Eina_Value_Struct_Member *itr;
|
||||
int cmp = 0;
|
||||
|
||||
if (ta->desc != tb->desc)
|
||||
{
|
||||
eina_error_set(EINA_ERROR_VALUE_FAILED);
|
||||
return -1;
|
||||
}
|
||||
if (ta->desc->ops != tb->desc->ops)
|
||||
{
|
||||
eina_error_set(EINA_ERROR_VALUE_FAILED);
|
||||
return -1;
|
||||
}
|
||||
if ((!ta->memory) && (!tb->memory))
|
||||
return 0;
|
||||
else if (!ta->memory)
|
||||
return -1;
|
||||
else if (!tb->memory)
|
||||
return 1;
|
||||
|
||||
if ((ops) && (ops->compare))
|
||||
return ops->compare(ops, ta->desc, ta->memory, tb->memory);
|
||||
|
||||
itr = ta->desc->members;
|
||||
if (ta->desc->member_count > 0)
|
||||
{
|
||||
const Eina_Value_Struct_Member *itr_end = itr + ta->desc->member_count;
|
||||
for (; (cmp == 0) && (itr < itr_end); itr++)
|
||||
cmp = _eina_value_type_struct_compare_member(itr, ta, tb);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; (cmp == 0) && (itr->name != NULL); itr++)
|
||||
cmp = _eina_value_type_struct_compare_member(itr, ta, tb);
|
||||
}
|
||||
return cmp;
|
||||
}
|
||||
|
||||
static void
|
||||
_eina_value_type_struct_convert_to_string_member(const Eina_Value_Struct *st, const Eina_Value_Struct_Member *member, Eina_Strbuf *str)
|
||||
{
|
||||
const unsigned char *p = st->memory;
|
||||
Eina_Bool first = st->desc->members == member;
|
||||
Eina_Bool r = EINA_FALSE;
|
||||
|
||||
if (first) eina_strbuf_append_printf(str, "%s: ", member->name);
|
||||
else eina_strbuf_append_printf(str, ", %s: ", member->name);
|
||||
|
||||
if ((member->type) && (member->type->convert_to))
|
||||
{
|
||||
const Eina_Value_Type *type = member->type;
|
||||
char *conv = NULL;
|
||||
|
||||
r = eina_value_type_convert_to(type, EINA_VALUE_TYPE_STRING,
|
||||
p + member->offset, &conv);
|
||||
if (r)
|
||||
{
|
||||
eina_strbuf_append(str, conv);
|
||||
free(conv);
|
||||
}
|
||||
}
|
||||
|
||||
if (!r)
|
||||
eina_strbuf_append_char(str, '?');
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_eina_value_type_struct_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
|
||||
{
|
||||
const Eina_Value_Struct *tmem = type_mem;
|
||||
|
||||
eina_error_set(0);
|
||||
if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
|
||||
convert == EINA_VALUE_TYPE_STRING)
|
||||
{
|
||||
Eina_Strbuf *str = eina_strbuf_new();
|
||||
const char *s;
|
||||
Eina_Bool ret;
|
||||
|
||||
if (!tmem->memory) eina_strbuf_append(str, "{}");
|
||||
else
|
||||
{
|
||||
const Eina_Value_Struct_Member *itr = tmem->desc->members;
|
||||
|
||||
eina_strbuf_append_char(str, '{');
|
||||
|
||||
if (tmem->desc->member_count > 0)
|
||||
{
|
||||
const Eina_Value_Struct_Member *itr_end;
|
||||
|
||||
itr_end = itr + tmem->desc->member_count;
|
||||
for (; itr < itr_end; itr++)
|
||||
_eina_value_type_struct_convert_to_string_member
|
||||
(tmem, itr, str);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; itr->name != NULL; itr++)
|
||||
_eina_value_type_struct_convert_to_string_member
|
||||
(tmem, itr, str);
|
||||
}
|
||||
|
||||
eina_strbuf_append_char(str, '}');
|
||||
}
|
||||
s = eina_strbuf_string_get(str);
|
||||
ret = eina_value_type_pset(convert, convert_mem, &s);
|
||||
eina_strbuf_free(str);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
eina_error_set(EINA_ERROR_VALUE_FAILED);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_eina_value_type_struct_desc_check(const Eina_Value_Struct_Desc *desc)
|
||||
{
|
||||
unsigned int minsize = 0;
|
||||
const Eina_Value_Struct_Member *itr;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(desc, EINA_FALSE);
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL
|
||||
(desc->version == EINA_VALUE_STRUCT_DESC_VERSION, EINA_FALSE);
|
||||
|
||||
itr = desc->members;
|
||||
if (desc->member_count > 0)
|
||||
{
|
||||
const Eina_Value_Struct_Member *itr_end = itr + desc->member_count;
|
||||
for (; itr < itr_end; itr++)
|
||||
{
|
||||
unsigned int member_end;
|
||||
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL
|
||||
(eina_value_type_check(itr->type), EINA_FALSE);
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL
|
||||
(itr->type->value_size > 0, EINA_FALSE);
|
||||
|
||||
member_end = itr->offset + itr->type->value_size;
|
||||
if (minsize < member_end)
|
||||
minsize = member_end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; itr->name != NULL; itr++)
|
||||
{
|
||||
unsigned int member_end;
|
||||
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL
|
||||
(eina_value_type_check(itr->type), EINA_FALSE);
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL
|
||||
(itr->type->value_size > 0, EINA_FALSE);
|
||||
|
||||
member_end = itr->offset + itr->type->value_size;
|
||||
if (minsize < member_end)
|
||||
minsize = member_end;
|
||||
}
|
||||
}
|
||||
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(minsize > 0, EINA_FALSE);
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(desc->size >= minsize, EINA_FALSE);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_eina_value_type_struct_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr)
|
||||
{
|
||||
const Eina_Value_Struct_Operations *ops = _eina_value_type_struct_ops_get(mem);
|
||||
Eina_Value_Struct *tmem = mem;
|
||||
const Eina_Value_Struct *desc = ptr;
|
||||
|
||||
if (!_eina_value_type_struct_desc_check(desc->desc))
|
||||
{
|
||||
eina_error_set(EINA_ERROR_VALUE_FAILED);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
if ((ops) && (ops->free))
|
||||
ops->free(ops, tmem->desc, tmem->memory);
|
||||
else
|
||||
free(tmem->memory);
|
||||
|
||||
*tmem = *desc;
|
||||
|
||||
ops = _eina_value_type_struct_ops_get(desc);
|
||||
if (!tmem->memory)
|
||||
{
|
||||
if ((ops) && (ops->alloc))
|
||||
tmem->memory = ops->alloc(ops, tmem->desc);
|
||||
else
|
||||
tmem->memory = malloc(tmem->desc->size);
|
||||
|
||||
if (!tmem->memory)
|
||||
{
|
||||
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
eina_error_set(0);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_eina_value_type_struct_vset(const Eina_Value_Type *type, void *mem, va_list args)
|
||||
{
|
||||
const Eina_Value_Struct desc = va_arg(args, Eina_Value_Struct);
|
||||
_eina_value_type_struct_pset(type, mem, &desc);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_eina_value_type_struct_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr)
|
||||
{
|
||||
memcpy(ptr, mem, sizeof(Eina_Value_Struct));
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static const Eina_Value_Type _EINA_VALUE_TYPE_STRUCT = {
|
||||
EINA_VALUE_TYPE_VERSION,
|
||||
sizeof(Eina_Value_Struct),
|
||||
"Eina_Value_Struct",
|
||||
_eina_value_type_struct_setup,
|
||||
_eina_value_type_struct_flush,
|
||||
_eina_value_type_struct_copy,
|
||||
_eina_value_type_struct_compare,
|
||||
_eina_value_type_struct_convert_to,
|
||||
NULL, /* no convert from */
|
||||
_eina_value_type_struct_vset,
|
||||
_eina_value_type_struct_pset,
|
||||
_eina_value_type_struct_pget
|
||||
};
|
||||
|
||||
/* keep all basic types inlined in an array so we can compare if it's
|
||||
* a basic type using pointer arithmetic.
|
||||
*
|
||||
|
@ -4249,9 +4740,13 @@ eina_value_init(void)
|
|||
EINA_VALUE_TYPE_HASH = &_EINA_VALUE_TYPE_HASH;
|
||||
EINA_VALUE_TYPE_TIMEVAL = &_EINA_VALUE_TYPE_TIMEVAL;
|
||||
EINA_VALUE_TYPE_BLOB = &_EINA_VALUE_TYPE_BLOB;
|
||||
EINA_VALUE_TYPE_STRUCT = &_EINA_VALUE_TYPE_STRUCT;
|
||||
|
||||
EINA_VALUE_BLOB_OPERATIONS_MALLOC = &_EINA_VALUE_BLOB_OPERATIONS_MALLOC;
|
||||
|
||||
EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH = &_EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH;
|
||||
EINA_VALUE_STRUCT_OPERATIONS_STRINGSHARE = &_EINA_VALUE_STRUCT_OPERATIONS_STRINGSHARE;
|
||||
|
||||
return EINA_TRUE;
|
||||
|
||||
on_init_fail_hash:
|
||||
|
@ -4326,9 +4821,13 @@ EAPI const Eina_Value_Type *EINA_VALUE_TYPE_LIST = NULL;
|
|||
EAPI const Eina_Value_Type *EINA_VALUE_TYPE_HASH = NULL;
|
||||
EAPI const Eina_Value_Type *EINA_VALUE_TYPE_TIMEVAL = NULL;
|
||||
EAPI const Eina_Value_Type *EINA_VALUE_TYPE_BLOB = NULL;
|
||||
EAPI const Eina_Value_Type *EINA_VALUE_TYPE_STRUCT = NULL;
|
||||
|
||||
EAPI const Eina_Value_Blob_Operations *EINA_VALUE_BLOB_OPERATIONS_MALLOC = NULL;
|
||||
|
||||
EAPI const Eina_Value_Struct_Operations *EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH = NULL;
|
||||
EAPI const Eina_Value_Struct_Operations *EINA_VALUE_STRUCT_OPERATIONS_STRINGSHARE = NULL;
|
||||
|
||||
EAPI Eina_Error EINA_ERROR_VALUE_FAILED = 0;
|
||||
|
||||
EAPI const unsigned int eina_prime_table[] =
|
||||
|
@ -4445,13 +4944,13 @@ eina_value_array_new(const Eina_Value_Type *subtype, unsigned int step)
|
|||
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(subtype), EINA_FALSE);
|
||||
|
||||
value = calloc(1, sizeof(Eina_Value));
|
||||
value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));;
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
||||
if (!eina_value_array_setup(value, subtype, step))
|
||||
{
|
||||
free(value);
|
||||
eina_mempool_free(_eina_value_mp, value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -4465,13 +4964,13 @@ eina_value_list_new(const Eina_Value_Type *subtype)
|
|||
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(subtype), EINA_FALSE);
|
||||
|
||||
value = calloc(1, sizeof(Eina_Value));
|
||||
value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));;
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
||||
if (!eina_value_list_setup(value, subtype))
|
||||
{
|
||||
free(value);
|
||||
eina_mempool_free(_eina_value_mp, value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -4485,13 +4984,31 @@ eina_value_hash_new(const Eina_Value_Type *subtype, unsigned int buckets_power_s
|
|||
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_check(subtype), EINA_FALSE);
|
||||
|
||||
value = calloc(1, sizeof(Eina_Value));
|
||||
value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));;
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
||||
if (!eina_value_hash_setup(value, subtype, buckets_power_size))
|
||||
{
|
||||
free(value);
|
||||
eina_mempool_free(_eina_value_mp, value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
EAPI Eina_Value *
|
||||
eina_value_struct_new(const Eina_Value_Struct_Desc *desc)
|
||||
{
|
||||
Eina_Value *value;
|
||||
|
||||
value = eina_mempool_malloc(_eina_value_mp, sizeof(Eina_Value));;
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
||||
if (!eina_value_struct_setup(value, desc))
|
||||
{
|
||||
eina_mempool_free(_eina_value_mp, value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -1538,6 +1538,180 @@ START_TEST(eina_value_test_blob)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
START_TEST(eina_value_test_struct)
|
||||
{
|
||||
struct mybigst {
|
||||
int a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, x;
|
||||
};
|
||||
#define EINA_VALUE_STRUCT_MEMBER(eina_value_type, type, member) \
|
||||
{#member, eina_value_type, offsetof(type, member)}
|
||||
#define EINA_VALUE_STRUCT_MEMBER_SENTINEL {NULL, NULL, 0}
|
||||
const Eina_Value_Struct_Member mybigst_members[] = {
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, a),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, b),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, c),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, d),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, e),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, f),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, g),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, h),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, i),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, j),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, k),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, l),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, m),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, n),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, o),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, p),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, q),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, r),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, s),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, t),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, u),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, v),
|
||||
EINA_VALUE_STRUCT_MEMBER(EINA_VALUE_TYPE_INT, struct mybigst, x),
|
||||
EINA_VALUE_STRUCT_MEMBER_SENTINEL
|
||||
};
|
||||
const Eina_Value_Struct_Desc mybigst_desc = {
|
||||
EINA_VALUE_STRUCT_DESC_VERSION,
|
||||
EINA_VALUE_STRUCT_OPERATIONS_BINSEARCH,
|
||||
mybigst_members, 23, sizeof(struct mybigst)
|
||||
};
|
||||
struct myst {
|
||||
int i;
|
||||
char c;
|
||||
};
|
||||
const Eina_Value_Struct_Member myst_members[] = {
|
||||
{"i", EINA_VALUE_TYPE_INT, 0},
|
||||
{"c", EINA_VALUE_TYPE_CHAR, 4},
|
||||
{NULL, NULL, 0}
|
||||
};
|
||||
const Eina_Value_Struct_Desc myst_desc = {
|
||||
EINA_VALUE_STRUCT_DESC_VERSION,
|
||||
NULL, myst_members, 2, sizeof(struct myst)
|
||||
};
|
||||
Eina_Value *value, other;
|
||||
int i;
|
||||
char c;
|
||||
char *str;
|
||||
|
||||
eina_init();
|
||||
|
||||
value = eina_value_struct_new(&myst_desc);
|
||||
fail_unless(value != NULL);
|
||||
|
||||
fail_unless(eina_value_struct_set(value, "i", 5678));
|
||||
fail_unless(eina_value_struct_set(value, "c", 0xf));
|
||||
|
||||
fail_unless(eina_value_struct_get(value, "i", &i));
|
||||
fail_unless(i == 5678);
|
||||
fail_unless(eina_value_struct_get(value, "c", &c));
|
||||
fail_unless(c == 0xf);
|
||||
|
||||
str = eina_value_to_string(value);
|
||||
fail_unless(str != NULL);
|
||||
fail_unless(strcmp(str, "{i: 5678, c: 15}") == 0);
|
||||
free(str);
|
||||
|
||||
fail_if(eina_value_struct_get(value, "x", 1234));
|
||||
|
||||
i = 0x11223344;
|
||||
fail_unless(eina_value_struct_pset(value, "i", &i));
|
||||
i = -1;
|
||||
fail_unless(eina_value_struct_pget(value, "i", &i));
|
||||
fail_unless(i == 0x11223344);
|
||||
|
||||
fail_unless(eina_value_copy(value, &other));
|
||||
str = eina_value_to_string(&other);
|
||||
fail_unless(str != NULL);
|
||||
fail_unless(strcmp(str, "{i: 287454020, c: 15}") == 0);
|
||||
free(str);
|
||||
|
||||
eina_value_flush(&other);
|
||||
|
||||
fail_unless(eina_value_struct_setup(&other, &mybigst_desc));
|
||||
fail_unless(eina_value_struct_set(&other, "a", 1) );
|
||||
fail_unless(eina_value_struct_set(&other, "b", 2));
|
||||
fail_unless(eina_value_struct_set(&other, "c", 3));
|
||||
fail_unless(eina_value_struct_set(&other, "d", 4));
|
||||
fail_unless(eina_value_struct_set(&other, "e", 5));
|
||||
fail_unless(eina_value_struct_set(&other, "f", 6));
|
||||
fail_unless(eina_value_struct_set(&other, "g", 7));
|
||||
fail_unless(eina_value_struct_set(&other, "h", 8));
|
||||
fail_unless(eina_value_struct_set(&other, "i", 9));
|
||||
fail_unless(eina_value_struct_set(&other, "j", 10));
|
||||
fail_unless(eina_value_struct_set(&other, "k", 12));
|
||||
fail_unless(eina_value_struct_set(&other, "l", 13));
|
||||
fail_unless(eina_value_struct_set(&other, "m", 14));
|
||||
fail_unless(eina_value_struct_set(&other, "n", 15));
|
||||
fail_unless(eina_value_struct_set(&other, "o", 16));
|
||||
fail_unless(eina_value_struct_set(&other, "p", 17));
|
||||
fail_unless(eina_value_struct_set(&other, "q", 18));
|
||||
fail_unless(eina_value_struct_set(&other, "r", 19));
|
||||
fail_unless(eina_value_struct_set(&other, "s", 20));
|
||||
fail_unless(eina_value_struct_set(&other, "t", 21));
|
||||
fail_unless(eina_value_struct_set(&other, "u", 22));
|
||||
fail_unless(eina_value_struct_set(&other, "v", 23));
|
||||
fail_unless(eina_value_struct_set(&other, "x", 24));
|
||||
|
||||
fail_unless(eina_value_struct_get(&other, "a", &i));
|
||||
fail_unless(i == 1);
|
||||
fail_unless(eina_value_struct_get(&other, "b", &i));
|
||||
fail_unless(i == 2);
|
||||
fail_unless(eina_value_struct_get(&other, "c", &i));
|
||||
fail_unless(i == 3);
|
||||
fail_unless(eina_value_struct_get(&other, "d", &i));
|
||||
fail_unless(i == 4);
|
||||
fail_unless(eina_value_struct_get(&other, "e", &i));
|
||||
fail_unless(i == 5);
|
||||
fail_unless(eina_value_struct_get(&other, "f", &i));
|
||||
fail_unless(i == 6);
|
||||
fail_unless(eina_value_struct_get(&other, "g", &i));
|
||||
fail_unless(i == 7);
|
||||
fail_unless(eina_value_struct_get(&other, "h", &i));
|
||||
fail_unless(i == 8);
|
||||
fail_unless(eina_value_struct_get(&other, "i", &i));
|
||||
fail_unless(i == 9);
|
||||
fail_unless(eina_value_struct_get(&other, "j", &i));
|
||||
fail_unless(i == 10);
|
||||
fail_unless(eina_value_struct_get(&other, "k", &i));
|
||||
fail_unless(i == 12);
|
||||
fail_unless(eina_value_struct_get(&other, "l", &i));
|
||||
fail_unless(i == 13);
|
||||
fail_unless(eina_value_struct_get(&other, "m", &i));
|
||||
fail_unless(i == 14);
|
||||
fail_unless(eina_value_struct_get(&other, "n", &i));
|
||||
fail_unless(i == 15);
|
||||
fail_unless(eina_value_struct_get(&other, "o", &i));
|
||||
fail_unless(i == 16);
|
||||
fail_unless(eina_value_struct_get(&other, "p", &i));
|
||||
fail_unless(i == 17);
|
||||
fail_unless(eina_value_struct_get(&other, "q", &i));
|
||||
fail_unless(i == 18);
|
||||
fail_unless(eina_value_struct_get(&other, "r", &i));
|
||||
fail_unless(i == 19);
|
||||
fail_unless(eina_value_struct_get(&other, "s", &i));
|
||||
fail_unless(i == 20);
|
||||
fail_unless(eina_value_struct_get(&other, "t", &i));
|
||||
fail_unless(i == 21);
|
||||
fail_unless(eina_value_struct_get(&other, "u", &i));
|
||||
fail_unless(i == 22);
|
||||
fail_unless(eina_value_struct_get(&other, "v", &i));
|
||||
fail_unless(i == 23);
|
||||
fail_unless(eina_value_struct_get(&other, "x", &i));
|
||||
fail_unless(i == 24);
|
||||
|
||||
str = eina_value_to_string(&other);
|
||||
fail_unless(str != NULL);
|
||||
fail_unless(strcmp(str, "{a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10, k: 12, l: 13, m: 14, n: 15, o: 16, p: 17, q: 18, r: 19, s: 20, t: 21, u: 22, v: 23, x: 24}") == 0);
|
||||
free(str);
|
||||
|
||||
eina_value_free(value);
|
||||
eina_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
eina_test_value(TCase *tc)
|
||||
{
|
||||
|
@ -1554,4 +1728,5 @@ eina_test_value(TCase *tc)
|
|||
tcase_add_test(tc, eina_value_test_hash);
|
||||
tcase_add_test(tc, eina_value_test_timeval);
|
||||
tcase_add_test(tc, eina_value_test_blob);
|
||||
tcase_add_test(tc, eina_value_test_struct);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue