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