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