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