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