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