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