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