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