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