eina_value: add list type.

Similar to array, but less efficient as uses list nodes. If possible
values are stored on list->data itself, otherwise they are allocated
and the pointer goes as list->data.



SVN revision: 67096
This commit is contained in:
Gustavo Sverzut Barbieri 2012-01-11 21:52:32 +00:00
parent b7539c2ad0
commit 16c03cc014
4 changed files with 1475 additions and 13 deletions

View File

@ -834,6 +834,392 @@ eina_value_array_pappend(Eina_Value *value, const void *ptr)
#undef EINA_VALUE_TYPE_ARRAY_CHECK_RETURN_VAL
#define EINA_VALUE_TYPE_LIST_CHECK_RETURN_VAL(value, retval) \
EINA_SAFETY_ON_NULL_RETURN_VAL(value, retval); \
EINA_SAFETY_ON_FALSE_RETURN_VAL(value->type == EINA_VALUE_TYPE_LIST, retval)
static inline void *
eina_value_list_node_memory_get(const Eina_Value_Type *type, const Eina_List *node)
{
if (node == NULL) return NULL;
if (type->value_size <= sizeof(void*))
return (void *)&(node->data);
return node->data;
}
static inline void *
eina_value_list_node_memory_setup(const Eina_Value_Type *type, Eina_List *node)
{
if (type->value_size <= sizeof(void*))
return (void *)&(node->data);
node->data = malloc(type->value_size);
return node->data;
}
static inline void
eina_value_list_node_memory_flush(const Eina_Value_Type *type, Eina_List *node)
{
if (type->value_size <= sizeof(void*))
return;
free(node->data);
}
static inline Eina_Bool
eina_value_list_setup(Eina_Value *value, const Eina_Value_Type *subtype)
{
Eina_Value_List desc = { subtype, NULL };
if (!eina_value_setup(value, EINA_VALUE_TYPE_LIST))
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_list_count(const Eina_Value *value)
{
Eina_Value_List *desc;
EINA_VALUE_TYPE_LIST_CHECK_RETURN_VAL(value, 0);
desc = eina_value_memory_get(value);
if (!desc)
return 0;
return eina_list_count(desc->list);
}
static inline Eina_Bool
eina_value_list_remove(Eina_Value *value, unsigned int position)
{
Eina_Value_List *desc;
Eina_List *node;
void *mem;
EINA_VALUE_TYPE_LIST_CHECK_RETURN_VAL(value, 0);
desc = eina_value_memory_get(value);
if (!desc)
return EINA_FALSE;
node = eina_list_nth_list(desc->list, position);
mem = eina_value_list_node_memory_get(desc->subtype, node);
if (!mem)
return EINA_FALSE;
eina_value_type_flush(desc->subtype, mem);
eina_value_list_node_memory_flush(desc->subtype, node);
desc->list = eina_list_remove_list(desc->list, node);
return EINA_TRUE;
}
static inline Eina_Bool
eina_value_list_vset(Eina_Value *value, unsigned int position, va_list args)
{
Eina_Value_List *desc;
Eina_List *node;
void *mem;
EINA_VALUE_TYPE_LIST_CHECK_RETURN_VAL(value, 0);
desc = eina_value_memory_get(value);
if (!desc)
return EINA_FALSE;
node = eina_list_nth_list(desc->list, position);
mem = eina_value_list_node_memory_get(desc->subtype, node);
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_list_vget(const Eina_Value *value, unsigned int position, va_list args)
{
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_memory_get(value);
if (!desc)
return EINA_FALSE;
node = eina_list_nth_list(desc->list, position);
mem = eina_value_list_node_memory_get(desc->subtype, node);
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_list_vinsert(Eina_Value *value, unsigned int position, va_list args)
{
Eina_Value_List *desc;
Eina_List *node;
void *mem;
EINA_VALUE_TYPE_LIST_CHECK_RETURN_VAL(value, 0);
desc = eina_value_memory_get(value);
if (!desc)
return EINA_FALSE;
if (!desc->list)
node = desc->list = eina_list_append(NULL, (void*)1L);
else if (position == 0)
node = desc->list = eina_list_prepend(desc->list, (void*)1L);
else
{
Eina_List *rel = eina_list_nth_list(desc->list, position - 1);
desc->list = eina_list_append_relative_list(desc->list, (void*)1L, rel);
node = rel->next;
}
EINA_SAFETY_ON_NULL_RETURN_VAL(node, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL(node->data == (void*)1L, EINA_FALSE);
mem = eina_value_list_node_memory_setup(desc->subtype, node);
if (!mem)
{
desc->list = eina_list_remove_list(desc->list, node);
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_value_list_node_memory_flush(desc->subtype, node);
desc->list = eina_list_remove_list(desc->list, node);
return EINA_FALSE;
}
static inline Eina_Bool
eina_value_list_vappend(Eina_Value *value, va_list args)
{
Eina_Value_List *desc;
Eina_List *node;
void *mem;
EINA_VALUE_TYPE_LIST_CHECK_RETURN_VAL(value, 0);
desc = eina_value_memory_get(value);
if (!desc)
return EINA_FALSE;
desc->list = eina_list_append(desc->list, (void*)1L);
node = eina_list_last(desc->list);
EINA_SAFETY_ON_NULL_RETURN_VAL(node, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL(node->data == (void*)1L, EINA_FALSE);
mem = eina_value_list_node_memory_setup(desc->subtype, node);
if (!mem)
{
desc->list = eina_list_remove_list(desc->list, node);
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_value_list_node_memory_flush(desc->subtype, node);
desc->list = eina_list_remove_list(desc->list, node);
return EINA_FALSE;
}
static inline Eina_Bool
eina_value_list_set(Eina_Value *value, unsigned int position, ...)
{
va_list args;
Eina_Bool ret;
va_start(args, position);
ret = eina_value_list_vset(value, position, args);
va_end(args);
return ret;
}
static inline Eina_Bool
eina_value_list_get(const Eina_Value *value, unsigned int position, ...)
{
va_list args;
Eina_Bool ret;
va_start(args, position);
ret = eina_value_list_vget(value, position, args);
va_end(args);
return ret;
}
static inline Eina_Bool
eina_value_list_insert(Eina_Value *value, unsigned int position, ...)
{
va_list args;
Eina_Bool ret;
va_start(args, position);
ret = eina_value_list_vinsert(value, position, args);
va_end(args);
return ret;
}
static inline Eina_Bool eina_value_list_append(Eina_Value *value, ...)
{
va_list args;
Eina_Bool ret;
va_start(args, value);
ret = eina_value_list_vappend(value, args);
va_end(args);
return ret;
}
static inline Eina_Bool
eina_value_list_pset(Eina_Value *value, unsigned int position, const void *ptr)
{
Eina_Value_List *desc;
Eina_List *node;
void *mem;
EINA_VALUE_TYPE_LIST_CHECK_RETURN_VAL(value, 0);
desc = eina_value_memory_get(value);
if (!desc)
return EINA_FALSE;
node = eina_list_nth_list(desc->list, position);
mem = eina_value_list_node_memory_get(desc->subtype, node);
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_list_pget(const Eina_Value *value, unsigned int position, void *ptr)
{
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_memory_get(value);
if (!desc)
return EINA_FALSE;
node = eina_list_nth_list(desc->list, position);
mem = eina_value_list_node_memory_get(desc->subtype, node);
if (!mem)
return EINA_FALSE;
ret = eina_value_type_pget(desc->subtype, mem, ptr);
return ret;
}
static inline Eina_Bool
eina_value_list_pinsert(Eina_Value *value, unsigned int position, const void *ptr)
{
Eina_Value_List *desc;
Eina_List *node;
void *mem;
EINA_VALUE_TYPE_LIST_CHECK_RETURN_VAL(value, 0);
desc = eina_value_memory_get(value);
if (!desc)
return EINA_FALSE;
if (!desc->list)
node = desc->list = eina_list_append(NULL, (void*)1L);
else if (position == 0)
node = desc->list = eina_list_prepend(desc->list, (void*)1L);
else
{
Eina_List *rel = eina_list_nth_list(desc->list, position - 1);
desc->list = eina_list_append_relative_list(desc->list, (void*)1L, rel);
node = rel->next;
}
EINA_SAFETY_ON_NULL_RETURN_VAL(node, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL(node->data == (void*)1L, EINA_FALSE);
mem = eina_value_list_node_memory_setup(desc->subtype, node);
if (!mem)
{
desc->list = eina_list_remove_list(desc->list, node);
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_value_list_node_memory_flush(desc->subtype, node);
desc->list = eina_list_remove_list(desc->list, node);
return EINA_FALSE;
}
static inline Eina_Bool
eina_value_list_pappend(Eina_Value *value, const void *ptr)
{
Eina_Value_List *desc;
Eina_List *node;
void *mem;
EINA_VALUE_TYPE_LIST_CHECK_RETURN_VAL(value, 0);
desc = eina_value_memory_get(value);
if (!desc)
return EINA_FALSE;
desc->list = eina_list_append(desc->list, (void*)1L);
node = eina_list_last(desc->list);
EINA_SAFETY_ON_NULL_RETURN_VAL(node, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL(node->data == (void*)1L, EINA_FALSE);
mem = eina_value_list_node_memory_setup(desc->subtype, node);
if (!mem)
{
desc->list = eina_list_remove_list(desc->list, node);
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_value_list_node_memory_flush(desc->subtype, node);
desc->list = eina_list_remove_list(desc->list, node);
return EINA_FALSE;
}
#undef EINA_VALUE_TYPE_LIST_CHECK_RETURN_VAL
static inline Eina_Bool
eina_value_type_setup(const Eina_Value_Type *type, void *mem)

View File

@ -22,6 +22,7 @@
#include "eina_types.h"
#include "eina_fp.h" /* defines int64_t and uint64_t */
#include "eina_inarray.h"
#include "eina_list.h"
#include <stdarg.h>
/**
@ -208,6 +209,19 @@ EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_STRING;
*/
EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_ARRAY;
/**
* @var EINA_VALUE_TYPE_LIST
*
* manages list type. The value get/set are the type of elements in
* the list, use the alternaties:
* @li eina_value_list_get() and eina_value_list_set()
* @li eina_value_list_vget() and eina_value_list_vset()
* @li eina_value_list_pget() and eina_value_list_pset()
*
* @since 1.2
*/
EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_LIST;
/**
* @var EINA_ERROR_VALUE_FAILED
@ -368,6 +382,7 @@ static inline int eina_value_compare(const Eina_Value *a,
* @li EINA_VALUE_TYPE_STRINGSHARE: const char *
* @li EINA_VALUE_TYPE_STRING: const char *
* @li EINA_VALUE_TYPE_ARRAY: Eina_Value_Array
* @li EINA_VALUE_TYPE_LIST: Eina_Value_List
*
* @code
* Eina_Value *value = eina_value_new(EINA_VALUE_TYPE_INT);
@ -384,6 +399,7 @@ static inline int eina_value_compare(const Eina_Value *a,
* @endcode
*
* @note for array member see eina_value_array_set()
* @note for list member see eina_value_list_set()
*
* @see eina_value_get()
* @see eina_value_vset()
@ -422,6 +438,7 @@ static inline Eina_Bool eina_value_set(Eina_Value *value,
* @li EINA_VALUE_TYPE_STRINGSHARE: const char **
* @li EINA_VALUE_TYPE_STRING: const char **
* @li EINA_VALUE_TYPE_ARRAY: Eina_Value_Array*
* @li EINA_VALUE_TYPE_LIST: Eina_Value_List*
*
* @code
* Eina_Value *value = eina_value_new(EINA_VALUE_TYPE_INT);
@ -441,6 +458,7 @@ static inline Eina_Bool eina_value_set(Eina_Value *value,
* @endcode
*
* @note for array member see eina_value_array_get()
* @note for list member see eina_value_list_get()
*
* @see eina_value_set()
* @see eina_value_vset()
@ -458,6 +476,7 @@ static inline Eina_Bool eina_value_get(const Eina_Value *value,
* @return #EINA_TRUE on success, #EINA_FALSE otherwise.
*
* @note for array member see eina_value_array_vset()
* @note for list member see eina_value_list_vset()
*
* @see eina_value_vget()
* @see eina_value_set()
@ -480,6 +499,7 @@ static inline Eina_Bool eina_value_vset(Eina_Value *value,
* thus the contents should @b not be free'd.
*
* @note for array member see eina_value_array_vget()
* @note for list member see eina_value_list_vget()
*
* @see eina_value_vset()
* @see eina_value_get()
@ -514,6 +534,7 @@ static inline Eina_Bool eina_value_vget(const Eina_Value *value,
* @li EINA_VALUE_TYPE_STRINGSHARE: const char **
* @li EINA_VALUE_TYPE_STRING: const char **
* @li EINA_VALUE_TYPE_ARRAY: Eina_Value_Array*
* @li EINA_VALUE_TYPE_LIST: Eina_Value_List*
*
* @note the pointer contents are written using the size defined by
* type. It can be larger than void* or uint64_t.
@ -534,6 +555,7 @@ static inline Eina_Bool eina_value_vget(const Eina_Value *value,
* @endcode
*
* @note for array member see eina_value_array_pset()
* @note for list member see eina_value_list_pset()
*
* @see eina_value_pget()
* @see eina_value_set()
@ -573,6 +595,7 @@ static inline Eina_Bool eina_value_pset(Eina_Value *value,
* @li EINA_VALUE_TYPE_STRINGSHARE: const char **
* @li EINA_VALUE_TYPE_STRING: const char **
* @li EINA_VALUE_TYPE_ARRAY: Eina_Value_Array*
* @li EINA_VALUE_TYPE_LIST: Eina_Value_List*
*
* @code
* Eina_Value *value = eina_value_new(EINA_VALUE_TYPE_INT);
@ -592,6 +615,7 @@ static inline Eina_Bool eina_value_pset(Eina_Value *value,
* @endcode
*
* @note for array member see eina_value_array_get()
* @note for list member see eina_value_list_get()
*
* @see eina_value_set()
* @see eina_value_vset()
@ -1252,6 +1276,597 @@ static inline Eina_Bool eina_value_array_pappend(Eina_Value *value,
* @}
*/
/**
* @defgroup Eina_Value_List_Group Generic Value List management
*
* @{
*/
/**
* @typedef Eina_Value_List
* Value type for #EINA_VALUE_TYPE_LIST
*
* @since 1.2
*/
typedef struct _Eina_Value_List Eina_Value_List;
/**
* @struct _Eina_Value_List
* Used to store the list and its subtype.
*/
struct _Eina_Value_List
{
const Eina_Value_Type *subtype; /**< how to allocate and access items */
Eina_List *list; /**< the list that holds data, members are of subtype->value_size bytes. */
};
/**
* @brief Create generic value storage of type list.
* @param subtype how to manage this list members.
* @return The new value or @c NULL on failure.
*
* Create a new generic value storage of type list. 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_list_setup() doing malloc
* for you.
*
* @see eina_value_free()
* @see eina_value_list_setup()
*
* @since 1.2
*/
EAPI Eina_Value *eina_value_list_new(const Eina_Value_Type *subtype) EINA_ARG_NONNULL(1);
/**
* @brief Setup generic value storage of type list.
* @param value value object
* @param subtype how to manage this list members.
* @return #EINA_TRUE on success, #EINA_FALSE otherwise.
*
* Setups new generic value storage of type list with the given
* @a subtype.
*
* This is the same as calling eina_value_set() with
* #EINA_VALUE_TYPE_LIST followed by eina_value_pset() with the
* #Eina_Value_List 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_list_setup(Eina_Value *value,
const Eina_Value_Type *subtype) EINA_ARG_NONNULL(1, 2);
/**
* @brief Query number of elements in value of list type.
* @param value value object.
* @return number of child elements.
* @since 1.2
*/
static inline unsigned int eina_value_list_count(const Eina_Value *value);
/**
* @brief Remove element at given position in value of list 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_list_remove(Eina_Value *value,
unsigned int position) EINA_ARG_NONNULL(1);
/**
* @brief Set the generic value in an list 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_LIST: Eina_Value_List
*
* @code
* Eina_Value *value = eina_value_list_new(EINA_VALUE_TYPE_INT);
* int x;
*
* eina_value_list_append(value, 1234);
* eina_value_list_set(value, 0, 5678);
* eina_value_list_get(value, 0, &x);
* eina_value_free(value);
* @endcode
*
* @see eina_value_list_get()
* @see eina_value_list_vset()
* @see eina_value_list_pset()
* @see eina_value_list_insert()
* @see eina_value_list_vinsert()
* @see eina_value_list_pinsert()
* @see eina_value_list_append()
* @see eina_value_list_vappend()
* @see eina_value_list_pappend()
*
* @since 1.2
*/
static inline Eina_Bool eina_value_list_set(Eina_Value *value,
unsigned int position,
...) EINA_ARG_NONNULL(1);
/**
* @brief Get the generic value from an list 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_LIST: Eina_Value_List*
*
* @code
* Eina_Value *value = eina_value_list_new(EINA_VALUE_TYPE_INT);
* int x;
*
* eina_value_list_append(value, 1234);
* eina_value_list_get(value, 0, &x);
* eina_value_free(value);
* @endcode
*
* @see eina_value_list_set()
* @see eina_value_list_vset()
* @see eina_value_list_pset()
*
* @since 1.2
*/
static inline Eina_Bool eina_value_list_get(const Eina_Value *value,
unsigned int position,
...) EINA_ARG_NONNULL(1);
/**
* @brief Insert the generic value in an list 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_LIST: Eina_Value_List
*
* @code
* Eina_Value *value = eina_value_list_new(EINA_VALUE_TYPE_INT);
* int x;
*
* eina_value_list_insert(value, 0, 1234);
* eina_value_list_get(value, 0, &x);
* eina_value_free(value);
* @endcode
*
* @see eina_value_list_set()
* @see eina_value_list_get()
* @see eina_value_list_vset()
* @see eina_value_list_pset()
* @see eina_value_list_vinsert()
* @see eina_value_list_pinsert()
* @see eina_value_list_append()
* @see eina_value_list_vappend()
* @see eina_value_list_pappend()
*
* @since 1.2
*/
static inline Eina_Bool eina_value_list_insert(Eina_Value *value,
unsigned int position,
...) EINA_ARG_NONNULL(1);
/**
* @brief Append the generic value in an list.
* @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_LIST: Eina_Value_List
*
* @code
* Eina_Value *value = eina_value_list_new(EINA_VALUE_TYPE_INT);
* int x;
*
* eina_value_list_append(value, 1234);
* eina_value_list_get(value, 0, &x);
* eina_value_free(value);
* @endcode
*
* @see eina_value_list_set()
* @see eina_value_list_get()
* @see eina_value_list_vset()
* @see eina_value_list_pset()
* @see eina_value_list_vinsert()
* @see eina_value_list_pinsert()
* @see eina_value_list_append()
* @see eina_value_list_vappend()
* @see eina_value_list_pappend()
*
* @since 1.2
*/
static inline Eina_Bool eina_value_list_append(Eina_Value *value,
...) EINA_ARG_NONNULL(1);
/**
* @brief Set the generic value in an list 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_list_set()
* @see eina_value_list_get()
* @see eina_value_list_pset()
* @see eina_value_list_insert()
* @see eina_value_list_vinsert()
* @see eina_value_list_pinsert()
* @see eina_value_list_append()
* @see eina_value_list_vappend()
* @see eina_value_list_pappend()
*
* @since 1.2
*/
static inline Eina_Bool eina_value_list_vset(Eina_Value *value,
unsigned int position,
va_list args) EINA_ARG_NONNULL(1);
/**
* @brief Get the generic value from an list 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_list_vset()
* @see eina_value_list_get()
* @see eina_value_list_pget()
*
* @since 1.2
*/
static inline Eina_Bool eina_value_list_vget(const Eina_Value *value,
unsigned int position,
va_list args) EINA_ARG_NONNULL(1);
/**
* @brief Insert the generic value in an list 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_list_set()
* @see eina_value_list_get()
* @see eina_value_list_vset()
* @see eina_value_list_pset()
* @see eina_value_list_insert()
* @see eina_value_list_pinsert()
* @see eina_value_list_append()
* @see eina_value_list_vappend()
* @see eina_value_list_pappend()
*
* @since 1.2
*/
static inline Eina_Bool eina_value_list_vinsert(Eina_Value *value,
unsigned int position,
va_list args) EINA_ARG_NONNULL(1);
/**
* @brief Append the generic value in an list.
* @param value source value object
* @param args variable argument
* @return #EINA_TRUE on success, #EINA_FALSE otherwise.
* @see eina_value_list_set()
* @see eina_value_list_get()
* @see eina_value_list_vget()
* @see eina_value_list_pset()
* @see eina_value_list_insert()
* @see eina_value_list_vinsert()
* @see eina_value_list_pinsert()
* @see eina_value_list_append()
* @see eina_value_list_pappend()
*
* @since 1.2
*/
static inline Eina_Bool eina_value_list_vappend(Eina_Value *value,
va_list args) EINA_ARG_NONNULL(1);
/**
* @brief Set the generic value in an list 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_LIST: Eina_Value_List*
*
* @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_list_new(EINA_VALUE_TYPE_INT);
* int x = 1234;
*
* eina_value_list_append(value, 1234);
* eina_value_list_pset(value, 0, &x);
* eina_value_list_pget(value, 0, &x);
* eina_value_free(value);
* @endcode
*
* @see eina_value_list_set()
* @see eina_value_list_get()
* @see eina_value_list_vset()
* @see eina_value_list_insert()
* @see eina_value_list_vinsert()
* @see eina_value_list_pinsert()
* @see eina_value_list_append()
* @see eina_value_list_vappend()
* @see eina_value_list_pappend()
*
* @since 1.2
*/
static inline Eina_Bool eina_value_list_pset(Eina_Value *value,
unsigned int position,
const void *ptr) EINA_ARG_NONNULL(1, 3);
/**
* @brief Get the generic value to pointer from an list 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_LIST: Eina_Value_List*
*
* @code
* Eina_Value *value = eina_value_list_new(EINA_VALUE_TYPE_INT);
* int x;
*
* eina_value_list_append(value, 1234);
* eina_value_list_pget(value, 0, &x);
* eina_value_free(value);
* @endcode
*
* @see eina_value_list_set()
* @see eina_value_list_vset()
* @see eina_value_list_pset()
*
* @since 1.2
*/
static inline Eina_Bool eina_value_list_pget(const Eina_Value *value,
unsigned int position,
void *ptr) EINA_ARG_NONNULL(1, 3);
/**
* @brief Insert the generic value in an list 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_LIST: Eina_Value_List*
*
* @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_list_new(EINA_VALUE_TYPE_INT);
* int x = 1234;
*
* eina_value_list_pinsert(value, 0, &x);
* eina_value_list_pget(value, 0, &x);
* eina_value_free(value);
* @endcode
*
* @see eina_value_list_set()
* @see eina_value_list_get()
* @see eina_value_list_vset()
* @see eina_value_list_insert()
* @see eina_value_list_vinsert()
* @see eina_value_list_pinsert()
* @see eina_value_list_append()
* @see eina_value_list_vappend()
* @see eina_value_list_pappend()
*
* @since 1.2
*/
static inline Eina_Bool eina_value_list_pinsert(Eina_Value *value,
unsigned int position,
const void *ptr) EINA_ARG_NONNULL(1);
/**
* @brief Append the generic value in an list 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_LIST: Eina_Value_List*
*
* @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_list_new(EINA_VALUE_TYPE_INT);
* int x = 1234;
*
* eina_value_list_pappend(value, &x);
* eina_value_list_pget(value, 0, &x);
* eina_value_free(value);
* @endcode
*
* @see eina_value_list_set()
* @see eina_value_list_get()
* @see eina_value_list_vset()
* @see eina_value_list_insert()
* @see eina_value_list_vinsert()
* @see eina_value_list_pinsert()
* @see eina_value_list_append()
* @see eina_value_list_vappend()
* @see eina_value_list_pappend()
*
* @since 1.2
*/
static inline Eina_Bool eina_value_list_pappend(Eina_Value *value,
const void *ptr) EINA_ARG_NONNULL(1);
/**
* @}
*/
/**
* @defgroup Eina_Value_Type_Group Generic Value Type management
*

View File

@ -2397,7 +2397,10 @@ _eina_value_type_array_copy(const Eina_Value_Type *type __UNUSED__, const void *
}
if (!subtype->copy)
return EINA_FALSE;
{
eina_error_set(EINA_ERROR_VALUE_FAILED);
return EINA_FALSE;
}
d->array = eina_inarray_new(subtype->value_size, s->step);
if (!d->array)
@ -2494,8 +2497,18 @@ _eina_value_type_array_convert_to(const Eina_Value_Type *type __UNUSED__, const
const Eina_Value_Array *tmem = type_mem;
Eina_Bool ret = EINA_FALSE;
if ((convert == EINA_VALUE_TYPE_STRING) ||
(convert == EINA_VALUE_TYPE_STRINGSHARE))
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, "[]");
@ -2549,16 +2562,6 @@ _eina_value_type_array_convert_to(const Eina_Value_Type *type __UNUSED__, const
eina_strbuf_free(str);
}
}
else 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);
}
if (!ret)
{
@ -2659,6 +2662,306 @@ static const Eina_Value_Type _EINA_VALUE_TYPE_ARRAY = {
_eina_value_type_array_pget
};
static Eina_Bool
_eina_value_type_list_setup(const Eina_Value_Type *type __UNUSED__, void *mem)
{
memset(mem, 0, sizeof(Eina_Value_List));
return EINA_TRUE;
}
static Eina_Bool
_eina_value_type_list_flush_elements(Eina_Value_List *tmem)
{
const Eina_Value_Type *subtype = tmem->subtype;
Eina_Bool ret = EINA_TRUE;
if (!tmem->list) return EINA_TRUE;
while (tmem->list)
{
void *mem = eina_value_list_node_memory_get(tmem->subtype, tmem->list);
ret &= eina_value_type_flush(subtype, mem);
eina_value_list_node_memory_flush(tmem->subtype, tmem->list);
tmem->list = eina_list_remove_list(tmem->list, tmem->list);
}
return ret;
}
static Eina_Bool
_eina_value_type_list_flush(const Eina_Value_Type *type __UNUSED__, void *mem)
{
Eina_Value_List *tmem = mem;
Eina_Bool ret =_eina_value_type_list_flush_elements(tmem);
if (tmem->list) eina_list_free(tmem->list);
tmem->list = NULL;
tmem->subtype = NULL;
return ret;
}
static Eina_Bool
_eina_value_type_list_copy(const Eina_Value_Type *type __UNUSED__, const void *src, void *dst)
{
const Eina_Value_Type *subtype;
const Eina_Value_List *s = src;
Eina_Value_List *d = dst;
const Eina_List *snode;
d->subtype = subtype = s->subtype;
if ((!s->list) || (!s->subtype))
{
d->list = NULL;
return EINA_TRUE;
}
if (!subtype->copy)
{
eina_error_set(EINA_ERROR_VALUE_FAILED);
return EINA_FALSE;
}
d->list = NULL;
for (snode = s->list; snode != NULL; snode = snode->next)
{
const void *ptr = eina_value_list_node_memory_get(subtype, snode);
Eina_List *dnode;
void *imem;
d->list = eina_list_append(d->list, (void*)1L);
dnode = eina_list_last(d->list);
EINA_SAFETY_ON_NULL_GOTO(dnode, error);
EINA_SAFETY_ON_FALSE_GOTO(dnode->data == (void*)1L, error);
imem = eina_value_list_node_memory_setup(subtype, dnode);
if (!subtype->copy(subtype, ptr, imem))
{
eina_value_list_node_memory_flush(subtype, dnode);
d->list = eina_list_remove_list(d->list, dnode);
goto error;
}
}
return EINA_TRUE;
error:
_eina_value_type_list_flush_elements(d);
return EINA_FALSE;
}
static int
_eina_value_type_list_compare(const Eina_Value_Type *type __UNUSED__, const void *a, const void *b)
{
const Eina_Value_Type *subtype;
const Eina_Value_List *eva_a = a, *eva_b = b;
const Eina_List *anode, *bnode;
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->list) && (!eva_b->list))
return 0;
else if (!eva_a->list)
return -1;
else if (!eva_b->list)
return 1;
for (anode = eva_a->list, bnode = eva_b->list;
(cmp == 0) && (anode) && (bnode);
anode = anode->next, bnode = bnode->next)
{
const void *amem = eina_value_list_node_memory_get(subtype, anode);
const void *bmem = eina_value_list_node_memory_get(subtype, bnode);
cmp = subtype->compare(subtype, amem, bmem);
}
if (cmp == 0)
{
if ((!anode) && (bnode))
return -1;
else if ((anode) && (!bnode))
return 1;
return 0;
}
return cmp;
}
static Eina_Bool
_eina_value_type_list_convert_to(const Eina_Value_Type *type __UNUSED__, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
{
const Eina_Value_List *tmem = type_mem;
Eina_Bool ret = EINA_FALSE;
if ((convert == EINA_VALUE_TYPE_STRING) ||
(convert == EINA_VALUE_TYPE_STRINGSHARE))
{
Eina_Strbuf *str = eina_strbuf_new();
if (!tmem->list) eina_strbuf_append(str, "[]");
else
{
const Eina_Value_Type *subtype = tmem->subtype;
const Eina_List *node;
Eina_Value tmp;
const char *s;
Eina_Bool first = EINA_TRUE;
eina_value_setup(&tmp, EINA_VALUE_TYPE_STRING);
eina_strbuf_append_char(str, '[');
for (node = tmem->list; node != NULL; node = node->next)
{
Eina_Bool r = EINA_FALSE;
if (subtype->convert_to)
{
const void *ptr;
ptr = eina_value_list_node_memory_get(subtype, node);
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, ']');
s = eina_strbuf_string_get(str);
ret = eina_value_type_pset(convert, convert_mem, &s);
eina_strbuf_free(str);
}
}
else if ((tmem->list) && (tmem->list->next == NULL))
{
const Eina_Value_Type *subtype = tmem->subtype;
void *imem = eina_value_list_node_memory_get(subtype, tmem->list);
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);
}
if (!ret)
{
eina_error_set(EINA_ERROR_VALUE_FAILED);
return EINA_FALSE;
}
return EINA_TRUE;
}
static Eina_Bool
_eina_value_type_list_convert_from(const Eina_Value_Type *type, const Eina_Value_Type *convert, void *type_mem, const void *convert_mem)
{
Eina_Value_List *tmem = type_mem;
Eina_Value_List desc = {convert, NULL};
Eina_List *node;
char *buf;
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;
tmem->list = eina_list_append(tmem->list, (void*)1L);
node = eina_list_last(tmem->list);
EINA_SAFETY_ON_NULL_RETURN_VAL(node, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL(node->data == (void*)1L, EINA_FALSE);
imem = eina_value_list_node_memory_setup(tmem->subtype, node);
if (!imem)
{
tmem->list = eina_list_remove_list(tmem->list, node);
return EINA_FALSE;
}
if (!eina_value_type_setup(tmem->subtype, imem)) goto error_setup;
if (!eina_value_type_pset(tmem->subtype, imem, &buf)) goto error_set;
return EINA_TRUE;
error_set:
eina_value_type_flush(tmem->subtype, imem);
error_setup:
eina_value_list_node_memory_flush(tmem->subtype, node);
tmem->list = eina_list_remove_list(tmem->list, node);
return EINA_FALSE;
}
static Eina_Bool
_eina_value_type_list_pset(const Eina_Value_Type *type __UNUSED__, void *mem, const void *ptr)
{
Eina_Value_List *tmem = mem;
const Eina_Value_List *desc = ptr;
if ((!tmem->subtype) && (!desc->subtype))
return EINA_TRUE;
_eina_value_type_list_flush_elements(tmem);
tmem->subtype = desc->subtype;
return EINA_TRUE;
}
static Eina_Bool
_eina_value_type_list_vset(const Eina_Value_Type *type, void *mem, va_list args)
{
const Eina_Value_List desc = va_arg(args, Eina_Value_List);
_eina_value_type_list_pset(type, mem, &desc);
return EINA_TRUE;
}
static Eina_Bool
_eina_value_type_list_pget(const Eina_Value_Type *type __UNUSED__, const void *mem, void *ptr)
{
memcpy(ptr, mem, sizeof(Eina_Value_List));
return EINA_TRUE;
}
static const Eina_Value_Type _EINA_VALUE_TYPE_LIST = {
EINA_VALUE_TYPE_VERSION,
sizeof(Eina_Value_List),
"Eina_Value_List",
_eina_value_type_list_setup,
_eina_value_type_list_flush,
_eina_value_type_list_copy,
_eina_value_type_list_compare,
_eina_value_type_list_convert_to,
_eina_value_type_list_convert_from,
_eina_value_type_list_vset,
_eina_value_type_list_pset,
_eina_value_type_list_pget
};
/* keep all basic types inlined in an array so we can compare if it's
* a basic type using pointer arithmetic.
*
@ -2917,6 +3220,7 @@ eina_value_init(void)
EINA_VALUE_TYPE_ARRAY = &_EINA_VALUE_TYPE_ARRAY;
EINA_VALUE_TYPE_LIST = &_EINA_VALUE_TYPE_LIST;
return EINA_TRUE;
}
@ -2966,6 +3270,7 @@ 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 const Eina_Value_Type *EINA_VALUE_TYPE_LIST = NULL;
EAPI Eina_Error EINA_ERROR_VALUE_FAILED = 0;
@ -3096,6 +3401,26 @@ eina_value_array_new(const Eina_Value_Type *subtype, unsigned int step)
return value;
}
EAPI Eina_Value *
eina_value_list_new(const Eina_Value_Type *subtype)
{
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_list_setup(value, subtype))
{
free(value);
return NULL;
}
return value;
}
EAPI Eina_Bool
eina_value_type_check(const Eina_Value_Type *type)
{

View File

@ -334,6 +334,52 @@ START_TEST(eina_value_test_compare)
fail_unless(eina_value_array_set(b, 0, 10));
fail_unless(eina_value_compare(a, b) < 0);
eina_value_flush(a);
eina_value_flush(b);
fail_unless(eina_value_list_setup(a, EINA_VALUE_TYPE_CHAR));
fail_unless(eina_value_list_setup(b, EINA_VALUE_TYPE_CHAR));
fail_unless(eina_value_compare(a, b) == 0);
fail_unless(eina_value_list_append(a, 1));
fail_unless(eina_value_list_append(a, 2));
fail_unless(eina_value_list_append(a, 3));
fail_unless(eina_value_list_append(b, 1));
fail_unless(eina_value_list_append(b, 2));
fail_unless(eina_value_list_append(b, 3));
fail_unless(eina_value_compare(a, b) == 0);
fail_unless(eina_value_list_set(a, 0, 0));
fail_unless(eina_value_compare(a, b) < 0);
fail_unless(eina_value_list_set(a, 0, 10));
fail_unless(eina_value_compare(a, b) > 0);
fail_unless(eina_value_list_set(a, 0, 1));
fail_unless(eina_value_list_set(b, 0, 0));
fail_unless(eina_value_compare(a, b) > 0);
fail_unless(eina_value_list_set(b, 0, 10));
fail_unless(eina_value_compare(a, b) < 0);
fail_unless(eina_value_list_set(b, 0, 1));
fail_unless(eina_value_compare(a, b) == 0);
/* bigger lists are greater */
fail_unless(eina_value_list_append(b, 0));
fail_unless(eina_value_compare(a, b) < 0);
fail_unless(eina_value_list_append(a, 0));
fail_unless(eina_value_list_append(a, 0));
fail_unless(eina_value_compare(a, b) > 0);
/* bigger lists are greater, unless an element says otherwise */
fail_unless(eina_value_list_set(b, 0, 10));
fail_unless(eina_value_compare(a, b) < 0);
eina_value_free(a);
eina_value_free(b);
eina_shutdown();
@ -1022,6 +1068,95 @@ START_TEST(eina_value_test_array)
}
END_TEST
START_TEST(eina_value_test_list)
{
Eina_Value *value, other;
char c;
char buf[1024];
char *str;
eina_init();
value = eina_value_list_new(EINA_VALUE_TYPE_CHAR);
fail_unless(value != NULL);
fail_unless(eina_value_list_append(value, 'k'));
fail_unless(eina_value_list_append(value, '-'));
fail_unless(eina_value_list_append(value, 's'));
fail_unless(eina_value_list_get(value, 0, &c));
fail_unless(c == 'k');
fail_unless(eina_value_list_get(value, 1, &c));
fail_unless(c == '-');
fail_unless(eina_value_list_get(value, 2, &c));
fail_unless(c == 's');
fail_unless(eina_value_list_insert(value, 0, '!'));
fail_unless(eina_value_list_get(value, 0, &c));
fail_unless(c == '!');
fail_unless(eina_value_list_get(value, 1, &c));
fail_unless(c == 'k');
fail_unless(eina_value_list_get(value, 2, &c));
fail_unless(c == '-');
fail_unless(eina_value_list_get(value, 3, &c));
fail_unless(c == 's');
fail_unless(eina_value_list_set(value, 0, '*'));
fail_unless(eina_value_list_get(value, 0, &c));
fail_unless(c == '*');
fail_unless(eina_value_list_get(value, 1, &c));
fail_unless(c == 'k');
fail_unless(eina_value_list_get(value, 2, &c));
fail_unless(c == '-');
fail_unless(eina_value_list_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_list_setup(value, EINA_VALUE_TYPE_STRINGSHARE));
fail_unless(eina_value_list_append(value, "Enlightenment.org"));
fail_unless(eina_value_list_append(value, "X11"));
fail_unless(eina_value_list_append(value, "Pants"));
fail_unless(eina_value_list_append(value, "on!!!"));
fail_unless(eina_value_list_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_flush(value);
fail_unless(eina_value_list_setup(value, EINA_VALUE_TYPE_CHAR));
fail_unless(eina_value_setup(&other, EINA_VALUE_TYPE_CHAR));
fail_unless(eina_value_set(&other, 100));
fail_unless(eina_value_get(&other, &c));
fail_unless(c == 100);
fail_unless(eina_value_convert(&other, value));
str = eina_value_to_string(value);
fail_unless(str != NULL);
fail_unless(strcmp(str, "[100]") == 0);
free(str);
fail_unless(eina_value_list_set(value, 0, 33));
fail_unless(eina_value_convert(value, &other));
fail_unless(eina_value_get(&other, &c));
fail_unless(c == 33);
eina_value_free(value);
eina_shutdown();
}
END_TEST
void
eina_test_value(TCase *tc)
{
@ -1034,4 +1169,5 @@ eina_test_value(TCase *tc)
tcase_add_test(tc, eina_value_test_convert_uchar);
// TODO: other converters...
tcase_add_test(tc, eina_value_test_array);
tcase_add_test(tc, eina_value_test_list);
}