EINA_MAGIC is already defined with a ';'. Remove it to fix
[framework/uifw/eet.git] / src / lib / eet_data.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif /* ifdef HAVE_CONFIG_H */
4
5 #include <stdio.h>
6 #include <string.h>
7 #include <math.h>
8 #include <ctype.h>
9 #include <limits.h>
10
11 #ifdef HAVE_NETINET_IN_H
12 # include <netinet/in.h>
13 #endif /* ifdef HAVE_NETINET_IN_H */
14
15 #ifdef _WIN32
16 # include <winsock2.h>
17 #endif /* ifdef _WIN32 */
18
19 #include <Eina.h>
20
21 #include "Eet.h"
22 #include "Eet_private.h"
23
24 /*
25  * routines for doing data -> struct and struct -> data conversion
26  *
27  * types:
28  *
29  * basic types:
30  *   a sequence of...
31  *
32  *   char
33  *   short
34  *   int
35  *   long long
36  *   float
37  *   double
38  *   unsigned char
39  *   unsigned short
40  *   unsigned int
41  *   unsgined long long
42  *   string
43  *
44  * groupings:
45  *   multiple entries ordered as...
46  *
47  *   fixed size array    [ of basic types ]
48  *   variable size array [ of basic types ]
49  *   linked list         [ of basic types ]
50  *   hash table          [ of basic types ]
51  *
52  * need to provide builder/accessor funcs for:
53  *
54  *   list_next
55  *   list_append
56  *
57  *   hash_foreach
58  *   hash_add
59  *
60  */
61
62 /*---*/
63
64 typedef struct _Eet_Data_Element            Eet_Data_Element;
65 typedef struct _Eet_Data_Basic_Type_Codec   Eet_Data_Basic_Type_Codec;
66 typedef struct _Eet_Data_Group_Type_Codec   Eet_Data_Group_Type_Codec;
67 typedef struct _Eet_Data_Chunk              Eet_Data_Chunk;
68 typedef struct _Eet_Data_Stream             Eet_Data_Stream;
69 typedef struct _Eet_Data_Descriptor_Hash    Eet_Data_Descriptor_Hash;
70 typedef struct _Eet_Data_Encode_Hash_Info   Eet_Data_Encode_Hash_Info;
71 typedef struct _Eet_Free                    Eet_Free;
72 typedef struct _Eet_Free_Context            Eet_Free_Context;
73 typedef struct _Eet_Variant_Unknow          Eet_Variant_Unknow;
74
75 /*---*/
76
77 /* TODO:
78  * Eet_Data_Basic_Type_Codec (Coder, Decoder)
79  * Eet_Data_Group_Type_Codec (Coder, Decoder)
80  */
81 struct _Eet_Data_Basic_Type_Codec
82 {
83    int         size;
84    const char *name;
85    int         (*get)(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
86    void      * (*put)(Eet_Dictionary *ed, const void *src, int *size_ret);
87 };
88
89 struct _Eet_Data_Group_Type_Codec
90 {
91    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);
92    void (*put)(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
93 };
94
95 struct _Eet_Data_Chunk
96 {
97    char         *name;
98    int           len;
99    int           size;
100    int           hash;
101    void         *data;
102    unsigned char type;
103    unsigned char group_type;
104 };
105
106 struct _Eet_Data_Stream
107 {
108    void *data;
109    int   size;
110    int   pos;
111 };
112
113 struct _Eet_Data_Descriptor_Hash
114 {
115    Eet_Data_Element         *element;
116    Eet_Data_Descriptor_Hash *next;
117 };
118
119 struct _Eet_Data_Descriptor
120 {
121    const char           *name;
122    const Eet_Dictionary *ed;
123    int                   size;
124    struct
125    {
126       void      * (*mem_alloc)(size_t size);
127       void        (*mem_free)(void *mem);
128       char      * (*str_alloc)(const char *str);
129       char      * (*str_direct_alloc)(const char *str);
130       void        (*str_free)(const char *str);
131       void        (*str_direct_free)(const char *str);
132       void      * (*list_next)(void *l);
133       void      * (*list_append)(void *l, void *d);
134       void      * (*list_data)(void *l);
135       void      * (*list_free)(void *l);
136       void        (*hash_foreach)(void *h, int (*func)(void *h, const char *k, void *dt, void *fdt), void *fdt);
137       void      * (*hash_add)(void *h, const char *k, void *d);
138       void        (*hash_free)(void *h);
139       const char *(*type_get)(const void *data, Eina_Bool *unknow);
140       Eina_Bool   (*type_set)(const char *type, void *data, Eina_Bool unknow);
141       void      * (*array_alloc)(size_t size);
142       void        (*array_free)(void *mem);
143    } func;
144    struct
145    {
146       int               num;
147       Eet_Data_Element *set;
148       struct
149       {
150          int                       size;
151          Eet_Data_Descriptor_Hash *buckets;
152       } hash;
153    } elements;
154
155    Eina_Bool unified_type : 1;
156 //   char *strings;
157 //   int   strings_len;
158 };
159
160 struct _Eet_Data_Element
161 {
162    const char          *name;
163    const char          *counter_name;
164    const char          *directory_name_ptr;
165    Eet_Data_Descriptor *subtype;
166    int                  offset;  /* offset in bytes from the base element */
167    int                  count;  /* number of elements for a fixed array */
168    int                  counter_offset;  /* for a variable array we need the offset of the count variable */
169    unsigned char        type;  /* EET_T_XXX */
170    unsigned char        group_type;  /* EET_G_XXX */
171 };
172
173 struct _Eet_Data_Encode_Hash_Info
174 {
175    Eet_Data_Stream  *ds;
176    Eet_Data_Element *ede;
177    Eet_Dictionary   *ed;
178 };
179
180 #define EET_FREE_COUNT 256
181 struct _Eet_Free
182 {
183    int    ref;
184    Eina_Array list[EET_FREE_COUNT];
185 };
186
187 struct _Eet_Free_Context
188 {
189    Eet_Free freelist;
190    Eet_Free freelist_array;
191    Eet_Free freelist_list;
192    Eet_Free freelist_hash;
193    Eet_Free freelist_str;
194    Eet_Free freelist_direct_str;
195 };
196
197 struct _Eet_Variant_Unknow
198 {
199    EINA_MAGIC
200
201    int  size;
202    char data[1];
203 };
204
205 /*---*/
206
207 static void     eet_free_context_init(Eet_Free_Context *context);
208 static void     eet_free_context_shutdown(Eet_Free_Context *context);
209
210 static int             eet_data_get_char(const Eet_Dictionary *ed,
211                                          const void           *src,
212                                          const void           *src_end,
213                                          void                 *dest);
214 static void *          eet_data_put_char(Eet_Dictionary *ed,
215                                          const void     *src,
216                                          int            *size_ret);
217 static int             eet_data_get_short(const Eet_Dictionary *ed,
218                                           const void           *src,
219                                           const void           *src_end,
220                                           void                 *dest);
221 static void *          eet_data_put_short(Eet_Dictionary *ed,
222                                           const void     *src,
223                                           int            *size_ret);
224 static inline int      eet_data_get_int(const Eet_Dictionary *ed,
225                                         const void           *src,
226                                         const void           *src_end,
227                                         void                 *dest);
228 static void *          eet_data_put_int(Eet_Dictionary *ed,
229                                         const void     *src,
230                                         int            *size_ret);
231 static int             eet_data_get_long_long(const Eet_Dictionary *ed,
232                                               const void           *src,
233                                               const void           *src_end,
234                                               void                 *dest);
235 static void *          eet_data_put_long_long(Eet_Dictionary *ed,
236                                               const void     *src,
237                                               int            *size_ret);
238 static int             eet_data_get_float(const Eet_Dictionary *ed,
239                                           const void           *src,
240                                           const void           *src_end,
241                                           void                 *dest);
242 static void *          eet_data_put_float(Eet_Dictionary *ed,
243                                           const void     *src,
244                                           int            *size_ret);
245 static int             eet_data_get_double(const Eet_Dictionary *ed,
246                                            const void           *src,
247                                            const void           *src_end,
248                                            void                 *dest);
249 static void *          eet_data_put_double(Eet_Dictionary *ed,
250                                            const void     *src,
251                                            int            *size_ret);
252 static int             eet_data_get_f32p32(const Eet_Dictionary *ed,
253                                            const void           *src,
254                                            const void           *src_end,
255                                            void                 *dest);
256 static void *          eet_data_put_f32p32(Eet_Dictionary *ed,
257                                            const void     *src,
258                                            int            *size_ret);
259 static int             eet_data_get_f16p16(const Eet_Dictionary *ed,
260                                            const void           *src,
261                                            const void           *src_end,
262                                            void                 *dest);
263 static void *          eet_data_put_f16p16(Eet_Dictionary *ed,
264                                            const void     *src,
265                                            int            *size_ret);
266 static int             eet_data_get_f8p24(const Eet_Dictionary *ed,
267                                           const void           *src,
268                                           const void           *src_end,
269                                           void                 *dest);
270 static void *          eet_data_put_f8p24(Eet_Dictionary *ed,
271                                           const void     *src,
272                                           int            *size_ret);
273 static inline int      eet_data_get_string(const Eet_Dictionary *ed,
274                                            const void           *src,
275                                            const void           *src_end,
276                                            void                 *dest);
277 static void *          eet_data_put_string(Eet_Dictionary *ed,
278                                            const void     *src,
279                                            int            *size_ret);
280 static int             eet_data_get_istring(const Eet_Dictionary *ed,
281                                             const void           *src,
282                                             const void           *src_end,
283                                             void                 *dest);
284 static void *          eet_data_put_istring(Eet_Dictionary *ed,
285                                             const void     *src,
286                                             int            *size_ret);
287 static int             eet_data_get_null(const Eet_Dictionary *ed,
288                                          const void           *src,
289                                          const void           *src_end,
290                                          void                 *dest);
291 static void *          eet_data_put_null(Eet_Dictionary *ed,
292                                          const void     *src,
293                                          int            *size_ret);
294
295 static int             eet_data_get_type(const Eet_Dictionary *ed,
296                                          int                   type,
297                                          const void           *src,
298                                          const void           *src_end,
299                                          void                 *dest);
300 static void *          eet_data_put_type(Eet_Dictionary *ed,
301                                          int             type,
302                                          const void     *src,
303                                          int            *size_ret);
304
305 static Eet_Node *      eet_data_node_simple_type(int         type,
306                                                  const char *name,
307                                                  void       *dd);
308
309 static int             eet_data_get_unknown(Eet_Free_Context     *context,
310                                             const Eet_Dictionary *ed,
311                                             Eet_Data_Descriptor  *edd,
312                                             Eet_Data_Element     *ede,
313                                             Eet_Data_Chunk       *echnk,
314                                             int                   type,
315                                             int                   group_type,
316                                             void                 *data_in,
317                                             char                **p,
318                                             int                  *size);
319 static void      eet_data_put_unknown(Eet_Dictionary      *ed,
320                                       Eet_Data_Descriptor *edd,
321                                       Eet_Data_Element    *ede,
322                                       Eet_Data_Stream     *ds,
323                                       void                *data_in);
324 static void      eet_data_put_array(Eet_Dictionary      *ed,
325                                     Eet_Data_Descriptor *edd,
326                                     Eet_Data_Element    *ede,
327                                     Eet_Data_Stream     *ds,
328                                     void                *data_in);
329 static int       eet_data_get_array(Eet_Free_Context     *context,
330                                     const Eet_Dictionary *ed,
331                                     Eet_Data_Descriptor  *edd,
332                                     Eet_Data_Element     *ede,
333                                     Eet_Data_Chunk       *echnk,
334                                     int                   type,
335                                     int                   group_type,
336                                     void                 *data,
337                                     char                **p,
338                                     int                  *size);
339 static int      eet_data_get_list(Eet_Free_Context     *context,
340                                   const Eet_Dictionary *ed,
341                                   Eet_Data_Descriptor  *edd,
342                                   Eet_Data_Element     *ede,
343                                   Eet_Data_Chunk       *echnk,
344                                   int                   type,
345                                   int                   group_type,
346                                   void                 *data_in,
347                                   char                **p,
348                                   int                  *size);
349 static void      eet_data_put_list(Eet_Dictionary      *ed,
350                                    Eet_Data_Descriptor *edd,
351                                    Eet_Data_Element    *ede,
352                                    Eet_Data_Stream     *ds,
353                                    void                *data_in);
354 static void      eet_data_put_hash(Eet_Dictionary      *ed,
355                                    Eet_Data_Descriptor *edd,
356                                    Eet_Data_Element    *ede,
357                                    Eet_Data_Stream     *ds,
358                                    void                *data_in);
359 static int       eet_data_get_hash(Eet_Free_Context     *context,
360                                    const Eet_Dictionary *ed,
361                                    Eet_Data_Descriptor  *edd,
362                                    Eet_Data_Element     *ede,
363                                    Eet_Data_Chunk       *echnk,
364                                    int                   type,
365                                    int                   group_type,
366                                    void                 *data,
367                                    char                **p,
368                                    int                  *size);
369 static void      eet_data_put_union(Eet_Dictionary      *ed,
370                                     Eet_Data_Descriptor *edd,
371                                     Eet_Data_Element    *ede,
372                                     Eet_Data_Stream     *ds,
373                                     void                *data_in);
374 static int       eet_data_get_union(Eet_Free_Context     *context,
375                                     const Eet_Dictionary *ed,
376                                     Eet_Data_Descriptor  *edd,
377                                     Eet_Data_Element     *ede,
378                                     Eet_Data_Chunk       *echnk,
379                                     int                   type,
380                                     int                   group_type,
381                                     void                 *data,
382                                     char                **p,
383                                     int                  *size);
384 static void      eet_data_put_variant(Eet_Dictionary      *ed,
385                                       Eet_Data_Descriptor *edd,
386                                       Eet_Data_Element    *ede,
387                                       Eet_Data_Stream     *ds,
388                                       void                *data_in);
389 static int       eet_data_get_variant(Eet_Free_Context     *context,
390                                       const Eet_Dictionary *ed,
391                                       Eet_Data_Descriptor  *edd,
392                                       Eet_Data_Element     *ede,
393                                       Eet_Data_Chunk       *echnk,
394                                       int                   type,
395                                       int                   group_type,
396                                       void                 *data,
397                                       char                **p,
398                                       int                  *size);
399
400 static void                 eet_data_chunk_get(const Eet_Dictionary *ed,
401                                                Eet_Data_Chunk       *chnk,
402                                                const void           *src,
403                                                int                   size);
404 static Eet_Data_Chunk *     eet_data_chunk_new(void       *data,
405                                                int         size,
406                                                const char *name,
407                                                int         type,
408                                                int         group_type);
409 static void                 eet_data_chunk_free(Eet_Data_Chunk *chnk);
410
411 static Eet_Data_Stream *    eet_data_stream_new(void);
412 static void                 eet_data_stream_write(Eet_Data_Stream *ds,
413                                                   const void      *data,
414                                                   int              size);
415 static void                 eet_data_stream_free(Eet_Data_Stream *ds);
416
417 static void                 eet_data_chunk_put(Eet_Dictionary  *ed,
418                                                Eet_Data_Chunk  *chnk,
419                                                Eet_Data_Stream *ds);
420
421 static int                  eet_data_descriptor_encode_hash_cb(void       *hash,
422                                                                const char *key,
423                                                                void       *hdata,
424                                                                void       *fdata);
425 static void *               _eet_data_descriptor_encode(Eet_Dictionary      *ed,
426                                                         Eet_Data_Descriptor *edd,
427                                                         const void          *data_in,
428                                                         int                 *size_ret);
429 static void *               _eet_data_descriptor_decode(Eet_Free_Context     *context,
430                                                         const Eet_Dictionary *ed,
431                                                         Eet_Data_Descriptor  *edd,
432                                                         const void           *data_in,
433                                                         int                   size_in);
434
435 /*---*/
436
437 static const Eet_Data_Basic_Type_Codec eet_basic_codec[] =
438 {
439    {sizeof(char),      "char",       eet_data_get_char,      eet_data_put_char     },
440    {sizeof(short),     "short",      eet_data_get_short,     eet_data_put_short    },
441    {sizeof(int),       "int",        eet_data_get_int,       eet_data_put_int      },
442    {sizeof(long long), "long_long",  eet_data_get_long_long, eet_data_put_long_long},
443    {sizeof(float),     "float",      eet_data_get_float,     eet_data_put_float    },
444    {sizeof(double),    "double",     eet_data_get_double,    eet_data_put_double   },
445    {sizeof(char),      "uchar",      eet_data_get_char,      eet_data_put_char     },
446    {sizeof(short),     "ushort",     eet_data_get_short,     eet_data_put_short    },
447    {sizeof(int),       "uint",       eet_data_get_int,       eet_data_put_int      },
448    {sizeof(long long), "ulong_long", eet_data_get_long_long, eet_data_put_long_long},
449    {sizeof(char *),    "string",     eet_data_get_string,    eet_data_put_string   },
450    {sizeof(char *),    "inlined",    eet_data_get_istring,   eet_data_put_istring  },
451    {sizeof(void *),    "NULL",       eet_data_get_null,      eet_data_put_null     },
452    {sizeof(Eina_F32p32),"f32p32",    eet_data_get_f32p32,    eet_data_put_f32p32   },
453    {sizeof(Eina_F16p16),"f16p16",    eet_data_get_f16p16,    eet_data_put_f16p16   },
454    {sizeof(Eina_F8p24),"f8p24",      eet_data_get_f8p24,     eet_data_put_f8p24    }
455 };
456
457 static const Eet_Data_Group_Type_Codec eet_group_codec[] =
458 {
459    { eet_data_get_unknown,  eet_data_put_unknown },
460    { eet_data_get_array,    eet_data_put_array },
461    { eet_data_get_array,    eet_data_put_array },
462    { eet_data_get_list,     eet_data_put_list },
463    { eet_data_get_hash,     eet_data_put_hash },
464    { eet_data_get_union,    eet_data_put_union },
465    { eet_data_get_variant,  eet_data_put_variant }
466 };
467
468 static int _eet_data_words_bigendian = -1;
469
470 /*---*/
471
472 #define SWAP64(x) (x) =\
473    ((((unsigned long long)(x) & 0x00000000000000ffULL) << 56) |\
474     (((unsigned long long)(x) & 0x000000000000ff00ULL) << 40) |\
475     (((unsigned long long)(x) & 0x0000000000ff0000ULL) << 24) |\
476     (((unsigned long long)(x) & 0x00000000ff000000ULL) << 8) |\
477     (((unsigned long long)(x) & 0x000000ff00000000ULL) >> 8) |\
478     (((unsigned long long)(x) & 0x0000ff0000000000ULL) >> 24) |\
479     (((unsigned long long)(x) & 0x00ff000000000000ULL) >> 40) |\
480     (((unsigned long long)(x) & 0xff00000000000000ULL) >> 56))
481 #define SWAP32(x) (x) =\
482    ((((int)(x) & 0x000000ff) << 24) |\
483     (((int)(x) & 0x0000ff00) << 8) |\
484     (((int)(x) & 0x00ff0000) >> 8) |\
485     (((int)(x) & 0xff000000) >> 24))
486 #define SWAP16(x) (x) =\
487    ((((short)(x) & 0x00ff) << 8) |\
488     (((short)(x) & 0xff00) >> 8))
489
490 #ifdef CONV8
491 # undef CONV8
492 #endif /* ifdef CONV8 */
493 #ifdef CONV16
494 # undef CONV16
495 #endif /* ifdef CONV16 */
496 #ifdef CONV32
497 # undef CONV32
498 #endif /* ifdef CONV32 */
499 #ifdef CONV64
500 # undef CONV64
501 #endif /* ifdef CONV64 */
502
503 #define CONV8(x)
504 #define CONV16(x)             {if (_eet_data_words_bigendian) {SWAP16(x); }}
505 #define CONV32(x)             {if (_eet_data_words_bigendian) {SWAP32(x); }}
506 #define CONV64(x)             {if (_eet_data_words_bigendian) {SWAP64(x); }}
507
508 #define IS_SIMPLE_TYPE(Type)  (Type > EET_T_UNKNOW && Type < EET_T_LAST)
509 #define IS_POINTER_TYPE(Type) (Type >= EET_T_STRING && Type <= EET_T_NULL)
510
511 #define POINTER_TYPE_DECODE(Context,\
512                             Ed,\
513                             Edd,\
514                             Ede,\
515                             Echnk,\
516                             Type,\
517                             Data,\
518                             P,\
519                             Size,\
520                             Label)\
521    do {\
522         int ___r;\
523         ___r = eet_data_get_unknown(Context,\
524                                     Ed,\
525                                     Edd, Ede,\
526                                     Echnk,\
527                                     Type, EET_G_UNKNOWN,\
528                                     Data, P, Size);\
529         if (!___r) { goto Label; }\
530      } while (0)
531
532 #define STRUCT_TYPE_DECODE(Data_Ret, Context, Ed, Ede, Data, Size, Label)\
533    do {\
534         Data_Ret = _eet_data_descriptor_decode(Context,\
535                                                Ed,\
536                                                Ede,\
537                                                Data,\
538                                                Size);\
539         if (!Data_Ret) { goto Label; }\
540      } while (0)
541
542 #define EET_I_STRING         1 << 4
543 #define EET_I_INLINED_STRING 2 << 4
544 #define EET_I_NULL           3 << 4
545
546 #define EET_MAGIC_VARIANT    0xF1234BC
547 /*---*/
548
549 /* CHAR TYPE */
550 static int
551 eet_data_get_char(const Eet_Dictionary *ed __UNUSED__,
552                   const void              *src,
553                   const void              *src_end,
554                   void                    *dst)
555 {
556    char *s, *d;
557
558    if (((char *)src + sizeof(char)) > (char *)src_end)
559       return -1;
560
561    s = (char *)src;
562    d = (char *)dst;
563    *d = *s;
564    CONV8(*d);
565    return sizeof(char);
566 } /* eet_data_get_char */
567
568 static void *
569 eet_data_put_char(Eet_Dictionary *ed __UNUSED__,
570                   const void        *src,
571                   int               *size_ret)
572 {
573    char *s, *d;
574
575    d = (char *)malloc(sizeof(char));
576    if (!d)
577       return NULL;
578
579    s = (char *)src;
580    *d = *s;
581    CONV8(*d);
582    *size_ret = sizeof(char);
583    return d;
584 } /* eet_data_put_char */
585
586 /* SHORT TYPE */
587 static int
588 eet_data_get_short(const Eet_Dictionary *ed __UNUSED__,
589                    const void              *src,
590                    const void              *src_end,
591                    void                    *dst)
592 {
593    short *d;
594
595    if (((char *)src + sizeof(short)) > (char *)src_end)
596       return -1;
597
598    memcpy(dst, src, sizeof(short));
599    d = (short *)dst;
600    CONV16(*d);
601    return sizeof(short);
602 } /* eet_data_get_short */
603
604 static void *
605 eet_data_put_short(Eet_Dictionary *ed __UNUSED__,
606                    const void        *src,
607                    int               *size_ret)
608 {
609    short *s, *d;
610
611    d = (short *)malloc(sizeof(short));
612    if (!d)
613       return NULL;
614
615    s = (short *)src;
616    *d = *s;
617    CONV16(*d);
618    *size_ret = sizeof(short);
619    return d;
620 } /* eet_data_put_short */
621
622 /* INT TYPE */
623 static inline int
624 eet_data_get_int(const Eet_Dictionary *ed __UNUSED__,
625                  const void              *src,
626                  const void              *src_end,
627                  void                    *dst)
628 {
629    int *d;
630
631    if (((char *)src + sizeof(int)) > (char *)src_end)
632       return -1;
633
634    memcpy(dst, src, sizeof(int));
635    d = (int *)dst;
636    CONV32(*d);
637    return sizeof(int);
638 } /* eet_data_get_int */
639
640 static void *
641 eet_data_put_int(Eet_Dictionary *ed __UNUSED__,
642                  const void        *src,
643                  int               *size_ret)
644 {
645    int *s, *d;
646
647    d = (int *)malloc(sizeof(int));
648    if (!d)
649       return NULL;
650
651    s = (int *)src;
652    *d = *s;
653    CONV32(*d);
654    *size_ret = sizeof(int);
655    return d;
656 } /* eet_data_put_int */
657
658 /* LONG LONG TYPE */
659 static int
660 eet_data_get_long_long(const Eet_Dictionary *ed __UNUSED__,
661                        const void              *src,
662                        const void              *src_end,
663                        void                    *dst)
664 {
665    unsigned long long *d;
666
667    if (((char *)src + sizeof(unsigned long long)) > (char *)src_end)
668       return -1;
669
670    memcpy(dst, src, sizeof(unsigned long long));
671    d = (unsigned long long *)dst;
672    CONV64(*d);
673    return sizeof(unsigned long long);
674 } /* eet_data_get_long_long */
675
676 static void *
677 eet_data_put_long_long(Eet_Dictionary *ed __UNUSED__,
678                        const void        *src,
679                        int               *size_ret)
680 {
681    unsigned long long *s, *d;
682
683    d = (unsigned long long *)malloc(sizeof(unsigned long long));
684    if (!d)
685       return NULL;
686
687    s = (unsigned long long *)src;
688    *d = *s;
689    CONV64(*d);
690    *size_ret = sizeof(unsigned long long);
691    return d;
692 } /* eet_data_put_long_long */
693
694 /* STRING TYPE */
695 static inline int
696 eet_data_get_string_hash(const Eet_Dictionary *ed,
697                          const void           *src,
698                          const void           *src_end)
699 {
700    if (ed)
701      {
702         int idx;
703
704         if (eet_data_get_int(ed, src, src_end, &idx) < 0)
705            return -1;
706
707         return eet_dictionary_string_get_hash(ed, idx);
708      }
709
710    return -1;
711 } /* eet_data_get_string_hash */
712
713 static inline int
714 eet_data_get_string(const Eet_Dictionary *ed,
715                     const void           *src,
716                     const void           *src_end,
717                     void                 *dst)
718 {
719    char *s, **d;
720
721    d = (char **)dst;
722
723    if (ed)
724      {
725         const char *str;
726         int idx;
727
728         if (eet_data_get_int(ed, src, src_end, &idx) < 0)
729            return -1;
730
731         str = eet_dictionary_string_get_char(ed, idx);
732         if (!str)
733            return -1;
734
735         *d = (char *)str;
736         return eet_dictionary_string_get_size(ed, idx);
737      }
738
739    s = (char *)src;
740    if (!s)
741      {
742         *d = NULL;
743         return 0;
744      }
745
746    *d = s;
747    return strlen(s) + 1;
748 } /* eet_data_get_string */
749
750 static void *
751 eet_data_put_string(Eet_Dictionary *ed,
752                     const void     *src,
753                     int            *size_ret)
754 {
755    char *s, *d;
756    int len;
757
758    if (ed)
759      {
760         const char *str;
761         int idx;
762
763         str = *((const char **)src);
764         if (!str)
765            return NULL;
766
767         idx = eet_dictionary_string_add(ed, str);
768         if (idx == -1)
769            return NULL;
770
771         return eet_data_put_int(ed, &idx, size_ret);
772      }
773
774    s = (char *)(*((char **)src));
775    if (!s)
776       return NULL;
777
778    len = strlen(s);
779    d = malloc(len + 1);
780    if (!d)
781       return NULL;
782
783    memcpy(d, s, len + 1);
784    *size_ret = len + 1;
785    return d;
786 } /* eet_data_put_string */
787
788 /* ALWAYS INLINED STRING TYPE */
789 static int
790 eet_data_get_istring(const Eet_Dictionary *ed __UNUSED__,
791                      const void              *src,
792                      const void              *src_end,
793                      void                    *dst)
794 {
795    return eet_data_get_string(NULL, src, src_end, dst);
796 } /* eet_data_get_istring */
797
798 static void *
799 eet_data_put_istring(Eet_Dictionary *ed __UNUSED__,
800                      const void        *src,
801                      int               *size_ret)
802 {
803    return eet_data_put_string(NULL, src, size_ret);
804 } /* eet_data_put_istring */
805
806 /* ALWAYS NULL TYPE */
807 static int
808 eet_data_get_null(const Eet_Dictionary *ed __UNUSED__,
809                   const void *src          __UNUSED__,
810                   const void *src_end      __UNUSED__,
811                   void                    *dst)
812 {
813    char **d;
814
815    d = (char **)dst;
816
817    *d = NULL;
818    return 1;
819 } /* eet_data_get_null */
820
821 static void *
822 eet_data_put_null(Eet_Dictionary *ed __UNUSED__,
823                   const void *src    __UNUSED__,
824                   int               *size_ret)
825 {
826    *size_ret = 0;
827    return NULL;
828 } /* eet_data_put_null */
829
830 /**
831  * Fast lookups of simple doubles/floats.
832  *
833  * These aren't properly a cache because they don't store pre-calculated
834  * values, but have a so simple math that is almost as fast.
835  */
836 static inline int
837 _eet_data_float_cache_get(const char *s,
838                           int         len,
839                           float      *d)
840 {
841    /* fast handle of simple case 0xMp+E*/
842    if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p'))
843      {
844         int mantisse = (s[2] >= 'a') ? (s[2] - 'a' + 10) : (s[2] - '0');
845         int exponent = (s[5] - '0');
846
847         if (s[4] == '+')
848            *d = (float)(mantisse << exponent);
849         else
850            *d = (float)mantisse / (float)(1 << exponent);
851
852         return 1;
853      }
854
855    return 0;
856 } /* _eet_data_float_cache_get */
857
858 static inline int
859 _eet_data_double_cache_get(const char *s,
860                            int         len,
861                            double     *d)
862 {
863    /* fast handle of simple case 0xMp+E*/
864    if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p'))
865      {
866         int mantisse = (s[2] >= 'a') ? (s[2] - 'a' + 10) : (s[2] - '0');
867         int exponent = (s[5] - '0');
868
869         if (s[4] == '+')
870            *d = (double)(mantisse << exponent);
871         else
872            *d = (double)mantisse / (double)(1 << exponent);
873
874         return 1;
875      }
876
877    return 0;
878 } /* _eet_data_double_cache_get */
879
880 /* FLOAT TYPE */
881 static int
882 eet_data_get_float(const Eet_Dictionary *ed,
883                    const void           *src,
884                    const void           *src_end,
885                    void                 *dst)
886 {
887    float *d;
888    int idx;
889
890    d = (float *)dst;
891    if (!ed)
892      {
893         const char *s, *p;
894         long long mantisse;
895         long exponent;
896         int len;
897
898         s = (const char *)src;
899         p = s;
900         len = 0;
901         while ((p < (const char *)src_end) && (*p != 0)) {len++; p++; }
902
903         if (_eet_data_float_cache_get(s, len, d) != 0)
904            return len + 1;
905
906         if (eina_convert_atod(s, len, &mantisse, &exponent) == EINA_FALSE)
907            return -1;
908
909         *d = (float)ldexp((double)mantisse, exponent);
910
911         return len + 1;
912      }
913
914    if (eet_data_get_int(ed, src, src_end, &idx) < 0)
915       return -1;
916
917    if (!eet_dictionary_string_get_float(ed, idx, d))
918       return -1;
919
920    return 1;
921 } /* eet_data_get_float */
922
923 static void *
924 eet_data_put_float(Eet_Dictionary *ed,
925                    const void     *src,
926                    int            *size_ret)
927 {
928    char buf[128];
929    int idx;
930
931    eina_convert_dtoa((double)(*(float *)src), buf);
932
933    if (!ed)
934      {
935         char *d;
936         int len;
937
938         len = strlen(buf);
939         d = malloc(len + 1);
940         if (!d)
941            return NULL;
942
943         memcpy(d, buf, len + 1);
944         *size_ret = len + 1;
945         return d;
946      }
947
948    idx = eet_dictionary_string_add(ed, buf);
949    if (idx == -1)
950       return NULL;
951
952    return eet_data_put_int(ed, &idx, size_ret);
953 } /* eet_data_put_float */
954
955 /* DOUBLE TYPE */
956 static int
957 eet_data_get_double(const Eet_Dictionary *ed,
958                     const void           *src,
959                     const void           *src_end,
960                     void                 *dst)
961 {
962    double *d;
963    int idx;
964
965    d = (double *)dst;
966
967    if (!ed)
968      {
969         const char *s, *p;
970         long long mantisse = 0;
971         long exponent = 0;
972         int len;
973
974         s = (const char *)src;
975         p = s;
976         len = 0;
977         while ((p < (const char *)src_end) && (*p != 0)) {len++; p++; }
978
979         if (_eet_data_double_cache_get(s, len, d) != 0)
980            return len + 1;
981
982         if (eina_convert_atod(s, len, &mantisse, &exponent) == EINA_FALSE)
983            return -1;
984
985         *d = ldexp((double)mantisse, exponent);
986
987         return len + 1;
988      }
989
990    if (eet_data_get_int(ed, src, src_end, &idx) < 0)
991       return -1;
992
993    if (!eet_dictionary_string_get_double(ed, idx, d))
994       return -1;
995
996    return 1;
997 } /* eet_data_get_double */
998
999 static void *
1000 eet_data_put_double(Eet_Dictionary *ed,
1001                     const void     *src,
1002                     int            *size_ret)
1003 {
1004    char buf[128];
1005    int idx;
1006
1007    eina_convert_dtoa((double)(*(double *)src), buf);
1008
1009    if (!ed)
1010      {
1011         char *d;
1012         int len;
1013
1014         len = strlen(buf);
1015         d = malloc(len + 1);
1016         if (!d)
1017            return NULL;
1018
1019         memcpy(d, buf, len + 1);
1020         *size_ret = len + 1;
1021
1022         return d;
1023      }
1024
1025    idx = eet_dictionary_string_add(ed, buf);
1026    if (idx == -1)
1027       return NULL;
1028
1029    return eet_data_put_int(ed, &idx, size_ret);
1030 } /* eet_data_put_double */
1031
1032 static int
1033 eet_data_get_f32p32(const Eet_Dictionary *ed,
1034                     const void           *src,
1035                     const void           *src_end,
1036                     void                 *dst)
1037 {
1038    Eina_F32p32 *fp;
1039    int idx;
1040
1041    fp = (Eina_F32p32 *)dst;
1042
1043    if (!ed)
1044      {
1045         const char *s, *p;
1046         int len;
1047
1048         s = (const char *)src;
1049         p = s;
1050         len = 0;
1051         while ((p < (const char *)src_end) && (*p != 0)) { len++; p++; }
1052
1053         if (!(eina_convert_atofp(s, len, fp)))
1054            return -1;
1055
1056         return 1;
1057      }
1058
1059    if (eet_data_get_int(ed, src, src_end, &idx) < 0)
1060       return -1;
1061
1062    if (!eet_dictionary_string_get_fp(ed, idx, fp))
1063       return -1;
1064
1065    return 1;
1066 } /* eet_data_get_f32p32 */
1067
1068 static void *
1069 eet_data_put_f32p32(Eet_Dictionary *ed,
1070                     const void     *src,
1071                     int            *size_ret)
1072 {
1073    char buf[128];
1074    int idx;
1075
1076    eina_convert_fptoa((Eina_F32p32)(*(Eina_F32p32 *)src), buf);
1077
1078    if (!ed)
1079      {
1080         char *d;
1081         int len;
1082
1083         len = strlen(buf);
1084         d = malloc(len + 1);
1085         if (!d)
1086            return NULL;
1087
1088         memcpy(d, buf, len + 1);
1089         *size_ret = len + 1;
1090
1091         return d;
1092      }
1093
1094    idx = eet_dictionary_string_add(ed, buf);
1095    if (idx == -1)
1096       return NULL;
1097
1098    return eet_data_put_int(ed, &idx, size_ret);
1099 } /* eet_data_put_f32p32 */
1100
1101 static int
1102 eet_data_get_f16p16(const Eet_Dictionary *ed,
1103                     const void           *src,
1104                     const void           *src_end,
1105                     void                 *dst)
1106 {
1107    Eina_F32p32 tmp;
1108    Eina_F16p16 *fp;
1109
1110    fp = (Eina_F16p16 *)dst;
1111
1112    if (eet_data_get_f32p32(ed, src, src_end, &tmp) < 0)
1113       return -1;
1114
1115    *fp = eina_f32p32_to_f16p16(tmp);
1116    return 1;
1117 } /* eet_data_get_f16p16 */
1118
1119 static void *
1120 eet_data_put_f16p16(Eet_Dictionary *ed,
1121                     const void     *src,
1122                     int            *size_ret)
1123 {
1124    Eina_F32p32 tmp;
1125
1126    tmp = eina_f16p16_to_f32p32((Eina_F16p16)(*(Eina_F16p16 *)src));
1127    return eet_data_put_f32p32(ed, &tmp, size_ret);
1128 } /* eet_data_put_f16p16 */
1129
1130 static int
1131 eet_data_get_f8p24(const Eet_Dictionary *ed,
1132                    const void           *src,
1133                    const void           *src_end,
1134                    void                 *dst)
1135 {
1136    Eina_F32p32 tmp;
1137    Eina_F8p24 *fp;
1138
1139    fp = (Eina_F8p24 *)dst;
1140
1141    if (eet_data_get_f32p32(ed, src, src_end, &tmp) < 0)
1142       return -1;
1143
1144    *fp = eina_f32p32_to_f8p24(tmp);
1145    return 1;
1146 } /* eet_data_get_f8p24 */
1147
1148 static void *
1149 eet_data_put_f8p24(Eet_Dictionary *ed,
1150                    const void     *src,
1151                    int            *size_ret)
1152 {
1153    Eina_F32p32 tmp;
1154
1155    tmp = eina_f8p24_to_f32p32((Eina_F8p24)(*(Eina_F8p24 *)src));
1156    return eet_data_put_f32p32(ed, &tmp, size_ret);
1157 } /* eet_data_put_f8p24 */
1158
1159 static inline int
1160 eet_data_get_type(const Eet_Dictionary *ed,
1161                   int                   type,
1162                   const void           *src,
1163                   const void           *src_end,
1164                   void                 *dest)
1165 {
1166    int ret;
1167
1168    ret = eet_basic_codec[type - 1].get(ed, src, src_end, dest);
1169    return ret;
1170 } /* eet_data_get_type */
1171
1172 static inline void *
1173 eet_data_put_type(Eet_Dictionary *ed,
1174                   int             type,
1175                   const void     *src,
1176                   int            *size_ret)
1177 {
1178    void *ret;
1179
1180    ret = eet_basic_codec[type - 1].put(ed, src, size_ret);
1181    return ret;
1182 } /* eet_data_put_type */
1183
1184 static inline Eina_Bool
1185 eet_data_type_match(int type1,
1186                     int type2)
1187 {
1188    if (type1 == type2)
1189       return EINA_TRUE;
1190
1191    /* Note: All floating point type are equivalent and could be read
1192       without problem by any other floating point getter. */
1193    switch (type1)
1194      {
1195       case EET_T_FLOAT:
1196       case EET_T_DOUBLE:
1197       case EET_T_F32P32:
1198       case EET_T_F16P16:
1199       case EET_T_F8P24:
1200          switch (type2)
1201            {
1202             case EET_T_FLOAT:
1203             case EET_T_DOUBLE:
1204             case EET_T_F32P32:
1205             case EET_T_F16P16:
1206             case EET_T_F8P24:
1207                return EINA_TRUE;
1208
1209             default:
1210                break;
1211            } /* switch */
1212          break;
1213
1214       default:
1215          break;
1216      } /* switch */
1217
1218    return EINA_FALSE;
1219 } /* eet_data_type_match */
1220
1221 /* chunk format...
1222  *
1223  * char[4] = "CHnK"; // untyped data ... or
1224  * char[4] = "CHKx"; // typed data - x == type
1225  *
1226  * int     = chunk size (including magic string);
1227  * char[]  = chunk magic/name string (0 byte terminated);
1228  * ... sub-chunks (a chunk can contain chuncks recusrively) ...
1229  * or
1230  * ... payload data ...
1231  *
1232  */
1233
1234 static inline void
1235 eet_data_chunk_get(const Eet_Dictionary *ed,
1236                    Eet_Data_Chunk       *chnk,
1237                    const void           *src,
1238                    int                   size)
1239 {
1240    const char *s;
1241    int ret1, ret2;
1242
1243    if (!src)
1244       return;
1245
1246    if (size <= 8)
1247       return;
1248
1249    if (!chnk)
1250       return;
1251
1252    s = src;
1253    if (s[2] == 'K')
1254      {
1255         if ((s[0] != 'C') || (s[1] != 'H') || (s[2] != 'K'))
1256            return;
1257
1258         chnk->type = (unsigned char)(s[3]);
1259         if (chnk->type >= EET_I_LIMIT)
1260           {
1261              chnk->group_type =
1262                 ((chnk->type - EET_I_LIMIT) & 0xF) + EET_G_UNKNOWN;
1263              switch ((chnk->type - EET_I_LIMIT) & 0xF0)
1264                {
1265 #define EET_UNMATCH_TYPE(Type)\
1266  case EET_I_ ## Type: chnk->type = EET_T_ ## Type; break;
1267
1268                   EET_UNMATCH_TYPE(STRING);
1269                   EET_UNMATCH_TYPE(INLINED_STRING);
1270                   EET_UNMATCH_TYPE(NULL);
1271
1272                 default:
1273                    return;
1274                } /* switch */
1275           }
1276         else if (chnk->type > EET_T_LAST)
1277           {
1278              chnk->group_type = chnk->type;
1279              chnk->type = EET_T_UNKNOW;
1280           }
1281         else
1282            chnk->group_type = EET_G_UNKNOWN;
1283         if ((chnk->type >= EET_T_LAST) ||
1284             (chnk->group_type >=
1285              EET_G_LAST))
1286           {
1287              chnk->type = 0;
1288              chnk->group_type = 0;
1289           }
1290      }
1291    else if ((s[0] != 'C') || (s[1] != 'H') || (s[2] != 'n') || (s[3] != 'K'))
1292       return;
1293
1294    ret1 = eet_data_get_type(ed, EET_T_INT, (s + 4), (s + size), &(chnk->size));
1295
1296    if (ret1 <= 0)
1297       return;
1298
1299    if ((chnk->size < 0) || ((chnk->size + 8) > size))
1300       return;
1301
1302    ret2 = eet_data_get_type(ed, EET_T_STRING, (s + 8), (s + size), &(chnk->name));
1303
1304    if (ret2 <= 0)
1305       return;
1306
1307    chnk->len = ret2;
1308
1309    /* Precalc hash */
1310    chnk->hash = eet_data_get_string_hash(ed, (s + 8), (s + size));
1311
1312    if (ed)
1313      {
1314         chnk->data = (char *)src + 4 + ret1 + sizeof(int);
1315         chnk->size -= sizeof(int);
1316      }
1317    else
1318      {
1319         chnk->data = (char *)src + 4 + ret1 + chnk->len;
1320         chnk->size -= chnk->len;
1321      }
1322
1323    return;
1324 } /* eet_data_chunk_get */
1325
1326 static inline Eet_Data_Chunk *
1327 eet_data_chunk_new(void       *data,
1328                    int         size,
1329                    const char *name,
1330                    int         type,
1331                    int         group_type)
1332 {
1333    Eet_Data_Chunk *chnk;
1334
1335    if (!name)
1336       return NULL;
1337
1338    chnk = calloc(1, sizeof(Eet_Data_Chunk));
1339    if (!chnk)
1340       return NULL;
1341
1342    /* Note: Another security, so older eet library could read file
1343       saved with fixed point value. */
1344    if (type == EET_T_F32P32
1345        || type == EET_T_F16P16
1346        || type == EET_T_F8P24)
1347       type = EET_T_DOUBLE;
1348
1349    chnk->name = strdup(name);
1350    chnk->len = strlen(name) + 1;
1351    chnk->size = size;
1352    chnk->data = data;
1353    chnk->type = type;
1354    chnk->group_type = group_type;
1355    return chnk;
1356 } /* eet_data_chunk_new */
1357
1358 static inline void
1359 eet_data_chunk_free(Eet_Data_Chunk *chnk)
1360 {
1361    if (chnk->name)
1362       free(chnk->name);
1363
1364    free(chnk);
1365 } /* eet_data_chunk_free */
1366
1367 static inline Eet_Data_Stream *
1368 eet_data_stream_new(void)
1369 {
1370    Eet_Data_Stream *ds;
1371
1372    ds = calloc(1, sizeof(Eet_Data_Stream));
1373    if (!ds)
1374       return NULL;
1375
1376    return ds;
1377 } /* eet_data_stream_new */
1378
1379 static inline void
1380 eet_data_stream_free(Eet_Data_Stream *ds)
1381 {
1382    if (ds->data)
1383       free(ds->data);
1384
1385    free(ds);
1386 } /* eet_data_stream_free */
1387
1388 static inline void
1389 eet_data_stream_flush(Eet_Data_Stream *ds)
1390 {
1391    free(ds);
1392 } /* eet_data_stream_flush */
1393
1394 static inline void
1395 eet_data_stream_write(Eet_Data_Stream *ds,
1396                       const void      *data,
1397                       int              size)
1398 {
1399    char *p;
1400
1401    if ((ds->pos + size) > ds->size)
1402      {
1403         ds->data = realloc(ds->data, ds->size + size + 512);
1404         if (!ds->data)
1405           {
1406              ds->pos = 0;
1407              ds->size = 0;
1408              return;
1409           }
1410
1411         ds->size = ds->size + size + 512;
1412      }
1413
1414    p = ds->data;
1415    memcpy(p + ds->pos, data, size);
1416    ds->pos += size;
1417 } /* eet_data_stream_write */
1418
1419 static void
1420 eet_data_chunk_put(Eet_Dictionary  *ed,
1421                    Eet_Data_Chunk  *chnk,
1422                    Eet_Data_Stream *ds)
1423 {
1424    int *size;
1425    void *string;
1426    int s;
1427    int size_ret = 0;
1428    int string_ret = 0;
1429    unsigned char buf[4] = "CHK";
1430
1431    /* disable this check - it will allow empty chunks to be written. this is
1432     * right for corner-cases when y have a struct with empty fields (empty
1433     * strings or empty list ptrs etc.) */
1434    /* if (!chnk->data && chnk->type != EET_T_NULL) return; */
1435    /* chunk head */
1436
1437 /*   eet_data_stream_write(ds, "CHnK", 4);*/
1438    if (chnk->type != EET_T_UNKNOW)
1439      {
1440         if (chnk->group_type != EET_G_UNKNOWN)
1441           {
1442              int type = EET_I_LIMIT + chnk->group_type - EET_G_UNKNOWN;
1443
1444              switch (chnk->type)
1445                {
1446                   /* Only make sense with pointer type. */
1447 #define EET_MATCH_TYPE(Type)\
1448  case EET_T_ ## Type: type += EET_I_ ## Type; break;
1449
1450                   EET_MATCH_TYPE(STRING);
1451                   EET_MATCH_TYPE(INLINED_STRING);
1452                   EET_MATCH_TYPE(NULL);
1453
1454                 default:
1455                    return;
1456                } /* switch */
1457
1458              buf[3] = type;
1459           }
1460         else
1461            buf[3] = chnk->type;
1462      }
1463    else
1464       buf[3] = chnk->group_type;
1465
1466    string = eet_data_put_string(ed, &chnk->name, &string_ret);
1467    if (!string)
1468       return;
1469
1470    /* size of chunk payload data + name */
1471    s = chnk->size + string_ret;
1472    size = eet_data_put_int(ed, &s, &size_ret);
1473
1474    /* FIXME: If something goes wrong the resulting file will be corrupted. */
1475    if (!size)
1476       goto on_error;
1477
1478    eet_data_stream_write(ds, buf,    4);
1479
1480    /* write chunk length */
1481    eet_data_stream_write(ds, size,   size_ret);
1482
1483    /* write chunk name */
1484    eet_data_stream_write(ds, string, string_ret);
1485
1486    /* write payload */
1487    if (chnk->data)
1488       eet_data_stream_write(ds, chnk->data, chnk->size);
1489
1490    free(string);
1491 on_error:
1492    free(size);
1493 } /* eet_data_chunk_put */
1494
1495 /*---*/
1496
1497 static void
1498 _eet_descriptor_hash_new(Eet_Data_Descriptor *edd)
1499 {
1500    int i;
1501
1502    edd->elements.hash.size = 1 << 6;
1503    edd->elements.hash.buckets = calloc(
1504          1,
1505          sizeof(Eet_Data_Descriptor_Hash) *
1506          edd->elements.hash.size);
1507    for (i = 0; i < edd->elements.num; i++)
1508      {
1509         Eet_Data_Element *ede;
1510         int hash;
1511
1512         ede = &(edd->elements.set[i]);
1513         hash = _eet_hash_gen((char *)ede->name, 6);
1514         if (!edd->elements.hash.buckets[hash].element)
1515            edd->elements.hash.buckets[hash].element = ede;
1516         else
1517           {
1518              Eet_Data_Descriptor_Hash *bucket;
1519
1520              bucket = calloc(1, sizeof(Eet_Data_Descriptor_Hash));
1521              bucket->element = ede;
1522              bucket->next = edd->elements.hash.buckets[hash].next;
1523              edd->elements.hash.buckets[hash].next = bucket;
1524           }
1525      }
1526 } /* _eet_descriptor_hash_new */
1527
1528 static void
1529 _eet_descriptor_hash_free(Eet_Data_Descriptor *edd)
1530 {
1531    int i;
1532
1533    for (i = 0; i < edd->elements.hash.size; i++)
1534      {
1535         Eet_Data_Descriptor_Hash *bucket, *pbucket;
1536
1537         bucket = edd->elements.hash.buckets[i].next;
1538         while (bucket)
1539           {
1540              pbucket = bucket;
1541              bucket = bucket->next;
1542              free(pbucket);
1543           }
1544      }
1545    if (edd->elements.hash.buckets)
1546       free(edd->elements.hash.buckets);
1547 } /* _eet_descriptor_hash_free */
1548
1549 static Eet_Data_Element *
1550 _eet_descriptor_hash_find(Eet_Data_Descriptor *edd,
1551                           char                *name,
1552                           int                  hash)
1553 {
1554    Eet_Data_Descriptor_Hash *bucket;
1555
1556    if (hash < 0)
1557       hash = _eet_hash_gen(name, 6);
1558    else
1559       hash &= 0x3f;
1560
1561    if (!edd->elements.hash.buckets[hash].element)
1562       return NULL;  /*
1563                        When we use the dictionnary as a source for chunk name, we will always
1564                        have the same pointer in name. It's a good idea to just compare pointer
1565                        instead of running strcmp on both string.
1566                      */
1567
1568    if (edd->elements.hash.buckets[hash].element->directory_name_ptr == name)
1569       return edd->elements.hash.buckets[hash].element;
1570
1571    if (!strcmp(edd->elements.hash.buckets[hash].element->name, name))
1572      {
1573         edd->elements.hash.buckets[hash].element->directory_name_ptr = name;
1574         return edd->elements.hash.buckets[hash].element;
1575      }
1576
1577    bucket = edd->elements.hash.buckets[hash].next;
1578    while (bucket)
1579      {
1580         if (bucket->element->directory_name_ptr == name)
1581            return bucket->element;
1582
1583         if (!strcmp(bucket->element->name, name))
1584           {
1585              bucket->element->directory_name_ptr = name;
1586              return bucket->element;
1587           }
1588
1589         bucket = bucket->next;
1590      }
1591    return NULL;
1592 } /* _eet_descriptor_hash_find */
1593
1594 static void *
1595 _eet_mem_alloc(size_t size)
1596 {
1597    return calloc(1, size);
1598 } /* _eet_mem_alloc */
1599
1600 static void
1601 _eet_mem_free(void *mem)
1602 {
1603    free(mem);
1604 } /* _eet_mem_free */
1605
1606 static char *
1607 _eet_str_alloc(const char *str)
1608 {
1609    return strdup(str);
1610 } /* _eet_str_alloc */
1611
1612 static void
1613 _eet_str_free(const char *str)
1614 {
1615    free((char *)str);
1616 } /* _eet_str_free */
1617
1618 static Eina_Hash *
1619 _eet_eina_hash_add_alloc(Eina_Hash  *hash,
1620                          const char *key,
1621                          void       *data)
1622 {
1623    if (!hash)
1624       hash = eina_hash_string_small_new(NULL);
1625
1626    if (!hash)
1627       return NULL;
1628
1629    eina_hash_add(hash, key, data);
1630    return hash;
1631 } /* _eet_eina_hash_add_alloc */
1632
1633 static Eina_Hash *
1634 _eet_eina_hash_direct_add_alloc(Eina_Hash  *hash,
1635                                 const char *key,
1636                                 void       *data)
1637 {
1638    if (!hash)
1639       hash = eina_hash_string_small_new(NULL);
1640
1641    if (!hash)
1642       return NULL;
1643
1644    eina_hash_direct_add(hash, key, data);
1645    return hash;
1646 } /* _eet_eina_hash_direct_add_alloc */
1647
1648 static char *
1649 _eet_str_direct_alloc(const char *str)
1650 {
1651    return (char *)str;
1652 } /* _eet_str_direct_alloc */
1653
1654 static void
1655 _eet_str_direct_free(const char *str __UNUSED__)
1656 {
1657 } /* _eet_str_direct_free */
1658
1659 static void
1660 _eet_eina_hash_foreach(void             *hash,
1661                        Eina_Hash_Foreach cb,
1662                        void             *fdata)
1663 {
1664    if (hash)
1665       eina_hash_foreach(hash, cb, fdata);
1666 } /* _eet_eina_hash_foreach */
1667
1668 static void
1669 _eet_eina_hash_free(void *hash)
1670 {
1671    if (hash)
1672       eina_hash_free(hash);
1673 } /* _eet_eina_hash_free */
1674
1675 /*---*/
1676 EAPI Eina_Bool
1677 eet_eina_stream_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc,
1678                                           /* When we change the structure content in the future, we need to handle old structure type too */
1679                                           unsigned int               eddc_size,
1680                                           const char                *name,
1681                                           int                        size)
1682 {
1683    if (!eddc || !name || eddc_size != sizeof (Eet_Data_Descriptor_Class))
1684       return EINA_FALSE;
1685
1686    eddc->name = name;
1687    eddc->size = size;
1688    eddc->version = EET_DATA_DESCRIPTOR_CLASS_VERSION;
1689
1690    eddc->func.mem_alloc = _eet_mem_alloc;
1691    eddc->func.mem_free = _eet_mem_free;
1692    eddc->func.str_alloc = (char *(*)(const char *))eina_stringshare_add;
1693    eddc->func.str_free = eina_stringshare_del;
1694    eddc->func.list_next = (void *(*)(void *))eina_list_next;
1695    eddc->func.list_append = (void *(*)(void *, void *))eina_list_append;
1696    eddc->func.list_data = (void *(*)(void *))eina_list_data_get;
1697    eddc->func.list_free = (void *(*)(void *))eina_list_free;
1698    eddc->func.hash_foreach = (void (*)(void *, int (*)(void *, const char *, void *, void *), void *))_eet_eina_hash_foreach;
1699    eddc->func.hash_add = (void * (*)(void *, const char *, void *))_eet_eina_hash_add_alloc;
1700    eddc->func.hash_free = (void (*)(void *))_eet_eina_hash_free;
1701
1702    /* This will cause an ABI incompatibility */
1703    eddc->func.array_alloc = _eet_mem_alloc;
1704    eddc->func.array_free = _eet_mem_free;
1705
1706    return EINA_TRUE;
1707 } /* eet_eina_stream_data_descriptor_class_set */
1708
1709 EAPI Eina_Bool
1710 eet_eina_file_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc,
1711                                         /* When we change the structure content in the future, we need to handle old structure type too */
1712                                         unsigned int               eddc_size,
1713                                         const char                *name,
1714                                         int                        size)
1715 {
1716    if (!eet_eina_stream_data_descriptor_class_set(eddc, eddc_size, name, size))
1717       return EINA_FALSE;
1718
1719    eddc->version = EET_DATA_DESCRIPTOR_CLASS_VERSION;
1720
1721    eddc->func.hash_add = (void * (*)(void *, const char *, void *))_eet_eina_hash_direct_add_alloc;
1722    eddc->func.str_direct_alloc = _eet_str_direct_alloc;
1723    eddc->func.str_direct_free = _eet_str_direct_free;
1724
1725    return EINA_TRUE;
1726 } /* eet_eina_file_data_descriptor_class_set */
1727
1728 static Eet_Data_Descriptor *
1729 _eet_data_descriptor_new(const Eet_Data_Descriptor_Class *eddc,
1730                          int                              version)
1731 {
1732    Eet_Data_Descriptor *edd;
1733
1734    if (!eddc)
1735       return NULL;
1736
1737    edd = calloc(1, sizeof (Eet_Data_Descriptor));
1738    if (!edd)
1739       return NULL;
1740
1741    edd->name = eddc->name;
1742    edd->ed = NULL;
1743    edd->size = eddc->size;
1744    edd->func.mem_alloc = _eet_mem_alloc;
1745    edd->func.mem_free = _eet_mem_free;
1746    edd->func.str_alloc = _eet_str_alloc;
1747    edd->func.str_free = _eet_str_free;
1748    if (eddc->func.mem_alloc)
1749       edd->func.mem_alloc = eddc->func.mem_alloc;
1750
1751    if (eddc->func.mem_free)
1752       edd->func.mem_free = eddc->func.mem_free;
1753
1754    if (eddc->func.str_alloc)
1755       edd->func.str_alloc = eddc->func.str_alloc;
1756
1757    if (eddc->func.str_free)
1758       edd->func.str_free = eddc->func.str_free;
1759
1760    edd->func.list_next = eddc->func.list_next;
1761    edd->func.list_append = eddc->func.list_append;
1762    edd->func.list_data = eddc->func.list_data;
1763    edd->func.list_free = eddc->func.list_free;
1764    edd->func.hash_foreach = eddc->func.hash_foreach;
1765    edd->func.hash_add = eddc->func.hash_add;
1766    edd->func.hash_free = eddc->func.hash_free;
1767
1768    if (eddc->version > 1 && version > 1)
1769      {
1770         edd->func.str_direct_alloc = eddc->func.str_direct_alloc;
1771         edd->func.str_direct_free = eddc->func.str_direct_free;
1772      }
1773
1774    if (eddc->version > 2)
1775      {
1776         edd->func.type_get = eddc->func.type_get;
1777         edd->func.type_set = eddc->func.type_set;
1778      }
1779
1780    if (eddc->version > 3)
1781      {
1782         edd->func.array_alloc = eddc->func.array_alloc;
1783         edd->func.array_free = eddc->func.array_free;
1784      }
1785
1786    return edd;
1787 } /* _eet_data_descriptor_new */
1788
1789 EAPI Eet_Data_Descriptor *
1790 eet_data_descriptor_new(const char *name,
1791                         int size,
1792                         Eet_Descriptor_List_Next_Callback func_list_next,
1793                         Eet_Descriptor_List_Append_Callback func_list_append,
1794                         Eet_Descriptor_List_Data_Callback func_list_data,
1795                         Eet_Descriptor_List_Free_Callback func_list_free,
1796                         Eet_Descriptor_Hash_Foreach_Callback func_hash_foreach,
1797                         Eet_Descriptor_Hash_Add_Callback func_hash_add,
1798                         Eet_Descriptor_Hash_Free_Callback func_hash_free)
1799 {
1800    Eet_Data_Descriptor_Class eddc;
1801
1802    if (!name)
1803       return NULL;
1804
1805    memset(&eddc, 0, sizeof (Eet_Data_Descriptor_Class));
1806
1807    eddc.name = name;
1808    eddc.size = size;
1809    eddc.version = 0;
1810
1811    eddc.func.list_next = func_list_next;
1812    eddc.func.list_append = func_list_append;
1813    eddc.func.list_data = func_list_data;
1814    eddc.func.list_free = func_list_free;
1815    eddc.func.hash_foreach = func_hash_foreach;
1816    eddc.func.hash_add = func_hash_add;
1817    eddc.func.hash_free = func_hash_free;
1818
1819    return _eet_data_descriptor_new(&eddc, 0);
1820 } /* eet_data_descriptor_new */
1821
1822 EAPI Eet_Data_Descriptor *
1823 eet_data_descriptor2_new(const Eet_Data_Descriptor_Class *eddc)
1824 {
1825    return _eet_data_descriptor_new(eddc, 1);
1826 } /* eet_data_descriptor2_new */
1827
1828 EAPI Eet_Data_Descriptor *
1829 eet_data_descriptor3_new(const Eet_Data_Descriptor_Class *eddc)
1830 {
1831    return _eet_data_descriptor_new(eddc, 2);
1832 } /* eet_data_descriptor3_new */
1833
1834 EAPI Eet_Data_Descriptor *
1835 eet_data_descriptor_stream_new(const Eet_Data_Descriptor_Class *eddc)
1836 {
1837    return _eet_data_descriptor_new(eddc, 1);
1838 } /* eet_data_descriptor_stream_new */
1839
1840 EAPI Eet_Data_Descriptor *
1841 eet_data_descriptor_file_new(const Eet_Data_Descriptor_Class *eddc)
1842 {
1843    return _eet_data_descriptor_new(eddc, 2);
1844 } /* eet_data_descriptor_file_new */
1845
1846 EAPI void
1847 eet_data_descriptor_free(Eet_Data_Descriptor *edd)
1848 {
1849    if (!edd)
1850       return;
1851
1852    _eet_descriptor_hash_free(edd);
1853    if (edd->elements.set)
1854       free(edd->elements.set);
1855
1856    free(edd);
1857 } /* eet_data_descriptor_free */
1858
1859 EAPI void
1860 eet_data_descriptor_element_add(Eet_Data_Descriptor *edd,
1861                                 const char          *name,
1862                                 int                  type,
1863                                 int                  group_type,
1864                                 int                  offset,
1865                                 int                  count,
1866 /*        int counter_offset, */
1867                                 const char          *counter_name /* FIXME: Useless should go on a major release */,
1868                                 Eet_Data_Descriptor *subtype)
1869 {
1870    Eet_Data_Element *ede;
1871    Eet_Data_Element *tmp;
1872
1873    /* UNION, VARIANT type would not work with simple type, we need a way to map the type. */
1874    if ((group_type == EET_G_UNION
1875         || group_type == EET_G_VARIANT)
1876        &&
1877        (type != EET_T_UNKNOW
1878         || !subtype
1879         || !subtype->func.type_get
1880         || !subtype->func.type_set))
1881       return;
1882
1883    /* VARIANT type will only work if the map only contains EET_G_*, but not UNION, VARIANT and ARRAY. */
1884    if (group_type == EET_G_VARIANT)
1885      {
1886         int i;
1887
1888         for (i = 0; i < subtype->elements.num; ++i)
1889            if (subtype->elements.set[i].type != EET_T_UNKNOW
1890                && subtype->elements.set[i].group_type > EET_G_VAR_ARRAY
1891                && subtype->elements.set[i].group_type < EET_G_UNION)
1892               return;
1893
1894         subtype->unified_type = EINA_TRUE;
1895      }
1896
1897    if (subtype
1898        && subtype->unified_type
1899        && (type != EET_T_UNKNOW
1900            || group_type < EET_G_UNION))
1901       return;
1902
1903    /* Sanity check done, let allocate ! */
1904    edd->elements.num++;
1905    tmp = realloc(edd->elements.set, edd->elements.num * sizeof(Eet_Data_Element));
1906    if (!tmp)
1907       return;
1908
1909    edd->elements.set = tmp;
1910    ede = &(edd->elements.set[edd->elements.num - 1]);
1911    ede->name = name;
1912    ede->directory_name_ptr = NULL;
1913
1914    /*
1915     * We do a special case when we do list,hash or whatever group of simple type.
1916     * Instead of handling it in encode/decode/dump/undump, we create an
1917     * implicit structure with only the simple type.
1918     */
1919    if ((group_type > EET_G_UNKNOWN)
1920        && (group_type < EET_G_LAST)
1921        && (((type > EET_T_UNKNOW) && (type < EET_T_STRING))
1922            || ((type > EET_T_NULL) && (type < EET_T_LAST)))
1923        && (!subtype))
1924      {
1925         subtype = calloc(1, sizeof (Eet_Data_Descriptor));
1926         if (!subtype)
1927            return;
1928
1929         subtype->name = "implicit";
1930         subtype->size = eet_basic_codec[type - 1].size;
1931         memcpy(&subtype->func, &edd->func, sizeof(subtype->func));
1932
1933         eet_data_descriptor_element_add(subtype,
1934                                         eet_basic_codec[type - 1].name,
1935                                         type,
1936                                         EET_G_UNKNOWN,
1937                                         0,
1938                                         0,
1939                                         /* 0,  */ NULL,
1940                                         NULL);
1941         type = EET_T_UNKNOW;
1942      }
1943
1944    ede->type = type;
1945    ede->group_type = group_type;
1946    ede->offset = offset;
1947    ede->count = count;
1948    /* FIXME: For the time being, VAR_ARRAY, UNION and VARIANT  will put the counter_offset in count. */
1949    ede->counter_offset = count;
1950 /*    ede->counter_offset = counter_offset; */
1951    ede->counter_name = counter_name;
1952
1953    ede->subtype = subtype;
1954 } /* eet_data_descriptor_element_add */
1955
1956 EAPI void *
1957 eet_data_read_cipher(Eet_File            *ef,
1958                      Eet_Data_Descriptor *edd,
1959                      const char          *name,
1960                      const char          *cipher_key)
1961 {
1962    const Eet_Dictionary *ed = NULL;
1963    const void *data = NULL;
1964    void *data_dec;
1965    Eet_Free_Context context;
1966    int required_free = 0;
1967    int size;
1968
1969    ed = eet_dictionary_get(ef);
1970
1971    if (!cipher_key)
1972       data = eet_read_direct(ef, name, &size);
1973
1974    if (!data)
1975      {
1976         required_free = 1;
1977         data = eet_read_cipher(ef, name, &size, cipher_key);
1978         if (!data)
1979            return NULL;
1980      }
1981
1982    eet_free_context_init(&context);
1983    data_dec = _eet_data_descriptor_decode(&context, ed, edd, data, size);
1984    eet_free_context_shutdown(&context);
1985
1986    if (required_free)
1987       free((void *)data);
1988
1989    return data_dec;
1990 } /* eet_data_read_cipher */
1991
1992 EAPI Eet_Node *
1993 eet_data_node_read_cipher(Eet_File   *ef,
1994                           const char *name,
1995                           const char *cipher_key)
1996 {
1997    const Eet_Dictionary *ed = NULL;
1998    const void *data = NULL;
1999    Eet_Node *result;
2000    Eet_Free_Context context;
2001    int required_free = 0;
2002    int size;
2003
2004    ed = eet_dictionary_get(ef);
2005
2006    if (!cipher_key)
2007       data = eet_read_direct(ef, name, &size);
2008
2009    if (!data)
2010      {
2011         required_free = 1;
2012         data = eet_read_cipher(ef, name, &size, cipher_key);
2013         if (!data)
2014            return NULL;
2015      }
2016
2017    eet_free_context_init(&context);
2018    result = _eet_data_descriptor_decode(&context, ed, NULL, data, size);
2019    eet_free_context_shutdown(&context);
2020
2021    if (required_free)
2022       free((void *)data);
2023
2024    return result;
2025 } /* eet_data_node_read_cipher */
2026
2027 EAPI void *
2028 eet_data_read(Eet_File            *ef,
2029               Eet_Data_Descriptor *edd,
2030               const char          *name)
2031 {
2032    return eet_data_read_cipher(ef, edd, name, NULL);
2033 } /* eet_data_read */
2034
2035 EAPI int
2036 eet_data_write_cipher(Eet_File            *ef,
2037                       Eet_Data_Descriptor *edd,
2038                       const char          *name,
2039                       const char          *cipher_key,
2040                       const void          *data,
2041                       int                  compress)
2042 {
2043    Eet_Dictionary *ed;
2044    void *data_enc;
2045    int size;
2046    int val;
2047
2048    ed = eet_dictionary_get(ef);
2049
2050    data_enc = _eet_data_descriptor_encode(ed, edd, data, &size);
2051    if (!data_enc)
2052       return 0;
2053
2054    val = eet_write_cipher(ef, name, data_enc, size, compress, cipher_key);
2055    free(data_enc);
2056    return val;
2057 } /* eet_data_write_cipher */
2058
2059 EAPI int
2060 eet_data_write(Eet_File            *ef,
2061                Eet_Data_Descriptor *edd,
2062                const char          *name,
2063                const void          *data,
2064                int                  compress)
2065 {
2066    return eet_data_write_cipher(ef, edd, name, NULL, data, compress);
2067 } /* eet_data_write */
2068
2069 static void
2070 eet_free_context_init(Eet_Free_Context *context)
2071 {
2072    unsigned int i = 0;
2073
2074    memset(context, 0, sizeof (Eet_Free_Context));
2075    for (i = 0; i < EET_FREE_COUNT; ++i)
2076      {
2077         eina_array_step_set(&context->freelist.list[i],
2078                             sizeof (context->freelist.list[i]),
2079                             32);
2080         eina_array_step_set(&context->freelist_array.list[i],
2081                             sizeof (context->freelist.list[i]),
2082                             32);
2083         eina_array_step_set(&context->freelist_list.list[i],
2084                             sizeof (context->freelist.list[i]),
2085                             32);
2086         eina_array_step_set(&context->freelist_hash.list[i],
2087                             sizeof (context->freelist.list[i]),
2088                             32);
2089         eina_array_step_set(&context->freelist_str.list[i],
2090                             sizeof (context->freelist.list[i]),
2091                             32);
2092         eina_array_step_set(&context->freelist_direct_str.list[i],
2093                             sizeof (context->freelist.list[i]),
2094                             32);
2095      }
2096 }
2097
2098 static void
2099 eet_free_context_shutdown(Eet_Free_Context *context)
2100 {
2101    unsigned int i = 0;
2102
2103    for (i = 0; i < EET_FREE_COUNT; ++i)
2104      {
2105         eina_array_flush(&context->freelist.list[i]);
2106         eina_array_flush(&context->freelist_array.list[i]);
2107         eina_array_flush(&context->freelist_list.list[i]);
2108         eina_array_flush(&context->freelist_hash.list[i]);
2109         eina_array_flush(&context->freelist_str.list[i]);
2110         eina_array_flush(&context->freelist_direct_str.list[i]);
2111      }
2112 }
2113
2114 static int
2115 _eet_free_hash(void *data)
2116 {
2117 #ifdef _WIN64
2118    __int64 ptr = (UINT_PTR)data;
2119 #else /* ifdef _WIN64 */
2120    unsigned long ptr = (unsigned long)(data);
2121 #endif /* ifdef _WIN64 */
2122    int hash;
2123
2124    hash = ptr;
2125    hash ^= ptr >> 8;
2126    hash ^= ptr >> 16;
2127    hash ^= ptr >> 24;
2128
2129 #if defined (_WIN64) || ((!defined (_WIN32)) && (LONG_BIT != 32))
2130    hash ^= ptr >> 32;
2131    hash ^= ptr >> 40;
2132    hash ^= ptr >> 48;
2133    hash ^= ptr >> 56;
2134 #endif /* if defined (_WIN64) || ((!defined (_WIN32)) && (LONG_BIT != 32)) */
2135
2136    return hash & 0xFF;
2137 } /* _eet_free_hash */
2138
2139 static void
2140 _eet_free_add(Eet_Free *ef,
2141               void     *data)
2142 {
2143    void *track;
2144    Eina_Array_Iterator it;
2145    unsigned int i;
2146    int hash;
2147
2148    hash = _eet_free_hash(data);
2149
2150    EINA_ARRAY_ITER_NEXT(&ef->list[hash], i, track, it)
2151      if (track == data)
2152        return;
2153
2154    eina_array_push(&ef->list[hash], data);
2155 } /* _eet_free_add */
2156
2157 static void
2158 _eet_free_del(Eet_Free *ef,
2159               void     *data)
2160 {
2161    void *track;
2162    Eina_Array_Iterator it;
2163    unsigned int i;
2164    int hash;
2165
2166    hash = _eet_free_hash(data);
2167
2168    EINA_ARRAY_ITER_NEXT(&ef->list[hash], i, track, it)
2169      if (track == data)
2170        {
2171           eina_array_data_set(&ef->list[hash], i, NULL);
2172           return;
2173        }
2174 }
2175
2176 static void
2177 _eet_free_reset(Eet_Free *ef)
2178 {
2179    unsigned int i;
2180
2181    if (ef->ref > 0)
2182       return;
2183
2184    for (i = 0; i < EET_FREE_COUNT; ++i)
2185      eina_array_clean(&ef->list[i]);
2186 } /* _eet_free_reset */
2187
2188 static void
2189 _eet_free_ref(Eet_Free *ef)
2190 {
2191    ef->ref++;
2192 } /* _eet_free_ref */
2193
2194 static void
2195 _eet_free_unref(Eet_Free *ef)
2196 {
2197    ef->ref--;
2198 } /* _eet_free_unref */
2199
2200 #define _eet_freelist_add(Ctx, Data) _eet_free_add(&Ctx->freelist, Data);
2201 #define _eet_freelist_del(Ctx, Data) _eet_free_del(&Ctx->freelist, Data);
2202 #define _eet_freelist_reset(Ctx)     _eet_free_reset(&Ctx->freelist);
2203 #define _eet_freelist_ref(Ctx)       _eet_free_ref(&Ctx->freelist);
2204 #define _eet_freelist_unref(Ctx)     _eet_free_unref(&Ctx->freelist);
2205
2206 static void
2207 _eet_freelist_free(Eet_Free_Context    *context,
2208                    Eet_Data_Descriptor *edd)
2209 {
2210    void *track;
2211    Eina_Array_Iterator it;
2212    unsigned int j;
2213    unsigned int i;
2214
2215    if (context->freelist.ref > 0)
2216       return;
2217
2218    for (j = 0; j < EET_FREE_COUNT; ++j)
2219      EINA_ARRAY_ITER_NEXT(&context->freelist.list[j], i, track, it)
2220        if (track)
2221          {
2222             if (edd)
2223               edd->func.mem_free(track);
2224             else
2225               free(track);
2226          }
2227    _eet_free_reset(&context->freelist);
2228 } /* _eet_freelist_free */
2229
2230 #define _eet_freelist_array_add(Ctx, Data) _eet_free_add(&Ctx->freelist_array, Data);
2231 #define _eet_freelist_array_del(Ctx, Data) _eet_free_del(&Ctx->freelist_array, Data);
2232 #define _eet_freelist_array_reset(Ctx)     _eet_free_reset(&Ctx->freelist_array);
2233 #define _eet_freelist_array_ref(Ctx)       _eet_free_ref(&Ctx->freelist_array);
2234 #define _eet_freelist_array_unref(Ctx)     _eet_free_unref(&Ctx->freelist_array);
2235
2236 static void
2237 _eet_freelist_array_free(Eet_Free_Context    *context,
2238                          Eet_Data_Descriptor *edd)
2239 {
2240    void *track;
2241    Eina_Array_Iterator it;
2242    unsigned int j;
2243    unsigned int i;
2244
2245    if (context->freelist_array.ref > 0)
2246       return;
2247
2248    for (j = 0; j < EET_FREE_COUNT; ++j)
2249      EINA_ARRAY_ITER_NEXT(&context->freelist_array.list[j], i, track, it)
2250        if (track)
2251          {
2252             if (edd)
2253               {
2254                  if (edd->func.array_free)
2255                    edd->func.array_free(track);
2256                  else
2257                    edd->func.mem_free(track);
2258               }
2259             else
2260               free(track);
2261          }
2262    _eet_free_reset(&context->freelist_array);
2263 } /* _eet_freelist_array_free */
2264
2265 #define _eet_freelist_list_add(Ctx, Data) _eet_free_add(&Ctx->freelist_list, Data);
2266 #define _eet_freelist_list_del(Ctx, Data) _eet_free_del(&Ctx->freelist_list, Data);
2267 #define _eet_freelist_list_reset(Ctx)     _eet_free_reset(&Ctx->freelist_list);
2268 #define _eet_freelist_list_ref(Ctx)       _eet_free_ref(&Ctx->freelist_list);
2269 #define _eet_freelist_list_unref(Ctx)     _eet_free_unref(&Ctx->freelist_list);
2270
2271 static void
2272 _eet_freelist_list_free(Eet_Free_Context    *context,
2273                         Eet_Data_Descriptor *edd)
2274 {
2275    void *track;
2276    Eina_Array_Iterator it;
2277    unsigned int j;
2278    unsigned int i;
2279
2280    if (context->freelist_list.ref > 0)
2281       return;
2282
2283    for (j = 0; j < EET_FREE_COUNT; ++j)
2284      EINA_ARRAY_ITER_NEXT(&context->freelist_list.list[j], i, track, it)
2285        if (track)
2286          {
2287             if (edd)
2288               edd->func.list_free(*((void **)(track)));
2289          }
2290    _eet_free_reset(&context->freelist_list);
2291 } /* _eet_freelist_list_free */
2292
2293 #define _eet_freelist_str_add(Ctx, Data) _eet_free_add(&Ctx->freelist_str, Data);
2294 #define _eet_freelist_str_del(Ctx, Data) _eet_free_del(&Ctx->freelist_str, Data);
2295 #define _eet_freelist_str_reset(Ctx)     _eet_free_reset(&Ctx->freelist_str);
2296 #define _eet_freelist_str_ref(Ctx)       _eet_free_ref(&Ctx->freelist_str);
2297 #define _eet_freelist_str_unref(Ctx)     _eet_free_unref(&Ctx->freelist_str);
2298
2299 static void
2300 _eet_freelist_str_free(Eet_Free_Context *context, Eet_Data_Descriptor *edd)
2301 {
2302    void *track;
2303    Eina_Array_Iterator it;
2304    unsigned int j;
2305    unsigned int i;
2306
2307    if (context->freelist_str.ref > 0)
2308       return;
2309
2310    for (j = 0; j < EET_FREE_COUNT; ++j)
2311      EINA_ARRAY_ITER_NEXT(&context->freelist_str.list[j], i, track, it)
2312        if (track)
2313          {
2314             if (edd)
2315               edd->func.str_free(track);
2316             else
2317               free(track);
2318          }
2319    _eet_free_reset(&context->freelist_str);
2320 } /* _eet_freelist_str_free */
2321
2322 #define _eet_freelist_direct_str_add(Ctx, Data) _eet_free_add(&Ctx->freelist_direct_str, Data);
2323 #define _eet_freelist_direct_str_del(Ctx, Data) _eet_free_del(&Ctx->freelist_direct_str, Data);
2324 #define _eet_freelist_direct_str_reset(Ctx)     _eet_free_reset(&Ctx->freelist_direct_str);
2325 #define _eet_freelist_direct_str_ref(Ctx)       _eet_free_ref(&Ctx->freelist_direct_str);
2326 #define _eet_freelist_direct_str_unref(Ctx)     _eet_free_unref(&Ctx->freelist_direct_str);
2327
2328 static void
2329 _eet_freelist_direct_str_free(Eet_Free_Context    *context,
2330                               Eet_Data_Descriptor *edd)
2331 {
2332    void *track;
2333    Eina_Array_Iterator it;
2334    unsigned int j;
2335    unsigned int i;
2336
2337    if (context->freelist_direct_str.ref > 0)
2338       return;
2339
2340    for (j = 0; j < EET_FREE_COUNT; ++j)
2341      EINA_ARRAY_ITER_NEXT(&context->freelist_str.list[j], i, track, it)
2342        if (track)
2343          {
2344             if (edd)
2345               edd->func.str_direct_free(track);
2346             else
2347               free(track);
2348           }
2349    _eet_free_reset(&context->freelist_direct_str);
2350 } /* _eet_freelist_direct_str_free */
2351
2352 #define _eet_freelist_hash_add(Ctx, Data) _eet_free_add(&Ctx->freelist_hash, Data);
2353 #define _eet_freelist_hash_del(Ctx, Data) _eet_free_del(&Ctx->freelist_hash, Data);
2354 #define _eet_freelist_hash_reset(Ctx)     _eet_free_reset(&Ctx->freelist_hash);
2355 #define _eet_freelist_hash_ref(Ctx)       _eet_free_ref(&Ctx->freelist_hash);
2356 #define _eet_freelist_hash_unref(Ctx)     _eet_free_unref(&Ctx->freelist_hash);
2357
2358 static void
2359 _eet_freelist_hash_free(Eet_Free_Context    *context,
2360                         Eet_Data_Descriptor *edd)
2361 {
2362    void *track;
2363    Eina_Array_Iterator it;
2364    unsigned int j;
2365    unsigned int i;
2366
2367    if (context->freelist_hash.ref > 0)
2368       return;
2369
2370    for (j = 0; j < EET_FREE_COUNT; ++j)
2371      EINA_ARRAY_ITER_NEXT(&context->freelist_hash.list[j], i, track, it)
2372        if (track)
2373          {
2374             if (edd)
2375               edd->func.hash_free(track);
2376             else
2377               free(track);
2378          }
2379    _eet_free_reset(&context->freelist_hash);
2380 } /* _eet_freelist_hash_free */
2381
2382 static void
2383 _eet_freelist_all_ref(Eet_Free_Context *freelist_context)
2384 {
2385    _eet_freelist_ref(freelist_context);
2386    _eet_freelist_str_ref(freelist_context);
2387    _eet_freelist_list_ref(freelist_context);
2388    _eet_freelist_hash_ref(freelist_context);
2389    _eet_freelist_direct_str_ref(freelist_context);
2390 } /* _eet_freelist_all_ref */
2391
2392 static void
2393 _eet_freelist_all_unref(Eet_Free_Context *freelist_context)
2394 {
2395    _eet_freelist_unref(freelist_context);
2396    _eet_freelist_str_unref(freelist_context);
2397    _eet_freelist_list_unref(freelist_context);
2398    _eet_freelist_hash_unref(freelist_context);
2399    _eet_freelist_direct_str_unref(freelist_context);
2400 } /* _eet_freelist_all_unref */
2401
2402 static int
2403 eet_data_descriptor_encode_hash_cb(void *hash  __UNUSED__,
2404                                    const char *cipher_key,
2405                                    void       *hdata,
2406                                    void       *fdata)
2407 {
2408    Eet_Dictionary *ed;
2409    Eet_Data_Encode_Hash_Info *edehi;
2410    Eet_Data_Stream *ds;
2411    Eet_Data_Element *ede;
2412    Eet_Data_Chunk *echnk;
2413    void *data = NULL;
2414    int size;
2415
2416    edehi = fdata;
2417    ede = edehi->ede;
2418    ds = edehi->ds;
2419    ed = edehi->ed;
2420
2421    /* Store key */
2422    data = eet_data_put_type(ed,
2423                             EET_T_STRING,
2424                             &cipher_key,
2425                             &size);
2426    if (data)
2427      {
2428         echnk = eet_data_chunk_new(data,
2429                                    size,
2430                                    ede->name,
2431                                    ede->type,
2432                                    ede->group_type);
2433         eet_data_chunk_put(ed, echnk, ds);
2434         eet_data_chunk_free(echnk);
2435         free(data);
2436         data = NULL;
2437      }
2438
2439    EET_ASSERT(!((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING)), return );
2440
2441    /* Store data */
2442    if (ede->type >= EET_T_STRING)
2443       eet_data_put_unknown(ed, NULL, ede, ds, &hdata);
2444    else
2445      {
2446         if (ede->subtype)
2447            data = _eet_data_descriptor_encode(ed,
2448                                               ede->subtype,
2449                                               hdata,
2450                                               &size);
2451
2452         if (data)
2453           {
2454              echnk = eet_data_chunk_new(data,
2455                                         size,
2456                                         ede->name,
2457                                         ede->type,
2458                                         ede->group_type);
2459              eet_data_chunk_put(ed, echnk, ds);
2460              eet_data_chunk_free(echnk);
2461              free(data);
2462              data = NULL;
2463           }
2464      }
2465
2466    return 1;
2467 } /* eet_data_descriptor_encode_hash_cb */
2468
2469 static char *
2470 _eet_data_dump_token_get(const char *src,
2471                          int        *len)
2472 {
2473    const char *p;
2474    char *tok = NULL;
2475    int in_token = 0;
2476    int in_quote = 0;
2477    int tlen = 0, tsize = 0;
2478
2479 #define TOK_ADD(x)\
2480    do {\
2481         tlen++;\
2482         if (tlen >= tsize)\
2483           {\
2484              tsize += 32;\
2485              tok = realloc(tok, tsize);\
2486           }\
2487         tok[tlen - 1] = x;\
2488      } while (0)
2489
2490    for (p = src; *len > 0; p++, (*len)--)
2491      {
2492         if (in_token)
2493           {
2494              if (in_quote)
2495                {
2496                   if ((p[0] == '\"') && (p > src) && (p[-1] != '\\'))
2497                      in_quote = 0;
2498                   else if ((p[0] == '\\') && (*len > 1) &&
2499                            (p[1] == '\"'))
2500                     {
2501 /* skip */
2502                     }
2503                   else if ((p[0] == '\\') && (p > src) && (p[-1] == '\\'))
2504                     {
2505 /* skip */
2506                     }
2507                   else if ((p[0] == '\\') && (*len > 1) && (p[1] == 'n'))
2508                     {
2509 /* skip */
2510                     }
2511                   else if ((p[0] == 'n') && (p > src) && (p[-1] == '\\'))
2512                      TOK_ADD('\n');
2513                   else
2514                      TOK_ADD(p[0]);
2515                }
2516              else
2517                {
2518                   if (p[0] == '\"')
2519                      in_quote = 1;
2520                   else
2521                     {
2522                        if ((isspace(p[0])) || (p[0] == ';')) /* token ends here */
2523                          {
2524                             TOK_ADD(0);
2525                             (*len)--;
2526                             return tok;
2527                          }
2528                        else
2529                           TOK_ADD(p[0]);
2530                     }
2531                }
2532           }
2533         else if (!((isspace(p[0])) || (p[0] == ';')))
2534           {
2535              in_token = 1;
2536              (*len)++;
2537              p--;
2538           }
2539      }
2540    if (in_token)
2541      {
2542         TOK_ADD(0);
2543         return tok;
2544      }
2545
2546    if (tok)
2547       free(tok);
2548
2549    return NULL;
2550 } /* _eet_data_dump_token_get */
2551
2552 static void
2553 eet_data_encode(Eet_Dictionary  *ed,
2554                 Eet_Data_Stream *ds,
2555                 void            *data,
2556                 const char      *name,
2557                 int              size,
2558                 int              type,
2559                 int              group_type)
2560 {
2561    Eet_Data_Chunk *echnk;
2562
2563    if (!data)
2564       type = EET_T_NULL;
2565
2566    if (group_type != EET_G_UNKNOWN)
2567       if (type >= EET_T_LAST)
2568          type = EET_T_UNKNOW;
2569
2570    echnk = eet_data_chunk_new(data, size, name, type, group_type);
2571    eet_data_chunk_put(ed, echnk, ds);
2572    eet_data_chunk_free(echnk);
2573    free(data);
2574 } /* eet_data_encode */
2575
2576 static void *
2577 _eet_data_dump_encode(int             parent_type,
2578                       Eet_Dictionary *ed,
2579                       Eet_Node       *node,
2580                       int            *size_ret)
2581 {
2582    Eet_Data_Chunk *chnk = NULL;
2583    Eet_Data_Stream *ds;
2584    void *cdata, *data;
2585    int csize, size;
2586    int count;
2587    int child_type;
2588    Eet_Node *n;
2589
2590    if (_eet_data_words_bigendian == -1)
2591      {
2592         unsigned long int v;
2593
2594         v = htonl(0x12345678);
2595         if (v == 0x12345678)
2596            _eet_data_words_bigendian = 1;
2597         else
2598            _eet_data_words_bigendian = 0;
2599      }
2600
2601    if (!node)
2602       return NULL;
2603
2604    ds = eet_data_stream_new();
2605    if (!ds)
2606       return NULL;
2607
2608    switch (node->type)
2609      {
2610       case EET_G_UNKNOWN:
2611          for (n = node->values; n; n = n->next)
2612            {
2613               data = _eet_data_dump_encode(node->type, ed, n, &size);
2614               if (data)
2615                 {
2616                    eet_data_stream_write(ds, data, size);
2617                    free(data);
2618                 }
2619            }
2620          break;
2621
2622       case EET_G_ARRAY:
2623       case EET_G_VAR_ARRAY:
2624          for (child_type = EET_T_NULL, n = node->values; n; n = n->next)
2625            {
2626               if (n->type != EET_T_NULL)
2627                 {
2628                    child_type = n->type;
2629                    break;
2630                 }
2631            }
2632
2633          data = eet_data_put_type(ed,
2634                                   EET_T_INT,
2635                                   &node->count,
2636                                   &size);
2637          eet_data_encode(ed,
2638                          ds,
2639                          data,
2640                          node->name,
2641                          size,
2642                          child_type,
2643                          node->type);
2644
2645          count = node->count;
2646
2647          for (n = node->values; n; n = n->next)
2648            {
2649               int pos = ds->pos;
2650
2651               switch (n->type)
2652                 {
2653                  case EET_T_STRING:
2654                  case EET_T_INLINED_STRING:
2655                     data = eet_data_put_type(ed,
2656                                              n->type,
2657                                              &(n->data.value.str),
2658                                              &size);
2659                     if (data)
2660                        eet_data_encode(ed,
2661                                        ds,
2662                                        data,
2663                                        node->name,
2664                                        size,
2665                                        n->type,
2666                                        node->type);
2667
2668                     break;
2669
2670                  case EET_T_NULL:
2671                     continue;
2672
2673                  default:
2674                     data = _eet_data_dump_encode(n->type, ed, n, &size);
2675                     eet_data_encode(ed,
2676                                     ds,
2677                                     data,
2678                                     node->name,
2679                                     size,
2680                                     n->type,
2681                                     node->type);
2682                     break;
2683                 } /* switch */
2684               if (ds->pos != pos)
2685                  count--;
2686            }
2687
2688          for (; count; count--)
2689            {
2690               eet_data_encode(ed,
2691                               ds,
2692                               NULL,
2693                               node->name,
2694                               0,
2695                               EET_T_NULL,
2696                               node->type);
2697            }
2698
2699          /* Array is somekind of special case, so we should embed it inside another chunk. */
2700          *size_ret = ds->pos;
2701          cdata = ds->data;
2702
2703          ds->data = NULL;
2704          ds->size = 0;
2705          eet_data_stream_free(ds);
2706
2707          return cdata;
2708          break;
2709
2710       case EET_G_LIST:
2711          for (n = node->values; n; n = n->next)
2712            {
2713               switch (n->type)
2714                 {
2715                  case EET_T_STRING:
2716                  case EET_T_INLINED_STRING:
2717                     data = eet_data_put_type(ed,
2718                                              n->type,
2719                                              &(n->data.value.str),
2720                                              &size);
2721                     if (data)
2722                        eet_data_encode(ed,
2723                                        ds,
2724                                        data,
2725                                        node->name,
2726                                        size,
2727                                        n->type,
2728                                        node->type);
2729
2730                     break;
2731
2732                  case EET_T_NULL:
2733                     continue;
2734
2735                  default:
2736                     data = _eet_data_dump_encode(node->type, ed, n, &size);
2737                     eet_data_encode(ed,
2738                                     ds,
2739                                     data,
2740                                     node->name,
2741                                     size,
2742                                     n->type,
2743                                     node->type);
2744                 } /* switch */
2745            }
2746
2747          /* List is another somekind of special case, every chunk is embed inside a list chunk. */
2748          *size_ret = ds->pos;
2749          cdata = ds->data;
2750
2751          ds->data = NULL;
2752          ds->size = 0;
2753          eet_data_stream_free(ds);
2754
2755          return cdata;
2756          break;
2757
2758       case EET_G_HASH:
2759          if (node->key)
2760            {
2761               data = eet_data_put_type(ed,
2762                                        EET_T_STRING,
2763                                        &node->key,
2764                                        &size);
2765               eet_data_encode(ed,
2766                               ds,
2767                               data,
2768                               node->name,
2769                               size,
2770                               node->type,
2771                               node->type);
2772            }
2773          else
2774             /* A Hash without key will not decode correctly. */
2775             return NULL;
2776
2777          for (n = node->values; n; n = n->next)
2778            {
2779               switch (n->type)
2780                 {
2781                  case EET_T_STRING:
2782                  case EET_T_INLINED_STRING:
2783                     data = eet_data_put_type(ed,
2784                                              n->type,
2785                                              &(n->data.value.str),
2786                                              &size);
2787                     if (data)
2788                        eet_data_encode(ed,
2789                                        ds,
2790                                        data,
2791                                        node->name,
2792                                        size,
2793                                        n->type,
2794                                        node->type);
2795
2796                     break;
2797
2798                  case EET_T_NULL:
2799                     continue;
2800
2801                  default:
2802                     data = _eet_data_dump_encode(node->type, ed, n, &size);
2803                     eet_data_encode(ed,
2804                                     ds,
2805                                     data,
2806                                     node->name,
2807                                     size,
2808                                     n->type,
2809                                     node->type);
2810                 } /* switch */
2811            }
2812
2813          /* Hash is somekind of special case, so we should embed it inside another chunk. */
2814          *size_ret = ds->pos;
2815          cdata = ds->data;
2816
2817          eet_data_stream_flush(ds);
2818
2819          return cdata;
2820
2821       case EET_T_NULL:
2822          break;
2823
2824 #define EET_DATA_NODE_ENCODE(Eet_Type, Type)\
2825  case Eet_Type:\
2826     data = eet_data_put_type(ed, node->type, &(node->data.value.Type), &size);\
2827     if (data)\
2828       {\
2829          eet_data_encode(ed,\
2830                          ds,\
2831                          data,\
2832                          node->name,\
2833                          size,\
2834                          node->type,\
2835                          parent_type);\
2836          cdata = ds->data;\
2837          *size_ret = ds->pos;\
2838          eet_data_stream_flush(ds);\
2839          return cdata;\
2840       } /* switch */\
2841     break;
2842
2843          EET_DATA_NODE_ENCODE(EET_T_CHAR,           c);
2844          EET_DATA_NODE_ENCODE(EET_T_SHORT,          s);
2845          EET_DATA_NODE_ENCODE(EET_T_INT,            i);
2846          EET_DATA_NODE_ENCODE(EET_T_LONG_LONG,      l);
2847          EET_DATA_NODE_ENCODE(EET_T_FLOAT,          f);
2848          EET_DATA_NODE_ENCODE(EET_T_DOUBLE,         d);
2849          EET_DATA_NODE_ENCODE(EET_T_UCHAR,          uc);
2850          EET_DATA_NODE_ENCODE(EET_T_USHORT,         us);
2851          EET_DATA_NODE_ENCODE(EET_T_UINT,           ui);
2852          EET_DATA_NODE_ENCODE(EET_T_ULONG_LONG,     ul);
2853          EET_DATA_NODE_ENCODE(EET_T_INLINED_STRING, str);
2854          EET_DATA_NODE_ENCODE(EET_T_STRING,         str);
2855
2856       default:
2857          break;
2858      }
2859
2860    if ((node->type >= EET_G_UNKNOWN) && (node->type < EET_G_LAST))
2861       chnk = eet_data_chunk_new(ds->data,
2862                                 ds->pos,
2863                                 node->name,
2864                                 EET_T_UNKNOW,
2865                                 node->type);
2866    else
2867       chnk = eet_data_chunk_new(ds->data,
2868                                 ds->pos,
2869                                 node->name,
2870                                 node->type,
2871                                 EET_G_UNKNOWN);
2872
2873    eet_data_stream_flush(ds);
2874
2875    ds = eet_data_stream_new();
2876    eet_data_chunk_put(ed, chnk, ds);
2877    cdata = ds->data;
2878    csize = ds->pos;
2879
2880    eet_data_stream_flush(ds);
2881    *size_ret = csize;
2882
2883    free(chnk->data);
2884    eet_data_chunk_free(chnk);
2885
2886    return cdata;
2887 } /* _eet_data_dump_encode */
2888
2889 static void *
2890 _eet_data_dump_parse(Eet_Dictionary *ed,
2891                      int            *size_ret,
2892                      const char     *src,
2893                      int             size)
2894 {
2895    void *cdata = NULL;
2896    const char *p = NULL;
2897 #define M_NONE   0
2898 #define M_STRUCT 1
2899 #define M_       2
2900    int left, jump;
2901    Eet_Node *node_base = NULL;
2902    Eet_Node *node = NULL;
2903    Eet_Node *n = NULL, *nn = NULL;
2904
2905    /* FIXME; handle parse errors */
2906 #define TOK_GET(t)\
2907    jump = left; t = _eet_data_dump_token_get(p, &left); p += jump - left;
2908    left = size;
2909    for (p = src; p < (src + size); )
2910      {
2911         char *tok1, *tok2, *tok3, *tok4;
2912
2913         TOK_GET(tok1);
2914         if (tok1)
2915           {
2916              if (!strcmp(tok1, "group"))
2917                {
2918                   TOK_GET(tok2);
2919                   if (tok2)
2920                     {
2921                        TOK_GET(tok3);
2922                        if (tok3)
2923                          {
2924                             TOK_GET(tok4);
2925                             if (tok4)
2926                               {
2927                                  if (!strcmp(tok4, "{"))
2928                                    {
2929 /* we have 'group NAM TYP {' */
2930                                       n = eet_node_new();
2931                                       if (n)
2932                                         {
2933                                            n->parent = node;
2934                                            if (!node_base)
2935                                               node_base = n;
2936
2937                                            if (node)
2938                                              {
2939 /* append node */
2940                                                 if (!node->values)
2941                                                    node->values = n;
2942                                                 else
2943                                                    for (nn = node->values; nn;
2944                                                         nn = nn->next)
2945                                                      {
2946                                                         if (!nn->next)
2947                                                           {
2948                                                              nn->next = n;
2949                                                              break;
2950                                                           }
2951                                                      }
2952                                              }
2953
2954                                            n->name = eina_stringshare_add(tok2);
2955                                            if      (!strcmp(tok3, "struct"))
2956                                               n->type = EET_G_UNKNOWN;
2957                                            else if (!strcmp(tok3, "array"))
2958                                               n->type = EET_G_ARRAY;
2959                                            else if (!strcmp(tok3, "var_array"))
2960                                               n->type = EET_G_VAR_ARRAY;
2961                                            else if (!strcmp(tok3, "list"))
2962                                               n->type = EET_G_LIST;
2963                                            else if (!strcmp(tok3, "hash"))
2964                                               n->type = EET_G_HASH;
2965                                            else
2966                                               ERR(
2967                                                  "ERROR: group type '%s' invalid.",
2968                                                  tok3);
2969
2970                                            node = n;
2971                                         }
2972                                    }
2973
2974                                  free(tok4);
2975                               }
2976
2977                             free(tok3);
2978                          }
2979
2980                        free(tok2);
2981                     }
2982                }
2983              else if (!strcmp(tok1, "value"))
2984                {
2985                   TOK_GET(tok2);
2986                   if (tok2)
2987                     {
2988                        TOK_GET(tok3);
2989                        if (tok3)
2990                          {
2991                             TOK_GET(tok4);
2992                             if (tok4)
2993                               {
2994 /* we have 'value NAME TYP XXX' */
2995                                  if (node_base)
2996                                    {
2997                                       n = eet_node_new();
2998                                       if (n)
2999                                         {
3000                                            n->parent = node;
3001 /* append node */
3002                                            if (!node->values)
3003                                               node->values = n;
3004                                            else
3005                                               for (nn = node->values; nn;
3006                                                    nn = nn->next)
3007                                                 {
3008                                                    if (!nn->next)
3009                                                      {
3010                                                         nn->next = n;
3011                                                         break;
3012                                                      }
3013                                                 }
3014
3015                                            n->name = eina_stringshare_add(tok2);
3016                                            if      (!strcmp(tok3, "char:"))
3017                                              {
3018                                                 n->type = EET_T_CHAR;
3019                                                 sscanf(tok4, "%hhi",
3020                                                        &(n->data.value.c));
3021                                              }
3022                                            else if (!strcmp(tok3, "short:"))
3023                                              {
3024                                                 n->type = EET_T_SHORT;
3025                                                 sscanf(tok4, "%hi",
3026                                                        &(n->data.value.s));
3027                                              }
3028                                            else if (!strcmp(tok3, "int:"))
3029                                              {
3030                                                 n->type = EET_T_INT;
3031                                                 sscanf(tok4, "%i",
3032                                                        &(n->data.value.i));
3033                                              }
3034                                            else if (!strcmp(tok3, "long_long:"))
3035                                              {
3036                                                 n->type = EET_T_LONG_LONG;
3037                                                 sscanf(tok4, "%lli",
3038                                                        &(n->data.value.l));
3039                                              }
3040                                            else if (!strcmp(tok3, "float:"))
3041                                              {
3042                                                 n->type = EET_T_FLOAT;
3043                                                 sscanf(tok4, "%f",
3044                                                        &(n->data.value.f));
3045                                              }
3046                                            else if (!strcmp(tok3, "double:"))
3047                                              {
3048                                                 n->type = EET_T_DOUBLE;
3049                                                 sscanf(tok4, "%lf",
3050                                                        &(n->data.value.d));
3051                                              }
3052                                            else if (!strcmp(tok3, "uchar:"))
3053                                              {
3054                                                 n->type = EET_T_UCHAR;
3055                                                 sscanf(tok4, "%hhu",
3056                                                        &(n->data.value.uc));
3057                                              }
3058                                            else if (!strcmp(tok3, "ushort:"))
3059                                              {
3060                                                 n->type = EET_T_USHORT;
3061                                                 sscanf(tok4, "%hu",
3062                                                        &(n->data.value.us));
3063                                              }
3064                                            else if (!strcmp(tok3, "uint:"))
3065                                              {
3066                                                 n->type = EET_T_UINT;
3067                                                 sscanf(tok4, "%u",
3068                                                        &(n->data.value.ui));
3069                                              }
3070                                            else if (!strcmp(tok3, "ulong_long:"))
3071                                              {
3072                                                 n->type = EET_T_ULONG_LONG;
3073                                                 sscanf(tok4, "%llu",
3074                                                        &(n->data.value.ul));
3075                                              }
3076                                            else if (!strcmp(tok3, "string:"))
3077                                              {
3078                                                 n->type = EET_T_STRING;
3079                                                 n->data.value.str =
3080                                                    eina_stringshare_add(tok4);
3081                                              }
3082                                            else if (!strcmp(tok3, "inlined:"))
3083                                              {
3084                                                 n->type = EET_T_INLINED_STRING;
3085                                                 n->data.value.str =
3086                                                    eina_stringshare_add(tok4);
3087                                              }
3088                                            else if (!strcmp(tok3, "null"))
3089                                              {
3090                                                 n->type = EET_T_NULL;
3091                                                 n->data.value.str = NULL;
3092                                              }
3093                                            else
3094                                               ERR(
3095                                                  "ERROR: value type '%s' invalid.",
3096                                                  tok4);
3097                                         }
3098                                    }
3099
3100                                  free(tok4);
3101                               }
3102
3103                             free(tok3);
3104                          }
3105
3106                        free(tok2);
3107                     }
3108                }
3109              else if (!strcmp(tok1, "key"))
3110                {
3111                   TOK_GET(tok2);
3112                   if (tok2)
3113                     {
3114 /* we have 'key NAME' */
3115                        if (node)
3116                           node->key = eina_stringshare_add(tok2);
3117
3118                        free(tok2);
3119                     }
3120                }
3121              else if (!strcmp(tok1, "count"))
3122                {
3123                   TOK_GET(tok2);
3124                   if (tok2)
3125                     {
3126 /* we have a 'count COUNT' */
3127                        if (node)
3128                           sscanf(tok2, "%i", &(node->count));
3129
3130                        free(tok2);
3131                     }
3132                }
3133              else if (!strcmp(tok1, "}"))
3134                 /* we have an end of the group */
3135                 if (node)
3136                    node = node->parent;
3137
3138              free(tok1);
3139           }
3140      }
3141
3142    if (node_base)
3143      {
3144         cdata = _eet_data_dump_encode(EET_G_UNKNOWN, ed, node_base, size_ret);
3145         eet_node_del(node_base);
3146      }
3147
3148    return cdata;
3149 } /* _eet_data_dump_parse */
3150
3151 #define NEXT_CHUNK(P, Size, Echnk, Ed)\
3152    {\
3153       int tmp;\
3154       tmp = Ed ? (int)(sizeof(int) * 2) : Echnk.len + 4;\
3155       P += (4 + Echnk.size + tmp);\
3156       Size -= (4 + Echnk.size + tmp);\
3157    }
3158
3159 static void *
3160 _eet_data_descriptor_decode(Eet_Free_Context     *context,
3161                             const Eet_Dictionary *ed,
3162                             Eet_Data_Descriptor  *edd,
3163                             const void           *data_in,
3164                             int                   size_in)
3165 {
3166    Eet_Node *result = NULL;
3167    void *data = NULL;
3168    char *p;
3169    int size, i;
3170    Eet_Data_Chunk chnk;
3171
3172    if (_eet_data_words_bigendian == -1)
3173      {
3174         unsigned long int v;
3175
3176         v = htonl(0x12345678);
3177         if (v == 0x12345678)
3178            _eet_data_words_bigendian = 1;
3179         else
3180            _eet_data_words_bigendian = 0;
3181      }
3182
3183    if (edd)
3184      {
3185         data = edd->func.mem_alloc(edd->size);
3186         if (!data)
3187            return NULL;
3188
3189         if (edd->ed != ed)
3190           {
3191              for (i = 0; i < edd->elements.num; i++)
3192                 edd->elements.set[i].directory_name_ptr = NULL;
3193              edd->ed = ed;
3194           }
3195      }
3196
3197    _eet_freelist_all_ref(context);
3198    if (data)
3199       _eet_freelist_add(context, data);
3200
3201    memset(&chnk, 0, sizeof(Eet_Data_Chunk));
3202    eet_data_chunk_get(ed, &chnk, data_in, size_in);
3203    if (!chnk.name)
3204       goto error;
3205
3206    if (edd)
3207       if (strcmp(chnk.name, edd->name))
3208          goto error;
3209
3210    p = chnk.data;
3211    if (ed)
3212       size = size_in - (4 + sizeof(int) * 2);
3213    else
3214       size = size_in - (4 + 4 + chnk.len);
3215
3216    if (edd)
3217      {
3218         if (!edd->elements.hash.buckets)
3219            _eet_descriptor_hash_new(edd);
3220      }
3221    else
3222      {
3223         switch (chnk.group_type)
3224           {
3225            case EET_G_UNKNOWN:
3226               switch (chnk.type)
3227                 {
3228                  case EET_T_STRING:
3229                     return eet_node_string_new(chnk.name, chnk.data);
3230
3231                  case EET_T_INLINED_STRING:
3232                     return eet_node_inlined_string_new(chnk.name, chnk.data);
3233
3234                  case EET_T_NULL:
3235                     return eet_node_null_new(chnk.name);
3236
3237                  default:
3238                     result = eet_node_struct_new(chnk.name, NULL);
3239                 } /* switch */
3240               break;
3241
3242            case EET_G_VAR_ARRAY:
3243               return eet_node_var_array_new(chnk.name, NULL);
3244
3245            case EET_G_LIST:
3246            case EET_G_HASH:
3247            case EET_G_ARRAY:
3248            case EET_G_UNION:
3249            case EET_G_VARIANT:
3250            default:
3251               goto error;
3252           } /* switch */
3253      }
3254
3255    while (size > 0)
3256      {
3257         Eet_Data_Chunk echnk;
3258         Eet_Data_Element *ede = NULL;
3259         Eet_Node *child = NULL;
3260         int group_type = EET_G_UNKNOWN, type = EET_T_UNKNOW;
3261         int ret = 0;
3262
3263         /* get next data chunk */
3264         memset(&echnk, 0, sizeof(Eet_Data_Chunk));
3265         eet_data_chunk_get(ed, &echnk, p, size);
3266         if (!echnk.name)
3267            goto error;  /* FIXME: don't REPLY on edd - work without */
3268
3269         if (edd)
3270           {
3271              ede = _eet_descriptor_hash_find(edd, echnk.name, echnk.hash);
3272              if (ede)
3273                {
3274                   group_type = ede->group_type;
3275                   type = ede->type;
3276                   if ((echnk.type == 0) && (echnk.group_type == 0))
3277                     {
3278                        type = ede->type;
3279                        group_type = ede->group_type;
3280                     }
3281                   else
3282                     {
3283                        if (IS_SIMPLE_TYPE(echnk.type) &&
3284                            eet_data_type_match(echnk.type, ede->type))
3285 /* Needed when converting on the fly from FP to Float */
3286                           type = ede->type;
3287                        else if ((echnk.group_type > EET_G_UNKNOWN) &&
3288                                 (echnk.group_type < EET_G_LAST) &&
3289                                 (echnk.group_type == ede->group_type))
3290                           group_type = echnk.group_type;
3291                     }
3292                }
3293           }
3294         /*...... dump to node */
3295         else
3296           {
3297              type = echnk.type;
3298              group_type = echnk.group_type;
3299           }
3300
3301         if (!edd && group_type == EET_G_UNKNOWN && IS_SIMPLE_TYPE(type))
3302           {
3303              unsigned char dd[128];
3304
3305              ret = eet_data_get_type(ed,
3306                                      type,
3307                                      echnk.data,
3308                                      ((char *)echnk.data) + echnk.size,
3309                                      dd);
3310              if (ret <= 0)
3311                 goto error;
3312
3313              child = eet_data_node_simple_type(type, echnk.name, dd);
3314
3315              eet_node_struct_append(result, echnk.name, child);
3316           }
3317         else
3318           {
3319              ret = eet_group_codec[group_type - 100].get(
3320                    context,
3321                    ed,
3322                    edd,
3323                    ede,
3324                    &echnk,
3325                    type,
3326                    group_type,
3327                    ede ? (void *)(((char*) data) + ede->offset) : (void **)&result,
3328                    &p,
3329                    &size);
3330
3331              if (ret <= 0)
3332                 goto error;
3333           }
3334
3335         /* advance to next chunk */
3336         NEXT_CHUNK(p, size, echnk, ed);
3337      }
3338
3339    _eet_freelist_all_unref(context);
3340    if (!edd)
3341      {
3342         _eet_freelist_str_free(context, edd);
3343         _eet_freelist_direct_str_free(context, edd);
3344         _eet_freelist_list_free(context, edd);
3345         _eet_freelist_hash_free(context, edd);
3346         _eet_freelist_array_free(context, edd);
3347         _eet_freelist_free(context, edd);
3348      }
3349    else
3350      {
3351         _eet_freelist_reset(context);
3352         _eet_freelist_str_reset(context);
3353         _eet_freelist_list_reset(context);
3354         _eet_freelist_hash_reset(context);
3355         _eet_freelist_direct_str_reset(context);
3356         _eet_freelist_array_reset(context);
3357      }
3358
3359    if (!edd)
3360       return result;
3361
3362    return data;
3363
3364 error:
3365    eet_node_del(result);
3366
3367    _eet_freelist_all_unref(context);
3368    _eet_freelist_str_free(context, edd);
3369    _eet_freelist_direct_str_free(context, edd);
3370    _eet_freelist_list_free(context, edd);
3371    _eet_freelist_hash_free(context, edd);
3372    _eet_freelist_array_free(context, edd);
3373    _eet_freelist_free(context, edd);
3374
3375    /* FIXME: Warn that something goes wrong here. */
3376    return NULL;
3377 } /* _eet_data_descriptor_decode */
3378
3379 static int
3380 eet_data_get_list(Eet_Free_Context     *context,
3381                   const Eet_Dictionary *ed,
3382                   Eet_Data_Descriptor  *edd,
3383                   Eet_Data_Element     *ede,
3384                   Eet_Data_Chunk       *echnk,
3385                   int                   type,
3386                   int group_type        __UNUSED__,
3387                   void                 *data,
3388                   char                **p,
3389                   int                  *size)
3390 {
3391    Eet_Data_Descriptor *subtype = NULL;
3392    void *list = NULL;
3393    void **ptr;
3394    void *data_ret;
3395
3396    EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0);
3397
3398    if (ede)
3399      {
3400         subtype = ede->subtype;
3401
3402         if (type != ede->type)
3403            return 0;
3404      }
3405
3406    ptr = (void **)data;
3407    list = *ptr;
3408    data_ret = NULL;
3409
3410    if (IS_POINTER_TYPE(type))
3411       POINTER_TYPE_DECODE(context,
3412                           ed,
3413                           edd,
3414                           ede,
3415                           echnk,
3416                           type,
3417                           &data_ret,
3418                           p,
3419                           size,
3420                           on_error);
3421    else
3422       STRUCT_TYPE_DECODE(data_ret,
3423                          context,
3424                          ed,
3425                          subtype,
3426                          echnk->data,
3427                          echnk->size,
3428                          on_error);
3429
3430    if (edd)
3431      {
3432         list = edd->func.list_append(list, data_ret);
3433         *ptr = list;
3434         _eet_freelist_list_add(context, ptr);
3435      }
3436    else
3437       eet_node_list_append(*((Eet_Node **)data), echnk->name, data_ret);
3438
3439    return 1;
3440
3441 on_error:
3442    return 0;
3443 } /* eet_data_get_list */
3444
3445 static int
3446 eet_data_get_hash(Eet_Free_Context     *context,
3447                   const Eet_Dictionary *ed,
3448                   Eet_Data_Descriptor  *edd,
3449                   Eet_Data_Element     *ede,
3450                   Eet_Data_Chunk       *echnk,
3451                   int                   type,
3452                   int group_type        __UNUSED__,
3453                   void                 *data,
3454                   char                **p,
3455                   int                  *size)
3456 {
3457    void **ptr;
3458    void *hash = NULL;
3459    char *key = NULL;
3460    void *data_ret = NULL;
3461    int ret = 0;
3462
3463    EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0);
3464
3465    ptr = (void **)data;
3466    hash = *ptr;
3467
3468    /* Read key */
3469    ret = eet_data_get_type(ed,
3470                            EET_T_STRING,
3471                            echnk->data,
3472                            ((char *)echnk->data) + echnk->size,
3473                            &key);
3474    if (ret <= 0)
3475       goto on_error;
3476
3477    if (!key)
3478       goto on_error;
3479
3480    /* Advance to next chunk */
3481    NEXT_CHUNK((*p), (*size), (*echnk), ed);
3482    memset(echnk, 0, sizeof(Eet_Data_Chunk));
3483
3484    /* Read value */
3485    eet_data_chunk_get(ed, echnk, *p, *size);
3486    if (!echnk->name)
3487       goto on_error;
3488
3489    if (ede)
3490      if ((ede->group_type != echnk->group_type)
3491          || (ede->type != echnk->type))
3492        goto on_error;
3493
3494    if (IS_POINTER_TYPE(echnk->type))
3495       POINTER_TYPE_DECODE(context,
3496                           ed,
3497                           edd,
3498                           ede,
3499                           echnk,
3500                           echnk->type,
3501                           &data_ret,
3502                           p,
3503                           size,
3504                           on_error);
3505    else
3506       STRUCT_TYPE_DECODE(data_ret,
3507                          context,
3508                          ed,
3509                          ede ? ede->subtype : NULL,
3510                          echnk->data,
3511                          echnk->size,
3512                          on_error);
3513
3514    if (edd)
3515      {
3516         hash = edd->func.hash_add(hash, key, data_ret);
3517         *ptr = hash;
3518         _eet_freelist_hash_add(context, hash);
3519      }
3520    else
3521       eet_node_hash_add(*((Eet_Node **)data), echnk->name, key, data_ret);
3522
3523    return 1;
3524
3525 on_error:
3526    return 0;
3527 } /* eet_data_get_hash */
3528
3529 /* var arrays and fixed arrays have to
3530  * get all chunks at once. for fixed arrays
3531  * we can get each chunk and increment a
3532  * counter stored on the element itself but
3533  * it wont be thread safe. for var arrays
3534  * we still need a way to get the number of
3535  * elements from the data, so storing the
3536  * number of elements and the element data on
3537  * each chunk is pointless.
3538  */
3539 static int
3540 eet_data_get_array(Eet_Free_Context     *context,
3541                    const Eet_Dictionary *ed,
3542                    Eet_Data_Descriptor  *edd,
3543                    Eet_Data_Element     *ede,
3544                    Eet_Data_Chunk       *echnk,
3545                    int                   type,
3546                    int                   group_type,
3547                    void                 *data,
3548                    char                **p,
3549                    int                  *size)
3550 {
3551    Eina_List *childs = NULL;
3552    const char *name;
3553    Eet_Node *tmp;
3554    void *ptr;
3555    int count;
3556    int ret;
3557    int subsize = 0;
3558    int i;
3559
3560    EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0);
3561
3562    ptr = data;
3563    /* read the number of elements */
3564    ret = eet_data_get_type(ed,
3565                            EET_T_INT,
3566                            echnk->data,
3567                            ((char *)echnk->data) + echnk->size,
3568                            &count);
3569    if (ret <= 0)
3570       return ret;
3571
3572    name = echnk->name;
3573
3574    if (ede)
3575      {
3576         if (IS_POINTER_TYPE(type))
3577            subsize = eet_basic_codec[ede->type].size;
3578         else
3579            subsize = ede->subtype->size;
3580
3581         if (group_type == EET_G_VAR_ARRAY)
3582           {
3583              /* store the number of elements
3584               * on the counter offset */
3585              *(int *)(((char *)data) + ede->count - ede->offset) = count;
3586              /* allocate space for the array of elements */
3587              if (edd->func.array_alloc)
3588                *(void **) ptr = edd->func.array_alloc(count * subsize);
3589              else
3590                *(void **) ptr = edd->func.mem_alloc(count * subsize);
3591
3592              if (!*(void **)ptr)
3593                 return 0;
3594
3595              memset(*(void **)ptr, 0, count * subsize);
3596
3597              _eet_freelist_array_add(context, *(void **)ptr);
3598           }
3599      }
3600
3601    /* get all array elements */
3602    for (i = 0; i < count; i++)
3603      {
3604         void *dst = NULL;
3605         void *data_ret = NULL;
3606
3607         /* Advance to next chunk */
3608         NEXT_CHUNK((*p), (*size), (*echnk), ed);
3609         memset(echnk, 0, sizeof(Eet_Data_Chunk));
3610
3611         eet_data_chunk_get(ed, echnk, *p, *size);
3612         if (!echnk->name || strcmp(echnk->name, name) != 0)
3613            goto on_error;  /* get the data */
3614
3615         if ((echnk->group_type != group_type)
3616             || ((echnk->type != type) && (echnk->type != EET_T_NULL)))
3617            goto on_error;
3618
3619         if (ede)
3620            if ((ede->group_type != echnk->group_type)
3621                || ((echnk->type != ede->type) && (echnk->type != EET_T_NULL)))
3622               goto on_error;
3623
3624         /* get the destination pointer */
3625         if (ede)
3626           {
3627              if (group_type == EET_G_ARRAY)
3628                 dst = (char *)ptr + (subsize * i);
3629              else
3630                 dst = *(char **)ptr + (subsize * i);
3631           }
3632
3633         if (IS_POINTER_TYPE(echnk->type))
3634           {
3635              POINTER_TYPE_DECODE(context,
3636                                  ed,
3637                                  edd,
3638                                  ede,
3639                                  echnk,
3640                                  echnk->type,
3641                                  &data_ret,
3642                                  p,
3643                                  size,
3644                                  on_error);
3645              if (dst)
3646                 memcpy(dst, &data_ret, subsize);
3647
3648              if (!edd)
3649                 childs = eina_list_append(childs, data_ret);
3650           }
3651         else
3652           {
3653              STRUCT_TYPE_DECODE(data_ret,
3654                                 context,
3655                                 ed,
3656                                 ede ? ede->subtype : NULL,
3657                                 echnk->data,
3658                                 echnk->size,
3659                                 on_error);
3660              if (dst)
3661                {
3662                   memcpy(dst, data_ret, subsize);
3663                   if ((ede) && (ede->subtype))
3664                      ede->subtype->func.mem_free(data_ret);
3665                   else if (edd)
3666                      edd->func.mem_free(data_ret);
3667                   else free(data_ret);
3668                   _eet_freelist_del(context, data_ret);
3669                }
3670
3671              if (!edd)
3672                 childs = eina_list_append(childs, data_ret);
3673           }
3674      }
3675
3676    if (!edd)
3677      {
3678         Eet_Node *parent = *((Eet_Node **)data);
3679         Eet_Node *array;
3680
3681         if (group_type == EET_G_ARRAY)
3682            array = eet_node_array_new(name, count, childs);
3683         else
3684            array = eet_node_var_array_new(name, childs);
3685
3686         if (!array)
3687            goto on_error;
3688
3689         eet_node_struct_append(parent, name, array);
3690      }
3691
3692    return 1;
3693
3694 on_error:
3695    EINA_LIST_FREE(childs, tmp)
3696    eet_node_del(tmp);
3697
3698    return 0;
3699 } /* eet_data_get_array */
3700
3701 static void
3702 eet_data_put_union(Eet_Dictionary          *ed,
3703                    Eet_Data_Descriptor *edd __UNUSED__,
3704                    Eet_Data_Element        *ede,
3705                    Eet_Data_Stream         *ds,
3706                    void                    *data_in)
3707 {
3708    const char *union_type;
3709    int i;
3710
3711    EET_ASSERT(!((ede->type != EET_T_UNKNOW) || (!ede->subtype)), return );
3712
3713    union_type = ede->subtype->func.type_get(
3714          ((char *)data_in) + ede->count - ede->offset,
3715          NULL);
3716
3717    if (!union_type)
3718       return;
3719
3720    /* Search the structure of the union to encode. */
3721    for (i = 0; i < ede->subtype->elements.num; ++i)
3722       if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0)
3723         {
3724            Eet_Data_Element *sede;
3725            void *data;
3726            int size;
3727
3728            /* Yeah we found it ! */
3729            data = eet_data_put_type(ed, EET_T_STRING, &union_type, &size);
3730            if (data)
3731               eet_data_encode(ed,
3732                               ds,
3733                               data,
3734                               ede->name,
3735                               size,
3736                               ede->type,
3737                               ede->group_type);
3738
3739            sede = &(ede->subtype->elements.set[i]);
3740            data = _eet_data_descriptor_encode(ed,
3741                                               sede->subtype,
3742                                               data_in,
3743                                               &size);
3744            if (data)
3745               eet_data_encode(ed,
3746                               ds,
3747                               data,
3748                               ede->name,
3749                               size,
3750                               ede->type,
3751                               ede->group_type);
3752
3753            break;
3754         }
3755
3756 } /* eet_data_put_union */
3757
3758 static int
3759 eet_data_get_union(Eet_Free_Context        *context,
3760                    const Eet_Dictionary    *ed,
3761                    Eet_Data_Descriptor *edd __UNUSED__,
3762                    Eet_Data_Element        *ede,
3763                    Eet_Data_Chunk          *echnk,
3764                    int                      type,
3765                    int                      group_type,
3766                    void                    *data,
3767                    char                   **p,
3768                    int                     *size)
3769 {
3770    const char *union_type;
3771    void *data_ret = NULL;
3772    int ret = 0;
3773    int i;
3774
3775    /* Read type */
3776    ret = eet_data_get_type(ed,
3777                            EET_T_STRING,
3778                            echnk->data,
3779                            ((char *)echnk->data) + echnk->size,
3780                            &union_type);
3781    if (ret <= 0)
3782       goto on_error;
3783
3784    /* Advance to next chunk */
3785    NEXT_CHUNK((*p), (*size), (*echnk), ed);
3786    memset(echnk, 0, sizeof(Eet_Data_Chunk));
3787
3788    /* Read value */
3789    eet_data_chunk_get(ed, echnk, *p, *size);
3790    if (!echnk->name)
3791       goto on_error;
3792
3793    if (ede)
3794      {
3795         EET_ASSERT(!(ede->group_type != group_type || ede->type != type),
3796                    goto on_error);
3797
3798         /* Search the structure of the union to decode */
3799         for (i = 0; i < ede->subtype->elements.num; ++i)
3800            if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0)
3801              {
3802                 Eet_Data_Element *sede;
3803                 char *ut;
3804
3805                 /* Yeah we found it ! */
3806                 sede = &(ede->subtype->elements.set[i]);
3807                 EET_ASSERT(sede->subtype, goto on_error);
3808
3809                 data_ret = _eet_data_descriptor_decode(context,
3810                                                        ed,
3811                                                        sede->subtype,
3812                                                        echnk->data,
3813                                                        echnk->size);
3814                 if (!data_ret)
3815                    goto on_error;
3816
3817                 /* Memcopy the structure content to remove pointer indirection. */
3818                 memcpy(data, data_ret, sede->subtype->size);
3819
3820                 /* data_ret is now useless. */
3821                 sede->subtype->func.mem_free(data_ret);
3822
3823                 /* Set union type. */
3824                 if ((!ed) || (!ede->subtype->func.str_direct_alloc))
3825                   {
3826                      ut = ede->subtype->func.str_alloc(union_type);
3827                      _eet_freelist_str_add(context, ut);
3828                   }
3829                 else
3830                   {
3831                      ut = ede->subtype->func.str_direct_alloc(union_type);
3832                      _eet_freelist_direct_str_add(context, ut);
3833                   }
3834
3835                 ede->subtype->func.type_set(
3836                    ut,
3837                    ((char *)data) + ede->count -
3838                    ede->offset,
3839                    EINA_FALSE);
3840
3841                 break;
3842              }
3843
3844      }
3845    else
3846      {
3847         /* FIXME: generate node structure. */
3848         data_ret = _eet_data_descriptor_decode(context,
3849                                                ed, NULL,
3850                                                echnk->data, echnk->size);
3851         goto on_error;
3852      }
3853
3854    return 1;
3855
3856 on_error:
3857    return 0;
3858 } /* eet_data_get_union */
3859
3860 static void
3861 eet_data_put_variant(Eet_Dictionary          *ed,
3862                      Eet_Data_Descriptor *edd __UNUSED__,
3863                      Eet_Data_Element        *ede,
3864                      Eet_Data_Stream         *ds,
3865                      void                    *data_in)
3866 {
3867    const char *union_type;
3868    void *data;
3869    Eina_Bool unknow = EINA_FALSE;
3870    int size;
3871    int i;
3872
3873    EET_ASSERT(!((ede->type != EET_T_UNKNOW) || (!ede->subtype)), return );
3874
3875    union_type = ede->subtype->func.type_get(
3876          ((char *)data_in) + ede->count - ede->offset,
3877          &unknow);
3878
3879    if (!union_type && unknow == EINA_FALSE)
3880       return;
3881
3882    if (unknow)
3883      {
3884         /* Handle opaque internal representation */
3885         Eet_Variant_Unknow *evu;
3886
3887         data = eet_data_put_type(ed, EET_T_STRING, &union_type, &size);
3888         if (data)
3889            eet_data_encode(ed,
3890                            ds,
3891                            data,
3892                            ede->name,
3893                            size,
3894                            ede->type,
3895                            ede->group_type);
3896
3897         evu = (Eet_Variant_Unknow *)data_in;
3898         if (evu && EINA_MAGIC_CHECK(evu, EET_MAGIC_VARIANT))
3899            eet_data_encode(ed,
3900                            ds,
3901                            evu->data,
3902                            ede->name,
3903                            evu->size,
3904                            ede->type,
3905                            ede->group_type);
3906      }
3907    else
3908       /* Search the structure of the union to encode. */
3909       for (i = 0; i < ede->subtype->elements.num; ++i)
3910          if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0)
3911            {
3912               Eet_Data_Element *sede;
3913
3914               /* Yeah we found it ! */
3915               data = eet_data_put_type(ed, EET_T_STRING, &union_type, &size);
3916               if (data)
3917                  eet_data_encode(ed,
3918                                  ds,
3919                                  data,
3920                                  ede->name,
3921                                  size,
3922                                  ede->type,
3923                                  ede->group_type);
3924
3925               sede = &(ede->subtype->elements.set[i]);
3926
3927               if (sede->group_type != EET_G_UNKNOWN)
3928                 {
3929                    Eet_Data_Stream *lds;
3930
3931                    lds = eet_data_stream_new();
3932                    eet_group_codec[sede->group_type - 100].put(ed,
3933                                                                sede->subtype,
3934                                                                sede,
3935                                                                lds,
3936                                                                data_in);
3937                    if (lds->size != 0)
3938                      {
3939                         eet_data_encode(ed, ds, lds->data, ede->name, lds->pos,
3940                                         ede->type, ede->group_type);
3941
3942                         lds->data = NULL;
3943                         lds->size = 0;
3944                      }
3945                    else
3946                       eet_data_encode(ed, ds, NULL, ede->name, 0,
3947                                       EET_T_NULL, ede->group_type);
3948
3949                    eet_data_stream_free(lds);
3950                 }
3951               else
3952                 {
3953                    data = _eet_data_descriptor_encode(ed,
3954                                                       sede->subtype,
3955                                                       *(void **)data_in,
3956                                                       &size);
3957                    if (data)
3958                       eet_data_encode(ed,
3959                                       ds,
3960                                       data,
3961                                       ede->name,
3962                                       size,
3963                                       ede->type,
3964                                       ede->group_type);
3965                 }
3966
3967               break;
3968            }
3969
3970 } /* eet_data_put_variant */
3971
3972 static int
3973 eet_data_get_variant(Eet_Free_Context        *context,
3974                      const Eet_Dictionary    *ed,
3975                      Eet_Data_Descriptor *edd __UNUSED__,
3976                      Eet_Data_Element        *ede,
3977                      Eet_Data_Chunk          *echnk,
3978                      int type                 __UNUSED__,
3979                      int group_type           __UNUSED__,
3980                      void                    *data,
3981                      char                   **p,
3982                      int                     *size)
3983 {
3984    const char *union_type;
3985    void *data_ret = NULL;
3986    int ret = 0;
3987    int i;
3988
3989    /* Read type */
3990    ret = eet_data_get_type(ed,
3991                            EET_T_STRING,
3992                            echnk->data,
3993                            ((char *)echnk->data) + echnk->size,
3994                            &union_type);
3995    if (ret <= 0)
3996       goto on_error;
3997
3998    /* Advance to next chunk */
3999    NEXT_CHUNK((*p), (*size), (*echnk), ed);
4000    memset(echnk, 0, sizeof(Eet_Data_Chunk));
4001
4002    /* Read value */
4003    eet_data_chunk_get(ed, echnk, *p, *size);
4004    if (!echnk->name)
4005       goto on_error;
4006
4007    if (ede)
4008      {
4009         char *ut;
4010
4011         EET_ASSERT(ede->subtype, goto on_error);
4012
4013         if ((!ed) || (!ede->subtype->func.str_direct_alloc))
4014           {
4015              ut = ede->subtype->func.str_alloc(union_type);
4016              _eet_freelist_str_add(context, ut);
4017           }
4018         else
4019           {
4020              ut = ede->subtype->func.str_direct_alloc(union_type);
4021              _eet_freelist_direct_str_add(context, ut);
4022           }
4023
4024         /* Search the structure of the union to decode */
4025         for (i = 0; i < ede->subtype->elements.num; ++i)
4026            if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0)
4027              {
4028                 Eet_Data_Element *sede;
4029
4030                 /* Yeah we found it ! */
4031                 sede = &(ede->subtype->elements.set[i]);
4032
4033                 if (sede->group_type != EET_G_UNKNOWN)
4034                   {
4035                      Eet_Data_Chunk chnk;
4036                      char *p2;
4037                      int size2;
4038                      int ret;
4039
4040                      p2 = echnk->data;
4041                      size2 = echnk->size;
4042
4043                      /* Didn't find a proper way to provide this
4044                         without duplicating code */
4045                      while (size2 > 0)
4046                        {
4047                           memset(&chnk, 0, sizeof(Eet_Data_Chunk));
4048                           eet_data_chunk_get(ed, &chnk, p2, size2);
4049
4050                           if (!chnk.name)
4051                              goto on_error;
4052
4053                           ret = eet_group_codec[sede->group_type - 100].get
4054                                 (context, ed, sede->subtype, sede, &chnk, sede->type,
4055                                 sede->group_type, data, &p2, &size2);
4056
4057                           if (ret <= 0)
4058                              goto on_error;
4059
4060 /* advance to next chunk */
4061                           NEXT_CHUNK(p2, size2, chnk, ed);
4062                        }
4063
4064                      /* Put garbage so that we will not put eet_variant_unknow in it */
4065                      data_ret = (void *)data;
4066
4067                      /* Set variant type. */
4068                      ede->subtype->func.type_set
4069                         (ut, ((char *)data) + ede->count - ede->offset,
4070                         EINA_FALSE);
4071                      break;
4072                   }
4073
4074                 data_ret = _eet_data_descriptor_decode(context,
4075                                                        ed,
4076                                                        sede->subtype,
4077                                                        echnk->data,
4078                                                        echnk->size);
4079                 if (!data_ret)
4080                    break;
4081
4082                 /* And point to the variant data. */
4083                 *(void **)data = data_ret;
4084
4085                 /* Set variant type. */
4086                 ede->subtype->func.type_set
4087                    (ut, ((char *)data) + ede->count - ede->offset, EINA_FALSE);
4088                 break;
4089              }
4090
4091         if (!data_ret)
4092           {
4093              Eet_Variant_Unknow *evu;
4094
4095              evu = calloc(1, sizeof (Eet_Variant_Unknow) + echnk->size - 1);
4096              if (!evu)
4097                 goto on_error;
4098
4099              evu->size = echnk->size;
4100              memcpy(evu->data, echnk->data, evu->size);
4101              EINA_MAGIC_SET(evu, EET_MAGIC_VARIANT);
4102
4103              /* And point to the opaque internal data scructure */
4104              *(void **)data = evu;
4105
4106              /* Set variant type. */
4107              ede->subtype->func.type_set
4108                 (ut, ((char *)data) + ede->count - ede->offset, EINA_TRUE);
4109           }
4110      }
4111    else
4112      {
4113         /* FIXME: dump node structure. */
4114         data_ret = _eet_data_descriptor_decode(context,
4115                                                ed, NULL,
4116                                                echnk->data, echnk->size);
4117         goto on_error;
4118      }
4119
4120    return 1;
4121
4122 on_error:
4123    return 0;
4124 } /* eet_data_get_variant */
4125
4126 static Eet_Node *
4127 eet_data_node_simple_type(int type, const char *name, void *dd)
4128 {
4129 #ifdef EET_T_TYPE
4130 # undef EET_T_TYPE
4131 #endif /* ifdef EET_T_TYPE */
4132
4133 #define EET_T_TYPE(Eet_Type, Eet_Node_Type, Type)\
4134  case Eet_Type:\
4135     return eet_node_ ## Eet_Node_Type ## _new(name, *((Type *)dd));\
4136
4137    switch (type)
4138      {
4139         EET_T_TYPE(EET_T_CHAR,           char,               char);
4140         EET_T_TYPE(EET_T_SHORT,          short,              short);
4141         EET_T_TYPE(EET_T_INT,            int,                int);
4142         EET_T_TYPE(EET_T_LONG_LONG,      long_long,          long long);
4143         EET_T_TYPE(EET_T_FLOAT,          float,              float);
4144         EET_T_TYPE(EET_T_DOUBLE,         double,             double);
4145         EET_T_TYPE(EET_T_UCHAR,          unsigned_char,      unsigned char);
4146         EET_T_TYPE(EET_T_USHORT,         unsigned_short,     unsigned short);
4147         EET_T_TYPE(EET_T_UINT,           unsigned_int,       unsigned int);
4148         EET_T_TYPE(EET_T_ULONG_LONG,     unsigned_long_long, unsigned long long);
4149         EET_T_TYPE(EET_T_STRING,         string,             char *);
4150         EET_T_TYPE(EET_T_INLINED_STRING, inlined_string,     char *);
4151
4152       case EET_T_NULL:
4153          return eet_node_null_new(name);
4154
4155       default:
4156          ERR("Unknow type passed to eet_data_node_simple_type");
4157          return NULL;
4158      } /* switch */
4159 } /* eet_data_node_simple_type */
4160
4161 static int
4162 eet_data_get_unknown(Eet_Free_Context     *context,
4163                      const Eet_Dictionary *ed,
4164                      Eet_Data_Descriptor  *edd,
4165                      Eet_Data_Element     *ede,
4166                      Eet_Data_Chunk       *echnk,
4167                      int                   type,
4168                      int group_type        __UNUSED__,
4169                      void                 *data,
4170                      char **p              __UNUSED__,
4171                      int *size             __UNUSED__)
4172 {
4173    int ret;
4174    void *data_ret;
4175
4176    if (IS_SIMPLE_TYPE(type))
4177      {
4178         unsigned char dd[128];
4179
4180         ret = eet_data_get_type(ed,
4181                                 type,
4182                                 echnk->data,
4183                                 ((char *)echnk->data) + echnk->size,
4184                                 edd ? (char *)data : (char *)dd);
4185         if (ret <= 0)
4186            return ret;
4187
4188         if (!edd)
4189           {
4190              Eet_Node **parent = data;
4191              Eet_Node *node;
4192
4193              node = eet_data_node_simple_type(type, echnk->name, dd);
4194
4195              if (*parent)
4196                 eet_node_struct_append(*parent, echnk->name, node);
4197              else
4198                 *parent = node;
4199           }
4200         else
4201           {
4202              if (type == EET_T_STRING)
4203                {
4204                   char **str;
4205
4206                   str = (char **)(((char *)data));
4207                   if (*str)
4208                     {
4209                        if ((!ed) || (!edd->func.str_direct_alloc))
4210                          {
4211                             *str = edd->func.str_alloc(*str);
4212                             _eet_freelist_str_add(context, *str);
4213                          }
4214                        else
4215                          {
4216                             *str = edd->func.str_direct_alloc(*str);
4217                             _eet_freelist_direct_str_add(context, *str);
4218                          }
4219                     }
4220                }
4221              else if (edd && type == EET_T_INLINED_STRING)
4222                {
4223                   char **str;
4224
4225                   str = (char **)(((char *)data));
4226                   if (*str)
4227                     {
4228                        *str = edd->func.str_alloc(*str);
4229                        _eet_freelist_str_add(context, *str);
4230                     }
4231                }
4232           }
4233      }
4234    else
4235      {
4236         Eet_Data_Descriptor *subtype;
4237
4238         subtype = ede ? ede->subtype : NULL;
4239
4240         if (subtype || !edd)
4241           {
4242              Eet_Node **parent = data;
4243              void **ptr;
4244
4245              data_ret = _eet_data_descriptor_decode(context,
4246                                                     ed,
4247                                                     subtype,
4248                                                     echnk->data,
4249                                                     echnk->size);
4250              if (!data_ret)
4251                 return 0;
4252
4253              if (edd)
4254                {
4255                   ptr = (void **)(((char *)data));
4256                   *ptr = (void *)data_ret;
4257                }
4258              else
4259                {
4260                   Eet_Node *node = data_ret;
4261
4262                   if (*parent)
4263                     {
4264                        node = eet_node_struct_child_new(echnk->name, node);
4265                        eet_node_struct_append(*parent, echnk->name, node);
4266                     }
4267                   else
4268                      *parent = node;
4269                }
4270           }
4271      }
4272
4273    return 1;
4274 } /* eet_data_get_unknown */
4275
4276 static void
4277 eet_data_put_array(Eet_Dictionary          *ed,
4278                    Eet_Data_Descriptor *edd __UNUSED__,
4279                    Eet_Data_Element        *ede,
4280                    Eet_Data_Stream         *ds,
4281                    void                    *data_in)
4282 {
4283    void *data;
4284    int offset = 0;
4285    int subsize;
4286    int count;
4287    int size;
4288    int j;
4289
4290    EET_ASSERT(!((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING)),
4291               return );
4292
4293    if (ede->group_type == EET_G_ARRAY)
4294       count = ede->counter_offset;
4295    else
4296       count = *(int *)(((char *)data_in) + ede->count - ede->offset);
4297
4298    if (count <= 0)
4299       return;  /* Store number of elements */
4300
4301    data = eet_data_put_type(ed, EET_T_INT, &count, &size);
4302    if (data)
4303       eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
4304
4305    if (IS_POINTER_TYPE(ede->type))
4306       subsize = eet_basic_codec[ede->type].size;
4307    else
4308       subsize = ede->subtype->size;
4309
4310    for (j = 0; j < count; j++)
4311      {
4312         void *d;
4313         int pos = ds->pos;
4314
4315         if (ede->group_type == EET_G_ARRAY)
4316            d = (void *)(((char *)data_in) + offset);
4317         else
4318            d = *(((char **)data_in)) + offset;
4319
4320         if (IS_POINTER_TYPE(ede->type))
4321           {
4322              if (*(char **)d)
4323                 eet_data_put_unknown(ed, NULL, ede, ds, d);
4324           }
4325         else
4326           {
4327              data = _eet_data_descriptor_encode(ed, ede->subtype, d, &size);
4328              if (data)
4329                 eet_data_encode(ed,
4330                                 ds,
4331                                 data,
4332                                 ede->name,
4333                                 size,
4334                                 ede->type,
4335                                 ede->group_type);
4336           }
4337
4338         if (pos == ds->pos)
4339            /* Add a NULL element just to have the correct array layout. */
4340            eet_data_encode(ed,
4341                            ds,
4342                            NULL,
4343                            ede->name,
4344                            0,
4345                            EET_T_NULL,
4346                            ede->group_type);
4347
4348         offset += subsize;
4349      }
4350 } /* eet_data_put_array */
4351
4352 static void
4353 eet_data_put_unknown(Eet_Dictionary          *ed,
4354                      Eet_Data_Descriptor *edd __UNUSED__,
4355                      Eet_Data_Element        *ede,
4356                      Eet_Data_Stream         *ds,
4357                      void                    *data_in)
4358 {
4359    void *data = NULL;
4360    int size;
4361
4362    if (IS_SIMPLE_TYPE(ede->type))
4363       data = eet_data_put_type(ed, ede->type, data_in, &size);
4364    else if (ede->subtype)
4365       if (*((char **)data_in))
4366          data = _eet_data_descriptor_encode(ed,
4367                                             ede->subtype,
4368                                             *((char **)((char *)(data_in))),
4369                                             &size);
4370
4371    if (data)
4372       eet_data_encode(ed,
4373                       ds,
4374                       data,
4375                       ede->name,
4376                       size,
4377                       ede->type,
4378                       ede->group_type);
4379 } /* eet_data_put_unknown */
4380
4381 static void
4382 eet_data_put_list(Eet_Dictionary      *ed,
4383                   Eet_Data_Descriptor *edd,
4384                   Eet_Data_Element    *ede,
4385                   Eet_Data_Stream     *ds,
4386                   void                *data_in)
4387 {
4388    void *data;
4389    void *l;
4390    int size;
4391
4392    EET_ASSERT(!(((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING))
4393                 || ((ede->type > EET_T_NULL) && (ede->type < EET_T_LAST))),
4394               return );
4395
4396    l = *((void **)(((char *)data_in)));
4397    for (; l; l = edd->func.list_next(l))
4398      {
4399         if (IS_POINTER_TYPE(ede->type))
4400           {
4401              const void *str = edd->func.list_data(l);
4402              eet_data_put_unknown(ed, NULL, ede, ds, &str);
4403           }
4404         else
4405           {
4406              data = _eet_data_descriptor_encode(ed,
4407                                                 ede->subtype,
4408                                                 edd->func.list_data(l),
4409                                                 &size);
4410              if (data)
4411                 eet_data_encode(ed,
4412                                 ds,
4413                                 data,
4414                                 ede->name,
4415                                 size,
4416                                 ede->type,
4417                                 ede->group_type);
4418           }
4419      }
4420 } /* eet_data_put_list */
4421
4422 static void
4423 eet_data_put_hash(Eet_Dictionary      *ed,
4424                   Eet_Data_Descriptor *edd,
4425                   Eet_Data_Element    *ede,
4426                   Eet_Data_Stream     *ds,
4427                   void                *data_in)
4428 {
4429    Eet_Data_Encode_Hash_Info fdata;
4430    void *l;
4431
4432    l = *((void **)(((char *)data_in)));
4433    fdata.ds = ds;
4434    fdata.ede = ede;
4435    fdata.ed = ed;
4436    edd->func.hash_foreach(l, eet_data_descriptor_encode_hash_cb, &fdata);
4437 } /* eet_data_put_hash */
4438
4439 EAPI int
4440 eet_data_dump_cipher(Eet_File *ef,
4441                      const char *name,
4442                      const char *cipher_key,
4443                      Eet_Dump_Callback dumpfunc,
4444                      void *dumpdata)
4445 {
4446    const Eet_Dictionary *ed = NULL;
4447    const void *data = NULL;
4448    Eet_Node *result;
4449    Eet_Free_Context context;
4450    int required_free = 0;
4451    int size;
4452
4453    ed = eet_dictionary_get(ef);
4454
4455    if (!cipher_key)
4456       data = eet_read_direct(ef, name, &size);
4457
4458    if (!data)
4459      {
4460         required_free = 1;
4461         data = eet_read_cipher(ef, name, &size, cipher_key);
4462         if (!data)
4463            return 0;
4464      }
4465
4466    eet_free_context_init(&context);
4467    result = _eet_data_descriptor_decode(&context, ed, NULL, data, size);
4468    eet_free_context_shutdown(&context);
4469
4470    eet_node_dump(result, 0, dumpfunc, dumpdata);
4471
4472    eet_node_del(result);
4473
4474    if (required_free)
4475       free((void *)data);
4476
4477    return result ? 1 : 0;
4478 } /* eet_data_dump_cipher */
4479
4480 EAPI int
4481 eet_data_dump(Eet_File *ef,
4482               const char *name,
4483               Eet_Dump_Callback dumpfunc,
4484               void *dumpdata)
4485 {
4486    return eet_data_dump_cipher(ef, name, NULL, dumpfunc, dumpdata);
4487 } /* eet_data_dump */
4488
4489 EAPI int
4490 eet_data_text_dump_cipher(const void *data_in,
4491                           const char *cipher_key,
4492                           int size_in,
4493                           Eet_Dump_Callback dumpfunc,
4494                           void *dumpdata)
4495 {
4496    void *ret = NULL;
4497    Eet_Node *result;
4498    Eet_Free_Context context;
4499    unsigned int ret_len = 0;
4500
4501    if (!data_in)
4502       return 0;
4503
4504    if (cipher_key)
4505      {
4506         if (eet_decipher(data_in, size_in, cipher_key,
4507                          strlen(cipher_key), &ret, &ret_len))
4508           {
4509              if (ret)
4510                 free(ret);
4511
4512              return 0;
4513           }
4514      }
4515    else
4516      {
4517         ret = (void *)data_in;
4518         ret_len = size_in;
4519      }
4520
4521    eet_free_context_init(&context);
4522    result = _eet_data_descriptor_decode(&context, NULL, NULL, ret, ret_len);
4523    eet_free_context_shutdown(&context);
4524
4525    eet_node_dump(result, 0, dumpfunc, dumpdata);
4526
4527    eet_node_del(result);
4528    if (cipher_key)
4529       free(ret);
4530
4531    return result ? 1 : 0;
4532 } /* eet_data_text_dump_cipher */
4533
4534 EAPI int
4535 eet_data_text_dump(const void *data_in,
4536                    int size_in,
4537                    Eet_Dump_Callback dumpfunc,
4538                    void *dumpdata)
4539 {
4540    return eet_data_text_dump_cipher(data_in, NULL, size_in, dumpfunc, dumpdata);
4541 } /* eet_data_text_dump */
4542
4543 EAPI void *
4544 eet_data_text_undump_cipher(const char *text,
4545                             const char *cipher_key,
4546                             int         textlen,
4547                             int        *size_ret)
4548 {
4549    void *ret = NULL;
4550
4551    ret = _eet_data_dump_parse(NULL, size_ret, text, textlen);
4552    if (ret && cipher_key)
4553      {
4554         void *ciphered = NULL;
4555         unsigned int ciphered_len;
4556
4557         if (eet_cipher(ret, *size_ret, cipher_key,
4558                        strlen(cipher_key), &ciphered, &ciphered_len))
4559           {
4560              if (ciphered)
4561                 free(ciphered);
4562
4563              size_ret = 0;
4564              free(ret);
4565              return NULL;
4566           }
4567
4568         free(ret);
4569         *size_ret = ciphered_len;
4570         ret = ciphered;
4571      }
4572
4573    return ret;
4574 } /* eet_data_text_undump_cipher */
4575
4576 EAPI void *
4577 eet_data_text_undump(const char *text,
4578                      int         textlen,
4579                      int        *size_ret)
4580 {
4581    return eet_data_text_undump_cipher(text, NULL, textlen, size_ret);
4582 } /* eet_data_text_undump */
4583
4584 EAPI int
4585 eet_data_undump_cipher(Eet_File   *ef,
4586                        const char *name,
4587                        const char *cipher_key,
4588                        const char *text,
4589                        int         textlen,
4590                        int         compress)
4591 {
4592    Eet_Dictionary *ed;
4593    void *data_enc;
4594    int size;
4595    int val;
4596
4597    ed = eet_dictionary_get(ef);
4598
4599    data_enc = _eet_data_dump_parse(ed, &size, text, textlen);
4600    if (!data_enc)
4601       return 0;
4602
4603    val = eet_write_cipher(ef, name, data_enc, size, compress, cipher_key);
4604    free(data_enc);
4605    return val;
4606 } /* eet_data_undump_cipher */
4607
4608 EAPI int
4609 eet_data_undump(Eet_File   *ef,
4610                 const char *name,
4611                 const char *text,
4612                 int         textlen,
4613                 int         compress)
4614 {
4615    return eet_data_undump_cipher(ef, name, NULL, text, textlen, compress);
4616 } /* eet_data_undump */
4617
4618 EAPI void *
4619 eet_data_descriptor_decode_cipher(Eet_Data_Descriptor *edd,
4620                                   const void          *data_in,
4621                                   const char          *cipher_key,
4622                                   int                  size_in)
4623 {
4624    void *deciphered = (void *)data_in;
4625    void *ret;
4626    Eet_Free_Context context;
4627    unsigned int deciphered_len = size_in;
4628
4629    if (cipher_key && data_in)
4630       if (eet_decipher(data_in, size_in, cipher_key,
4631                        strlen(cipher_key), &deciphered, &deciphered_len))
4632         {
4633            if (deciphered)
4634               free(deciphered);
4635
4636            return NULL;
4637         }
4638
4639    eet_free_context_init(&context);
4640    ret = _eet_data_descriptor_decode(&context,
4641                                      NULL,
4642                                      edd,
4643                                      deciphered,
4644                                      deciphered_len);
4645    eet_free_context_shutdown(&context);
4646
4647    if (data_in != deciphered)
4648       free(deciphered);
4649
4650    return ret;
4651 } /* eet_data_descriptor_decode_cipher */
4652
4653 EAPI void *
4654 eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
4655                            const void          *data_in,
4656                            int                  size_in)
4657 {
4658    return eet_data_descriptor_decode_cipher(edd, data_in, NULL, size_in);
4659 } /* eet_data_descriptor_decode */
4660
4661 EAPI Eet_Node *
4662 eet_data_node_decode_cipher(const void *data_in,
4663                             const char *cipher_key,
4664                             int         size_in)
4665 {
4666    void *deciphered = (void *)data_in;
4667    Eet_Node *ret;
4668    Eet_Free_Context context;
4669    unsigned int deciphered_len = size_in;
4670
4671    if (cipher_key && data_in)
4672       if (eet_decipher(data_in, size_in, cipher_key,
4673                        strlen(cipher_key), &deciphered, &deciphered_len))
4674         {
4675            if (deciphered)
4676               free(deciphered);
4677
4678            return NULL;
4679         }
4680
4681    eet_free_context_init(&context);
4682    ret = _eet_data_descriptor_decode(&context,
4683                                      NULL,
4684                                      NULL,
4685                                      deciphered,
4686                                      deciphered_len);
4687    eet_free_context_shutdown(&context);
4688
4689    if (data_in != deciphered)
4690       free(deciphered);
4691
4692    return ret;
4693 } /* eet_data_node_decode_cipher */
4694
4695 static void *
4696 _eet_data_descriptor_encode(Eet_Dictionary      *ed,
4697                             Eet_Data_Descriptor *edd,
4698                             const void          *data_in,
4699                             int                 *size_ret)
4700 {
4701    Eet_Data_Stream *ds;
4702    Eet_Data_Chunk *chnk;
4703    void *cdata;
4704    int csize;
4705    int i;
4706
4707    if (_eet_data_words_bigendian == -1)
4708      {
4709         unsigned long int v;
4710
4711         v = htonl(0x12345678);
4712         if (v == 0x12345678)
4713            _eet_data_words_bigendian = 1;
4714         else
4715            _eet_data_words_bigendian = 0;
4716      }
4717
4718    ds = eet_data_stream_new();
4719    for (i = 0; i < edd->elements.num; i++)
4720      {
4721         Eet_Data_Element *ede;
4722
4723         ede = &(edd->elements.set[i]);
4724         eet_group_codec[ede->group_type - 100].put(
4725            ed,
4726            edd,
4727            ede,
4728            ds,
4729            ((char *)data_in) +
4730            ede->offset);
4731      }
4732    chnk = eet_data_chunk_new(ds->data,
4733                              ds->pos,
4734                              edd->name,
4735                              EET_T_UNKNOW,
4736                              EET_G_UNKNOWN);
4737    ds->data = NULL;
4738    ds->size = 0;
4739    eet_data_stream_free(ds);
4740
4741    ds = eet_data_stream_new();
4742    eet_data_chunk_put(ed, chnk, ds);
4743    cdata = ds->data;
4744    csize = ds->pos;
4745
4746    ds->data = NULL;
4747    ds->size = 0;
4748    eet_data_stream_free(ds);
4749    *size_ret = csize;
4750
4751    free(chnk->data);
4752    eet_data_chunk_free(chnk);
4753
4754    return cdata;
4755 } /* _eet_data_descriptor_encode */
4756
4757 EAPI int
4758 eet_data_node_write_cipher(Eet_File   *ef,
4759                            const char *name,
4760                            const char *cipher_key,
4761                            Eet_Node   *node,
4762                            int         compress)
4763 {
4764    Eet_Dictionary *ed;
4765    void *data_enc;
4766    int size;
4767    int val;
4768
4769    ed = eet_dictionary_get(ef);
4770
4771    data_enc = _eet_data_dump_encode(EET_G_UNKNOWN, ed, node, &size);
4772    if (!data_enc)
4773       return 0;
4774
4775    val = eet_write_cipher(ef, name, data_enc, size, compress, cipher_key);
4776    free(data_enc);
4777    return val;
4778 } /* eet_data_node_write_cipher */
4779
4780 EAPI void *
4781 eet_data_node_encode_cipher(Eet_Node   *node,
4782                             const char *cipher_key,
4783                             int        *size_ret)
4784 {
4785    void *ret = NULL;
4786    void *ciphered = NULL;
4787    unsigned int ciphered_len = 0;
4788    int size;
4789
4790    ret = _eet_data_dump_encode(EET_G_UNKNOWN, NULL, node, &size);
4791    if (cipher_key && ret)
4792      {
4793         if (eet_cipher(ret, size, cipher_key,
4794                        strlen(cipher_key), &ciphered, &ciphered_len))
4795           {
4796              if (ciphered)
4797                 free(ciphered);
4798
4799              if (size_ret)
4800                 *size_ret = 0;
4801
4802              free(ret);
4803              return NULL;
4804           }
4805
4806         free(ret);
4807         size = (int)ciphered_len;
4808         ret = ciphered;
4809      }
4810
4811    if (size_ret)
4812       *size_ret = size;
4813
4814    return ret;
4815 } /* eet_data_node_encode_cipher */
4816
4817 EAPI void *
4818 eet_data_descriptor_encode_cipher(Eet_Data_Descriptor *edd,
4819                                   const void          *data_in,
4820                                   const char          *cipher_key,
4821                                   int                 *size_ret)
4822 {
4823    void *ret = NULL;
4824    void *ciphered = NULL;
4825    unsigned int ciphered_len = 0;
4826    int size;
4827
4828    ret = _eet_data_descriptor_encode(NULL, edd, data_in, &size);
4829    if (cipher_key && ret)
4830      {
4831         if (eet_cipher(ret, size, cipher_key,
4832                        strlen(cipher_key), &ciphered, &ciphered_len))
4833           {
4834              if (ciphered)
4835                 free(ciphered);
4836
4837              if (size_ret)
4838                 *size_ret = 0;
4839
4840              free(ret);
4841              return NULL;
4842           }
4843
4844         free(ret);
4845         size = ciphered_len;
4846         ret = ciphered;
4847      }
4848
4849    if (size_ret)
4850       *size_ret = size;
4851
4852    return ret;
4853 } /* eet_data_descriptor_encode_cipher */
4854
4855 EAPI void *
4856 eet_data_descriptor_encode(Eet_Data_Descriptor *edd,
4857                            const void          *data_in,
4858                            int                 *size_ret)
4859 {
4860    return eet_data_descriptor_encode_cipher(edd, data_in, NULL, size_ret);
4861 } /* eet_data_descriptor_encode */
4862