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