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