* eet: Add EET_G_VARIANT and EET_G_UNION.
[framework/uifw/eet.git] / src / lib / eet_data.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #ifdef HAVE_CONFIG_H
6 # include <config.h>
7 #endif
8
9 #include <stdio.h>
10 #include <string.h>
11 #include <math.h>
12 #include <ctype.h>
13 #include <limits.h>
14
15 #ifdef HAVE_NETINET_IN_H
16 # include <netinet/in.h>
17 #endif
18
19 #ifdef _WIN32
20 # include <winsock2.h>
21 #endif
22
23 #include <Eina.h>
24
25 #include "Eet.h"
26 #include "Eet_private.h"
27
28 /*
29  * routines for doing data -> struct and struct -> data conversion
30  *
31  * types:
32  *
33  * basic types:
34  *   a sequence of...
35  *
36  *   char
37  *   short
38  *   int
39  *   long long
40  *   float
41  *   double
42  *   unsigned char
43  *   unsigned short
44  *   unsigned int
45  *   unsgined long long
46  *   string
47  *
48  * groupings:
49  *   multiple entries ordered as...
50  *
51  *   fixed size array    [ of basic types ]
52  *   variable size array [ of basic types ]
53  *   linked list         [ of basic types ]
54  *   hash table          [ of basic types ]
55  *
56  * need to provide builder/accessor funcs for:
57  *
58  *   list_next
59  *   list_append
60  *
61  *   hash_foreach
62  *   hash_add
63  *
64  */
65
66 /*---*/
67
68 typedef struct _Eet_Data_Element            Eet_Data_Element;
69 typedef struct _Eet_Data_Basic_Type_Codec   Eet_Data_Basic_Type_Codec;
70 typedef struct _Eet_Data_Group_Type_Codec   Eet_Data_Group_Type_Codec;
71 typedef struct _Eet_Data_Chunk              Eet_Data_Chunk;
72 typedef struct _Eet_Data_Stream             Eet_Data_Stream;
73 typedef struct _Eet_Data_Descriptor_Hash    Eet_Data_Descriptor_Hash;
74 typedef struct _Eet_Data_Encode_Hash_Info   Eet_Data_Encode_Hash_Info;
75 typedef struct _Eet_Free                    Eet_Free;
76 typedef struct _Eet_Free_Context            Eet_Free_Context;
77 typedef struct _Eet_Variant_Unknow          Eet_Variant_Unknow;
78
79 /*---*/
80
81 /* TODO:
82  * Eet_Data_Basic_Type_Codec (Coder, Decoder)
83  * Eet_Data_Group_Type_Codec (Coder, Decoder)
84  */
85 struct _Eet_Data_Basic_Type_Codec
86 {
87    int         size;
88    const char *name;
89    int       (*get) (const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
90    void     *(*put) (Eet_Dictionary *ed, const void *src, int *size_ret);
91 };
92
93 struct _Eet_Data_Group_Type_Codec
94 {
95    int  (*get) (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_in, char **p, int *size);
96    void (*put) (Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
97 };
98
99 struct _Eet_Data_Chunk
100 {
101    char          *name;
102    int            len;
103    int            size;
104    int            hash;
105    void          *data;
106    unsigned char  type;
107    unsigned char  group_type;
108 };
109
110 struct _Eet_Data_Stream
111 {
112    void *data;
113    int   size;
114    int   pos;
115 };
116
117 struct _Eet_Data_Descriptor_Hash
118 {
119    Eet_Data_Element         *element;
120    Eet_Data_Descriptor_Hash *next;
121 };
122
123 struct _Eet_Data_Descriptor
124 {
125    const char           *name;
126    const Eet_Dictionary *ed;
127    int                   size;
128    struct {
129       void *(*mem_alloc) (size_t size);
130       void  (*mem_free) (void *mem);
131       char *(*str_alloc) (const char *str);
132       char *(*str_direct_alloc) (const char *str);
133       void  (*str_free) (const char *str);
134       void  (*str_direct_free) (const char *str);
135       void *(*list_next) (void *l);
136       void *(*list_append) (void *l, void *d);
137       void *(*list_data) (void *l);
138       void *(*list_free) (void *l);
139       void  (*hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt);
140       void *(*hash_add) (void *h, const char *k, void *d);
141       void  (*hash_free) (void *h);
142       const char *(*type_get) (const void *data, Eina_Bool *unknow);
143       Eina_Bool (*type_set) (const char *type, void *data, Eina_Bool unknow);
144    } func;
145    struct {
146       int                num;
147       Eet_Data_Element  *set;
148       struct {
149          int                             size;
150          Eet_Data_Descriptor_Hash       *buckets;
151       } hash;
152    } elements;
153
154    Eina_Bool unified_type : 1;
155 //   char *strings;
156 //   int   strings_len;
157 };
158
159 struct _Eet_Data_Element
160 {
161    const char          *name;
162    const char          *counter_name;
163    const char          *directory_name_ptr;
164    Eet_Data_Descriptor *subtype;
165    int                  offset;         /* offset in bytes from the base element */
166    int                  count;          /* number of elements for a fixed array */
167    int                  counter_offset; /* for a variable array we need the offset of the count variable */
168    unsigned char        type;           /* EET_T_XXX */
169    unsigned char        group_type;     /* EET_G_XXX */
170 };
171
172 struct _Eet_Data_Encode_Hash_Info
173 {
174   Eet_Data_Stream       *ds;
175   Eet_Data_Element      *ede;
176   Eet_Dictionary        *ed;
177 };
178
179 struct _Eet_Free
180 {
181   int     ref;
182   int     len[256];
183   int     num[256];
184   void  **list[256];
185 };
186
187 struct _Eet_Free_Context
188 {
189    Eet_Free freelist;
190    Eet_Free freelist_list;
191    Eet_Free freelist_hash;
192    Eet_Free freelist_str;
193    Eet_Free freelist_direct_str;
194 };
195
196 struct _Eet_Variant_Unknow
197 {
198    EINA_MAGIC;
199
200    int size;
201    char data[1];
202 };
203
204 /*---*/
205
206 static int   eet_data_get_char(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
207 static void *eet_data_put_char(Eet_Dictionary *ed, const void *src, int *size_ret);
208 static int   eet_data_get_short(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
209 static void *eet_data_put_short(Eet_Dictionary *ed, const void *src, int *size_ret);
210 static inline int   eet_data_get_int(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
211 static void *eet_data_put_int(Eet_Dictionary *ed, const void *src, int *size_ret);
212 static int   eet_data_get_long_long(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
213 static void *eet_data_put_long_long(Eet_Dictionary *ed, const void *src, int *size_ret);
214 static int   eet_data_get_float(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
215 static void *eet_data_put_float(Eet_Dictionary *ed, const void *src, int *size_ret);
216 static int   eet_data_get_double(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
217 static void *eet_data_put_double(Eet_Dictionary *ed, const void *src, int *size_ret);
218 static int   eet_data_get_f32p32(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
219 static void *eet_data_put_f32p32(Eet_Dictionary *ed, const void *src, int *size_ret);
220 static int   eet_data_get_f16p16(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
221 static void *eet_data_put_f16p16(Eet_Dictionary *ed, const void *src, int *size_ret);
222 static int   eet_data_get_f8p24(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
223 static void *eet_data_put_f8p24(Eet_Dictionary *ed, const void *src, int *size_ret);
224 static inline int   eet_data_get_string(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
225 static void *eet_data_put_string(Eet_Dictionary *ed, const void *src, int *size_ret);
226 static int   eet_data_get_istring(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
227 static void *eet_data_put_istring(Eet_Dictionary *ed, const void *src, int *size_ret);
228 static int   eet_data_get_null(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
229 static void *eet_data_put_null(Eet_Dictionary *ed, const void *src, int *size_ret);
230
231 static int   eet_data_get_type(const Eet_Dictionary *ed, int type, const void *src, const void *src_end, void *dest);
232 static void *eet_data_put_type(Eet_Dictionary *ed, int type, const void *src, int *size_ret);
233
234 static Eet_Node *eet_data_node_simple_type(int type, const char *name, void *dd);
235
236 static int  eet_data_get_unknown(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_in, char **p, int *size);
237 static void eet_data_put_unknown(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
238 static void eet_data_put_array(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
239 static int  eet_data_get_array(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);
240 static int  eet_data_get_list(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_in, char **p, int *size);
241 static void eet_data_put_list(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
242 static void eet_data_put_hash(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
243 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);
244 static void eet_data_put_union(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
245 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);
246 static void eet_data_put_inherit(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
247 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);
248 static void eet_data_put_variant(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
249 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);
250
251 static void            eet_data_chunk_get(const Eet_Dictionary *ed, Eet_Data_Chunk *chnk, const void *src, int size);
252 static Eet_Data_Chunk *eet_data_chunk_new(void *data, int size, const char *name, int type, int group_type);
253 static void            eet_data_chunk_free(Eet_Data_Chunk *chnk);
254
255 static Eet_Data_Stream *eet_data_stream_new(void);
256 static void             eet_data_stream_write(Eet_Data_Stream *ds, const void *data, int size);
257 static void             eet_data_stream_free(Eet_Data_Stream *ds);
258
259 static void             eet_data_chunk_put(Eet_Dictionary *ed, Eet_Data_Chunk *chnk, Eet_Data_Stream *ds);
260
261 static int       eet_data_descriptor_encode_hash_cb(void *hash, const char *key, void *hdata, void *fdata);
262 static void     *_eet_data_descriptor_encode(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, const void *data_in, int *size_ret);
263 static void     *_eet_data_descriptor_decode(Eet_Free_Context *context,
264                                              const Eet_Dictionary *ed,
265                                              Eet_Data_Descriptor *edd,
266                                              const void *data_in,
267                                              int size_in);
268
269 /*---*/
270
271 static const Eet_Data_Basic_Type_Codec eet_basic_codec[] =
272 {
273      {sizeof(char),      "char",       eet_data_get_char,      eet_data_put_char     },
274      {sizeof(short),     "short",      eet_data_get_short,     eet_data_put_short    },
275      {sizeof(int),       "int",        eet_data_get_int,       eet_data_put_int      },
276      {sizeof(long long), "long_long",  eet_data_get_long_long, eet_data_put_long_long},
277      {sizeof(float),     "float",      eet_data_get_float,     eet_data_put_float    },
278      {sizeof(double),    "double",     eet_data_get_double,    eet_data_put_double   },
279      {sizeof(char),      "uchar",      eet_data_get_char,      eet_data_put_char     },
280      {sizeof(short),     "ushort",     eet_data_get_short,     eet_data_put_short    },
281      {sizeof(int),       "uint",       eet_data_get_int,       eet_data_put_int      },
282      {sizeof(long long), "ulong_long", eet_data_get_long_long, eet_data_put_long_long},
283      {sizeof(char *),    "string",     eet_data_get_string,    eet_data_put_string   },
284      {sizeof(char *),    "inlined",    eet_data_get_istring,   eet_data_put_istring  },
285      {sizeof(void *),    "NULL",       eet_data_get_null,      eet_data_put_null     },
286      {sizeof(Eina_F32p32),"f32p32",    eet_data_get_f32p32,    eet_data_put_f32p32   },
287      {sizeof(Eina_F16p16),"f16p16",    eet_data_get_f16p16,    eet_data_put_f16p16   },
288      {sizeof(Eina_F8p24),"f8p24",      eet_data_get_f8p24,     eet_data_put_f8p24    }
289 };
290
291 static const Eet_Data_Group_Type_Codec eet_group_codec[] =
292 {
293      { eet_data_get_unknown,  eet_data_put_unknown },
294      { eet_data_get_array,    eet_data_put_array },
295      { eet_data_get_array,    eet_data_put_array },
296      { eet_data_get_list,     eet_data_put_list },
297      { eet_data_get_hash,     eet_data_put_hash },
298      { eet_data_get_union,    eet_data_put_union },
299      { eet_data_get_inherit,  eet_data_put_inherit },
300      { eet_data_get_variant,  eet_data_put_variant }
301 };
302
303 static int _eet_data_words_bigendian = -1;
304
305 /*---*/
306
307 #define SWAP64(x) (x) = \
308    ((((unsigned long long)(x) & 0x00000000000000ffULL ) << 56) |\
309        (((unsigned long long)(x) & 0x000000000000ff00ULL ) << 40) |\
310        (((unsigned long long)(x) & 0x0000000000ff0000ULL ) << 24) |\
311        (((unsigned long long)(x) & 0x00000000ff000000ULL ) << 8) |\
312        (((unsigned long long)(x) & 0x000000ff00000000ULL ) >> 8) |\
313        (((unsigned long long)(x) & 0x0000ff0000000000ULL ) >> 24) |\
314        (((unsigned long long)(x) & 0x00ff000000000000ULL ) >> 40) |\
315        (((unsigned long long)(x) & 0xff00000000000000ULL ) >> 56))
316 #define SWAP32(x) (x) = \
317    ((((int)(x) & 0x000000ff ) << 24) |\
318        (((int)(x) & 0x0000ff00 ) << 8) |\
319        (((int)(x) & 0x00ff0000 ) >> 8) |\
320        (((int)(x) & 0xff000000 ) >> 24))
321 #define SWAP16(x) (x) = \
322    ((((short)(x) & 0x00ff ) << 8) |\
323        (((short)(x) & 0xff00 ) >> 8))
324
325 #ifdef CONV8
326 # undef CONV8
327 #endif
328 #ifdef CONV16
329 # undef CONV16
330 #endif
331 #ifdef CONV32
332 # undef CONV32
333 #endif
334 #ifdef CONV64
335 # undef CONV64
336 #endif
337
338 #define CONV8(x)
339 #define CONV16(x) {if (_eet_data_words_bigendian) SWAP16(x);}
340 #define CONV32(x) {if (_eet_data_words_bigendian) SWAP32(x);}
341 #define CONV64(x) {if (_eet_data_words_bigendian) SWAP64(x);}
342
343 #define IS_SIMPLE_TYPE(Type)    (Type > EET_T_UNKNOW && Type < EET_T_LAST)
344 #define IS_POINTER_TYPE(Type)    (Type >= EET_T_STRING && Type <= EET_T_NULL)
345
346 #define EET_I_STRING            1 << 4
347 #define EET_I_INLINED_STRING    2 << 4
348 #define EET_I_NULL              3 << 4
349
350 #define EET_MAGIC_VARIANT 0xF1234BC
351 /*---*/
352
353 /* CHAR TYPE */
354 static int
355 eet_data_get_char(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst)
356 {
357    char *s, *d;
358
359    if (((char *)src + sizeof(char)) > (char *)src_end) return -1;
360    s = (char *)src;
361    d = (char *)dst;
362    *d = *s;
363    CONV8(*d);
364    return sizeof(char);
365 }
366
367 static void *
368 eet_data_put_char(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret)
369 {
370    char *s, *d;
371
372    d = (char *)malloc(sizeof(char));
373    if (!d) return NULL;
374    s = (char *)src;
375    *d = *s;
376    CONV8(*d);
377    *size_ret = sizeof(char);
378    return d;
379 }
380
381 /* SHORT TYPE */
382 static int
383 eet_data_get_short(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst)
384 {
385    short *d;
386
387    if (((char *)src + sizeof(short)) > (char *)src_end) return -1;
388    memcpy(dst, src, sizeof(short));
389    d = (short *)dst;
390    CONV16(*d);
391    return sizeof(short);
392 }
393
394 static void *
395 eet_data_put_short(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret)
396 {
397    short *s, *d;
398
399    d = (short *)malloc(sizeof(short));
400    if (!d) return NULL;
401    s = (short *)src;
402    *d = *s;
403    CONV16(*d);
404    *size_ret = sizeof(short);
405    return d;
406 }
407
408 /* INT TYPE */
409 static inline int
410 eet_data_get_int(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst)
411 {
412    int *d;
413
414    if (((char *)src + sizeof(int)) > (char *)src_end) return -1;
415    memcpy(dst, src, sizeof(int));
416    d = (int *)dst;
417    CONV32(*d);
418    return sizeof(int);
419 }
420
421 static void *
422 eet_data_put_int(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret)
423 {
424    int *s, *d;
425
426    d = (int *)malloc(sizeof(int));
427    if (!d) return NULL;
428    s = (int *)src;
429    *d = *s;
430    CONV32(*d);
431    *size_ret = sizeof(int);
432    return d;
433 }
434
435 /* LONG LONG TYPE */
436 static int
437 eet_data_get_long_long(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst)
438 {
439    unsigned long long *d;
440
441    if (((char *)src + sizeof(unsigned long long)) > (char *)src_end) return -1;
442    memcpy(dst, src, sizeof(unsigned long long));
443    d = (unsigned long long *)dst;
444    CONV64(*d);
445    return sizeof(unsigned long long);
446 }
447
448 static void *
449 eet_data_put_long_long(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret)
450 {
451    unsigned long long *s, *d;
452
453    d = (unsigned long long *)malloc(sizeof(unsigned long long));
454    if (!d) return NULL;
455    s = (unsigned long long *)src;
456    *d = *s;
457    CONV64(*d);
458    *size_ret = sizeof(unsigned long long);
459    return d;
460 }
461
462 /* STRING TYPE */
463 static inline int
464 eet_data_get_string_hash(const Eet_Dictionary *ed, const void *src, const void *src_end)
465 {
466    if (ed)
467      {
468         int               idx;
469
470         if (eet_data_get_int(ed, src, src_end, &idx) < 0) return -1;
471
472         return eet_dictionary_string_get_hash(ed, idx);
473      }
474
475    return -1;
476 }
477
478 static inline int
479 eet_data_get_string(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
480 {
481    char *s, **d;
482
483    d = (char **)dst;
484
485    if (ed)
486      {
487         const char       *str;
488         int               idx;
489
490         if (eet_data_get_int(ed, src, src_end, &idx) < 0) return -1;
491
492         str = eet_dictionary_string_get_char(ed, idx);
493         if (str == NULL)
494           return -1;
495
496         *d = (char *) str;
497         return eet_dictionary_string_get_size(ed, idx);
498      }
499
500    s = (char *)src;
501    if (s == NULL)
502      {
503         *d = NULL;
504         return 0;
505      }
506
507    *d = s;
508    return strlen(s) + 1;
509 }
510
511 static void *
512 eet_data_put_string(Eet_Dictionary *ed, const void *src, int *size_ret)
513 {
514    char *s, *d;
515    int len;
516
517    if (ed)
518      {
519         const char      *str;
520         int              idx;
521
522         str = *((const char **) src);
523         if (!str) return NULL;
524
525         idx = eet_dictionary_string_add(ed, str);
526         if (idx == -1) return NULL;
527
528         return eet_data_put_int(ed, &idx, size_ret);
529      }
530
531    s = (char *)(*((char **)src));
532    if (!s) return NULL;
533    len = strlen(s);
534    d = malloc(len + 1);
535    if (!d) return NULL;
536    memcpy(d, s, len + 1);
537    *size_ret = len + 1;
538    return d;
539 }
540
541 /* ALWAYS INLINED STRING TYPE */
542 static int
543 eet_data_get_istring(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst)
544 {
545    return eet_data_get_string(NULL, src, src_end, dst);
546 }
547
548 static void *
549 eet_data_put_istring(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret)
550 {
551    return eet_data_put_string(NULL, src, size_ret);
552 }
553
554 /* ALWAYS NULL TYPE */
555 static int
556 eet_data_get_null(const Eet_Dictionary *ed __UNUSED__, const void *src __UNUSED__, const void *src_end __UNUSED__, void *dst)
557 {
558    char **d;
559
560    d = (char**) dst;
561
562    *d = NULL;
563    return 1;
564 }
565
566 static void *
567 eet_data_put_null(Eet_Dictionary *ed __UNUSED__, const void *src __UNUSED__, int *size_ret)
568 {
569    *size_ret = 0;
570    return NULL;
571 }
572
573 /**
574  * Fast lookups of simple doubles/floats.
575  *
576  * These aren't properly a cache because they don't store pre-calculated
577  * values, but have a so simple math that is almost as fast.
578  */
579 static inline int
580 _eet_data_float_cache_get(const char *s, int len, float *d)
581 {
582    /* fast handle of simple case 0xMp+E*/
583    if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p'))
584      {
585         int mantisse = (s[2] >= 'a') ? (s[2] - 'a' + 10) : (s[2] - '0');
586         int exponent = (s[5] - '0');
587
588         if (s[4] == '+') *d = (float)(mantisse << exponent);
589         else             *d = (float)mantisse / (float)(1 << exponent);
590
591         return 1;
592      }
593    return 0;
594 }
595
596 static inline int
597 _eet_data_double_cache_get(const char *s, int len, double *d)
598 {
599    /* fast handle of simple case 0xMp+E*/
600    if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p'))
601      {
602         int mantisse = (s[2] >= 'a') ? (s[2] - 'a' + 10) : (s[2] - '0');
603         int exponent = (s[5] - '0');
604
605         if (s[4] == '+') *d = (double)(mantisse << exponent);
606         else             *d = (double)mantisse / (double)(1 << exponent);
607
608         return 1;
609      }
610    return 0;
611 }
612
613 /* FLOAT TYPE */
614 static int
615 eet_data_get_float(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
616 {
617    float        *d;
618    int           idx;
619
620    d = (float *) dst;
621    if (!ed)
622      {
623         const char   *s, *p;
624         long long     mantisse;
625         long          exponent;
626         int           len;
627
628         s = (const char *)src;
629         p = s;
630         len = 0;
631         while ((p < (const char *)src_end) && (*p != 0)) {len++; p++;}
632
633         if (_eet_data_float_cache_get(s, len, d) != 0) return len + 1;
634
635         if (eina_convert_atod(s, len, &mantisse, &exponent) == EINA_FALSE) return -1;
636         *d = (float)ldexp((double)mantisse, exponent);
637
638         return len + 1;
639      }
640
641    if (eet_data_get_int(ed, src, src_end, &idx) < 0) return -1;
642
643    if (!eet_dictionary_string_get_float(ed, idx, d))
644      return -1;
645    return 1;
646 }
647
648 static void *
649 eet_data_put_float(Eet_Dictionary *ed, const void *src, int *size_ret)
650 {
651    char  buf[128];
652    int   idx;
653
654    eina_convert_dtoa((double)(*(float *)src), buf);
655
656    if (!ed)
657      {
658         char    *d;
659         int      len;
660
661         len = strlen(buf);
662         d = malloc(len + 1);
663         if (!d) return NULL;
664         memcpy(d, buf, len + 1);
665         *size_ret = len + 1;
666         return d;
667      }
668
669    idx = eet_dictionary_string_add(ed, buf);
670    if (idx == -1) return NULL;
671
672    return eet_data_put_int(ed, &idx, size_ret);
673 }
674
675 /* DOUBLE TYPE */
676 static int
677 eet_data_get_double(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
678 {
679    double       *d;
680    int           idx;
681
682    d = (double *) dst;
683
684    if (!ed)
685      {
686         const char     *s, *p;
687         long long       mantisse = 0;
688         long            exponent = 0;
689         int             len;
690
691         s = (const char *) src;
692         p = s;
693         len = 0;
694         while ((p < (const char *)src_end) && (*p != 0)) {len++; p++;}
695
696         if (_eet_data_double_cache_get(s, len, d) != 0) return len + 1;
697
698         if (eina_convert_atod(s, len, &mantisse, &exponent) == EINA_FALSE) return -1;
699         *d = ldexp((double) mantisse, exponent);
700
701         return len + 1;
702      }
703
704    if (eet_data_get_int(ed, src, src_end, &idx) < 0) return -1;
705
706    if (!eet_dictionary_string_get_double(ed, idx, d))
707      return -1;
708    return 1;
709 }
710
711 static void *
712 eet_data_put_double(Eet_Dictionary *ed, const void *src, int *size_ret)
713 {
714    char  buf[128];
715    int   idx;
716
717    eina_convert_dtoa((double)(*(double *)src), buf);
718
719    if (!ed)
720      {
721         char   *d;
722         int     len;
723
724         len = strlen(buf);
725         d = malloc(len + 1);
726         if (!d) return NULL;
727         memcpy(d, buf, len + 1);
728         *size_ret = len + 1;
729
730         return d;
731      }
732
733    idx = eet_dictionary_string_add(ed, buf);
734    if (idx == -1) return NULL;
735
736    return eet_data_put_int(ed, &idx, size_ret);
737 }
738
739 static int
740 eet_data_get_f32p32(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
741 {
742    Eina_F32p32 *fp;
743    int idx;
744
745    fp = (Eina_F32p32*) dst;
746
747    if (!ed)
748      {
749         const char *s, *p;
750         int len;
751
752         s = (const char *) src;
753         p = s;
754         len = 0;
755         while ((p < (const char *)src_end) && (*p != 0)) { len++; p++; }
756
757         if (!(eina_convert_atofp(s, len, fp)))
758           return -1;
759         return 1;
760      }
761
762    if (eet_data_get_int(ed, src, src_end, &idx) < 0) return -1;
763
764    if (!eet_dictionary_string_get_fp(ed, idx, fp))
765      return -1;
766    return 1;
767 }
768
769 static void *
770 eet_data_put_f32p32(Eet_Dictionary *ed, const void *src, int *size_ret)
771 {
772    char  buf[128];
773    int   idx;
774
775    eina_convert_fptoa((Eina_F32p32)(*(Eina_F32p32 *)src), buf);
776
777    if (!ed)
778      {
779         char *d;
780         int len;
781
782         len = strlen(buf);
783         d = malloc(len + 1);
784         if (!d) return NULL;
785         memcpy(d, buf, len + 1);
786         *size_ret = len + 1;
787
788         return d;
789      }
790
791    idx = eet_dictionary_string_add(ed, buf);
792    if (idx == -1) return NULL;
793
794    return eet_data_put_int(ed, &idx, size_ret);
795 }
796
797 static int
798 eet_data_get_f16p16(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
799 {
800    Eina_F32p32 tmp;
801    Eina_F16p16 *fp;
802
803    fp = (Eina_F16p16*) dst;
804
805    if (eet_data_get_f32p32(ed, src, src_end, &tmp) < 0) return -1;
806
807    *fp = eina_f32p32_to_f16p16(tmp);
808    return 1;
809 }
810
811 static void *
812 eet_data_put_f16p16(Eet_Dictionary *ed, const void *src, int *size_ret)
813 {
814    Eina_F32p32 tmp;
815
816    tmp = eina_f16p16_to_f32p32((Eina_F16p16)(*(Eina_F16p16 *)src));
817    return eet_data_put_f32p32(ed, &tmp, size_ret);
818 }
819
820 static int
821 eet_data_get_f8p24(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
822 {
823    Eina_F32p32 tmp;
824    Eina_F8p24 *fp;
825
826    fp = (Eina_F8p24*) dst;
827
828    if (eet_data_get_f32p32(ed, src, src_end, &tmp) < 0) return -1;
829
830    *fp = eina_f32p32_to_f8p24(tmp);
831    return 1;
832 }
833
834 static void *
835 eet_data_put_f8p24(Eet_Dictionary *ed, const void *src, int *size_ret)
836 {
837    Eina_F32p32 tmp;
838
839    tmp = eina_f8p24_to_f32p32((Eina_F8p24)(*(Eina_F8p24 *)src));
840    return eet_data_put_f32p32(ed, &tmp, size_ret);
841 }
842
843 static inline int
844 eet_data_get_type(const Eet_Dictionary *ed, int type, const void *src, const void *src_end, void *dest)
845 {
846    int ret;
847
848    ret = eet_basic_codec[type - 1].get(ed, src, src_end, dest);
849    return ret;
850 }
851
852 static inline void *
853 eet_data_put_type(Eet_Dictionary *ed, int type, const void *src, int *size_ret)
854 {
855    void *ret;
856
857    ret = eet_basic_codec[type - 1].put(ed, src, size_ret);
858    return ret;
859 }
860
861 static inline Eina_Bool
862 eet_data_type_match(int type1, int type2)
863 {
864    if (type1 == type2) return EINA_TRUE;
865
866    /* Note: All floating point type are equivalent and could be read
867       without problem by any other floating point getter. */
868    switch (type1)
869      {
870       case EET_T_FLOAT:
871       case EET_T_DOUBLE:
872       case EET_T_F32P32:
873       case EET_T_F16P16:
874       case EET_T_F8P24:
875          switch (type2)
876            {
877             case EET_T_FLOAT:
878             case EET_T_DOUBLE:
879             case EET_T_F32P32:
880             case EET_T_F16P16:
881             case EET_T_F8P24:
882                return EINA_TRUE;
883             default:
884                break;
885            }
886          break;
887       default:
888          break;
889      }
890
891    return EINA_FALSE;
892 }
893
894 /* chunk format...
895  *
896  * char[4] = "CHnK"; // untyped data ... or
897  * char[4] = "CHKx"; // typed data - x == type
898  *
899  * int     = chunk size (including magic string);
900  * char[]  = chunk magic/name string (0 byte terminated);
901  * ... sub-chunks (a chunk can contain chuncks recusrively) ...
902  * or
903  * ... payload data ...
904  *
905  */
906
907 static inline void
908 eet_data_chunk_get(const Eet_Dictionary *ed, Eet_Data_Chunk *chnk,
909                    const void *src, int size)
910 {
911    const char *s;
912    int ret1, ret2;
913
914    if (!src) return;
915    if (size <= 8) return;
916    if (!chnk) return;
917
918    s = src;
919    if (s[2] == 'K')
920      {
921         if ((s[0] != 'C') || (s[1] != 'H') || (s[2] != 'K'))
922           return;
923
924         chnk->type = (unsigned char)(s[3]);
925         if (chnk->type >= EET_I_LIMIT)
926           {
927              chnk->group_type = ((chnk->type - EET_I_LIMIT) & 0xF) + EET_G_UNKNOWN;
928              switch ((chnk->type - EET_I_LIMIT) & 0xF0)
929                {
930 #define EET_UNMATCH_TYPE(Type) \
931                   case EET_I_##Type: chnk->type = EET_T_##Type; break;
932
933                   EET_UNMATCH_TYPE(STRING);
934                   EET_UNMATCH_TYPE(INLINED_STRING);
935                   EET_UNMATCH_TYPE(NULL);
936                 default:
937                    return;
938                }
939           }
940         else if (chnk->type > EET_T_LAST)
941           {
942              chnk->group_type = chnk->type;
943              chnk->type = EET_T_UNKNOW;
944           }
945         else
946           chnk->group_type = EET_G_UNKNOWN;
947         if ((chnk->type >= EET_T_LAST) ||
948             (chnk->group_type >= EET_G_LAST))
949           {
950              chnk->type = 0;
951              chnk->group_type = 0;
952           }
953      }
954    else
955      {
956         if ((s[0] != 'C') || (s[1] != 'H') || (s[2] != 'n') || (s[3] != 'K'))
957           return;
958      }
959    ret1 = eet_data_get_type(ed, EET_T_INT, (s + 4), (s + size), &(chnk->size));
960
961    if (ret1 <= 0) return;
962    if ((chnk->size < 0) || ((chnk->size + 8) > size)) return;
963    ret2 = eet_data_get_type(ed, EET_T_STRING, (s + 8), (s + size), &(chnk->name));
964
965    if (ret2 <= 0) return;
966
967    chnk->len = ret2;
968
969    /* Precalc hash */
970    chnk->hash = eet_data_get_string_hash(ed, (s + 8), (s + size));
971
972    if (ed)
973      {
974         chnk->data = (char *)src + 4 + ret1 + sizeof(int);
975         chnk->size -= sizeof(int);
976      }
977    else
978      {
979         chnk->data = (char *)src + 4 + ret1 + chnk->len;
980         chnk->size -= chnk->len;
981      }
982
983    return;
984 }
985
986 static inline Eet_Data_Chunk *
987 eet_data_chunk_new(void *data, int size, const char *name, int type, int group_type)
988 {
989    Eet_Data_Chunk *chnk;
990
991    if (!name) return NULL;
992    chnk = calloc(1, sizeof(Eet_Data_Chunk));
993    if (!chnk) return NULL;
994
995    /* Note: Another security, so older eet library could read file
996     saved with fixed point value. */
997    if (type == EET_T_F32P32
998        || type == EET_T_F16P16
999        || type == EET_T_F8P24)
1000      type = EET_T_DOUBLE;
1001
1002    chnk->name = strdup(name);
1003    chnk->len = strlen(name) + 1;
1004    chnk->size = size;
1005    chnk->data = data;
1006    chnk->type = type;
1007    chnk->group_type = group_type;
1008    return chnk;
1009 }
1010
1011 static inline void
1012 eet_data_chunk_free(Eet_Data_Chunk *chnk)
1013 {
1014    if (chnk->name) free(chnk->name);
1015    free(chnk);
1016 }
1017
1018 static inline Eet_Data_Stream *
1019 eet_data_stream_new(void)
1020 {
1021    Eet_Data_Stream *ds;
1022
1023    ds = calloc(1, sizeof(Eet_Data_Stream));
1024    if (!ds) return NULL;
1025    return ds;
1026 }
1027
1028 static inline void
1029 eet_data_stream_free(Eet_Data_Stream *ds)
1030 {
1031    if (ds->data) free(ds->data);
1032    free(ds);
1033 }
1034
1035 static inline void
1036 eet_data_stream_flush(Eet_Data_Stream *ds)
1037 {
1038    free(ds);
1039 }
1040
1041 static inline void
1042 eet_data_stream_write(Eet_Data_Stream *ds, const void *data, int size)
1043 {
1044    char *p;
1045
1046    if ((ds->pos + size) > ds->size)
1047      {
1048         ds->data = realloc(ds->data, ds->size + size + 512);
1049         if (!ds->data)
1050           {
1051              ds->pos = 0;
1052              ds->size = 0;
1053              return;
1054           }
1055         ds->size = ds->size + size + 512;
1056      }
1057    p = ds->data;
1058    memcpy(p + ds->pos, data, size);
1059    ds->pos += size;
1060 }
1061
1062 static void
1063 eet_data_chunk_put(Eet_Dictionary *ed, Eet_Data_Chunk *chnk, Eet_Data_Stream *ds)
1064 {
1065    int  *size;
1066    void *string;
1067    int   s;
1068    int   size_ret = 0;
1069    int   string_ret = 0;
1070    unsigned char buf[4] = "CHK";
1071
1072    /* disable this check - it will allow empty chunks to be written. this is
1073     * right for corner-cases when y have a struct with empty fields (empty
1074     * strings or empty list ptrs etc.) */
1075    /* if (!chnk->data && chnk->type != EET_T_NULL) return; */
1076    /* chunk head */
1077
1078 /*   eet_data_stream_write(ds, "CHnK", 4);*/
1079    if (chnk->type != EET_T_UNKNOW)
1080      {
1081         if (chnk->group_type != EET_G_UNKNOWN)
1082           {
1083              int type = EET_I_LIMIT + chnk->group_type - EET_G_UNKNOWN;
1084
1085              switch (chnk->type)
1086                {
1087                   /* Only make sense with pointer type. */
1088 #define EET_MATCH_TYPE(Type) \
1089                   case EET_T_##Type: type += EET_I_##Type; break;
1090
1091                   EET_MATCH_TYPE(STRING);
1092                   EET_MATCH_TYPE(INLINED_STRING);
1093                   EET_MATCH_TYPE(NULL);
1094                 default:
1095                    return ;
1096                }
1097
1098              buf[3] = type;
1099           }
1100         else
1101           buf[3] = chnk->type;
1102      }
1103    else buf[3] = chnk->group_type;
1104
1105    string = eet_data_put_string(ed, &chnk->name, &string_ret);
1106    if (!string)
1107      return ;
1108
1109    /* size of chunk payload data + name */
1110    s = chnk->size + string_ret;
1111    size = eet_data_put_int(ed, &s, &size_ret);
1112
1113    /* FIXME: If something goes wrong the resulting file will be corrupted. */
1114    if (!size)
1115      goto on_error;
1116
1117    eet_data_stream_write(ds, buf, 4);
1118
1119    /* write chunk length */
1120    eet_data_stream_write(ds, size, size_ret);
1121
1122    /* write chunk name */
1123    eet_data_stream_write(ds, string, string_ret);
1124
1125    /* write payload */
1126    if (chnk->data)
1127      eet_data_stream_write(ds, chnk->data, chnk->size);
1128
1129    free(string);
1130  on_error:
1131    free(size);
1132 }
1133
1134 /*---*/
1135
1136 static void
1137 _eet_descriptor_hash_new(Eet_Data_Descriptor *edd)
1138 {
1139    int i;
1140
1141    edd->elements.hash.size = 1 << 6;
1142    edd->elements.hash.buckets = calloc(1, sizeof(Eet_Data_Descriptor_Hash) * edd->elements.hash.size);
1143    for (i = 0; i < edd->elements.num; i++)
1144      {
1145         Eet_Data_Element *ede;
1146         int hash;
1147
1148         ede = &(edd->elements.set[i]);
1149         hash = _eet_hash_gen((char *) ede->name, 6);
1150         if (!edd->elements.hash.buckets[hash].element)
1151           edd->elements.hash.buckets[hash].element = ede;
1152         else
1153           {
1154              Eet_Data_Descriptor_Hash *bucket;
1155
1156              bucket = calloc(1, sizeof(Eet_Data_Descriptor_Hash));
1157              bucket->element = ede;
1158              bucket->next = edd->elements.hash.buckets[hash].next;
1159              edd->elements.hash.buckets[hash].next = bucket;
1160           }
1161      }
1162 }
1163
1164 static void
1165 _eet_descriptor_hash_free(Eet_Data_Descriptor *edd)
1166 {
1167    int i;
1168
1169    for (i = 0; i < edd->elements.hash.size; i++)
1170      {
1171         Eet_Data_Descriptor_Hash *bucket, *pbucket;
1172
1173         bucket = edd->elements.hash.buckets[i].next;
1174         while (bucket)
1175           {
1176              pbucket = bucket;
1177              bucket = bucket->next;
1178              free(pbucket);
1179           }
1180      }
1181    if (edd->elements.hash.buckets) free(edd->elements.hash.buckets);
1182 }
1183
1184 static Eet_Data_Element *
1185 _eet_descriptor_hash_find(Eet_Data_Descriptor *edd, char *name, int hash)
1186 {
1187    Eet_Data_Descriptor_Hash *bucket;
1188
1189    if (hash < 0) hash = _eet_hash_gen(name, 6);
1190    else hash &= 0x3f;
1191    if (!edd->elements.hash.buckets[hash].element) return NULL;
1192    /*
1193      When we use the dictionnary as a source for chunk name, we will always
1194      have the same pointer in name. It's a good idea to just compare pointer
1195      instead of running strcmp on both string.
1196    */
1197    if (edd->elements.hash.buckets[hash].element->directory_name_ptr == name)
1198      return edd->elements.hash.buckets[hash].element;
1199    if (!strcmp(edd->elements.hash.buckets[hash].element->name, name))
1200      {
1201         edd->elements.hash.buckets[hash].element->directory_name_ptr = name;
1202         return edd->elements.hash.buckets[hash].element;
1203      }
1204    bucket = edd->elements.hash.buckets[hash].next;
1205    while (bucket)
1206      {
1207         if (bucket->element->directory_name_ptr == name) return bucket->element;
1208         if (!strcmp(bucket->element->name, name))
1209           {
1210              bucket->element->directory_name_ptr = name;
1211              return bucket->element;
1212           }
1213         bucket = bucket->next;
1214      }
1215    return NULL;
1216 }
1217
1218 static void *
1219 _eet_mem_alloc(size_t size)
1220 {
1221    return calloc(1, size);
1222 }
1223
1224 static void
1225 _eet_mem_free(void *mem)
1226 {
1227    free(mem);
1228 }
1229
1230 static char *
1231 _eet_str_alloc(const char *str)
1232 {
1233    return strdup(str);
1234 }
1235
1236 static void
1237 _eet_str_free(const char *str)
1238 {
1239    free((char *)str);
1240 }
1241
1242 static Eina_Hash *
1243 _eet_eina_hash_add_alloc(Eina_Hash *hash, const char *key, void *data)
1244 {
1245    if (!hash) hash = eina_hash_string_small_new(NULL);
1246    if (!hash) return NULL;
1247
1248    eina_hash_add(hash, key, data);
1249    return hash;
1250 }
1251
1252 static Eina_Hash *
1253 _eet_eina_hash_direct_add_alloc(Eina_Hash *hash, const char *key, void *data)
1254 {
1255    if (!hash) hash = eina_hash_string_small_new(NULL);
1256    if (!hash) return NULL;
1257
1258    eina_hash_direct_add(hash, key, data);
1259    return hash;
1260 }
1261
1262 static char *
1263 _eet_str_direct_alloc(const char *str)
1264 {
1265    return (char *)str;
1266 }
1267
1268 static void
1269 _eet_str_direct_free(__UNUSED__ const char *str)
1270 {
1271 }
1272
1273 static void
1274 _eet_eina_hash_foreach(void *hash, Eina_Hash_Foreach cb, void *fdata)
1275 {
1276    if (hash) eina_hash_foreach(hash, cb, fdata);
1277 }
1278
1279 static void
1280 _eet_eina_hash_free(void *hash)
1281 {
1282    if (hash) eina_hash_free(hash);
1283 }
1284
1285 /*---*/
1286 EAPI Eina_Bool
1287 eet_eina_stream_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc, const char *name, int size)
1288 {
1289    if (!eddc || !name) return EINA_FALSE;
1290
1291    eddc->name = name;
1292    eddc->size = size;
1293    eddc->version = 1;
1294
1295    eddc->func.mem_alloc = _eet_mem_alloc;
1296    eddc->func.mem_free = _eet_mem_free;
1297    eddc->func.str_alloc = (char *(*)(const char *))eina_stringshare_add;
1298    eddc->func.str_free = eina_stringshare_del;
1299    eddc->func.list_next = (void *(*)(void *))eina_list_next;
1300    eddc->func.list_append = (void *(*)(void *, void *))eina_list_append;
1301    eddc->func.list_data = (void *(*)(void *))eina_list_data_get;
1302    eddc->func.list_free = (void *(*)(void *))eina_list_free;
1303    eddc->func.hash_foreach = (void (*)(void *, int (*)(void *, const char *, void *, void *), void *))_eet_eina_hash_foreach;
1304    eddc->func.hash_add = (void* (*)(void *, const char *, void *)) _eet_eina_hash_add_alloc;
1305    eddc->func.hash_free = (void (*)(void *))_eet_eina_hash_free;
1306
1307    return EINA_TRUE;
1308 }
1309
1310 EAPI Eina_Bool
1311 eet_eina_file_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc, const char *name, int size)
1312 {
1313    if (!eet_eina_stream_data_descriptor_class_set(eddc, name, size))
1314      return EINA_FALSE;
1315
1316    eddc->version = 2;
1317
1318    eddc->func.hash_add = (void* (*)(void *, const char *, void *)) _eet_eina_hash_direct_add_alloc;
1319    eddc->func.str_direct_alloc = _eet_str_direct_alloc;
1320    eddc->func.str_direct_free = _eet_str_direct_free;
1321
1322    return EINA_TRUE;
1323 }
1324
1325 static Eet_Data_Descriptor *
1326 _eet_data_descriptor_new(const Eet_Data_Descriptor_Class *eddc, int version)
1327 {
1328    Eet_Data_Descriptor *edd;
1329
1330    if (!eddc) return NULL;
1331
1332    edd = calloc(1, sizeof (Eet_Data_Descriptor));
1333    if (!edd) return NULL;
1334
1335    edd->name = eddc->name;
1336    edd->ed = NULL;
1337    edd->size = eddc->size;
1338    edd->func.mem_alloc = _eet_mem_alloc;
1339    edd->func.mem_free = _eet_mem_free;
1340    edd->func.str_alloc = _eet_str_alloc;
1341    edd->func.str_free = _eet_str_free;
1342    if (eddc->func.mem_alloc)
1343      edd->func.mem_alloc = eddc->func.mem_alloc;
1344    if (eddc->func.mem_free)
1345      edd->func.mem_free = eddc->func.mem_free;
1346    if (eddc->func.str_alloc)
1347      edd->func.str_alloc = eddc->func.str_alloc;
1348    if (eddc->func.str_free)
1349      edd->func.str_free = eddc->func.str_free;
1350    edd->func.list_next = eddc->func.list_next;
1351    edd->func.list_append = eddc->func.list_append;
1352    edd->func.list_data = eddc->func.list_data;
1353    edd->func.list_free = eddc->func.list_free;
1354    edd->func.hash_foreach = eddc->func.hash_foreach;
1355    edd->func.hash_add = eddc->func.hash_add;
1356    edd->func.hash_free = eddc->func.hash_free;
1357
1358    if (eddc->version > 1 && version > 1)
1359      {
1360         edd->func.str_direct_alloc = eddc->func.str_direct_alloc;
1361         edd->func.str_direct_free = eddc->func.str_direct_free;
1362      }
1363    if (eddc->version > 2)
1364      {
1365         edd->func.type_get = eddc->func.type_get;
1366         edd->func.type_set = eddc->func.type_set;
1367      }
1368
1369    return edd;
1370 }
1371
1372 EAPI Eet_Data_Descriptor *
1373 eet_data_descriptor_new(const char *name,
1374                         int size,
1375                         void *(*func_list_next) (void *l),
1376                         void *(*func_list_append) (void *l, void *d),
1377                         void *(*func_list_data) (void *l),
1378                         void *(*func_list_free) (void *l),
1379                         void  (*func_hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt),
1380                         void *(*func_hash_add) (void *h, const char *k, void *d),
1381                         void  (*func_hash_free) (void *h))
1382 {
1383    Eet_Data_Descriptor_Class eddc;
1384
1385    if (!name) return NULL;
1386
1387    memset(&eddc, 0, sizeof (Eet_Data_Descriptor_Class));
1388
1389    eddc.name = name;
1390    eddc.size = size;
1391    eddc.version = 0;
1392
1393    eddc.func.list_next = func_list_next;
1394    eddc.func.list_append = func_list_append;
1395    eddc.func.list_data = func_list_data;
1396    eddc.func.list_free = func_list_free;
1397    eddc.func.hash_foreach = func_hash_foreach;
1398    eddc.func.hash_add = func_hash_add;
1399    eddc.func.hash_free = func_hash_free;
1400
1401    return _eet_data_descriptor_new(&eddc, 0);
1402 }
1403
1404 EAPI Eet_Data_Descriptor *
1405 eet_data_descriptor2_new(const Eet_Data_Descriptor_Class *eddc)
1406 {
1407    return _eet_data_descriptor_new(eddc, 1);
1408 }
1409
1410 EAPI Eet_Data_Descriptor *
1411 eet_data_descriptor3_new(const Eet_Data_Descriptor_Class *eddc)
1412 {
1413    return _eet_data_descriptor_new(eddc, 2);
1414 }
1415
1416 EAPI Eet_Data_Descriptor *
1417 eet_data_descriptor_stream_new(const Eet_Data_Descriptor_Class *eddc)
1418 {
1419    return _eet_data_descriptor_new(eddc, 1);
1420 }
1421
1422 EAPI Eet_Data_Descriptor *
1423 eet_data_descriptor_file_new(const Eet_Data_Descriptor_Class *eddc)
1424 {
1425    return _eet_data_descriptor_new(eddc, 2);
1426 }
1427
1428 EAPI void
1429 eet_data_descriptor_free(Eet_Data_Descriptor *edd)
1430 {
1431    if (!edd) return ;
1432    _eet_descriptor_hash_free(edd);
1433    if (edd->elements.set) free(edd->elements.set);
1434    free(edd);
1435 }
1436
1437 EAPI void
1438 eet_data_descriptor_element_add(Eet_Data_Descriptor *edd,
1439                                 const char *name,
1440                                 int type,
1441                                 int group_type,
1442                                 int offset,
1443                                 int count,
1444 /*                              int counter_offset, */
1445                                 const char *counter_name /* FIXME: Useless should go on a major release */,
1446                                 Eet_Data_Descriptor *subtype)
1447 {
1448    Eet_Data_Element *ede;
1449    Eet_Data_Element *tmp;
1450
1451    /* UNION, INHERITED or VARIANT type would not work with simple type, we need a way to map the type. */
1452    if ((group_type == EET_G_INHERIT
1453         || group_type == EET_G_UNION
1454         || group_type == EET_G_VARIANT)
1455        &&
1456        (type != EET_T_UNKNOW
1457         || subtype == NULL
1458         || subtype->func.type_get == NULL
1459         || subtype->func.type_set == NULL))
1460      return ;
1461
1462    /* Only one element is allowed with INHERITED type */
1463    if (group_type == EET_G_INHERIT && edd->elements.num != 0)
1464      return ;
1465    if (edd->elements.num > 0 && edd->elements.set[0].group_type == EET_G_INHERIT)
1466      return ;
1467
1468    /* VARIANT type will only work if the map only contains EET_G_*, but not INHERIT, UNION, VARIANT and ARRAY. */
1469    if (group_type == EET_G_VARIANT)
1470      {
1471         int i;
1472
1473         for (i = 0; i < subtype->elements.num; ++i)
1474           if (subtype->elements.set[i].type != EET_T_UNKNOW
1475               && subtype->elements.set[i].group_type > EET_G_VAR_ARRAY
1476               && subtype->elements.set[i].group_type < EET_G_UNION)
1477             return ;
1478
1479         subtype->unified_type = EINA_TRUE;
1480      }
1481    if (subtype
1482        && subtype->unified_type
1483        && (type != EET_T_UNKNOW
1484            || group_type < EET_G_UNION))
1485      return ;
1486
1487    /* Sanity check done, let allocate ! */
1488    edd->elements.num++;
1489    tmp = realloc(edd->elements.set, edd->elements.num * sizeof(Eet_Data_Element));
1490    if (!tmp) return ;
1491    edd->elements.set = tmp;
1492    ede = &(edd->elements.set[edd->elements.num - 1]);
1493    ede->name = name;
1494    ede->directory_name_ptr = NULL;
1495
1496    /*
1497     * We do a special case when we do list,hash or whatever group of simple type.
1498     * Instead of handling it in encode/decode/dump/undump, we create an
1499     * implicit structure with only the simple type.
1500     */
1501    if (group_type > EET_G_UNKNOWN
1502        && group_type < EET_G_LAST
1503        && ((type > EET_T_UNKNOW && type < EET_T_STRING)
1504            || (type > EET_T_NULL && type < EET_T_LAST))
1505        && subtype == NULL)
1506      {
1507         subtype = calloc(1, sizeof (Eet_Data_Descriptor));
1508         if (!subtype) return ;
1509         subtype->name = "implicit";
1510         subtype->size = eet_basic_codec[type - 1].size;
1511         memcpy(&subtype->func, &edd->func, sizeof(subtype->func));
1512
1513         eet_data_descriptor_element_add(subtype, eet_basic_codec[type - 1].name, type,
1514                                         EET_G_UNKNOWN, 0, 0, /* 0,  */NULL, NULL);
1515         type = EET_T_UNKNOW;
1516      }
1517
1518    ede->type = type;
1519    ede->group_type = group_type;
1520    ede->offset = offset;
1521    ede->count = count;
1522    /* FIXME: For the time being, VAR_ARRAY, INHERIT, UNION and VARIANT  will put the counter_offset in count. */
1523    ede->counter_offset = count;
1524 /*    ede->counter_offset = counter_offset; */
1525    ede->counter_name = counter_name;
1526
1527    ede->subtype = subtype;
1528 }
1529
1530 EAPI void *
1531 eet_data_read_cipher(Eet_File *ef, Eet_Data_Descriptor *edd, const char *name, const char *cipher_key)
1532 {
1533    const Eet_Dictionary *ed = NULL;
1534    const void           *data = NULL;
1535    void                 *data_dec;
1536    Eet_Free_Context      context;
1537    int                   required_free = 0;
1538    int                   size;
1539
1540    ed = eet_dictionary_get(ef);
1541
1542    if (!cipher_key)
1543      data = eet_read_direct(ef, name, &size);
1544    if (!data)
1545      {
1546         required_free = 1;
1547         data = eet_read_cipher(ef, name, &size, cipher_key);
1548         if (!data) return NULL;
1549      }
1550
1551    memset(&context, 0, sizeof (context));
1552    data_dec = _eet_data_descriptor_decode(&context, ed, edd, data, size);
1553    if (required_free)
1554      free((void*)data);
1555
1556    return data_dec;
1557 }
1558
1559 EAPI Eet_Node *
1560 eet_data_node_read_cipher(Eet_File *ef, const char *name, const char *cipher_key)
1561 {
1562    const Eet_Dictionary *ed = NULL;
1563    const void *data = NULL;
1564    Eet_Node *result;
1565    Eet_Free_Context context;
1566    int required_free = 0;
1567    int size;
1568
1569    ed = eet_dictionary_get(ef);
1570
1571    if (!cipher_key)
1572      data = eet_read_direct(ef, name, &size);
1573    if (!data)
1574      {
1575         required_free = 1;
1576         data = eet_read_cipher(ef, name, &size, cipher_key);
1577         if (!data) return NULL;
1578      }
1579
1580    memset(&context, 0, sizeof (context));
1581    result = _eet_data_descriptor_decode(&context, ed, NULL, data, size);
1582    if (required_free)
1583      free((void*)data);
1584
1585    return result;
1586 }
1587
1588 EAPI void *
1589 eet_data_read(Eet_File *ef, Eet_Data_Descriptor *edd, const char *name)
1590 {
1591    return eet_data_read_cipher(ef, edd, name, NULL);
1592 }
1593
1594 EAPI int
1595 eet_data_write_cipher(Eet_File *ef, Eet_Data_Descriptor *edd, const char *name, const char *cipher_key, const void *data, int compress)
1596 {
1597    Eet_Dictionary       *ed;
1598    void                 *data_enc;
1599    int                   size;
1600    int                   val;
1601
1602    ed = eet_dictionary_get(ef);
1603
1604    data_enc = _eet_data_descriptor_encode(ed, edd, data, &size);
1605    if (!data_enc) return 0;
1606    val = eet_write_cipher(ef, name, data_enc, size, compress, cipher_key);
1607    free(data_enc);
1608    return val;
1609 }
1610
1611 EAPI int
1612 eet_data_write(Eet_File *ef, Eet_Data_Descriptor *edd, const char *name, const void *data, int compress)
1613 {
1614    return eet_data_write_cipher(ef, edd, name, NULL, data, compress);
1615 }
1616
1617 static int
1618 _eet_free_hash(void *data)
1619 {
1620    unsigned long ptr = (unsigned long)(data);
1621    int hash;
1622
1623    hash = ptr;
1624    hash ^= ptr >> 8;
1625    hash ^= ptr >> 16;
1626    hash ^= ptr >> 24;
1627
1628 #if LONG_BIT != 32
1629    hash ^= ptr >> 32;
1630    hash ^= ptr >> 40;
1631    hash ^= ptr >> 48;
1632    hash ^= ptr >> 56;
1633 #endif
1634
1635    return hash & 0xFF;
1636 }
1637
1638 static void
1639 _eet_free_add(Eet_Free *ef, void *data)
1640 {
1641    int hash;
1642    int i;
1643
1644    hash = _eet_free_hash(data);
1645
1646    for (i = 0; i < ef->num[hash]; ++i)
1647      if (ef->list[hash][i] == data) return;
1648
1649    ef->num[hash]++;
1650    if (ef->num[hash] > ef->len[hash])
1651      {
1652         void    **tmp;
1653
1654         tmp = realloc(ef->list[hash], (ef->len[hash] + 16) * sizeof(void*));
1655         if (!tmp) return ;
1656
1657         ef->len[hash] += 16;
1658         ef->list[hash] = tmp;
1659      }
1660    ef->list[hash][ef->num[hash] - 1] = data;
1661 }
1662 static void
1663 _eet_free_reset(Eet_Free *ef)
1664 {
1665    int i;
1666
1667    if (ef->ref > 0) return ;
1668    for (i = 0; i < 256; ++i)
1669      {
1670         ef->len[i] = 0;
1671         ef->num[i] = 0;
1672         if (ef->list[i]) free(ef->list[i]);
1673         ef->list[i] = NULL;
1674      }
1675 }
1676 static void
1677 _eet_free_ref(Eet_Free *ef)
1678 {
1679    ef->ref++;
1680 }
1681 static void
1682 _eet_free_unref(Eet_Free *ef)
1683 {
1684    ef->ref--;
1685 }
1686
1687 #define _eet_freelist_add(Ctx, Data)    _eet_free_add(&Ctx->freelist, Data);
1688 #define _eet_freelist_reset(Ctx)        _eet_free_reset(&Ctx->freelist);
1689 #define _eet_freelist_ref(Ctx)          _eet_free_ref(&Ctx->freelist);
1690 #define _eet_freelist_unref(Ctx)        _eet_free_unref(&Ctx->freelist);
1691
1692 static void
1693 _eet_freelist_free(Eet_Free_Context *context, Eet_Data_Descriptor *edd)
1694 {
1695    int j;
1696    int i;
1697
1698    if (context->freelist.ref > 0) return;
1699    for (j = 0; j < 256; ++j)
1700      for (i = 0; i < context->freelist.num[j]; ++i)
1701        {
1702           if (edd)
1703             edd->func.mem_free(context->freelist.list[j][i]);
1704           else
1705             free(context->freelist.list[j][i]);
1706        }
1707    _eet_free_reset(&context->freelist);
1708 }
1709
1710 #define _eet_freelist_list_add(Ctx, Data)  _eet_free_add(&Ctx->freelist_list, Data);
1711 #define _eet_freelist_list_reset(Ctx)      _eet_free_reset(&Ctx->freelist_list);
1712 #define _eet_freelist_list_ref(Ctx)        _eet_free_ref(&Ctx->freelist_list);
1713 #define _eet_freelist_list_unref(Ctx)      _eet_free_unref(&Ctx->freelist_list);
1714
1715 static void
1716 _eet_freelist_list_free(Eet_Free_Context *context, Eet_Data_Descriptor *edd)
1717 {
1718    int j;
1719    int i;
1720
1721    if (context->freelist_list.ref > 0) return;
1722    for (j = 0; j < 256; ++j)
1723      for (i = 0; i < context->freelist_list.num[j]; ++i)
1724        {
1725           if (edd)
1726             edd->func.list_free(*((void**)(context->freelist_list.list[j][i])));
1727        }
1728    _eet_free_reset(&context->freelist_list);
1729 }
1730
1731 #define _eet_freelist_str_add(Ctx, Data)   _eet_free_add(&Ctx->freelist_str, Data);
1732 #define _eet_freelist_str_reset(Ctx)       _eet_free_reset(&Ctx->freelist_str);
1733 #define _eet_freelist_str_ref(Ctx)         _eet_free_ref(&Ctx->freelist_str);
1734 #define _eet_freelist_str_unref(Ctx)       _eet_free_unref(&Ctx->freelist_str);
1735
1736 static void
1737 _eet_freelist_str_free(Eet_Free_Context *context, Eet_Data_Descriptor *edd)
1738 {
1739    int j;
1740    int i;
1741
1742    if (context->freelist_str.ref > 0) return;
1743    for (j = 0; j < 256; ++j)
1744      for (i = 0; i < context->freelist_str.num[j]; ++i)
1745        {
1746           if (edd)
1747             edd->func.str_free(context->freelist_str.list[j][i]);
1748           else
1749             free(context->freelist_str.list[j][i]);
1750        }
1751    _eet_free_reset(&context->freelist_str);
1752 }
1753
1754 #define _eet_freelist_direct_str_add(Ctx, Data)    _eet_free_add(&Ctx->freelist_direct_str, Data);
1755 #define _eet_freelist_direct_str_reset(Ctx)        _eet_free_reset(&Ctx->freelist_direct_str);
1756 #define _eet_freelist_direct_str_ref(Ctx)          _eet_free_ref(&Ctx->freelist_direct_str);
1757 #define _eet_freelist_direct_str_unref(Ctx)        _eet_free_unref(&Ctx->freelist_direct_str);
1758
1759 static void
1760 _eet_freelist_direct_str_free(Eet_Free_Context *context, Eet_Data_Descriptor *edd)
1761 {
1762    int j;
1763    int i;
1764
1765    if (context->freelist_direct_str.ref > 0) return;
1766    for (j = 0; j < 256; ++j)
1767      for (i = 0; i < context->freelist_direct_str.num[j]; ++i)
1768        {
1769           if (edd)
1770             edd->func.str_direct_free(context->freelist_direct_str.list[j][i]);
1771           else
1772             free(context->freelist_direct_str.list[j][i]);
1773        }
1774    _eet_free_reset(&context->freelist_direct_str);
1775 }
1776
1777 #define _eet_freelist_hash_add(Ctx, Data) _eet_free_add(&Ctx->freelist_hash, Data);
1778 #define _eet_freelist_hash_reset(Ctx)     _eet_free_reset(&Ctx->freelist_hash);
1779 #define _eet_freelist_hash_ref(Ctx)       _eet_free_ref(&Ctx->freelist_hash);
1780 #define _eet_freelist_hash_unref(Ctx)     _eet_free_unref(&Ctx->freelist_hash);
1781
1782 static void
1783 _eet_freelist_hash_free(Eet_Free_Context *context, Eet_Data_Descriptor *edd)
1784 {
1785    int j;
1786    int i;
1787
1788    if (context->freelist_hash.ref > 0) return;
1789    for (j = 0; j < 256; ++j)
1790      for (i = 0; i < context->freelist_hash.num[j]; ++i)
1791        {
1792           if (edd)
1793             edd->func.hash_free(context->freelist_hash.list[j][i]);
1794           else
1795             free(context->freelist_hash.list[j][i]);
1796        }
1797    _eet_free_reset(&context->freelist_hash);
1798 }
1799
1800 static void
1801 _eet_freelist_all_ref(Eet_Free_Context *freelist_context)
1802 {
1803    _eet_freelist_ref(freelist_context);
1804    _eet_freelist_str_ref(freelist_context);
1805    _eet_freelist_list_ref(freelist_context);
1806    _eet_freelist_hash_ref(freelist_context);
1807    _eet_freelist_direct_str_ref(freelist_context);
1808 }
1809
1810 static void
1811 _eet_freelist_all_unref(Eet_Free_Context *freelist_context)
1812 {
1813    _eet_freelist_unref(freelist_context);
1814    _eet_freelist_str_unref(freelist_context);
1815    _eet_freelist_list_unref(freelist_context);
1816    _eet_freelist_hash_unref(freelist_context);
1817    _eet_freelist_direct_str_unref(freelist_context);
1818 }
1819
1820 static int
1821 eet_data_descriptor_encode_hash_cb(void *hash __UNUSED__, const char *cipher_key, void *hdata, void *fdata)
1822 {
1823    Eet_Dictionary               *ed;
1824    Eet_Data_Encode_Hash_Info    *edehi;
1825    Eet_Data_Stream              *ds;
1826    Eet_Data_Element             *ede;
1827    Eet_Data_Chunk               *echnk;
1828    void                         *data = NULL;
1829    int                           size;
1830
1831    edehi = fdata;
1832    ede = edehi->ede;
1833    ds = edehi->ds;
1834    ed = edehi->ed;
1835
1836    /* Store key */
1837    data = eet_data_put_type(ed,
1838                             EET_T_STRING,
1839                             &cipher_key,
1840                             &size);
1841    if (data)
1842      {
1843         echnk = eet_data_chunk_new(data, size, ede->name, ede->type, ede->group_type);
1844         eet_data_chunk_put(ed, echnk, ds);
1845         eet_data_chunk_free(echnk);
1846         free(data);
1847         data = NULL;
1848      }
1849
1850    EET_ASSERT(!((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING)), return );
1851
1852    /* Store data */
1853    if (ede->type >= EET_T_STRING)
1854      eet_data_put_unknown(ed, NULL, ede, ds, &hdata);
1855    else
1856      {
1857         if (ede->subtype)
1858           data = _eet_data_descriptor_encode(ed,
1859                                              ede->subtype,
1860                                              hdata,
1861                                              &size);
1862         if (data)
1863           {
1864              echnk = eet_data_chunk_new(data, size, ede->name, ede->type, ede->group_type);
1865              eet_data_chunk_put(ed, echnk, ds);
1866              eet_data_chunk_free(echnk);
1867              free(data);
1868              data = NULL;
1869           }
1870      }
1871
1872    return 1;
1873 }
1874
1875 static char *
1876 _eet_data_dump_token_get(const char *src, int *len)
1877 {
1878    const char *p;
1879    char *tok = NULL;
1880    int in_token = 0;
1881    int in_quote = 0;
1882    int tlen = 0, tsize = 0;
1883
1884 #define TOK_ADD(x) \
1885    { \
1886       tlen++; \
1887       if (tlen >= tsize) \
1888         { \
1889            tsize += 32; \
1890            tok = realloc(tok, tsize); \
1891         } \
1892       tok[tlen - 1] = x; \
1893    }
1894
1895    for (p = src; *len > 0; p++, (*len)--)
1896      {
1897         if (in_token)
1898           {
1899              if (in_quote)
1900                {
1901                   if ((p[0] == '\"') && (p > src) && (p[-1] != '\\'))
1902                     {
1903                        in_quote = 0;
1904                     }
1905                   else if ((p[0] == '\\') && (*len > 1) && (p[1] == '\"'))
1906                     {
1907                        /* skip */
1908                     }
1909                   else if ((p[0] == '\\') && (p > src) && (p[-1] == '\\'))
1910                     {
1911                        /* skip */
1912                     }
1913                   else if ((p[0] == '\\') && (*len > 1) && (p[1] == 'n'))
1914                     {
1915                        /* skip */
1916                     }
1917                   else if ((p[0] == 'n') && (p > src) && (p[-1] == '\\'))
1918                     {
1919                        TOK_ADD('\n');
1920                     }
1921                   else
1922                     TOK_ADD(p[0]);
1923                }
1924              else
1925                {
1926                   if (p[0] == '\"') in_quote = 1;
1927                   else
1928                     {
1929                        if ((isspace(p[0])) || (p[0] == ';')) /* token ends here */
1930                          {
1931                             TOK_ADD(0);
1932                             (*len)--;
1933                             return tok;
1934                          }
1935                        else
1936                          TOK_ADD(p[0]);
1937                     }
1938                }
1939           }
1940         else
1941           {
1942              if (!((isspace(p[0])) || (p[0] == ';')))
1943                {
1944                   in_token = 1;
1945                   (*len)++;
1946                   p--;
1947                }
1948           }
1949      }
1950    if (in_token)
1951      {
1952         TOK_ADD(0);
1953         return tok;
1954      }
1955    if (tok) free(tok);
1956    return NULL;
1957 }
1958
1959 static void
1960 eet_data_encode(Eet_Dictionary *ed, Eet_Data_Stream *ds, void *data, const char *name, int size, int type, int group_type)
1961 {
1962    Eet_Data_Chunk *echnk;
1963
1964    if (!data) type = EET_T_NULL;
1965
1966    if (group_type != EET_G_UNKNOWN)
1967      if (type >= EET_T_LAST)
1968        type = EET_T_UNKNOW;
1969
1970    echnk = eet_data_chunk_new(data, size, name, type, group_type);
1971    eet_data_chunk_put(ed, echnk, ds);
1972    eet_data_chunk_free(echnk);
1973    free(data);
1974 }
1975
1976 static void *
1977 _eet_data_dump_encode(int parent_type,
1978                       Eet_Dictionary *ed,
1979                       Eet_Node *node,
1980                       int *size_ret)
1981 {
1982    Eet_Data_Chunk *chnk = NULL;
1983    Eet_Data_Stream *ds;
1984    void *cdata, *data;
1985    int csize, size;
1986    int count;
1987    int child_type;
1988    Eet_Node *n;
1989
1990    if (_eet_data_words_bigendian == -1)
1991      {
1992         unsigned long int v;
1993
1994         v = htonl(0x12345678);
1995         if (v == 0x12345678) _eet_data_words_bigendian = 1;
1996         else _eet_data_words_bigendian = 0;
1997      }
1998
1999    if (node == NULL) return NULL;
2000
2001    ds = eet_data_stream_new();
2002    if (!ds) return NULL;
2003
2004    switch (node->type)
2005      {
2006       case EET_G_UNKNOWN:
2007         for (n = node->values; n; n = n->next)
2008           {
2009              data = _eet_data_dump_encode(node->type, ed, n, &size);
2010              if (data)
2011                {
2012                   eet_data_stream_write(ds, data, size);
2013                   free(data);
2014                }
2015           }
2016         break;
2017       case EET_G_ARRAY:
2018       case EET_G_VAR_ARRAY:
2019         for (child_type = EET_T_NULL, n = node->values; n; n = n->next)
2020           {
2021              if (n->type != EET_T_NULL)
2022                {
2023                   child_type = n->type;
2024                   break;
2025                }
2026           }
2027
2028         data = eet_data_put_type(ed,
2029                                  EET_T_INT,
2030                                  &node->count,
2031                                  &size);
2032         eet_data_encode(ed, ds, data, node->name, size, child_type, node->type);
2033
2034         count = node->count;
2035
2036         for (n = node->values; n; n = n->next)
2037           {
2038              int pos = ds->pos;
2039
2040              switch (n->type)
2041                {
2042                 case EET_T_STRING:
2043                 case EET_T_INLINED_STRING:
2044                    data = eet_data_put_type(ed, n->type, &(n->data.value.str), &size);
2045                    if (data) eet_data_encode(ed, ds, data, node->name, size, n->type, node->type);
2046                    break;
2047                 case EET_T_NULL:
2048                    continue;
2049                 default:
2050                    data = _eet_data_dump_encode(n->type, ed, n, &size);
2051                    eet_data_encode(ed, ds, data, node->name, size, n->type, node->type);
2052                    break;
2053                }
2054              if (ds->pos != pos) count--;
2055           }
2056
2057         for (; count; count--)
2058           {
2059              eet_data_encode(ed, ds, NULL, node->name, 0, EET_T_NULL, node->type);
2060           }
2061
2062         /* Array is somekind of special case, so we should embed it inside another chunk. */
2063         *size_ret = ds->pos;
2064         cdata = ds->data;
2065
2066         ds->data = NULL;
2067         ds->size = 0;
2068         eet_data_stream_free(ds);
2069
2070         return cdata;
2071         break;
2072       case EET_G_LIST:
2073         for (n = node->values; n; n = n->next)
2074           {
2075              switch (n->type)
2076                {
2077                 case EET_T_STRING:
2078                 case EET_T_INLINED_STRING:
2079                    data = eet_data_put_type(ed, n->type, &(n->data.value.str), &size);
2080                    if (data) eet_data_encode(ed, ds, data, node->name, size, n->type, node->type);
2081                    break;
2082                 case EET_T_NULL:
2083                    continue;
2084                 default:
2085                    data = _eet_data_dump_encode(node->type, ed, n, &size);
2086                    eet_data_encode(ed, ds, data, node->name, size, n->type, node->type);
2087                }
2088           }
2089
2090         /* List is another somekind of special case, every chunk is embed inside a list chunk. */
2091         *size_ret = ds->pos;
2092         cdata = ds->data;
2093
2094         ds->data = NULL;
2095         ds->size = 0;
2096         eet_data_stream_free(ds);
2097
2098         return cdata;
2099         break;
2100       case EET_G_HASH:
2101         if (node->key)
2102           {
2103              data = eet_data_put_type(ed,
2104                                       EET_T_STRING,
2105                                       &node->key,
2106                                       &size);
2107              eet_data_encode(ed, ds, data, node->name, size, node->type, node->type);
2108           }
2109         else
2110           /* A Hash without key will not decode correctly. */
2111           return NULL;
2112
2113         for (n = node->values; n; n = n->next)
2114           {
2115              switch (n->type)
2116                {
2117                 case EET_T_STRING:
2118                 case EET_T_INLINED_STRING:
2119                    data = eet_data_put_type(ed, n->type, &(n->data.value.str), &size);
2120                    if (data) eet_data_encode(ed, ds, data, node->name, size, n->type, node->type);
2121                    break;
2122                 case EET_T_NULL:
2123                    continue;
2124                 default:
2125                    data = _eet_data_dump_encode(node->type, ed, n, &size);
2126                    eet_data_encode(ed, ds, data, node->name, size, n->type, node->type);
2127                }
2128           }
2129
2130         /* Hash is somekind of special case, so we should embed it inside another chunk. */
2131         *size_ret = ds->pos;
2132         cdata = ds->data;
2133
2134         eet_data_stream_flush(ds);
2135
2136         return cdata;
2137       case EET_T_NULL:
2138          break;
2139
2140 #define EET_DATA_NODE_ENCODE(Eet_Type, Type)                            \
2141       case Eet_Type:                                                    \
2142         data = eet_data_put_type(ed, node->type, &(node->data.value.Type), &size); \
2143         if (data)                                                               \
2144           {                                                             \
2145              eet_data_encode(ed, ds, data, node->name, size, node->type, parent_type); \
2146              cdata = ds->data;                                          \
2147              *size_ret = ds->pos;                                       \
2148              eet_data_stream_flush(ds);                                 \
2149              return cdata;                                              \
2150           }                                                             \
2151         break;
2152
2153          EET_DATA_NODE_ENCODE(EET_T_CHAR, c);
2154          EET_DATA_NODE_ENCODE(EET_T_SHORT, s);
2155          EET_DATA_NODE_ENCODE(EET_T_INT, i);
2156          EET_DATA_NODE_ENCODE(EET_T_LONG_LONG, l);
2157          EET_DATA_NODE_ENCODE(EET_T_FLOAT, f);
2158          EET_DATA_NODE_ENCODE(EET_T_DOUBLE, d);
2159          EET_DATA_NODE_ENCODE(EET_T_UCHAR, uc);
2160          EET_DATA_NODE_ENCODE(EET_T_USHORT, us);
2161          EET_DATA_NODE_ENCODE(EET_T_UINT, ui);
2162          EET_DATA_NODE_ENCODE(EET_T_ULONG_LONG, ul);
2163          EET_DATA_NODE_ENCODE(EET_T_INLINED_STRING, str);
2164          EET_DATA_NODE_ENCODE(EET_T_STRING, str);
2165       default:
2166         break;
2167      }
2168
2169    if ((node->type >= EET_G_UNKNOWN) && (node->type < EET_G_LAST))
2170      chnk = eet_data_chunk_new(ds->data, ds->pos, node->name, EET_T_UNKNOW, node->type);
2171    else
2172      chnk = eet_data_chunk_new(ds->data, ds->pos, node->name, node->type, EET_G_UNKNOWN);
2173    eet_data_stream_flush(ds);
2174
2175    ds = eet_data_stream_new();
2176    eet_data_chunk_put(ed, chnk, ds);
2177    cdata = ds->data;
2178    csize = ds->pos;
2179
2180    eet_data_stream_flush(ds);
2181    *size_ret = csize;
2182
2183    free(chnk->data);
2184    eet_data_chunk_free(chnk);
2185
2186    return cdata;
2187 }
2188
2189 static void *
2190 _eet_data_dump_parse(Eet_Dictionary *ed,
2191                      int *size_ret,
2192                      const char *src,
2193                      int size)
2194 {
2195    void *cdata = NULL;
2196    const char *p = NULL;
2197 #define M_NONE 0
2198 #define M_STRUCT 1
2199 #define M_ 2
2200    int left, jump;
2201    Eet_Node *node_base = NULL;
2202    Eet_Node *node = NULL;
2203    Eet_Node *n = NULL, *nn = NULL;
2204
2205    /* FIXME; handle parse errors */
2206 #define TOK_GET(t) \
2207    jump = left; t = _eet_data_dump_token_get(p, &left); p += jump - left;
2208    left = size;
2209    for (p = src; p < (src + size);)
2210      {
2211         char *tok1, *tok2, *tok3, *tok4;
2212
2213         TOK_GET(tok1);
2214         if (tok1)
2215           {
2216              if (!strcmp(tok1, "group"))
2217                {
2218                   TOK_GET(tok2);
2219                   if (tok2)
2220                     {
2221                        TOK_GET(tok3);
2222                        if (tok3)
2223                          {
2224                             TOK_GET(tok4);
2225                             if (tok4)
2226                               {
2227                                  if (!strcmp(tok4, "{"))
2228                                    {
2229                                       /* we have 'group NAM TYP {' */
2230                                       n = eet_node_new();
2231                                       if (n)
2232                                         {
2233                                            n->parent = node;
2234                                            if (!node_base)
2235                                              {
2236                                                 node_base = n;
2237                                              }
2238                                            if (node)
2239                                              {
2240                                                 /* append node */
2241                                                 if (!node->values)
2242                                                   node->values = n;
2243                                                 else
2244                                                   {
2245                                                      for (nn = node->values; nn; nn = nn->next)
2246                                                        {
2247                                                           if (!nn->next)
2248                                                             {
2249                                                                nn->next = n;
2250                                                                break;
2251                                                             }
2252                                                        }
2253                                                   }
2254                                              }
2255                                            n->name = eina_stringshare_add(tok2);
2256                                            if      (!strcmp(tok3, "struct"))    n->type = EET_G_UNKNOWN;
2257                                            else if (!strcmp(tok3, "array"))     n->type = EET_G_ARRAY;
2258                                            else if (!strcmp(tok3, "var_array")) n->type = EET_G_VAR_ARRAY;
2259                                            else if (!strcmp(tok3, "list"))      n->type = EET_G_LIST;
2260                                            else if (!strcmp(tok3, "hash"))      n->type = EET_G_HASH;
2261                                            else
2262                                              {
2263                                                ERR("ERROR: group type '%s' invalid.", tok3);
2264                                              }
2265                                            node = n;
2266                                         }
2267                                    }
2268                                  free(tok4);
2269                               }
2270                             free(tok3);
2271                          }
2272                        free(tok2);
2273                     }
2274                }
2275              else if (!strcmp(tok1, "value"))
2276                {
2277                   TOK_GET(tok2);
2278                   if (tok2)
2279                     {
2280                        TOK_GET(tok3);
2281                        if (tok3)
2282                          {
2283                             TOK_GET(tok4);
2284                             if (tok4)
2285                               {
2286                                  /* we have 'value NAME TYP XXX' */
2287                                  if (node_base)
2288                                    {
2289                                       n = eet_node_new();
2290                                       if (n)
2291                                         {
2292                                            n->parent = node;
2293                                            /* append node */
2294                                            if (!node->values)
2295                                              node->values = n;
2296                                            else
2297                                              {
2298                                                 for (nn = node->values; nn; nn = nn->next)
2299                                                   {
2300                                                      if (!nn->next)
2301                                                        {
2302                                                           nn->next = n;
2303                                                           break;
2304                                                        }
2305                                                   }
2306                                              }
2307                                            n->name = eina_stringshare_add(tok2);
2308                                            if      (!strcmp(tok3, "char:"))
2309                                              {
2310                                                 n->type = EET_T_CHAR;
2311                                                 sscanf(tok4, "%hhi", &(n->data.value.c));
2312                                              }
2313                                            else if (!strcmp(tok3, "short:"))
2314                                              {
2315                                                 n->type = EET_T_SHORT;
2316                                                 sscanf(tok4, "%hi", &(n->data.value.s));
2317                                              }
2318                                            else if (!strcmp(tok3, "int:"))
2319                                              {
2320                                                 n->type = EET_T_INT;
2321                                                 sscanf(tok4, "%i", &(n->data.value.i));
2322                                              }
2323                                            else if (!strcmp(tok3, "long_long:"))
2324                                              {
2325                                                 n->type = EET_T_LONG_LONG;
2326                                                 sscanf(tok4, "%lli", &(n->data.value.l));
2327                                              }
2328                                            else if (!strcmp(tok3, "float:"))
2329                                              {
2330                                                 n->type = EET_T_FLOAT;
2331                                                 sscanf(tok4, "%f", &(n->data.value.f));
2332                                              }
2333                                            else if (!strcmp(tok3, "double:"))
2334                                              {
2335                                                 n->type = EET_T_DOUBLE;
2336                                                 sscanf(tok4, "%lf", &(n->data.value.d));
2337                                              }
2338                                            else if (!strcmp(tok3, "uchar:"))
2339                                              {
2340                                                 n->type = EET_T_UCHAR;
2341                                                 sscanf(tok4, "%hhu", &(n->data.value.uc));
2342                                              }
2343                                            else if (!strcmp(tok3, "ushort:"))
2344                                              {
2345                                                 n->type = EET_T_USHORT;
2346                                                 sscanf(tok4, "%hu", &(n->data.value.us));
2347                                              }
2348                                            else if (!strcmp(tok3, "uint:"))
2349                                              {
2350                                                 n->type = EET_T_UINT;
2351                                                 sscanf(tok4, "%u", &(n->data.value.ui));
2352                                              }
2353                                            else if (!strcmp(tok3, "ulong_long:"))
2354                                              {
2355                                                 n->type = EET_T_ULONG_LONG;
2356                                                 sscanf(tok4, "%llu", &(n->data.value.ul));
2357                                              }
2358                                            else if (!strcmp(tok3, "string:"))
2359                                              {
2360                                                 n->type = EET_T_STRING;
2361                                                 n->data.value.str = eina_stringshare_add(tok4);
2362                                              }
2363                                            else if (!strcmp(tok3, "inlined:"))
2364                                              {
2365                                                 n->type = EET_T_INLINED_STRING;
2366                                                 n->data.value.str = eina_stringshare_add(tok4);
2367                                              }
2368                                            else if (!strcmp(tok3, "null"))
2369                                              {
2370                                                 n->type = EET_T_NULL;
2371                                                 n->data.value.str = NULL;
2372                                              }
2373                                            else
2374                                              {
2375                                                 ERR("ERROR: value type '%s' invalid.", tok4);
2376                                              }
2377                                         }
2378                                    }
2379                                  free(tok4);
2380                               }
2381                             free(tok3);
2382                          }
2383                        free(tok2);
2384                     }
2385                }
2386              else if (!strcmp(tok1, "key"))
2387                {
2388                   TOK_GET(tok2);
2389                   if (tok2)
2390                     {
2391                        /* we have 'key NAME' */
2392                        if (node)
2393                          {
2394                             node->key = eina_stringshare_add(tok2);
2395                          }
2396                        free(tok2);
2397                     }
2398                }
2399              else if (!strcmp(tok1, "count"))
2400                {
2401                   TOK_GET(tok2);
2402                   if (tok2)
2403                     {
2404                        /* we have a 'count COUNT' */
2405                        if (node)
2406                          {
2407                             sscanf(tok2, "%i", &(node->count));
2408                          }
2409                        free(tok2);
2410                     }
2411                }
2412              else if (!strcmp(tok1, "}"))
2413                {
2414                   /* we have an end of the group */
2415                   if (node) node = node->parent;
2416                }
2417              free(tok1);
2418           }
2419      }
2420
2421    if (node_base)
2422      {
2423         cdata = _eet_data_dump_encode(EET_G_UNKNOWN, ed, node_base, size_ret);
2424         eet_node_del(node_base);
2425      }
2426    return cdata;
2427 }
2428
2429 #define NEXT_CHUNK(P, Size, Echnk, Ed)                  \
2430   {                                                     \
2431      int        tmp;                                    \
2432      tmp = Ed ? (int) (sizeof(int) * 2) : Echnk.len + 4;\
2433      P += (4 + Echnk.size + tmp);                       \
2434      Size -= (4 + Echnk.size + tmp);                    \
2435   }
2436
2437 static void *
2438 _eet_data_descriptor_decode(Eet_Free_Context *context,
2439                             const Eet_Dictionary *ed,
2440                             Eet_Data_Descriptor *edd,
2441                             const void *data_in,
2442                             int size_in)
2443 {
2444    Eet_Node *result = NULL;
2445    void *data = NULL;
2446    char *p;
2447    int size, i;
2448    Eet_Data_Chunk chnk;
2449
2450    if (_eet_data_words_bigendian == -1)
2451      {
2452         unsigned long int v;
2453
2454         v = htonl(0x12345678);
2455         if (v == 0x12345678) _eet_data_words_bigendian = 1;
2456         else _eet_data_words_bigendian = 0;
2457      }
2458
2459    if (edd)
2460      {
2461         data = edd->func.mem_alloc(edd->size);
2462         if (!data) return NULL;
2463         if (edd->ed != ed)
2464           {
2465              for (i = 0; i < edd->elements.num; i++)
2466                edd->elements.set[i].directory_name_ptr = NULL;
2467              edd->ed = ed;
2468           }
2469      }
2470    _eet_freelist_all_ref(context);
2471    if (data) _eet_freelist_add(context, data);
2472    memset(&chnk, 0, sizeof(Eet_Data_Chunk));
2473    eet_data_chunk_get(ed, &chnk, data_in, size_in);
2474    if (!chnk.name) goto error;
2475    if (edd)
2476      {
2477         if (strcmp(chnk.name, edd->name)) goto error;
2478      }
2479    p = chnk.data;
2480    if (ed)
2481      size = size_in - (4 + sizeof(int) * 2);
2482    else
2483      size = size_in - (4 + 4 + chnk.len);
2484    if (edd)
2485      {
2486         if (!edd->elements.hash.buckets) _eet_descriptor_hash_new(edd);
2487      }
2488    else
2489      {
2490         switch (chnk.group_type)
2491           {
2492            case EET_G_UNKNOWN:
2493               switch (chnk.type)
2494                 {
2495                  case EET_T_STRING:
2496                     return eet_node_string_new(chnk.name, chnk.data);
2497                  case EET_T_INLINED_STRING:
2498                     return eet_node_inlined_string_new(chnk.name, chnk.data);
2499                  case EET_T_NULL:
2500                     return eet_node_null_new(chnk.name);
2501                  default:
2502                     result = eet_node_struct_new(chnk.name, NULL);
2503                 }
2504               break;
2505            case EET_G_VAR_ARRAY:
2506               return eet_node_var_array_new(chnk.name, NULL);
2507            case EET_G_INHERIT:
2508               /* This one should work */
2509               goto error;
2510            case EET_G_LIST:
2511            case EET_G_HASH:
2512            case EET_G_ARRAY:
2513            case EET_G_UNION:
2514            case EET_G_VARIANT:
2515            default:
2516               goto error;
2517           }
2518      }
2519    while (size > 0)
2520      {
2521         Eet_Data_Chunk echnk;
2522         Eet_Data_Element *ede = NULL;
2523         Eet_Node *child = NULL;
2524         int group_type = EET_G_UNKNOWN, type = EET_T_UNKNOW;
2525         int ret = 0;
2526
2527         /* get next data chunk */
2528         memset(&echnk, 0, sizeof(Eet_Data_Chunk));
2529         eet_data_chunk_get(ed, &echnk, p, size);
2530         if (!echnk.name) goto error;
2531         /* FIXME: don't REPLY on edd - work without */
2532         if (edd)
2533           {
2534              ede = _eet_descriptor_hash_find(edd, echnk.name, echnk.hash);
2535              if (ede)
2536                {
2537                   group_type = ede->group_type;
2538                   type = ede->type;
2539                   if ((echnk.type == 0) && (echnk.group_type == 0))
2540                     {
2541                        type = ede->type;
2542                        group_type = ede->group_type;
2543                     }
2544                   else
2545                     {
2546                        if (IS_SIMPLE_TYPE(echnk.type) &&
2547                            eet_data_type_match(echnk.type, ede->type))
2548                          /* Needed when converting on the fly from FP to Float */
2549                          type = ede->type;
2550                        else if ((echnk.group_type > EET_G_UNKNOWN) &&
2551                                 (echnk.group_type < EET_G_LAST) &&
2552                                 (echnk.group_type == ede->group_type))
2553                          group_type = echnk.group_type;
2554                     }
2555                }
2556           }
2557         /*...... dump to node */
2558         else
2559           {
2560              type = echnk.type;
2561              group_type = echnk.group_type;
2562           }
2563
2564         if (!edd && group_type == EET_G_UNKNOWN && IS_SIMPLE_TYPE(type))
2565           {
2566              unsigned char dd[128];
2567
2568              ret = eet_data_get_type(ed,
2569                                      type,
2570                                      echnk.data,
2571                                      ((char *)echnk.data) + echnk.size,
2572                                      dd);
2573              if (ret <= 0) goto error;
2574
2575              child = eet_data_node_simple_type(type, echnk.name, dd);
2576
2577              eet_node_struct_append(result, echnk.name, child);
2578           }
2579         else
2580           {
2581              ret = eet_group_codec[group_type - 100].get(context,
2582                                                          ed, edd, ede, &echnk,
2583                                                          type, group_type, ede ? (void*) (((char *)data) + ede->offset) : (void**) &result,
2584                                                          &p, &size);
2585
2586              if (ret <= 0) goto error;
2587           }
2588
2589         /* advance to next chunk */
2590         NEXT_CHUNK(p, size, echnk, ed);
2591      }
2592
2593    _eet_freelist_all_unref(context);
2594    if (!edd)
2595      {
2596         _eet_freelist_str_free(context, edd);
2597         _eet_freelist_direct_str_free(context, edd);
2598         _eet_freelist_list_free(context, edd);
2599         _eet_freelist_hash_free(context, edd);
2600         _eet_freelist_free(context, edd);
2601      }
2602    else
2603      {
2604         _eet_freelist_reset(context);
2605         _eet_freelist_str_reset(context);
2606         _eet_freelist_list_reset(context);
2607         _eet_freelist_hash_reset(context);
2608         _eet_freelist_direct_str_reset(context);
2609      }
2610
2611    if (!edd)
2612      return result;
2613
2614    return data;
2615
2616 error:
2617    eet_node_del(result);
2618
2619    _eet_freelist_all_unref(context);
2620    _eet_freelist_str_free(context, edd);
2621    _eet_freelist_direct_str_free(context, edd);
2622    _eet_freelist_list_free(context, edd);
2623    _eet_freelist_hash_free(context, edd);
2624    _eet_freelist_free(context, edd);
2625
2626    /* FIXME: Warn that something goes wrong here. */
2627    return NULL;
2628 }
2629
2630 static int
2631 eet_data_get_list(Eet_Free_Context *context, const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
2632                   int type, int group_type __UNUSED__, void *data,
2633                   char **p, int *size)
2634 {
2635    Eet_Data_Descriptor *subtype = NULL;
2636    void *list = NULL;
2637    void **ptr;
2638    void *data_ret;
2639
2640    EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0);
2641
2642    if (edd)
2643      {
2644         subtype = ede->subtype;
2645
2646         if (type != ede->type)
2647           return 0;
2648      }
2649
2650    ptr = (void **)data;
2651    list = *ptr;
2652    data_ret = NULL;
2653
2654    if (IS_POINTER_TYPE(type))
2655      {
2656         int ret;
2657
2658         ret = eet_data_get_unknown(context, ed, edd, ede, echnk, type, EET_G_UNKNOWN,
2659                                    &data_ret, p, size);
2660         if (!ret) return 0;
2661      }
2662    else
2663      {
2664         data_ret = _eet_data_descriptor_decode(context, ed, subtype,
2665                                                echnk->data, echnk->size);
2666         if (!data_ret) return 0;
2667      }
2668
2669    if (edd)
2670      {
2671         list = edd->func.list_append(list, data_ret);
2672         *ptr = list;
2673         _eet_freelist_list_add(context, ptr);
2674      }
2675    else
2676      {
2677         eet_node_list_append(*((Eet_Node**) data), echnk->name, data_ret);
2678      }
2679
2680    return 1;
2681 }
2682
2683 static int
2684 eet_data_get_hash(Eet_Free_Context *context, const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
2685                   int type, int group_type __UNUSED__, void *data,
2686                   char **p, int *size)
2687 {
2688    void **ptr;
2689    void *hash = NULL;
2690    char *key = NULL;
2691    void *data_ret = NULL;
2692    int ret = 0;
2693
2694    EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0);
2695
2696    ptr = (void **)data;
2697    hash = *ptr;
2698
2699    /* Read key */
2700    ret = eet_data_get_type(ed,
2701                            EET_T_STRING,
2702                            echnk->data,
2703                            ((char *)echnk->data) + echnk->size,
2704                            &key);
2705    if (ret <= 0) goto on_error;
2706
2707    /* Advance to next chunk */
2708    NEXT_CHUNK((*p), (*size), (*echnk), ed);
2709    memset(echnk, 0, sizeof(Eet_Data_Chunk));
2710
2711    /* Read value */
2712    eet_data_chunk_get(ed, echnk, *p, *size);
2713    if (!echnk->name) goto on_error;
2714
2715    if (IS_POINTER_TYPE(echnk->type))
2716      {
2717         ret = eet_data_get_unknown(context, ed, edd, ede, echnk, echnk->type, EET_G_UNKNOWN,
2718                                    &data_ret, p, size);
2719         if (!ret) goto on_error;
2720      }
2721    else
2722      {
2723         data_ret = _eet_data_descriptor_decode(context,
2724                                                ed,
2725                                                ede ? ede->subtype : NULL,
2726                                                echnk->data,
2727                                                echnk->size);
2728         if (!data_ret) goto on_error;
2729      }
2730
2731    if (edd)
2732      {
2733         hash = edd->func.hash_add(hash, key, data_ret);
2734         *ptr = hash;
2735         _eet_freelist_hash_add(context, hash);
2736      }
2737    else
2738      {
2739         eet_node_hash_add(*((Eet_Node **) data), echnk->name, key, data_ret);
2740      }
2741
2742    return 1;
2743
2744  on_error:
2745    return ret;
2746 }
2747
2748 /* var arrays and fixed arrays have to
2749  * get all chunks at once. for fixed arrays
2750  * we can get each chunk and increment a
2751  * counter stored on the element itself but
2752  * it wont be thread safe. for var arrays
2753  * we still need a way to get the number of
2754  * elements from the data, so storing the
2755  * number of elements and the element data on
2756  * each chunk is pointless.
2757  */
2758 static int
2759 eet_data_get_array(Eet_Free_Context *context, const Eet_Dictionary *ed, Eet_Data_Descriptor *edd,
2760                    Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
2761                    int type, int group_type, void *data,
2762                    char **p, int *size)
2763 {
2764    Eina_List *childs = NULL;
2765    const char *name;
2766    Eet_Node *tmp;
2767    void *ptr;
2768    int count;
2769    int ret;
2770    int subsize = 0;
2771    int i;
2772
2773    EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0);
2774
2775    ptr = data;
2776    /* read the number of elements */
2777    ret = eet_data_get_type(ed,
2778                            EET_T_INT,
2779                            echnk->data,
2780                            ((char *)echnk->data) + echnk->size,
2781                            &count);
2782    if (ret <= 0) return ret;
2783
2784    name = echnk->name;
2785
2786    if (ede)
2787      {
2788         if (IS_POINTER_TYPE(type))
2789           subsize = eet_basic_codec[ede->type].size;
2790         else
2791           subsize = ede->subtype->size;
2792
2793         if (group_type == EET_G_VAR_ARRAY)
2794           {
2795              /* store the number of elements
2796               * on the counter offset */
2797              *(int *)(((char *)data) + ede->count - ede->offset) = count;
2798              /* allocate space for the array of elements */
2799              *(void **)ptr = edd->func.mem_alloc(count * subsize);
2800
2801              if (!*(void **)ptr) return 0;
2802
2803              memset(*(void **)ptr, 0, count * subsize);
2804
2805              _eet_freelist_add(context, *(void **)ptr);
2806           }
2807      }
2808
2809    /* get all array elements */
2810    for (i = 0; i < count; i++)
2811      {
2812         void *dst = NULL;
2813         void *data_ret = NULL;
2814
2815         /* Advance to next chunk */
2816         NEXT_CHUNK((*p), (*size), (*echnk), ed);
2817         memset(echnk, 0, sizeof(Eet_Data_Chunk));
2818
2819         eet_data_chunk_get(ed, echnk, *p, *size);
2820         if (!echnk->name || strcmp(echnk->name, name) != 0) goto on_error;
2821         /* get the data */
2822
2823         if (echnk->group_type != group_type
2824             || (echnk->type != type && echnk->type != EET_T_NULL))
2825           goto on_error;
2826
2827         if (ede)
2828           if (ede->group_type != echnk->group_type
2829               || (echnk->type != ede->type && echnk->type != EET_T_NULL))
2830             goto on_error;
2831
2832         /* get the destination pointer */
2833         if (ede)
2834           {
2835              if (group_type == EET_G_ARRAY)
2836                dst = (char *)ptr + (subsize * i);
2837              else
2838                dst = *(char **)ptr + (subsize * i);
2839           }
2840
2841         if (IS_POINTER_TYPE(echnk->type))
2842           {
2843              ret = eet_data_get_unknown(context, ed, edd, ede, echnk, echnk->type, EET_G_UNKNOWN,
2844                                         &data_ret, p, size);
2845              if (!ret) goto on_error;
2846              if (dst) memcpy(dst, &data_ret, subsize);
2847              if (!edd) childs = eina_list_append(childs, data_ret);
2848           }
2849         else
2850           {
2851              data_ret = _eet_data_descriptor_decode(context, ed, ede ? ede->subtype : NULL,
2852                                                     echnk->data, echnk->size);
2853              if (!data_ret) goto on_error;
2854              if (dst)
2855                {
2856                   memcpy(dst, data_ret, subsize);
2857                   _eet_freelist_add(context, data_ret);
2858                }
2859              if (!edd) childs = eina_list_append(childs, data_ret);
2860           }
2861      }
2862
2863    if (!edd)
2864      {
2865         Eet_Node *parent = *((Eet_Node **) data);
2866         Eet_Node *array;
2867
2868         if (group_type == EET_G_ARRAY)
2869           array = eet_node_array_new(name, count, childs);
2870         else
2871           array = eet_node_var_array_new(name, childs);
2872
2873         if (!array) goto on_error;
2874
2875         eet_node_struct_append(parent, name, array);
2876      }
2877
2878    return 1;
2879
2880  on_error:
2881    EINA_LIST_FREE(childs, tmp)
2882      eet_node_del(tmp);
2883
2884    return 0;
2885 }
2886
2887 static void
2888 eet_data_put_union(Eet_Dictionary *ed,
2889                    __UNUSED__ Eet_Data_Descriptor *edd,
2890                    Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in)
2891 {
2892    const char *union_type;
2893    int i;
2894
2895    EET_ASSERT(!((ede->type != EET_T_UNKNOW) || (!ede->subtype)), return );
2896
2897    union_type = ede->subtype->func.type_get(((char*) data_in) + ede->count - ede->offset,
2898                                             NULL);
2899
2900    if (!union_type) return ;
2901
2902    /* Search the structure of the union to encode. */
2903    for (i = 0; i < ede->subtype->elements.num; ++i)
2904      if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0)
2905        {
2906           Eet_Data_Element *sede;
2907           void *data;
2908           int size;
2909
2910           /* Yeah we found it ! */
2911           data = eet_data_put_type(ed, EET_T_STRING, &union_type, &size);
2912           if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
2913
2914           sede = &(ede->subtype->elements.set[i]);
2915           data = _eet_data_descriptor_encode(ed,
2916                                              sede->subtype,
2917                                              data_in,
2918                                              &size);
2919           if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
2920           break;
2921        }
2922 }
2923
2924 static int
2925 eet_data_get_union(Eet_Free_Context *context, const Eet_Dictionary *ed,
2926                    __UNUSED__ Eet_Data_Descriptor *edd,
2927                    Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
2928                    int type, int group_type, void *data,
2929                    char **p, int *size)
2930 {
2931    const char *union_type;
2932    void *data_ret = NULL;
2933    int ret = 0;
2934    int i;
2935
2936    /* Read type */
2937    ret = eet_data_get_type(ed,
2938                            EET_T_STRING,
2939                            echnk->data,
2940                            ((char *)echnk->data) + echnk->size,
2941                            &union_type);
2942    if (ret <= 0) goto on_error;
2943
2944    /* Advance to next chunk */
2945    NEXT_CHUNK((*p), (*size), (*echnk), ed);
2946    memset(echnk, 0, sizeof(Eet_Data_Chunk));
2947
2948    /* Read value */
2949    eet_data_chunk_get(ed, echnk, *p, *size);
2950    if (!echnk->name) goto on_error;
2951
2952    if (ede)
2953      {
2954         EET_ASSERT(!(ede->group_type != group_type || ede->type != type), goto on_error);
2955
2956         /* Search the structure of the union to decode */
2957         for (i = 0; i < ede->subtype->elements.num; ++i)
2958           if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0)
2959             {
2960                Eet_Data_Element *sede;
2961
2962                /* Yeah we found it ! */
2963                sede = &(ede->subtype->elements.set[i]);
2964                EET_ASSERT(sede->subtype, goto on_error);
2965
2966                data_ret = _eet_data_descriptor_decode(context,
2967                                                       ed,
2968                                                       sede->subtype,
2969                                                       echnk->data,
2970                                                       echnk->size);
2971                if (!data_ret) goto on_error;
2972
2973                /* Memcopy the structure content to remove pointer indirection. */
2974                memcpy(data, data_ret, sede->subtype->size);
2975
2976                /* data_ret is now useless. */
2977                sede->subtype->func.mem_free(data_ret);
2978
2979                /* Set union type. */
2980                if ((!ed) || (!ede->subtype->func.str_direct_alloc))
2981                  {
2982                     union_type = ede->subtype->func.str_alloc(union_type);
2983                     _eet_freelist_str_add(context, (char*) union_type);
2984                  }
2985                else
2986                  {
2987                     union_type = ede->subtype->func.str_direct_alloc(union_type);
2988                     _eet_freelist_direct_str_add(context, (char*) union_type);
2989                  }
2990
2991                ede->subtype->func.type_set(union_type,
2992                                            ((char*) data) + ede->count - ede->offset,
2993                                            EINA_FALSE);
2994
2995                break;
2996             }
2997      }
2998    else
2999      {
3000         /* FIXME: generate node structure. */
3001         data_ret = _eet_data_descriptor_decode(context,
3002                                                ed, NULL,
3003                                                echnk->data, echnk->size);
3004         goto on_error;
3005      }
3006
3007    return 1;
3008
3009  on_error:
3010    return 0;
3011 }
3012
3013 static void
3014 eet_data_put_inherit(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede,
3015                      Eet_Data_Stream *ds, void *data_in)
3016 {
3017    /* FIXME */
3018    fprintf(stderr, "wrong !!!\n");
3019 }
3020
3021 static int
3022 eet_data_get_inherit(Eet_Free_Context *context, const Eet_Dictionary *ed, Eet_Data_Descriptor *edd,
3023                      Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
3024                      int type, int group_type, void *data,
3025                      char **p, int *size)
3026 {
3027    /* FIXME */
3028    return 0;
3029 }
3030
3031 static void
3032 eet_data_put_variant(Eet_Dictionary *ed,
3033                      __UNUSED__ Eet_Data_Descriptor *edd,
3034                      Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in)
3035 {
3036    const char *union_type;
3037    void *data;
3038    Eina_Bool unknow = EINA_FALSE;
3039    int size;
3040    int i;
3041
3042    EET_ASSERT(!((ede->type != EET_T_UNKNOW) || (!ede->subtype)), return );
3043
3044    union_type = ede->subtype->func.type_get(((char*) data_in) + ede->count - ede->offset,
3045                                             &unknow);
3046
3047    if (!union_type && unknow == EINA_FALSE) return ;
3048
3049    if (unknow)
3050      {
3051         /* Handle opaque internal representation */
3052         Eet_Variant_Unknow *evu;
3053
3054         data = eet_data_put_type(ed, EET_T_STRING, &union_type, &size);
3055         if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
3056
3057         evu = (Eet_Variant_Unknow*) data_in;
3058         if (evu && EINA_MAGIC_CHECK(evu, EET_MAGIC_VARIANT))
3059           eet_data_encode(ed, ds, evu->data, ede->name, evu->size, ede->type, ede->group_type);
3060      }
3061    else
3062      {
3063         /* Search the structure of the union to encode. */
3064         for (i = 0; i < ede->subtype->elements.num; ++i)
3065           if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0)
3066             {
3067                Eet_Data_Element *sede;
3068
3069                /* Yeah we found it ! */
3070                data = eet_data_put_type(ed, EET_T_STRING, &union_type, &size);
3071                if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
3072
3073                sede = &(ede->subtype->elements.set[i]);
3074
3075                if (sede->group_type != EET_G_UNKNOWN)
3076                  {
3077                     Eet_Data_Stream *lds;
3078
3079                     lds = eet_data_stream_new();
3080                     eet_group_codec[sede->group_type - 100].put(ed,
3081                                                                 sede->subtype,
3082                                                                 sede,
3083                                                                 lds,
3084                                                                 data_in);
3085                     if (lds->size != 0)
3086                       {
3087                          eet_data_encode(ed, ds, lds->data, ede->name, lds->pos,
3088                                          ede->type, ede->group_type);
3089
3090                          lds->data = NULL;
3091                          lds->size = 0;
3092                       }
3093                     else
3094                       {
3095                          eet_data_encode(ed, ds, NULL, ede->name, 0,
3096                                          EET_T_NULL, ede->group_type);
3097                       }
3098
3099                     eet_data_stream_free(lds);
3100                  }
3101                else
3102                  {
3103                     data = _eet_data_descriptor_encode(ed,
3104                                                        sede->subtype,
3105                                                        *(void**)data_in,
3106                                                        &size);
3107                     if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
3108                  }
3109
3110                break;
3111             }
3112      }
3113 }
3114
3115 static int
3116 eet_data_get_variant(Eet_Free_Context *context, const Eet_Dictionary *ed,
3117                      __UNUSED__ Eet_Data_Descriptor *edd,
3118                      Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
3119                      int type, int group_type, void *data,
3120                      char **p, int *size)
3121 {
3122    const char *union_type;
3123    void *data_ret = NULL;
3124    int ret = 0;
3125    int i;
3126
3127    /* Read type */
3128    ret = eet_data_get_type(ed,
3129                            EET_T_STRING,
3130                            echnk->data,
3131                            ((char *)echnk->data) + echnk->size,
3132                            &union_type);
3133    if (ret <= 0) goto on_error;
3134
3135    /* Advance to next chunk */
3136    NEXT_CHUNK((*p), (*size), (*echnk), ed);
3137    memset(echnk, 0, sizeof(Eet_Data_Chunk));
3138
3139    /* Read value */
3140    eet_data_chunk_get(ed, echnk, *p, *size);
3141    if (!echnk->name) goto on_error;
3142
3143    if (ede)
3144      {
3145         EET_ASSERT(ede->subtype, goto on_error);
3146
3147         if ((!ed) || (!ede->subtype->func.str_direct_alloc))
3148           {
3149              union_type = ede->subtype->func.str_alloc(union_type);
3150              _eet_freelist_str_add(context, (char*) union_type);
3151           }
3152         else
3153           {
3154              union_type = ede->subtype->func.str_direct_alloc(union_type);
3155              _eet_freelist_direct_str_add(context, (char*) union_type);
3156           }
3157
3158         /* Search the structure of the union to decode */
3159         for (i = 0; i < ede->subtype->elements.num; ++i)
3160           if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0)
3161             {
3162                Eet_Data_Element *sede;
3163
3164                /* Yeah we found it ! */
3165                sede = &(ede->subtype->elements.set[i]);
3166
3167                if (sede->group_type != EET_G_UNKNOWN)
3168                  {
3169                     Eet_Data_Chunk chnk;
3170                     char *p2;
3171                     int size2;
3172                     int ret;
3173
3174                     p2 = echnk->data;
3175                     size2 = echnk->size;
3176
3177                     /* Didn't find a proper way to provide this
3178                        without duplicating code */
3179                     while (size2 > 0)
3180                       {
3181                          memset(&chnk, 0, sizeof(Eet_Data_Chunk));
3182                          eet_data_chunk_get(ed, &chnk, p2, size2);
3183
3184                          if (!chnk.name) goto on_error;
3185
3186                          ret = eet_group_codec[sede->group_type - 100].get(context,
3187                                                                            ed, sede->subtype,
3188                                                                            sede, &chnk,
3189                                                                            sede->type, sede->group_type,
3190                                                                            data, &p2, &size2);
3191
3192                          if (ret <= 0) goto on_error;
3193
3194                          /* advance to next chunk */
3195                          NEXT_CHUNK(p2, size2, chnk, ed);
3196                       }
3197
3198                     /* Put garbage so that we will not put eet_variant_unknow in it */
3199                     data_ret = (void*) data;
3200
3201                     /* Set variant type. */
3202                     ede->subtype->func.type_set(union_type,
3203                                                 ((char*) data) + ede->count - ede->offset,
3204                                                 EINA_FALSE);
3205                     break;
3206                  }
3207
3208                data_ret = _eet_data_descriptor_decode(context,
3209                                                       ed,
3210                                                       sede->subtype,
3211                                                       echnk->data,
3212                                                       echnk->size);
3213                if (!data_ret) break;
3214
3215                /* And point to the variant data. */
3216                *(void**) data = data_ret;
3217
3218                /* Set variant type. */
3219                ede->subtype->func.type_set(union_type,
3220                                            ((char*) data) + ede->count - ede->offset,
3221                                            EINA_FALSE);
3222                break;
3223             }
3224
3225         if (!data_ret)
3226           {
3227              Eet_Variant_Unknow *evu;
3228
3229              evu = calloc(1, sizeof (Eet_Variant_Unknow) + echnk->size - 1);
3230              if (!evu) goto on_error;
3231
3232              evu->size = echnk->size;
3233              memcpy(evu->data, echnk->data, evu->size);
3234              EINA_MAGIC_SET(evu, EET_MAGIC_VARIANT);
3235
3236              /* And point to the opaque internal data scructure */
3237              *(void**) data = evu;
3238
3239              /* Set variant type. */
3240              ede->subtype->func.type_set(union_type,
3241                                          ((char*) data) + ede->count - ede->offset,
3242                                          EINA_TRUE);
3243           }
3244      }
3245    else
3246      {
3247         /* FIXME: dump node structure. */
3248         data_ret = _eet_data_descriptor_decode(context,
3249                                                ed, NULL,
3250                                                echnk->data, echnk->size);
3251         goto on_error;
3252      }
3253
3254    return 1;
3255
3256  on_error:
3257    return 0;
3258 }
3259
3260 static Eet_Node *
3261 eet_data_node_simple_type(int type, const char *name, void *dd)
3262 {
3263 #ifdef EET_T_TYPE
3264 # undef EET_T_TYPE
3265 #endif
3266
3267 #define EET_T_TYPE(Eet_Type, Eet_Node_Type, Type)                       \
3268    case Eet_Type:                                                       \
3269      return eet_node_##Eet_Node_Type##_new(name, *((Type *) dd));       \
3270
3271    switch (type)
3272      {
3273         EET_T_TYPE(EET_T_CHAR, char, char);
3274         EET_T_TYPE(EET_T_SHORT, short, short);
3275         EET_T_TYPE(EET_T_INT, int, int);
3276         EET_T_TYPE(EET_T_LONG_LONG, long_long, long long);
3277         EET_T_TYPE(EET_T_FLOAT, float, float);
3278         EET_T_TYPE(EET_T_DOUBLE, double, double);
3279         EET_T_TYPE(EET_T_UCHAR, unsigned_char, unsigned char);
3280         EET_T_TYPE(EET_T_USHORT, unsigned_short, unsigned short);
3281         EET_T_TYPE(EET_T_UINT, unsigned_int, unsigned int);
3282         EET_T_TYPE(EET_T_ULONG_LONG, unsigned_long_long, unsigned long long);
3283         EET_T_TYPE(EET_T_STRING, string, char*);
3284         EET_T_TYPE(EET_T_INLINED_STRING, inlined_string, char*);
3285       case EET_T_NULL:
3286          return eet_node_null_new(name);
3287       default:
3288          ERR("Unknow type passed to eet_data_node_simple_type");
3289          return NULL;
3290      }
3291 }
3292
3293 static int
3294 eet_data_get_unknown(Eet_Free_Context *context, const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
3295                      int type, int group_type __UNUSED__, void *data,
3296                      char **p __UNUSED__, int *size __UNUSED__)
3297 {
3298    int ret;
3299    void *data_ret;
3300
3301    if (IS_SIMPLE_TYPE(type))
3302      {
3303         unsigned char dd[128];
3304
3305         ret = eet_data_get_type(ed, type, echnk->data, ((char *)echnk->data) + echnk->size, edd ? (char*) data : (char*) dd);
3306         if (ret <= 0) return ret;
3307
3308         if (!edd)
3309           {
3310              Eet_Node **parent = data;
3311              Eet_Node *node;
3312
3313              node = eet_data_node_simple_type(type, echnk->name, dd);
3314
3315              if (*parent) eet_node_struct_append(*parent, echnk->name, node);
3316              else *parent = node;
3317           }
3318         else
3319           {
3320              if (type == EET_T_STRING)
3321                {
3322                   char **str;
3323
3324                   str = (char **)(((char *)data));
3325                   if (*str)
3326                     {
3327                        if ((ed == NULL) || (edd->func.str_direct_alloc == NULL))
3328                          {
3329                             *str = edd->func.str_alloc(*str);
3330                             _eet_freelist_str_add(context, *str);
3331                          }
3332                        else
3333                          {
3334                             *str = edd->func.str_direct_alloc(*str);
3335                             _eet_freelist_direct_str_add(context, *str);
3336                          }
3337                     }
3338                }
3339              else if (edd && type == EET_T_INLINED_STRING)
3340                {
3341                   char **str;
3342
3343                   str = (char **)(((char *)data));
3344                   if (*str)
3345                     {
3346                        *str = edd->func.str_alloc(*str);
3347                        _eet_freelist_str_add(context, *str);
3348                     }
3349                }
3350           }
3351      }
3352    else
3353      {
3354         Eet_Data_Descriptor *subtype;
3355
3356         subtype = ede ? ede->subtype : NULL;
3357
3358         if (subtype || !edd)
3359           {
3360              Eet_Node **parent = data;
3361              void **ptr;
3362
3363              data_ret = _eet_data_descriptor_decode(context, ed, subtype, echnk->data, echnk->size);
3364              if (!data_ret) return 0;
3365
3366              if (edd)
3367                {
3368                   ptr = (void **)(((char *)data));
3369                   *ptr = (void *)data_ret;
3370                }
3371              else
3372                {
3373                   Eet_Node *node = data_ret;
3374
3375                   if (*parent)
3376                     {
3377                        node = eet_node_struct_child_new(echnk->name, node);
3378                        eet_node_struct_append(*parent, echnk->name, node);
3379                     }
3380                   else *parent = node;
3381                }
3382           }
3383      }
3384
3385    return 1;
3386 }
3387
3388 static void
3389 eet_data_put_array(Eet_Dictionary *ed, Eet_Data_Descriptor *edd __UNUSED__, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in)
3390 {
3391    void *data;
3392    int offset = 0;
3393    int subsize;
3394    int count;
3395    int size;
3396    int j;
3397
3398    EET_ASSERT(!((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING)), return );
3399
3400    if (ede->group_type == EET_G_ARRAY)
3401      count = ede->counter_offset;
3402    else
3403      count = *(int *)(((char *)data_in) + ede->count - ede->offset);
3404
3405    if (count <= 0) return;
3406    /* Store number of elements */
3407    data = eet_data_put_type(ed, EET_T_INT, &count, &size);
3408    if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
3409
3410    if (IS_POINTER_TYPE(ede->type))
3411      subsize = eet_basic_codec[ede->type].size;
3412    else
3413      subsize = ede->subtype->size;
3414
3415    for (j = 0; j < count; j++)
3416      {
3417         void *d;
3418         int pos = ds->pos;
3419
3420         if (ede->group_type == EET_G_ARRAY)
3421           d = (void *)(((char *)data_in) + offset);
3422         else
3423           d = *(((char **)data_in)) + offset;
3424
3425         if (IS_POINTER_TYPE(ede->type))
3426           {
3427              if (*(char**) d)
3428                eet_data_put_unknown(ed, NULL, ede, ds, d);
3429           }
3430         else
3431           {
3432              data = _eet_data_descriptor_encode(ed, ede->subtype, d, &size);
3433              if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
3434           }
3435
3436         if (pos == ds->pos)
3437           {
3438              /* Add a NULL element just to have the correct array layout. */
3439              eet_data_encode(ed, ds, NULL, ede->name, 0, EET_T_NULL, ede->group_type);
3440           }
3441
3442         offset += subsize;
3443      }
3444 }
3445
3446 static void
3447 eet_data_put_unknown(Eet_Dictionary *ed, Eet_Data_Descriptor *edd __UNUSED__, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in)
3448 {
3449    void *data = NULL;
3450    int size;
3451
3452    if (IS_SIMPLE_TYPE(ede->type))
3453      data = eet_data_put_type(ed, ede->type, data_in, &size);
3454    else if (ede->subtype)
3455      {
3456         if (*((char **)data_in))
3457           data = _eet_data_descriptor_encode(ed,
3458                                              ede->subtype,
3459                                              *((char **)((char *)(data_in))),
3460                                              &size);
3461      }
3462    if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
3463 }
3464
3465 static void
3466 eet_data_put_list(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in)
3467 {
3468    void *data;
3469    void *l;
3470    int size;
3471
3472    EET_ASSERT(!(((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING))
3473                 || ((ede->type > EET_T_NULL) && (ede->type < EET_T_LAST))),
3474               return );
3475
3476    l = *((void **)(((char *)data_in)));
3477    for (; l; l = edd->func.list_next(l))
3478      {
3479         if (IS_POINTER_TYPE(ede->type))
3480           {
3481              const void *str = edd->func.list_data(l);
3482              eet_data_put_unknown(ed, NULL, ede, ds, &str);
3483           }
3484         else
3485           {
3486              data = _eet_data_descriptor_encode(ed,
3487                                                 ede->subtype,
3488                                                 edd->func.list_data(l),
3489                                                 &size);
3490              if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
3491           }
3492      }
3493 }
3494
3495 static void
3496 eet_data_put_hash(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in)
3497 {
3498    Eet_Data_Encode_Hash_Info fdata;
3499    void *l;
3500
3501    l = *((void **)(((char *)data_in)));
3502    fdata.ds = ds;
3503    fdata.ede = ede;
3504    fdata.ed = ed;
3505    edd->func.hash_foreach(l, eet_data_descriptor_encode_hash_cb, &fdata);
3506 }
3507
3508 EAPI int
3509 eet_data_dump_cipher(Eet_File *ef,
3510                      const char *name, const char *cipher_key,
3511                      void (*dumpfunc) (void *data, const char *str),
3512                      void *dumpdata)
3513 {
3514    const Eet_Dictionary *ed = NULL;
3515    const void           *data = NULL;
3516    Eet_Node             *result;
3517    Eet_Free_Context      context;
3518    int                   required_free = 0;
3519    int                   size;
3520
3521    ed = eet_dictionary_get(ef);
3522
3523    if (!cipher_key)
3524      data = eet_read_direct(ef, name, &size);
3525    if (!data)
3526      {
3527         required_free = 1;
3528         data = eet_read_cipher(ef, name, &size, cipher_key);
3529         if (!data) return 0;
3530      }
3531
3532    memset(&context, 0, sizeof (context));
3533    result = _eet_data_descriptor_decode(&context, ed, NULL, data, size);
3534
3535    eet_node_dump(result, 0, dumpfunc, dumpdata);
3536
3537    eet_node_del(result);
3538
3539    if (required_free)
3540      free((void*)data);
3541
3542    return result ? 1 : 0;
3543 }
3544
3545 EAPI int
3546 eet_data_dump(Eet_File *ef,
3547               const char *name,
3548               void (*dumpfunc) (void *data, const char *str),
3549               void *dumpdata)
3550 {
3551    return eet_data_dump_cipher(ef, name, NULL, dumpfunc, dumpdata);
3552 }
3553
3554
3555 EAPI int
3556 eet_data_text_dump_cipher(const void *data_in,
3557                           const char *cipher_key, int size_in,
3558                           void (*dumpfunc) (void *data, const char *str),
3559                           void *dumpdata)
3560 {
3561    void *ret = NULL;
3562    Eet_Node *result;
3563    Eet_Free_Context context;
3564    unsigned int ret_len = 0;
3565
3566    if (!data_in) return 0;
3567
3568    if (cipher_key)
3569      {
3570        if (eet_decipher(data_in, size_in, cipher_key,
3571                         strlen(cipher_key), &ret, &ret_len))
3572          {
3573            if (ret) free(ret);
3574            return 0;
3575          }
3576      }
3577    else
3578      {
3579         ret = (void*) data_in;
3580         ret_len = size_in;
3581      }
3582
3583    memset(&context, 0, sizeof (context));
3584    result = _eet_data_descriptor_decode(&context, NULL, NULL, ret, ret_len);
3585
3586    eet_node_dump(result, 0, dumpfunc, dumpdata);
3587
3588    eet_node_del(result);
3589    if (cipher_key) free(ret);
3590
3591    return result ? 1 : 0;
3592 }
3593
3594 EAPI int
3595 eet_data_text_dump(const void *data_in,
3596                    int size_in,
3597                    void (*dumpfunc) (void *data, const char *str),
3598                    void *dumpdata)
3599 {
3600    return eet_data_text_dump_cipher(data_in, NULL, size_in, dumpfunc, dumpdata);
3601 }
3602
3603 EAPI void *
3604 eet_data_text_undump_cipher(const char *text,
3605                             const char *cipher_key,
3606                             int textlen,
3607                             int *size_ret)
3608 {
3609    void *ret = NULL;
3610
3611    ret = _eet_data_dump_parse(NULL, size_ret, text, textlen);
3612    if (ret && cipher_key)
3613      {
3614         void *ciphered = NULL;
3615         unsigned int ciphered_len;
3616
3617         if (eet_cipher(ret, *size_ret, cipher_key,
3618                        strlen(cipher_key), &ciphered, &ciphered_len))
3619           {
3620              if (ciphered) free(ciphered);
3621              size_ret = 0;
3622              free(ret);
3623              return NULL;
3624           }
3625         free(ret);
3626         *size_ret = ciphered_len;
3627         ret = ciphered;
3628      }
3629    return ret;
3630 }
3631
3632 EAPI void *
3633 eet_data_text_undump(const char *text,
3634                      int textlen,
3635                      int *size_ret)
3636 {
3637    return eet_data_text_undump_cipher(text, NULL, textlen, size_ret);
3638 }
3639
3640 EAPI int
3641 eet_data_undump_cipher(Eet_File *ef,
3642                        const char *name,
3643                        const char *cipher_key,
3644                        const char *text,
3645                        int textlen,
3646                        int compress)
3647 {
3648    Eet_Dictionary       *ed;
3649    void                 *data_enc;
3650    int                   size;
3651    int                   val;
3652
3653    ed = eet_dictionary_get(ef);
3654
3655    data_enc = _eet_data_dump_parse(ed, &size, text, textlen);
3656    if (!data_enc) return 0;
3657    val = eet_write_cipher(ef, name, data_enc, size, compress, cipher_key);
3658    free(data_enc);
3659    return val;
3660 }
3661
3662 EAPI int
3663 eet_data_undump(Eet_File *ef,
3664                 const char *name,
3665                 const char *text,
3666                 int textlen,
3667                 int compress)
3668 {
3669    return eet_data_undump_cipher(ef, name, NULL, text, textlen, compress);
3670 }
3671
3672 EAPI void *
3673 eet_data_descriptor_decode_cipher(Eet_Data_Descriptor *edd,
3674                                   const void *data_in,
3675                                   const char *cipher_key,
3676                                   int size_in)
3677 {
3678    void *deciphered = (void*) data_in;
3679    void *ret;
3680    Eet_Free_Context context;
3681    unsigned int deciphered_len = size_in;
3682
3683    if (cipher_key && data_in)
3684      {
3685        if (eet_decipher(data_in, size_in, cipher_key,
3686                         strlen(cipher_key), &deciphered, &deciphered_len))
3687          {
3688            if (deciphered) free(deciphered);
3689            return NULL;
3690          }
3691      }
3692
3693    memset(&context, 0, sizeof (context));
3694    ret = _eet_data_descriptor_decode(&context, NULL, edd, deciphered, deciphered_len);
3695
3696    if (data_in != deciphered) free(deciphered);
3697
3698    return ret;
3699 }
3700
3701 EAPI void *
3702 eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
3703                            const void *data_in,
3704                            int size_in)
3705 {
3706    return eet_data_descriptor_decode_cipher(edd, data_in, NULL, size_in);
3707 }
3708
3709 EAPI Eet_Node *
3710 eet_data_node_decode_cipher(const void *data_in, const char *cipher_key, int size_in)
3711 {
3712    void *deciphered = (void*) data_in;
3713    Eet_Node *ret;
3714    Eet_Free_Context context;
3715    unsigned int deciphered_len = size_in;
3716
3717    if (cipher_key && data_in)
3718      {
3719        if (eet_decipher(data_in, size_in, cipher_key,
3720                         strlen(cipher_key), &deciphered, &deciphered_len))
3721          {
3722            if (deciphered) free(deciphered);
3723            return NULL;
3724          }
3725      }
3726
3727    memset(&context, 0, sizeof (context));
3728    ret = _eet_data_descriptor_decode(&context, NULL, NULL, deciphered, deciphered_len);
3729
3730    if (data_in != deciphered) free(deciphered);
3731
3732    return ret;
3733 }
3734
3735 static void *
3736 _eet_data_descriptor_encode(Eet_Dictionary *ed,
3737                             Eet_Data_Descriptor *edd,
3738                             const void *data_in,
3739                             int *size_ret)
3740 {
3741    Eet_Data_Stream      *ds;
3742    Eet_Data_Chunk       *chnk;
3743    void                 *cdata;
3744    int                   csize;
3745    int                   i;
3746
3747    if (_eet_data_words_bigendian == -1)
3748      {
3749         unsigned long int v;
3750
3751         v = htonl(0x12345678);
3752         if (v == 0x12345678) _eet_data_words_bigendian = 1;
3753         else _eet_data_words_bigendian = 0;
3754      }
3755
3756    ds = eet_data_stream_new();
3757    for (i = 0; i < edd->elements.num; i++)
3758      {
3759         Eet_Data_Element *ede;
3760
3761         ede = &(edd->elements.set[i]);
3762         eet_group_codec[ede->group_type - 100].put(ed, edd, ede, ds, ((char *)data_in) + ede->offset);
3763      }
3764    chnk = eet_data_chunk_new(ds->data, ds->pos, edd->name, EET_T_UNKNOW, EET_G_UNKNOWN);
3765    ds->data = NULL;
3766    ds->size = 0;
3767    eet_data_stream_free(ds);
3768
3769    ds = eet_data_stream_new();
3770    eet_data_chunk_put(ed, chnk, ds);
3771    cdata = ds->data;
3772    csize = ds->pos;
3773
3774    ds->data = NULL;
3775    ds->size = 0;
3776    eet_data_stream_free(ds);
3777    *size_ret = csize;
3778
3779    free(chnk->data);
3780    eet_data_chunk_free(chnk);
3781
3782    return cdata;
3783 }
3784
3785 EAPI int
3786 eet_data_node_write_cipher(Eet_File *ef, const char *name, const char *cipher_key, Eet_Node *node, int compress)
3787 {
3788    Eet_Dictionary       *ed;
3789    void                 *data_enc;
3790    int                   size;
3791    int                   val;
3792
3793    ed = eet_dictionary_get(ef);
3794
3795    data_enc = _eet_data_dump_encode(EET_G_UNKNOWN, ed, node, &size);
3796    if (!data_enc) return 0;
3797    val = eet_write_cipher(ef, name, data_enc, size, compress, cipher_key);
3798    free(data_enc);
3799    return val;
3800 }
3801
3802 EAPI void *
3803 eet_data_node_encode_cipher(Eet_Node *node,
3804                             const char *cipher_key,
3805                             int *size_ret)
3806 {
3807    void *ret = NULL;
3808    void *ciphered = NULL;
3809    unsigned int ciphered_len = 0;
3810    int size;
3811
3812    ret = _eet_data_dump_encode(EET_G_UNKNOWN, NULL, node, &size);
3813    if (cipher_key && ret)
3814      {
3815         if (eet_cipher(ret, size, cipher_key,
3816                        strlen(cipher_key), &ciphered, &ciphered_len))
3817           {
3818              if (ciphered) free(ciphered);
3819              if (size_ret) *size_ret = 0;
3820              free(ret);
3821              return NULL;
3822           }
3823         free(ret);
3824         size = (int) ciphered_len;
3825         ret = ciphered;
3826      }
3827
3828    if (size_ret) *size_ret = size;
3829    return ret;
3830 }
3831
3832 EAPI void *
3833 eet_data_descriptor_encode_cipher(Eet_Data_Descriptor *edd,
3834                                   const void *data_in,
3835                                   const char *cipher_key,
3836                                   int *size_ret)
3837 {
3838    void *ret = NULL;
3839    void *ciphered = NULL;
3840    unsigned int ciphered_len = 0;
3841    int size;
3842
3843    ret = _eet_data_descriptor_encode(NULL, edd, data_in, &size);
3844    if (cipher_key && ret)
3845      {
3846        if (eet_cipher(ret, size, cipher_key,
3847                       strlen(cipher_key), &ciphered, &ciphered_len))
3848          {
3849            if (ciphered) free(ciphered);
3850            if (size_ret) *size_ret = 0;
3851            free(ret);
3852            return NULL;
3853          }
3854        free(ret);
3855        size = ciphered_len;
3856        ret = ciphered;
3857      }
3858
3859    if (size_ret) *size_ret = size;
3860    return ret;
3861 }
3862
3863 EAPI void *
3864 eet_data_descriptor_encode(Eet_Data_Descriptor *edd,
3865                            const void *data_in,
3866                            int *size_ret)
3867 {
3868    return eet_data_descriptor_encode_cipher(edd, data_in, NULL, size_ret);
3869 }