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