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