* eet: Add EET_G_VARIANT and EET_G_UNION.

This are the basis for a new edje file format.
	Next to come EET_G_INHERIT.


SVN revision: 48201
This commit is contained in:
Cedric BAIL 2010-04-21 14:00:24 +00:00
parent 7c0098c1a3
commit a5aaf1723b
5 changed files with 989 additions and 11 deletions

View File

@ -365,3 +365,7 @@
2010-04-16 Cedric BAIL
* Handle fixed point in data stream.
2010-04-21 Cedric BAIL
* Add EET_G_UNION and EET_G_VARIANT.

View File

@ -274,7 +274,7 @@ extern "C" {
*
* If the eet file handle is not valid nothing will be done.
*
* @since 1.2.3
* @since 1.2.4
* @ingroup Eet_File_Group
*/
EAPI Eet_Error eet_sync(Eet_File *ef);
@ -1491,7 +1491,10 @@ extern "C" {
#define EET_G_VAR_ARRAY 102 /**< Variable size array group type */
#define EET_G_LIST 103 /**< Linked list group type */
#define EET_G_HASH 104 /**< Hash table group type */
#define EET_G_LAST 105 /**< Last group type */
#define EET_G_UNION 105 /**< Union group type */
#define EET_G_INHERIT 106 /**< Inherit object group type */
#define EET_G_VARIANT 107 /**< Selectable subtype group */
#define EET_G_LAST 108 /**< Last group type */
#define EET_I_LIMIT 128 /**< Other type exist but are reserved for internal purpose. */
@ -1518,7 +1521,7 @@ extern "C" {
* version member so it is compatible with abi changes, or at least
* will not crash with them.
*/
#define EET_DATA_DESCRIPTOR_CLASS_VERSION 2
#define EET_DATA_DESCRIPTOR_CLASS_VERSION 3
/**
* @typedef Eet_Data_Descriptor_Class
@ -1557,6 +1560,9 @@ extern "C" {
void (*hash_free) (void *h); /**< free all entries from the hash @p h */
char *(*str_direct_alloc) (const char *str); /**< how to allocate a string directly from file backed/mmaped region pointed by @p str */
void (*str_direct_free) (const char *str); /**< how to free a string returned by str_direct_alloc */
const char *(*type_get) (const void *data, Eina_Bool *unknow); /**< convert any kind of data type to a name that define an Eet_Data_Element. */
Eina_Bool (*type_set) (const char *type, void *data, Eina_Bool unknow); /**< set the type at a particular adress */
} func;
};
@ -2163,6 +2169,109 @@ extern "C" {
(char *)(&(___ett.member ## _count)) - (char *)(&(___ett)), /* 0, */NULL, subtype); \
}
/**
* Add an union type to a data descriptor
* @param edd The data descriptor to add the type to.
* @param struct_type The type of the struct.
* @param name The string name to use to encode/decode this member
* (must be a constant global and never change).
* @param member The struct member itself to be encoded.
* @param type_member The member that give hints on what is in the union.
* @param unified_type Describe all possible type the union could handle.
*
* This macro lets you easily add an union with a member that specify what is inside.
* The @p unified_type is an Eet_Data_Descriptor, but only the entry that match the name
* returned by type_get will be used for each serialized data. The type_get and type_set
* callback of unified_type should be defined.
*
* @since 1.2.4
* @ingroup Eet_Data_Group
* @see Eet_Data_Descriptor_Class
*/
#define EET_DATA_DESCRIPTOR_ADD_UNION(edd, struct_type, name, member, type_member, unified_type) \
{ \
struct_type ___ett; \
\
eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_UNION, \
(char *) (&(___ett.member)) - (char *)(&(___ett)), \
(char *) (&(___ett.type_member)) - (char *)(&(___ett)), \
NULL, unified_type); \
}
/**
* Make a structure variable in size/content depend on it's type
* @param edd The data descriptor to add the type to.
* @param struct_type The type of the struct.
* @param name The string name to use to encode/decode this member
* (must be a constant global and never change).
* @param member The struct member itself to be encoded.
* @param type_member The member that give hints on what is in the union.
* @param unified_type Describe all possible type the union could handle.
*
* This macro lets you easily add a switch for an object oriented representation. The position
* of the member that define the type must be fixed for all possible type. Eet will then choose
* in the unified_type the structure that need to be allocated to match the detected type.
* The type_get and type_set callback of unified_type should be defined. This should be the only
* type in edd.
*
* @since 1.2.4
* @ingroup Eet_Data_Group
* @see Eet_Data_Descriptor_Class
*/
#define EET_DATA_DESCRIPTOR_ADD_INHERIT(edd, struct_type, name, member, type_member, unified_type) \
{ \
struct_type ___ett; \
\
eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_INHERIT, \
(char *) (&(___ett.member)) - (char *)(&(___ett)), \
(char *) (&(___ett.type_member)) - (char *)(&(___ett)), \
NULL, unified_type); \
}
/**
* Add a automatically selectable type to a data descriptor
* @param edd The data descriptor to add the type to.
* @param struct_type The type of the struct.
* @param name The string name to use to encode/decode this member
* (must be a constant global and never change).
* @param member The struct member itself to be encoded.
* @param type_member The member that give hints on what is in the union.
* @param unified_type Describe all possible type the union could handle.
*
* This macro lets you easily define what the content of @p member points to depending of
* the content of @p type_member. The type_get and type_set callback of unified_type should
* be defined. If the the type is not know at the time of restoring it, eet will still call
* type_set of @p unified_type but the pointer will be set to a serialized binary representation
* of what eet know. This make it possible, to save this pointer again by just returning the string
* given previously and telling it by setting unknow to EINA_TRUE.
*
* @since 1.2.4
* @ingroup Eet_Data_Group
* @see Eet_Data_Descriptor_Class
*/
#define EET_DATA_DESCRIPTOR_ADD_VARIANT(edd, struct_type, name, member, type_member, unified_type) \
{ \
struct_type ___ett; \
\
eet_data_descriptor_element_add(edd, name, EET_T_UNKNOW, EET_G_VARIANT, \
(char *) (&(___ett.member)) - (char *)(&(___ett)), \
(char *) (&(___ett.type_member)) - (char *)(&(___ett)), \
NULL, unified_type); \
}
/**
* Add a mapping to a data descriptor that will be used by union, variant or inherited type
* @param unified_type The data descriptor to add the mapping to.
* @param name The string name to get/set type.
* @param subtype The matching data descriptor.
*
* @since 1.2.4
* @ingroup Eet_Data_Group
* @see Eet_Data_Descriptor_Class
*/
#define EET_DATA_DESCRIPTOR_ADD_MAPPING(unified_type, name, subtype) \
eet_data_descriptor_element_add(unified_type, name, EET_T_UNKNOW, EET_G_UNKNOWN, 0, 0, NULL, subtype);
/**
* @defgroup Eet_Data_Cipher_Group Eet Data Serialization using A Ciphers
*

View File

@ -74,6 +74,7 @@ typedef struct _Eet_Data_Descriptor_Hash Eet_Data_Descriptor_Hash;
typedef struct _Eet_Data_Encode_Hash_Info Eet_Data_Encode_Hash_Info;
typedef struct _Eet_Free Eet_Free;
typedef struct _Eet_Free_Context Eet_Free_Context;
typedef struct _Eet_Variant_Unknow Eet_Variant_Unknow;
/*---*/
@ -138,6 +139,8 @@ struct _Eet_Data_Descriptor
void (*hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt);
void *(*hash_add) (void *h, const char *k, void *d);
void (*hash_free) (void *h);
const char *(*type_get) (const void *data, Eina_Bool *unknow);
Eina_Bool (*type_set) (const char *type, void *data, Eina_Bool unknow);
} func;
struct {
int num;
@ -147,6 +150,8 @@ struct _Eet_Data_Descriptor
Eet_Data_Descriptor_Hash *buckets;
} hash;
} elements;
Eina_Bool unified_type : 1;
// char *strings;
// int strings_len;
};
@ -188,6 +193,14 @@ struct _Eet_Free_Context
Eet_Free freelist_direct_str;
};
struct _Eet_Variant_Unknow
{
EINA_MAGIC;
int size;
char data[1];
};
/*---*/
static int eet_data_get_char(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
@ -228,6 +241,12 @@ static int eet_data_get_list(Eet_Free_Context *context, const Eet_Dictionary *e
static void eet_data_put_list(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
static void eet_data_put_hash(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
static int eet_data_get_hash(Eet_Free_Context *context, const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, int type, int group_type, void *data, char **p, int *size);
static void eet_data_put_union(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
static int eet_data_get_union(Eet_Free_Context *context, const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, int type, int group_type, void *data, char **p, int *size);
static void eet_data_put_inherit(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
static int eet_data_get_inherit(Eet_Free_Context *context, const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, int type, int group_type, void *data, char **p, int *size);
static void eet_data_put_variant(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
static int eet_data_get_variant(Eet_Free_Context *context, const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, int type, int group_type, void *data, char **p, int *size);
static void eet_data_chunk_get(const Eet_Dictionary *ed, Eet_Data_Chunk *chnk, const void *src, int size);
static Eet_Data_Chunk *eet_data_chunk_new(void *data, int size, const char *name, int type, int group_type);
@ -275,7 +294,10 @@ static const Eet_Data_Group_Type_Codec eet_group_codec[] =
{ eet_data_get_array, eet_data_put_array },
{ eet_data_get_array, eet_data_put_array },
{ eet_data_get_list, eet_data_put_list },
{ eet_data_get_hash, eet_data_put_hash }
{ eet_data_get_hash, eet_data_put_hash },
{ eet_data_get_union, eet_data_put_union },
{ eet_data_get_inherit, eet_data_put_inherit },
{ eet_data_get_variant, eet_data_put_variant }
};
static int _eet_data_words_bigendian = -1;
@ -325,6 +347,7 @@ static int _eet_data_words_bigendian = -1;
#define EET_I_INLINED_STRING 2 << 4
#define EET_I_NULL 3 << 4
#define EET_MAGIC_VARIANT 0xF1234BC
/*---*/
/* CHAR TYPE */
@ -1305,7 +1328,6 @@ _eet_data_descriptor_new(const Eet_Data_Descriptor_Class *eddc, int version)
Eet_Data_Descriptor *edd;
if (!eddc) return NULL;
if (eddc->version < version) return NULL;
edd = calloc(1, sizeof (Eet_Data_Descriptor));
if (!edd) return NULL;
@ -1333,11 +1355,16 @@ _eet_data_descriptor_new(const Eet_Data_Descriptor_Class *eddc, int version)
edd->func.hash_add = eddc->func.hash_add;
edd->func.hash_free = eddc->func.hash_free;
if (version > 1)
if (eddc->version > 1 && version > 1)
{
edd->func.str_direct_alloc = eddc->func.str_direct_alloc;
edd->func.str_direct_free = eddc->func.str_direct_free;
}
if (eddc->version > 2)
{
edd->func.type_get = eddc->func.type_get;
edd->func.type_set = eddc->func.type_set;
}
return edd;
}
@ -1421,6 +1448,43 @@ eet_data_descriptor_element_add(Eet_Data_Descriptor *edd,
Eet_Data_Element *ede;
Eet_Data_Element *tmp;
/* UNION, INHERITED or VARIANT type would not work with simple type, we need a way to map the type. */
if ((group_type == EET_G_INHERIT
|| group_type == EET_G_UNION
|| group_type == EET_G_VARIANT)
&&
(type != EET_T_UNKNOW
|| subtype == NULL
|| subtype->func.type_get == NULL
|| subtype->func.type_set == NULL))
return ;
/* Only one element is allowed with INHERITED type */
if (group_type == EET_G_INHERIT && edd->elements.num != 0)
return ;
if (edd->elements.num > 0 && edd->elements.set[0].group_type == EET_G_INHERIT)
return ;
/* VARIANT type will only work if the map only contains EET_G_*, but not INHERIT, UNION, VARIANT and ARRAY. */
if (group_type == EET_G_VARIANT)
{
int i;
for (i = 0; i < subtype->elements.num; ++i)
if (subtype->elements.set[i].type != EET_T_UNKNOW
&& subtype->elements.set[i].group_type > EET_G_VAR_ARRAY
&& subtype->elements.set[i].group_type < EET_G_UNION)
return ;
subtype->unified_type = EINA_TRUE;
}
if (subtype
&& subtype->unified_type
&& (type != EET_T_UNKNOW
|| group_type < EET_G_UNION))
return ;
/* Sanity check done, let allocate ! */
edd->elements.num++;
tmp = realloc(edd->elements.set, edd->elements.num * sizeof(Eet_Data_Element));
if (!tmp) return ;
@ -1455,7 +1519,7 @@ eet_data_descriptor_element_add(Eet_Data_Descriptor *edd,
ede->group_type = group_type;
ede->offset = offset;
ede->count = count;
/* FIXME: For the time being, EET_G_VAR_ARRAY will put the counter_offset in count. */
/* FIXME: For the time being, VAR_ARRAY, INHERIT, UNION and VARIANT will put the counter_offset in count. */
ede->counter_offset = count;
/* ede->counter_offset = counter_offset; */
ede->counter_name = counter_name;
@ -2440,12 +2504,14 @@ _eet_data_descriptor_decode(Eet_Free_Context *context,
break;
case EET_G_VAR_ARRAY:
return eet_node_var_array_new(chnk.name, NULL);
case EET_G_INHERIT:
/* This one should work */
goto error;
case EET_G_LIST:
goto error;
case EET_G_HASH:
goto error;
case EET_G_ARRAY:
goto error;
case EET_G_UNION:
case EET_G_VARIANT:
default:
goto error;
}
@ -2818,6 +2884,379 @@ eet_data_get_array(Eet_Free_Context *context, const Eet_Dictionary *ed, Eet_Data
return 0;
}
static void
eet_data_put_union(Eet_Dictionary *ed,
__UNUSED__ Eet_Data_Descriptor *edd,
Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in)
{
const char *union_type;
int i;
EET_ASSERT(!((ede->type != EET_T_UNKNOW) || (!ede->subtype)), return );
union_type = ede->subtype->func.type_get(((char*) data_in) + ede->count - ede->offset,
NULL);
if (!union_type) return ;
/* Search the structure of the union to encode. */
for (i = 0; i < ede->subtype->elements.num; ++i)
if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0)
{
Eet_Data_Element *sede;
void *data;
int size;
/* Yeah we found it ! */
data = eet_data_put_type(ed, EET_T_STRING, &union_type, &size);
if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
sede = &(ede->subtype->elements.set[i]);
data = _eet_data_descriptor_encode(ed,
sede->subtype,
data_in,
&size);
if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
break;
}
}
static int
eet_data_get_union(Eet_Free_Context *context, const Eet_Dictionary *ed,
__UNUSED__ Eet_Data_Descriptor *edd,
Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
int type, int group_type, void *data,
char **p, int *size)
{
const char *union_type;
void *data_ret = NULL;
int ret = 0;
int i;
/* Read type */
ret = eet_data_get_type(ed,
EET_T_STRING,
echnk->data,
((char *)echnk->data) + echnk->size,
&union_type);
if (ret <= 0) goto on_error;
/* Advance to next chunk */
NEXT_CHUNK((*p), (*size), (*echnk), ed);
memset(echnk, 0, sizeof(Eet_Data_Chunk));
/* Read value */
eet_data_chunk_get(ed, echnk, *p, *size);
if (!echnk->name) goto on_error;
if (ede)
{
EET_ASSERT(!(ede->group_type != group_type || ede->type != type), goto on_error);
/* Search the structure of the union to decode */
for (i = 0; i < ede->subtype->elements.num; ++i)
if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0)
{
Eet_Data_Element *sede;
/* Yeah we found it ! */
sede = &(ede->subtype->elements.set[i]);
EET_ASSERT(sede->subtype, goto on_error);
data_ret = _eet_data_descriptor_decode(context,
ed,
sede->subtype,
echnk->data,
echnk->size);
if (!data_ret) goto on_error;
/* Memcopy the structure content to remove pointer indirection. */
memcpy(data, data_ret, sede->subtype->size);
/* data_ret is now useless. */
sede->subtype->func.mem_free(data_ret);
/* Set union type. */
if ((!ed) || (!ede->subtype->func.str_direct_alloc))
{
union_type = ede->subtype->func.str_alloc(union_type);
_eet_freelist_str_add(context, (char*) union_type);
}
else
{
union_type = ede->subtype->func.str_direct_alloc(union_type);
_eet_freelist_direct_str_add(context, (char*) union_type);
}
ede->subtype->func.type_set(union_type,
((char*) data) + ede->count - ede->offset,
EINA_FALSE);
break;
}
}
else
{
/* FIXME: generate node structure. */
data_ret = _eet_data_descriptor_decode(context,
ed, NULL,
echnk->data, echnk->size);
goto on_error;
}
return 1;
on_error:
return 0;
}
static void
eet_data_put_inherit(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede,
Eet_Data_Stream *ds, void *data_in)
{
/* FIXME */
fprintf(stderr, "wrong !!!\n");
}
static int
eet_data_get_inherit(Eet_Free_Context *context, const Eet_Dictionary *ed, Eet_Data_Descriptor *edd,
Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
int type, int group_type, void *data,
char **p, int *size)
{
/* FIXME */
return 0;
}
static void
eet_data_put_variant(Eet_Dictionary *ed,
__UNUSED__ Eet_Data_Descriptor *edd,
Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in)
{
const char *union_type;
void *data;
Eina_Bool unknow = EINA_FALSE;
int size;
int i;
EET_ASSERT(!((ede->type != EET_T_UNKNOW) || (!ede->subtype)), return );
union_type = ede->subtype->func.type_get(((char*) data_in) + ede->count - ede->offset,
&unknow);
if (!union_type && unknow == EINA_FALSE) return ;
if (unknow)
{
/* Handle opaque internal representation */
Eet_Variant_Unknow *evu;
data = eet_data_put_type(ed, EET_T_STRING, &union_type, &size);
if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
evu = (Eet_Variant_Unknow*) data_in;
if (evu && EINA_MAGIC_CHECK(evu, EET_MAGIC_VARIANT))
eet_data_encode(ed, ds, evu->data, ede->name, evu->size, ede->type, ede->group_type);
}
else
{
/* Search the structure of the union to encode. */
for (i = 0; i < ede->subtype->elements.num; ++i)
if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0)
{
Eet_Data_Element *sede;
/* Yeah we found it ! */
data = eet_data_put_type(ed, EET_T_STRING, &union_type, &size);
if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
sede = &(ede->subtype->elements.set[i]);
if (sede->group_type != EET_G_UNKNOWN)
{
Eet_Data_Stream *lds;
lds = eet_data_stream_new();
eet_group_codec[sede->group_type - 100].put(ed,
sede->subtype,
sede,
lds,
data_in);
if (lds->size != 0)
{
eet_data_encode(ed, ds, lds->data, ede->name, lds->pos,
ede->type, ede->group_type);
lds->data = NULL;
lds->size = 0;
}
else
{
eet_data_encode(ed, ds, NULL, ede->name, 0,
EET_T_NULL, ede->group_type);
}
eet_data_stream_free(lds);
}
else
{
data = _eet_data_descriptor_encode(ed,
sede->subtype,
*(void**)data_in,
&size);
if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
}
break;
}
}
}
static int
eet_data_get_variant(Eet_Free_Context *context, const Eet_Dictionary *ed,
__UNUSED__ Eet_Data_Descriptor *edd,
Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
int type, int group_type, void *data,
char **p, int *size)
{
const char *union_type;
void *data_ret = NULL;
int ret = 0;
int i;
/* Read type */
ret = eet_data_get_type(ed,
EET_T_STRING,
echnk->data,
((char *)echnk->data) + echnk->size,
&union_type);
if (ret <= 0) goto on_error;
/* Advance to next chunk */
NEXT_CHUNK((*p), (*size), (*echnk), ed);
memset(echnk, 0, sizeof(Eet_Data_Chunk));
/* Read value */
eet_data_chunk_get(ed, echnk, *p, *size);
if (!echnk->name) goto on_error;
if (ede)
{
EET_ASSERT(ede->subtype, goto on_error);
if ((!ed) || (!ede->subtype->func.str_direct_alloc))
{
union_type = ede->subtype->func.str_alloc(union_type);
_eet_freelist_str_add(context, (char*) union_type);
}
else
{
union_type = ede->subtype->func.str_direct_alloc(union_type);
_eet_freelist_direct_str_add(context, (char*) union_type);
}
/* Search the structure of the union to decode */
for (i = 0; i < ede->subtype->elements.num; ++i)
if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0)
{
Eet_Data_Element *sede;
/* Yeah we found it ! */
sede = &(ede->subtype->elements.set[i]);
if (sede->group_type != EET_G_UNKNOWN)
{
Eet_Data_Chunk chnk;
char *p2;
int size2;
int ret;
p2 = echnk->data;
size2 = echnk->size;
/* Didn't find a proper way to provide this
without duplicating code */
while (size2 > 0)
{
memset(&chnk, 0, sizeof(Eet_Data_Chunk));
eet_data_chunk_get(ed, &chnk, p2, size2);
if (!chnk.name) goto on_error;
ret = eet_group_codec[sede->group_type - 100].get(context,
ed, sede->subtype,
sede, &chnk,
sede->type, sede->group_type,
data, &p2, &size2);
if (ret <= 0) goto on_error;
/* advance to next chunk */
NEXT_CHUNK(p2, size2, chnk, ed);
}
/* Put garbage so that we will not put eet_variant_unknow in it */
data_ret = (void*) data;
/* Set variant type. */
ede->subtype->func.type_set(union_type,
((char*) data) + ede->count - ede->offset,
EINA_FALSE);
break;
}
data_ret = _eet_data_descriptor_decode(context,
ed,
sede->subtype,
echnk->data,
echnk->size);
if (!data_ret) break;
/* And point to the variant data. */
*(void**) data = data_ret;
/* Set variant type. */
ede->subtype->func.type_set(union_type,
((char*) data) + ede->count - ede->offset,
EINA_FALSE);
break;
}
if (!data_ret)
{
Eet_Variant_Unknow *evu;
evu = calloc(1, sizeof (Eet_Variant_Unknow) + echnk->size - 1);
if (!evu) goto on_error;
evu->size = echnk->size;
memcpy(evu->data, echnk->data, evu->size);
EINA_MAGIC_SET(evu, EET_MAGIC_VARIANT);
/* And point to the opaque internal data scructure */
*(void**) data = evu;
/* Set variant type. */
ede->subtype->func.type_set(union_type,
((char*) data) + ede->count - ede->offset,
EINA_TRUE);
}
}
else
{
/* FIXME: dump node structure. */
data_ret = _eet_data_descriptor_decode(context,
ed, NULL,
echnk->data, echnk->size);
goto on_error;
}
return 1;
on_error:
return 0;
}
static Eet_Node *
eet_data_node_simple_type(int type, const char *name, void *dd)
{

View File

@ -325,7 +325,7 @@ eet_dictionary_string_get_fp(const Eet_Dictionary *ed, int idx, Eina_F32p32 *res
str = ed->all[idx].str ? ed->all[idx].str : ed->all[idx].mmap;
if (!eina_convert_atofp(str, ed->all[idx].len, &fp))
if (!eina_convert_atofp(str, ed->all[idx].len, &fp))
return EINA_FALSE;
ed->all[idx].fp = fp;

View File

@ -1756,6 +1756,430 @@ START_TEST(eet_file_fp)
}
END_TEST
typedef struct _Eet_Union_Test Eet_Union_Test;
typedef struct _Eet_Variant_Test Eet_Variant_Test;
typedef struct _Eet_Variant_Type Eet_Variant_Type;
typedef struct _Eet_Inherit_Test1 Eet_Inherit_Test1;
typedef struct _Eet_Inherit_Test2 Eet_Inherit_Test2;
typedef struct _Eet_Inherit_Test3 Eet_Inherit_Test3;
typedef struct _Eet_St1 Eet_St1;
typedef struct _Eet_St2 Eet_St2;
typedef struct _Eet_St3 Eet_St3;
typedef struct _Eet_List Eet_List;
typedef enum _Eet_Union
{
EET_UNKNOWN,
EET_ST1,
EET_ST2,
EET_ST3
} Eet_Union;
struct {
Eet_Union u;
const char *name;
} eet_mapping[] = {
{ EET_ST1, "ST1" },
{ EET_ST2, "ST2" },
{ EET_ST3, "ST3" },
{ EET_UNKNOWN, NULL }
};
struct _Eet_St1
{
double val1;
int stuff;
char *s1;
};
struct _Eet_St2
{
Eina_Bool b1;
unsigned long long v1;
};
struct _Eet_St3
{
int boby;
};
struct _Eet_Union_Test
{
Eet_Union type;
union {
Eet_St1 st1;
Eet_St2 st2;
Eet_St3 st3;
} u;
};
struct _Eet_Variant_Type
{
const char *type;
Eina_Bool unknow : 1;
};
struct _Eet_Variant_Test
{
Eet_Variant_Type t;
void *data;
Eina_List *data_list;
};
struct _Eet_Inherit_Test1
{
Eet_Union type;
Eet_St1 st1;
};
struct _Eet_Inherit_Test2
{
Eet_Union type;
Eet_St2 st2;
};
struct _Eet_Inherit_Test3
{
Eet_Union type;
Eet_St3 st3;
};
struct _Eet_List
{
Eina_List *list;
};
static const char *
_eet_union_type_get(const void *data, Eina_Bool *unknow)
{
const Eet_Union *u = data;
int i;
if (unknow) *unknow = EINA_FALSE;
for (i = 0; eet_mapping[i].name != NULL; ++i)
if (*u == eet_mapping[i].u)
return eet_mapping[i].name;
if (unknow) *unknow = EINA_TRUE;
return NULL;
}
static Eina_Bool
_eet_union_type_set(const char *type, void *data, Eina_Bool unknow)
{
Eet_Union *u = data;
int i;
if (unknow) return EINA_FALSE;
for (i = 0; eet_mapping[i].name != NULL; ++i)
if (strcmp(eet_mapping[i].name, type) == 0)
{
*u = eet_mapping[i].u;
return EINA_TRUE;
}
return EINA_FALSE;
}
static const char *
_eet_variant_type_get(const void *data, Eina_Bool *unknow)
{
const Eet_Variant_Type *type = data;
int i;
if (unknow) *unknow = type->unknow;
for (i = 0; eet_mapping[i].name != NULL; ++i)
if (strcmp(type->type, eet_mapping[i].name) == 0)
return eet_mapping[i].name;
if (unknow) *unknow = EINA_FALSE;
return type->type;
}
static Eina_Bool
_eet_variant_type_set(const char *type, void *data, Eina_Bool unknow)
{
Eet_Variant_Type *vt = data;
vt->type = type;
vt->unknow = unknow;
return EINA_TRUE;
}
static Eet_Data_Descriptor*
_eet_st1_dd(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *res;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_St1);
res = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(res, Eet_St1, "val1", val1, EET_T_DOUBLE);
EET_DATA_DESCRIPTOR_ADD_BASIC(res, Eet_St1, "stuff", stuff, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(res, Eet_St1, "s1", s1, EET_T_STRING);
return res;
}
static void
_eet_st1_set(Eet_St1 *st1, int i)
{
st1->val1 = EET_TEST_DOUBLE;
st1->stuff = EET_TEST_INT + i;
st1->s1 = EET_TEST_STRING;
}
static void
_eet_st1_cmp(Eet_St1 *st1, int i)
{
double tmp;
fail_if(!st1);
tmp = st1->val1 - EET_TEST_DOUBLE;
if (tmp < 0) tmp = -tmp;
fail_if(tmp > 0.005);
fail_if(st1->stuff != EET_TEST_INT + i);
fail_if(strcmp(st1->s1, EET_TEST_STRING));
}
static Eet_Data_Descriptor*
_eet_st2_dd(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *res;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_St2);
res = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(res, Eet_St2, "b1", b1, EET_T_UCHAR);
EET_DATA_DESCRIPTOR_ADD_BASIC(res, Eet_St2, "v1", v1, EET_T_ULONG_LONG);
return res;
}
static void
_eet_st2_set(Eet_St2 *st2, int i)
{
st2->b1 = EINA_TRUE;
st2->v1 = EET_TEST_LONG_LONG + i;
}
static void
_eet_st2_cmp(Eet_St2 *st2, int i)
{
fail_if(!st2->b1);
fail_if(st2->v1 != EET_TEST_LONG_LONG + i);
}
static Eet_Data_Descriptor*
_eet_st3_dd(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *res;
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_St3);
res = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(res, Eet_St3, "boby", boby, EET_T_INT);
return res;
}
static void
_eet_st3_set(Eet_St3 *st3, int i)
{
st3->boby = EET_TEST_INT + i;
}
static void
_eet_st3_cmp(Eet_St3 *st3, int i)
{
fail_if(st3->boby != EET_TEST_INT + i);
}
START_TEST(eet_test_union)
{
Eet_Union_Test *eut;
Eet_List *l;
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *edd;
Eet_Data_Descriptor *unified;
Eet_Data_Descriptor *m;
void *blob;
int size;
int i;
eina_init();
eet_init();
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_Union_Test);
edd = eet_data_descriptor_stream_new(&eddc);
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_Union_Test);
m = eet_data_descriptor_stream_new(&eddc);
eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION;
eddc.func.type_get = _eet_union_type_get;
eddc.func.type_set = _eet_union_type_set;
unified = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "ST1", _eet_st1_dd());
EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "ST2", _eet_st2_dd());
EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "ST3", _eet_st3_dd());
EET_DATA_DESCRIPTOR_ADD_UNION(edd, Eet_Union_Test, "u", u, type, unified);
EET_DATA_DESCRIPTOR_ADD_LIST(m, Eet_List, "list", list, edd);
l = calloc(1, sizeof (Eet_List));
#define EUT_NEW(Type_Index) \
eut = calloc(1, sizeof (Eet_Union_Test)); \
eut->type = EET_ST##Type_Index; \
_eet_st##Type_Index##_set(&(eut->u.st##Type_Index), i);
for (i = 0; i < 3; ++i)
{
EUT_NEW(1);
l->list = eina_list_append(l->list, eut);
EUT_NEW(2);
l->list = eina_list_append(l->list, eut);
EUT_NEW(3);
l->list = eina_list_append(l->list, eut);
}
blob = eet_data_descriptor_encode(m, l, &size);
fail_if(!blob || size <= 0);
l = eet_data_descriptor_decode(m, blob, size);
fail_if(!l);
fail_if(eina_list_count(l->list) != 9);
#define EUT_CMP(Type_Index) \
eut = eina_list_nth(l->list, i * 3 + Type_Index - 1); \
fail_if(eut->type != EET_ST##Type_Index); \
_eet_st##Type_Index##_cmp(&(eut->u.st##Type_Index), i);
for (i = 0; i < 3; ++i)
{
EUT_CMP(1);
EUT_CMP(2);
EUT_CMP(3);
}
eet_shutdown();
eina_shutdown();
}
END_TEST
START_TEST(eet_test_variant)
{
Eet_Variant_Test *evt;
Eet_List *l;
Eet_St1 *st1;
Eet_St2 *st2;
Eet_St3 *st3;
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *edd;
Eet_Data_Descriptor *unified;
Eet_Data_Descriptor *m;
void *blob;
int size;
int i;
eina_init();
eet_init();
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_Variant_Test);
edd = eet_data_descriptor_stream_new(&eddc);
EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Eet_Variant_Test);
m = eet_data_descriptor_stream_new(&eddc);
eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION;
eddc.func.type_get = _eet_variant_type_get;
eddc.func.type_set = _eet_variant_type_set;
unified = eet_data_descriptor_stream_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "ST1", _eet_st1_dd());
EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "ST2", _eet_st2_dd());
EET_DATA_DESCRIPTOR_ADD_MAPPING(unified, "ST3", _eet_st3_dd());
EET_DATA_DESCRIPTOR_ADD_VARIANT(edd, Eet_Variant_Test, "data", data, t, unified);
unified = eet_data_descriptor_stream_new(&eddc);
eet_data_descriptor_element_add(unified, "ST1",
EET_T_UNKNOW, EET_G_LIST,
0, 0, NULL, _eet_st1_dd());
eet_data_descriptor_element_add(unified, "ST2",
EET_T_UNKNOW, EET_G_LIST,
0, 0, NULL, _eet_st2_dd());
EET_DATA_DESCRIPTOR_ADD_VARIANT(edd, Eet_Variant_Test,
"data_list", data_list, t, unified);
EET_DATA_DESCRIPTOR_ADD_LIST(m, Eet_List, "list", list, edd);
l = calloc(1, sizeof (Eet_List));
#define EVT_NEW(Type_Index) \
evt = calloc(1, sizeof (Eet_Variant_Test)); \
evt->t.type = eet_mapping[Type_Index - 1].name; \
st##Type_Index = calloc(1, sizeof (Eet_St##Type_Index)); \
_eet_st##Type_Index##_set(st##Type_Index, i); \
evt->data = st##Type_Index;
for (i = 0; i < 3; ++i)
{
EVT_NEW(1);
l->list = eina_list_append(l->list, evt);
st1 = calloc(1, sizeof (Eet_St1));
_eet_st1_set(st1, i);
evt->data_list = eina_list_append(evt->data_list, st1);
EVT_NEW(2);
l->list = eina_list_append(l->list, evt);
EVT_NEW(3);
l->list = eina_list_append(l->list, evt);
}
blob = eet_data_descriptor_encode(m, l, &size);
fail_if(!blob || size <= 0);
l = eet_data_descriptor_decode(m, blob, size);
fail_if(!l);
fail_if(eina_list_count(l->list) != 9);
#define EVT_CMP(Type_Index) \
evt = eina_list_nth(l->list, i * 3 + Type_Index - 1); \
fail_if(strcmp(evt->t.type, eet_mapping[Type_Index - 1].name) != 0); \
_eet_st##Type_Index##_cmp(evt->data, i);
for (i = 0; i < 3; ++i)
{
EVT_CMP(1);
fail_if(!evt->data_list);
fail_if(eina_list_count(evt->data_list) != 1);
st1 = eina_list_data_get(evt->data_list);
_eet_st1_cmp(st1, i);
EVT_CMP(2);
EVT_CMP(3);
}
eet_shutdown();
eina_shutdown();
}
END_TEST
Suite *
eet_suite(void)
{
@ -1773,6 +2197,8 @@ eet_suite(void)
tcase_add_test(tc, eet_test_data_type_encoding_decoding);
tcase_add_test(tc, eet_test_data_type_dump_undump);
tcase_add_test(tc, eet_fp);
tcase_add_test(tc, eet_test_union);
tcase_add_test(tc, eet_test_variant);
suite_add_tcase(s, tc);
tc = tcase_create("Eet File");