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