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