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