diff --git a/legacy/eet/ChangeLog b/legacy/eet/ChangeLog index 3d7edc9e56..3c42e91ec4 100644 --- a/legacy/eet/ChangeLog +++ b/legacy/eet/ChangeLog @@ -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. diff --git a/legacy/eet/src/lib/Eet.h b/legacy/eet/src/lib/Eet.h index 41755da38f..627c56590d 100644 --- a/legacy/eet/src/lib/Eet.h +++ b/legacy/eet/src/lib/Eet.h @@ -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 * diff --git a/legacy/eet/src/lib/eet_data.c b/legacy/eet/src/lib/eet_data.c index 7a3263e2c8..45160ca33b 100644 --- a/legacy/eet/src/lib/eet_data.c +++ b/legacy/eet/src/lib/eet_data.c @@ -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) { diff --git a/legacy/eet/src/lib/eet_dictionary.c b/legacy/eet/src/lib/eet_dictionary.c index 42dbd1ba18..7ccd18452f 100644 --- a/legacy/eet/src/lib/eet_dictionary.c +++ b/legacy/eet/src/lib/eet_dictionary.c @@ -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; diff --git a/legacy/eet/src/tests/eet_suite.c b/legacy/eet/src/tests/eet_suite.c index 5f46d7470d..d138e259ce 100644 --- a/legacy/eet/src/tests/eet_suite.c +++ b/legacy/eet/src/tests/eet_suite.c @@ -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");