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