fix formatting
[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 >=
1272              EET_G_LAST))
1273           {
1274              chnk->type = 0;
1275              chnk->group_type = 0;
1276           }
1277      }
1278    else if ((s[0] != 'C') || (s[1] != 'H') || (s[2] != 'n') || (s[3] != 'K'))
1279       return;
1280
1281    ret1 = eet_data_get_type(ed, EET_T_INT, (s + 4), (s + size), &(chnk->size));
1282
1283    if (ret1 <= 0)
1284       return;
1285
1286    if ((chnk->size < 0) || ((chnk->size + 8) > size))
1287       return;
1288
1289    ret2 = eet_data_get_type(ed, EET_T_STRING, (s + 8), (s + size), &(chnk->name));
1290
1291    if (ret2 <= 0)
1292       return;
1293
1294    chnk->len = ret2;
1295
1296    /* Precalc hash */
1297    chnk->hash = eet_data_get_string_hash(ed, (s + 8), (s + size));
1298
1299    if (ed)
1300      {
1301         chnk->data = (char *)src + 4 + ret1 + sizeof(int);
1302         chnk->size -= sizeof(int);
1303      }
1304    else
1305      {
1306         chnk->data = (char *)src + 4 + ret1 + chnk->len;
1307         chnk->size -= chnk->len;
1308      }
1309
1310    return;
1311 }
1312
1313 static inline Eet_Data_Chunk *
1314 eet_data_chunk_new(void *data,
1315                    int size,
1316                    const char *name,
1317                    int type,
1318                    int group_type)
1319 {
1320    Eet_Data_Chunk *chnk;
1321
1322    if (!name)
1323       return NULL;
1324
1325    chnk = calloc(1, sizeof(Eet_Data_Chunk));
1326    if (!chnk)
1327       return NULL;
1328
1329    /* Note: Another security, so older eet library could read file
1330       saved with fixed point value. */
1331    if (type == EET_T_F32P32
1332        || type == EET_T_F16P16
1333        || type == EET_T_F8P24)
1334       type = EET_T_DOUBLE;
1335
1336    chnk->name = strdup(name);
1337    chnk->len = strlen(name) + 1;
1338    chnk->size = size;
1339    chnk->data = data;
1340    chnk->type = type;
1341    chnk->group_type = group_type;
1342    return chnk;
1343 }
1344
1345 static inline void
1346 eet_data_chunk_free(Eet_Data_Chunk *chnk)
1347 {
1348    if (chnk->name)
1349       free(chnk->name);
1350
1351       free(chnk);
1352 }
1353
1354 static inline Eet_Data_Stream *
1355 eet_data_stream_new(void)
1356 {
1357    Eet_Data_Stream *ds;
1358
1359    ds = calloc(1, sizeof(Eet_Data_Stream));
1360    if (!ds)
1361       return NULL;
1362
1363    return ds;
1364 }
1365
1366 static inline void
1367 eet_data_stream_free(Eet_Data_Stream *ds)
1368 {
1369    if (ds->data)
1370       free(ds->data);
1371
1372       free(ds);
1373 }
1374
1375 static inline void
1376 eet_data_stream_flush(Eet_Data_Stream *ds)
1377 {
1378       free(ds);
1379 }
1380
1381 static inline void
1382 eet_data_stream_write(Eet_Data_Stream *ds, const void *data, int size)
1383 {
1384    char *p;
1385
1386    if ((ds->pos + size) > ds->size)
1387      {
1388         ds->data = realloc(ds->data, ds->size + size + 512);
1389         if (!ds->data)
1390           {
1391              ds->pos = 0;
1392              ds->size = 0;
1393              return;
1394           }
1395
1396         ds->size = ds->size + size + 512;
1397      }
1398
1399    p = ds->data;
1400    memcpy(p + ds->pos, data, size);
1401    ds->pos += size;
1402 }
1403
1404 static void
1405 eet_data_chunk_put(Eet_Dictionary *ed,
1406                    Eet_Data_Chunk *chnk,
1407                    Eet_Data_Stream *ds)
1408 {
1409    int *size;
1410    void *string;
1411    int s;
1412    int size_ret = 0;
1413    int string_ret = 0;
1414    unsigned char buf[4] = "CHK";
1415
1416    /* disable this check - it will allow empty chunks to be written. this is
1417     * right for corner-cases when y have a struct with empty fields (empty
1418     * strings or empty list ptrs etc.) */
1419    /* if (!chnk->data && chnk->type != EET_T_NULL) return; */
1420    /* chunk head */
1421
1422 /*   eet_data_stream_write(ds, "CHnK", 4);*/
1423    if (chnk->type != EET_T_UNKNOW)
1424      {
1425         if (chnk->group_type != EET_G_UNKNOWN)
1426           {
1427              int type = EET_I_LIMIT + chnk->group_type - EET_G_UNKNOWN;
1428
1429              switch (chnk->type)
1430                {
1431                   /* Only make sense with pointer type. */
1432 #define EET_MATCH_TYPE(Type) \
1433  case EET_T_ ## Type: type += EET_I_ ## Type; break;
1434
1435                   EET_MATCH_TYPE(STRING);
1436                   EET_MATCH_TYPE(INLINED_STRING);
1437                   EET_MATCH_TYPE(NULL);
1438
1439                 default:
1440                    return;
1441                }
1442
1443              buf[3] = type;
1444           }
1445         else
1446            buf[3] = chnk->type;
1447      }
1448    else
1449       buf[3] = chnk->group_type;
1450
1451    string = eet_data_put_string(ed, &chnk->name, &string_ret);
1452    if (!string)
1453       return;
1454
1455    /* size of chunk payload data + name */
1456    s = chnk->size + string_ret;
1457    size = eet_data_put_int(ed, &s, &size_ret);
1458
1459    /* FIXME: If something goes wrong the resulting file will be corrupted. */
1460    if (!size)
1461       goto on_error;
1462
1463              eet_data_stream_write(ds, buf,    4);
1464
1465    /* write chunk length */
1466              eet_data_stream_write(ds, size,   size_ret);
1467
1468    /* write chunk name */
1469              eet_data_stream_write(ds, string, string_ret);
1470
1471    /* write payload */
1472    if (chnk->data)
1473              eet_data_stream_write(ds, chnk->data, chnk->size);
1474
1475              free(string);
1476 on_error:
1477              free(size);
1478 }
1479
1480 /*---*/
1481
1482 static void
1483 _eet_descriptor_hash_new(Eet_Data_Descriptor *edd)
1484 {
1485    int i;
1486
1487    edd->elements.hash.size = 1 << 6;
1488    edd->elements.hash.buckets = calloc(
1489          1,
1490          sizeof(Eet_Data_Descriptor_Hash) *
1491          edd->elements.hash.size);
1492    for (i = 0; i < edd->elements.num; i++)
1493      {
1494         Eet_Data_Element *ede;
1495         int hash;
1496
1497         ede = &(edd->elements.set[i]);
1498         hash = _eet_hash_gen((char *)ede->name, 6);
1499         if (!edd->elements.hash.buckets[hash].element)
1500            edd->elements.hash.buckets[hash].element = ede;
1501         else
1502           {
1503              Eet_Data_Descriptor_Hash *bucket;
1504
1505              bucket = calloc(1, sizeof(Eet_Data_Descriptor_Hash));
1506              bucket->element = ede;
1507              bucket->next = edd->elements.hash.buckets[hash].next;
1508              edd->elements.hash.buckets[hash].next = bucket;
1509           }
1510      }
1511 }
1512
1513 static void
1514 _eet_descriptor_hash_free(Eet_Data_Descriptor *edd)
1515 {
1516    int i;
1517
1518    for (i = 0; i < edd->elements.hash.size; i++)
1519      {
1520         Eet_Data_Descriptor_Hash *bucket, *pbucket;
1521
1522         bucket = edd->elements.hash.buckets[i].next;
1523         while (bucket)
1524           {
1525              pbucket = bucket;
1526              bucket = bucket->next;
1527              free(pbucket);
1528           }
1529      }
1530    if (edd->elements.hash.buckets)
1531              free(edd->elements.hash.buckets);
1532 }
1533
1534 static Eet_Data_Element *
1535 _eet_descriptor_hash_find(Eet_Data_Descriptor *edd, char *name, int hash)
1536 {
1537    Eet_Data_Descriptor_Hash *bucket;
1538
1539    if (hash < 0)
1540       hash = _eet_hash_gen(name, 6);
1541    else
1542       hash &= 0x3f;
1543
1544    if (!edd->elements.hash.buckets[hash].element)
1545       return NULL;  /*
1546                        When we use the dictionnary as a source for chunk name, we will always
1547                        have the same pointer in name. It's a good idea to just compare pointer
1548                        instead of running strcmp on both string.
1549                      */
1550
1551    if (edd->elements.hash.buckets[hash].element->directory_name_ptr == name)
1552       return edd->elements.hash.buckets[hash].element;
1553
1554    if (!strcmp(edd->elements.hash.buckets[hash].element->name, name))
1555      {
1556         edd->elements.hash.buckets[hash].element->directory_name_ptr = name;
1557         return edd->elements.hash.buckets[hash].element;
1558      }
1559
1560    bucket = edd->elements.hash.buckets[hash].next;
1561    while (bucket)
1562      {
1563         if (bucket->element->directory_name_ptr == name)
1564            return bucket->element;
1565
1566         if (!strcmp(bucket->element->name, name))
1567           {
1568              bucket->element->directory_name_ptr = name;
1569              return bucket->element;
1570           }
1571
1572         bucket = bucket->next;
1573      }
1574    return NULL;
1575 }
1576
1577 static void *
1578 _eet_mem_alloc(size_t size)
1579 {
1580    return calloc(1, size);
1581 }
1582
1583 static void
1584 _eet_mem_free(void *mem)
1585 {
1586              free(mem);
1587 }
1588
1589 static char *
1590 _eet_str_alloc(const char *str)
1591 {
1592    return strdup(str);
1593 }
1594
1595 static void
1596 _eet_str_free(const char *str)
1597 {
1598              free((char *)str);
1599 }
1600
1601 static Eina_Hash *
1602 _eet_eina_hash_add_alloc(Eina_Hash *hash, const char *key, void *data)
1603 {
1604    if (!hash)
1605       hash = eina_hash_string_small_new(NULL);
1606
1607    if (!hash)
1608       return NULL;
1609
1610    eina_hash_add(hash, key, data);
1611    return hash;
1612 }
1613
1614 static Eina_Hash *
1615 _eet_eina_hash_direct_add_alloc(Eina_Hash *hash, const char *key, void *data)
1616 {
1617    if (!hash)
1618       hash = eina_hash_string_small_new(NULL);
1619
1620    if (!hash)
1621       return NULL;
1622
1623    eina_hash_direct_add(hash, key, data);
1624    return hash;
1625 }
1626
1627 static char *
1628 _eet_str_direct_alloc(const char *str)
1629 {
1630    return (char *)str;
1631 }
1632
1633 static void
1634 _eet_str_direct_free(const char *str __UNUSED__)
1635 {
1636 }
1637
1638 static void
1639 _eet_eina_hash_foreach(void *hash, Eina_Hash_Foreach cb, void *fdata)
1640 {
1641    if (hash)
1642       eina_hash_foreach(hash, cb, fdata);
1643 }
1644
1645 static void
1646 _eet_eina_hash_free(void *hash)
1647 {
1648    if (hash)
1649       eina_hash_free(hash);
1650 }
1651
1652 /*---*/
1653 EAPI Eina_Bool
1654 eet_eina_stream_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc,
1655                                           const char *name,
1656                                           int size)
1657 {
1658    if (!eddc || !name)
1659       return EINA_FALSE;
1660
1661    eddc->name = name;
1662    eddc->size = size;
1663    eddc->version = 1;
1664
1665    eddc->func.mem_alloc = _eet_mem_alloc;
1666    eddc->func.mem_free = _eet_mem_free;
1667    eddc->func.str_alloc = (char *(*)(const char *))eina_stringshare_add;
1668    eddc->func.str_free = eina_stringshare_del;
1669    eddc->func.list_next = (void *(*)(void *))eina_list_next;
1670    eddc->func.list_append = (void *(*)(void *, void *))eina_list_append;
1671    eddc->func.list_data = (void *(*)(void *))eina_list_data_get;
1672    eddc->func.list_free = (void *(*)(void *))eina_list_free;
1673    eddc->func.hash_foreach =
1674       (void (*)(void *,
1675                 int (*)(void *, const char *, void *,
1676                         void *), void *))_eet_eina_hash_foreach;
1677    eddc->func.hash_add =
1678       (void * (*)(void *, const char *, void *))_eet_eina_hash_add_alloc;
1679    eddc->func.hash_free = (void (*)(void *))_eet_eina_hash_free;
1680
1681    return EINA_TRUE;
1682 }
1683
1684 EAPI Eina_Bool
1685 eet_eina_file_data_descriptor_class_set(Eet_Data_Descriptor_Class *eddc,
1686                                         const char *name,
1687                                         int size)
1688 {
1689    if (!eet_eina_stream_data_descriptor_class_set(eddc, name, size))
1690       return EINA_FALSE;
1691
1692    eddc->version = 2;
1693
1694    eddc->func.hash_add =
1695       (void * (*)(void *, const char *, void *))_eet_eina_hash_direct_add_alloc;
1696    eddc->func.str_direct_alloc = _eet_str_direct_alloc;
1697    eddc->func.str_direct_free = _eet_str_direct_free;
1698
1699    return EINA_TRUE;
1700 }
1701
1702 static Eet_Data_Descriptor *
1703 _eet_data_descriptor_new(const Eet_Data_Descriptor_Class *eddc, int version)
1704 {
1705    Eet_Data_Descriptor *edd;
1706
1707    if (!eddc)
1708       return NULL;
1709
1710    edd = calloc(1, sizeof (Eet_Data_Descriptor));
1711    if (!edd)
1712       return NULL;
1713
1714    edd->name = eddc->name;
1715    edd->ed = NULL;
1716    edd->size = eddc->size;
1717    edd->func.mem_alloc = _eet_mem_alloc;
1718    edd->func.mem_free = _eet_mem_free;
1719    edd->func.str_alloc = _eet_str_alloc;
1720    edd->func.str_free = _eet_str_free;
1721    if (eddc->func.mem_alloc)
1722       edd->func.mem_alloc = eddc->func.mem_alloc;
1723
1724    if (eddc->func.mem_free)
1725       edd->func.mem_free = eddc->func.mem_free;
1726
1727    if (eddc->func.str_alloc)
1728       edd->func.str_alloc = eddc->func.str_alloc;
1729
1730    if (eddc->func.str_free)
1731       edd->func.str_free = eddc->func.str_free;
1732
1733    edd->func.list_next = eddc->func.list_next;
1734    edd->func.list_append = eddc->func.list_append;
1735    edd->func.list_data = eddc->func.list_data;
1736    edd->func.list_free = eddc->func.list_free;
1737    edd->func.hash_foreach = eddc->func.hash_foreach;
1738    edd->func.hash_add = eddc->func.hash_add;
1739    edd->func.hash_free = eddc->func.hash_free;
1740
1741    if (eddc->version > 1 && version > 1)
1742      {
1743         edd->func.str_direct_alloc = eddc->func.str_direct_alloc;
1744         edd->func.str_direct_free = eddc->func.str_direct_free;
1745      }
1746
1747    if (eddc->version > 2)
1748      {
1749         edd->func.type_get = eddc->func.type_get;
1750         edd->func.type_set = eddc->func.type_set;
1751      }
1752
1753    return edd;
1754 }
1755
1756 EAPI Eet_Data_Descriptor *
1757 eet_data_descriptor_new(const char *name,
1758                         int size,
1759                         void *(*func_list_next)(void *l),
1760                         void *(*func_list_append)(void *l, void *d),
1761                         void *(*func_list_data)(void *l),
1762                         void *(*func_list_free)(void *l),
1763                         void (*func_hash_foreach)(void *h, int (*func)(
1764                                                      void *h,
1765                                                      const
1766                                                      char *k,
1767                                                      void *dt,
1768                                                      void *
1769                                                      fdt), void *fdt),
1770                         void *(*func_hash_add)(void *h, const char *k, void *d),
1771                         void (*func_hash_free)(void *h))
1772 {
1773    Eet_Data_Descriptor_Class eddc;
1774
1775    if (!name)
1776       return NULL;
1777
1778    memset(&eddc, 0, sizeof (Eet_Data_Descriptor_Class));
1779
1780    eddc.name = name;
1781    eddc.size = size;
1782    eddc.version = 0;
1783
1784    eddc.func.list_next = func_list_next;
1785    eddc.func.list_append = func_list_append;
1786    eddc.func.list_data = func_list_data;
1787    eddc.func.list_free = func_list_free;
1788    eddc.func.hash_foreach = func_hash_foreach;
1789    eddc.func.hash_add = func_hash_add;
1790    eddc.func.hash_free = func_hash_free;
1791
1792    return _eet_data_descriptor_new(&eddc, 0);
1793 }
1794
1795 EAPI Eet_Data_Descriptor *
1796 eet_data_descriptor2_new(const Eet_Data_Descriptor_Class *eddc)
1797 {
1798    return _eet_data_descriptor_new(eddc, 1);
1799 }
1800
1801 EAPI Eet_Data_Descriptor *
1802 eet_data_descriptor3_new(const Eet_Data_Descriptor_Class *eddc)
1803 {
1804    return _eet_data_descriptor_new(eddc, 2);
1805 }
1806
1807 EAPI Eet_Data_Descriptor *
1808 eet_data_descriptor_stream_new(const Eet_Data_Descriptor_Class *eddc)
1809 {
1810    return _eet_data_descriptor_new(eddc, 1);
1811 }
1812
1813 EAPI Eet_Data_Descriptor *
1814 eet_data_descriptor_file_new(const Eet_Data_Descriptor_Class *eddc)
1815 {
1816    return _eet_data_descriptor_new(eddc, 2);
1817 }
1818
1819 EAPI void
1820 eet_data_descriptor_free(Eet_Data_Descriptor *edd)
1821 {
1822    if (!edd)
1823       return;
1824
1825    _eet_descriptor_hash_free(edd);
1826    if (edd->elements.set)
1827       free(edd->elements.set);
1828
1829       free(edd);
1830 }
1831
1832 EAPI void
1833 eet_data_descriptor_element_add(Eet_Data_Descriptor *edd,
1834                                 const char *name,
1835                                 int type,
1836                                 int group_type,
1837                                 int offset,
1838                                 int count,
1839 /*        int counter_offset, */
1840                                 const char *counter_name /* FIXME: Useless should go on a major release */,
1841                                 Eet_Data_Descriptor *subtype)
1842 {
1843    Eet_Data_Element *ede;
1844    Eet_Data_Element *tmp;
1845
1846    /* UNION, VARIANT type would not work with simple type, we need a way to map the type. */
1847    if ((group_type == EET_G_UNION
1848         || group_type == EET_G_VARIANT)
1849        &&
1850        (type != EET_T_UNKNOW
1851         || subtype == NULL
1852         || subtype->func.type_get == NULL
1853         || subtype->func.type_set == NULL))
1854       return;
1855
1856    /* VARIANT type will only work if the map only contains EET_G_*, but not UNION, VARIANT and ARRAY. */
1857    if (group_type == EET_G_VARIANT)
1858      {
1859         int i;
1860
1861         for (i = 0; i < subtype->elements.num; ++i)
1862            if (subtype->elements.set[i].type != EET_T_UNKNOW
1863                && subtype->elements.set[i].group_type > EET_G_VAR_ARRAY
1864                && subtype->elements.set[i].group_type < EET_G_UNION)
1865               return;
1866
1867         subtype->unified_type = EINA_TRUE;
1868      }
1869
1870    if (subtype
1871        && subtype->unified_type
1872        && (type != EET_T_UNKNOW
1873            || group_type < EET_G_UNION))
1874       return;
1875
1876    /* Sanity check done, let allocate ! */
1877    edd->elements.num++;
1878    tmp = realloc(edd->elements.set, edd->elements.num * sizeof(Eet_Data_Element));
1879    if (!tmp)
1880       return;
1881
1882    edd->elements.set = tmp;
1883    ede = &(edd->elements.set[edd->elements.num - 1]);
1884    ede->name = name;
1885    ede->directory_name_ptr = NULL;
1886
1887    /*
1888     * We do a special case when we do list,hash or whatever group of simple type.
1889     * Instead of handling it in encode/decode/dump/undump, we create an
1890     * implicit structure with only the simple type.
1891     */
1892    if (group_type > EET_G_UNKNOWN
1893        && group_type < EET_G_LAST
1894        && ((type > EET_T_UNKNOW && type < EET_T_STRING)
1895            || (type > EET_T_NULL && type < EET_T_LAST))
1896        && subtype == NULL)
1897      {
1898         subtype = calloc(1, sizeof (Eet_Data_Descriptor));
1899         if (!subtype)
1900            return;
1901
1902         subtype->name = "implicit";
1903         subtype->size = eet_basic_codec[type - 1].size;
1904         memcpy(&subtype->func, &edd->func, sizeof(subtype->func));
1905
1906         eet_data_descriptor_element_add(subtype,
1907                                         eet_basic_codec[type - 1].name,
1908                                         type,
1909                                         EET_G_UNKNOWN,
1910                                         0,
1911                                         0,
1912                                         /* 0,  */ NULL,
1913                                         NULL);
1914         type = EET_T_UNKNOW;
1915      }
1916
1917    ede->type = type;
1918    ede->group_type = group_type;
1919    ede->offset = offset;
1920    ede->count = count;
1921    /* FIXME: For the time being, VAR_ARRAY, UNION and VARIANT  will put the counter_offset in count. */
1922    ede->counter_offset = count;
1923 /*    ede->counter_offset = counter_offset; */
1924    ede->counter_name = counter_name;
1925
1926    ede->subtype = subtype;
1927 }
1928
1929 EAPI void *
1930 eet_data_read_cipher(Eet_File *ef,
1931                      Eet_Data_Descriptor *edd,
1932                      const char *name,
1933                      const char *cipher_key)
1934 {
1935    const Eet_Dictionary *ed = NULL;
1936    const void *data = NULL;
1937    void *data_dec;
1938    Eet_Free_Context context;
1939    int required_free = 0;
1940    int size;
1941
1942    ed = eet_dictionary_get(ef);
1943
1944    if (!cipher_key)
1945       data = eet_read_direct(ef, name, &size);
1946
1947    if (!data)
1948      {
1949         required_free = 1;
1950         data = eet_read_cipher(ef, name, &size, cipher_key);
1951         if (!data)
1952            return NULL;
1953      }
1954
1955    memset(&context, 0, sizeof (context));
1956    data_dec = _eet_data_descriptor_decode(&context, ed, edd, data, size);
1957    if (required_free)
1958       free((void *)data);
1959
1960    return data_dec;
1961 }
1962
1963 EAPI Eet_Node *
1964 eet_data_node_read_cipher(Eet_File *ef,
1965                           const char *name,
1966                           const char *cipher_key)
1967 {
1968    const Eet_Dictionary *ed = NULL;
1969    const void *data = NULL;
1970    Eet_Node *result;
1971    Eet_Free_Context context;
1972    int required_free = 0;
1973    int size;
1974
1975    ed = eet_dictionary_get(ef);
1976
1977    if (!cipher_key)
1978       data = eet_read_direct(ef, name, &size);
1979
1980    if (!data)
1981      {
1982         required_free = 1;
1983         data = eet_read_cipher(ef, name, &size, cipher_key);
1984         if (!data)
1985            return NULL;
1986      }
1987
1988    memset(&context, 0, sizeof (context));
1989    result = _eet_data_descriptor_decode(&context, ed, NULL, data, size);
1990    if (required_free)
1991               free((void *)data);
1992
1993    return result;
1994 }
1995
1996 EAPI void *
1997 eet_data_read(Eet_File *ef, Eet_Data_Descriptor *edd, const char *name)
1998 {
1999    return eet_data_read_cipher(ef, edd, name, NULL);
2000 }
2001
2002 EAPI int
2003 eet_data_write_cipher(Eet_File *ef,
2004                       Eet_Data_Descriptor *edd,
2005                       const char *name,
2006                       const char *cipher_key,
2007                       const void *data,
2008                       int compress)
2009 {
2010    Eet_Dictionary *ed;
2011    void *data_enc;
2012    int size;
2013    int val;
2014
2015    ed = eet_dictionary_get(ef);
2016
2017    data_enc = _eet_data_descriptor_encode(ed, edd, data, &size);
2018    if (!data_enc)
2019       return 0;
2020
2021    val = eet_write_cipher(ef, name, data_enc, size, compress, cipher_key);
2022               free(data_enc);
2023    return val;
2024 }
2025
2026 EAPI int
2027 eet_data_write(Eet_File *ef,
2028                Eet_Data_Descriptor *edd,
2029                const char *name,
2030                const void *data,
2031                int compress)
2032 {
2033    return eet_data_write_cipher(ef, edd, name, NULL, data, compress);
2034 }
2035
2036 static int
2037 _eet_free_hash(void *data)
2038 {
2039 #ifdef _WIN64
2040    __int64 ptr = (UINT_PTR)data;
2041 #else
2042    unsigned long ptr = (unsigned long)(data);
2043 #endif
2044    int hash;
2045
2046    hash = ptr;
2047    hash ^= ptr >> 8;
2048    hash ^= ptr >> 16;
2049    hash ^= ptr >> 24;
2050
2051 #if defined (_WIN64) || ((!defined (_WIN32)) && (LONG_BIT != 32))
2052    hash ^= ptr >> 32;
2053    hash ^= ptr >> 40;
2054    hash ^= ptr >> 48;
2055    hash ^= ptr >> 56;
2056 #endif
2057
2058    return hash & 0xFF;
2059 }
2060
2061 static void
2062 _eet_free_add(Eet_Free *ef, void *data)
2063 {
2064    int hash;
2065    int i;
2066
2067    hash = _eet_free_hash(data);
2068
2069    for (i = 0; i < ef->num[hash]; ++i)
2070       if (ef->list[hash][i] == data)
2071          return;
2072
2073    ef->num[hash]++;
2074    if (ef->num[hash] > ef->len[hash])
2075      {
2076         void **tmp;
2077
2078         tmp = realloc(ef->list[hash], (ef->len[hash] + 16) * sizeof(void *));
2079         if (!tmp)
2080            return;
2081
2082         ef->len[hash] += 16;
2083         ef->list[hash] = tmp;
2084      }
2085
2086    ef->list[hash][ef->num[hash] - 1] = data;
2087 }
2088 static void
2089 _eet_free_reset(Eet_Free *ef)
2090 {
2091    int i;
2092
2093    if (ef->ref > 0)
2094       return;
2095
2096    for (i = 0; i < 256; ++i)
2097      {
2098         ef->len[i] = 0;
2099         ef->num[i] = 0;
2100         if (ef->list[i])
2101               free(ef->list[i]);
2102
2103         ef->list[i] = NULL;
2104      }
2105 }
2106 static void
2107 _eet_free_ref(Eet_Free *ef)
2108 {
2109    ef->ref++;
2110 }
2111 static void
2112 _eet_free_unref(Eet_Free *ef)
2113 {
2114    ef->ref--;
2115 }
2116
2117 #define _eet_freelist_add(Ctx, Data)    _eet_free_add(&Ctx->freelist, Data);
2118 #define _eet_freelist_reset(Ctx)        _eet_free_reset(&Ctx->freelist);
2119 #define _eet_freelist_ref(Ctx)          _eet_free_ref(&Ctx->freelist);
2120 #define _eet_freelist_unref(Ctx)        _eet_free_unref(&Ctx->freelist);
2121
2122 static void
2123 _eet_freelist_free(Eet_Free_Context *context, Eet_Data_Descriptor *edd)
2124 {
2125    int j;
2126    int i;
2127
2128    if (context->freelist.ref > 0)
2129       return;
2130
2131    for (j = 0; j < 256; ++j)
2132       for (i = 0; i < context->freelist.num[j]; ++i)
2133         {
2134            if (edd)
2135               edd->func.mem_free(context->freelist.list[j][i]);
2136            else
2137               free(context->freelist.list[j][i]);
2138         }
2139               _eet_free_reset(&context->freelist);
2140 }
2141
2142 #define _eet_freelist_list_add(Ctx, Data)  _eet_free_add(&Ctx->freelist_list, \
2143                                                          Data);
2144 #define _eet_freelist_list_reset(Ctx)      _eet_free_reset(&Ctx->freelist_list);
2145 #define _eet_freelist_list_ref(Ctx)        _eet_free_ref(&Ctx->freelist_list);
2146 #define _eet_freelist_list_unref(Ctx)      _eet_free_unref(&Ctx->freelist_list);
2147
2148 static void
2149 _eet_freelist_list_free(Eet_Free_Context *context, Eet_Data_Descriptor *edd)
2150 {
2151    int j;
2152    int i;
2153
2154    if (context->freelist_list.ref > 0)
2155       return;
2156
2157    for (j = 0; j < 256; ++j)
2158       for (i = 0; i < context->freelist_list.num[j]; ++i)
2159         {
2160            if (edd)
2161               edd->func.list_free(*((void **)(context->freelist_list.list[j][i])));
2162         }
2163               _eet_free_reset(&context->freelist_list);
2164 }
2165
2166 #define _eet_freelist_str_add(Ctx, Data)   _eet_free_add(&Ctx->freelist_str, \
2167                                                          Data);
2168 #define _eet_freelist_str_reset(Ctx)       _eet_free_reset(&Ctx->freelist_str);
2169 #define _eet_freelist_str_ref(Ctx)         _eet_free_ref(&Ctx->freelist_str);
2170 #define _eet_freelist_str_unref(Ctx)       _eet_free_unref(&Ctx->freelist_str);
2171
2172 static void
2173 _eet_freelist_str_free(Eet_Free_Context *context, Eet_Data_Descriptor *edd)
2174 {
2175    int j;
2176    int i;
2177
2178    if (context->freelist_str.ref > 0)
2179       return;
2180
2181    for (j = 0; j < 256; ++j)
2182       for (i = 0; i < context->freelist_str.num[j]; ++i)
2183         {
2184            if (edd)
2185               edd->func.str_free(context->freelist_str.list[j][i]);
2186            else
2187               free(context->freelist_str.list[j][i]);
2188         }
2189    _eet_free_reset(&context->freelist_str);
2190 }
2191
2192 #define _eet_freelist_direct_str_add(Ctx, Data)    _eet_free_add( \
2193       &Ctx->freelist_direct_str, \
2194       Data);
2195 #define _eet_freelist_direct_str_reset(Ctx)        _eet_free_reset( \
2196       &Ctx->freelist_direct_str);
2197 #define _eet_freelist_direct_str_ref(Ctx)          _eet_free_ref( \
2198       &Ctx->freelist_direct_str);
2199 #define _eet_freelist_direct_str_unref(Ctx)        _eet_free_unref( \
2200       &Ctx->freelist_direct_str);
2201
2202 static void
2203 _eet_freelist_direct_str_free(Eet_Free_Context *context,
2204                               Eet_Data_Descriptor *edd)
2205 {
2206    int j;
2207    int i;
2208
2209    if (context->freelist_direct_str.ref > 0)
2210       return;
2211
2212    for (j = 0; j < 256; ++j)
2213       for (i = 0; i < context->freelist_direct_str.num[j]; ++i)
2214         {
2215            if (edd)
2216               edd->func.str_direct_free(context->freelist_direct_str.list[j][i]);
2217            else
2218               free(context->freelist_direct_str.list[j][i]);
2219         }
2220    _eet_free_reset(&context->freelist_direct_str);
2221 }
2222
2223 #define _eet_freelist_hash_add(Ctx, Data) _eet_free_add(&Ctx->freelist_hash, \
2224                                                         Data);
2225 #define _eet_freelist_hash_reset(Ctx)     _eet_free_reset(&Ctx->freelist_hash);
2226 #define _eet_freelist_hash_ref(Ctx)       _eet_free_ref(&Ctx->freelist_hash);
2227 #define _eet_freelist_hash_unref(Ctx)     _eet_free_unref(&Ctx->freelist_hash);
2228
2229 static void
2230 _eet_freelist_hash_free(Eet_Free_Context *context, Eet_Data_Descriptor *edd)
2231 {
2232    int j;
2233    int i;
2234
2235    if (context->freelist_hash.ref > 0)
2236       return;
2237
2238    for (j = 0; j < 256; ++j)
2239       for (i = 0; i < context->freelist_hash.num[j]; ++i)
2240         {
2241            if (edd)
2242               edd->func.hash_free(context->freelist_hash.list[j][i]);
2243            else
2244               free(context->freelist_hash.list[j][i]);
2245         }
2246    _eet_free_reset(&context->freelist_hash);
2247 }
2248
2249 static void
2250 _eet_freelist_all_ref(Eet_Free_Context *freelist_context)
2251 {
2252    _eet_freelist_ref(freelist_context);
2253    _eet_freelist_str_ref(freelist_context);
2254    _eet_freelist_list_ref(freelist_context);
2255    _eet_freelist_hash_ref(freelist_context);
2256    _eet_freelist_direct_str_ref(freelist_context);
2257 }
2258
2259 static void
2260 _eet_freelist_all_unref(Eet_Free_Context *freelist_context)
2261 {
2262    _eet_freelist_unref(freelist_context);
2263    _eet_freelist_str_unref(freelist_context);
2264    _eet_freelist_list_unref(freelist_context);
2265    _eet_freelist_hash_unref(freelist_context);
2266    _eet_freelist_direct_str_unref(freelist_context);
2267 }
2268
2269 static int
2270 eet_data_descriptor_encode_hash_cb(void *hash __UNUSED__,
2271                                    const char *cipher_key,
2272                                    void *hdata,
2273                                    void *fdata)
2274 {
2275    Eet_Dictionary *ed;
2276    Eet_Data_Encode_Hash_Info *edehi;
2277    Eet_Data_Stream *ds;
2278    Eet_Data_Element *ede;
2279    Eet_Data_Chunk *echnk;
2280    void *data = NULL;
2281    int size;
2282
2283    edehi = fdata;
2284    ede = edehi->ede;
2285    ds = edehi->ds;
2286    ed = edehi->ed;
2287
2288    /* Store key */
2289    data = eet_data_put_type(ed,
2290                             EET_T_STRING,
2291                             &cipher_key,
2292                             &size);
2293    if (data)
2294      {
2295         echnk = eet_data_chunk_new(data,
2296                                    size,
2297                                    ede->name,
2298                                    ede->type,
2299                                    ede->group_type);
2300         eet_data_chunk_put(ed, echnk, ds);
2301         eet_data_chunk_free(echnk);
2302         free(data);
2303         data = NULL;
2304      }
2305
2306    EET_ASSERT(!((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING)),
2307               return );
2308
2309    /* Store data */
2310    if (ede->type >= EET_T_STRING)
2311       eet_data_put_unknown(ed, NULL, ede, ds, &hdata);
2312    else
2313      {
2314         if (ede->subtype)
2315            data = _eet_data_descriptor_encode(ed,
2316                                               ede->subtype,
2317                                               hdata,
2318                                               &size);
2319
2320         if (data)
2321           {
2322              echnk = eet_data_chunk_new(data,
2323                                         size,
2324                                         ede->name,
2325                                         ede->type,
2326                                         ede->group_type);
2327              eet_data_chunk_put(ed, echnk, ds);
2328              eet_data_chunk_free(echnk);
2329              free(data);
2330              data = NULL;
2331           }
2332      }
2333
2334    return 1;
2335 }
2336
2337 static char *
2338 _eet_data_dump_token_get(const char *src, int *len)
2339 {
2340    const char *p;
2341    char *tok = NULL;
2342    int in_token = 0;
2343    int in_quote = 0;
2344    int tlen = 0, tsize = 0;
2345
2346 #define TOK_ADD(x) \
2347    do { \
2348         tlen++; \
2349         if (tlen >= tsize) \
2350           { \
2351              tsize += 32; \
2352              tok = realloc(tok, tsize); \
2353           } \
2354         tok[tlen - 1] = x; \
2355      } while (0)
2356
2357    for (p = src; *len > 0; p++, (*len)--)
2358      {
2359         if (in_token)
2360           {
2361              if (in_quote)
2362                {
2363                   if ((p[0] == '\"') && (p > src) && (p[-1] != '\\'))
2364                      in_quote = 0;
2365                   else if ((p[0] == '\\') && (*len > 1) &&
2366                            (p[1] == '\"'))
2367                     {
2368 /* skip */
2369                     }
2370                   else if ((p[0] == '\\') && (p > src) && (p[-1] == '\\'))
2371                     {
2372 /* skip */
2373                     }
2374                   else if ((p[0] == '\\') && (*len > 1) && (p[1] == 'n'))
2375                     {
2376 /* skip */
2377                     }
2378                   else if ((p[0] == 'n') && (p > src) && (p[-1] == '\\'))
2379                             TOK_ADD('\n');
2380                   else
2381                             TOK_ADD(p[0]);
2382                }
2383              else
2384                {
2385                   if (p[0] == '\"')
2386                      in_quote = 1;
2387                   else
2388                     {
2389                        if ((isspace(p[0])) || (p[0] == ';')) /* token ends here */
2390                          {
2391                             TOK_ADD(0);
2392                             (*len)--;
2393                             return tok;
2394                          }
2395                        else
2396                             TOK_ADD(p[0]);
2397                     }
2398                }
2399           }
2400         else if (!((isspace(p[0])) || (p[0] == ';')))
2401           {
2402              in_token = 1;
2403              (*len)++;
2404              p--;
2405           }
2406      }
2407    if (in_token)
2408      {
2409                             TOK_ADD(0);
2410         return tok;
2411      }
2412
2413    if (tok)
2414       free(tok);
2415
2416    return NULL;
2417 }
2418
2419 static void
2420 eet_data_encode(Eet_Dictionary *ed,
2421                 Eet_Data_Stream *ds,
2422                 void *data,
2423                 const char *name,
2424                 int size,
2425                 int type,
2426                 int group_type)
2427 {
2428    Eet_Data_Chunk *echnk;
2429
2430    if (!data)
2431       type = EET_T_NULL;
2432
2433    if (group_type != EET_G_UNKNOWN)
2434       if (type >= EET_T_LAST)
2435          type = EET_T_UNKNOW;
2436
2437    echnk = eet_data_chunk_new(data, size, name, type, group_type);
2438    eet_data_chunk_put(ed, echnk, ds);
2439    eet_data_chunk_free(echnk);
2440    free(data);
2441 }
2442
2443 static void *
2444 _eet_data_dump_encode(int parent_type,
2445                       Eet_Dictionary *ed,
2446                       Eet_Node *node,
2447                       int *size_ret)
2448 {
2449    Eet_Data_Chunk *chnk = NULL;
2450    Eet_Data_Stream *ds;
2451    void *cdata, *data;
2452    int csize, size;
2453    int count;
2454    int child_type;
2455    Eet_Node *n;
2456
2457    if (_eet_data_words_bigendian == -1)
2458      {
2459         unsigned long int v;
2460
2461         v = htonl(0x12345678);
2462         if (v == 0x12345678)
2463            _eet_data_words_bigendian = 1;
2464         else
2465            _eet_data_words_bigendian = 0;
2466      }
2467
2468    if (node == NULL)
2469       return NULL;
2470
2471    ds = eet_data_stream_new();
2472    if (!ds)
2473       return NULL;
2474
2475    switch (node->type)
2476      {
2477       case EET_G_UNKNOWN:
2478          for (n = node->values; n; n = n->next)
2479            {
2480               data = _eet_data_dump_encode(node->type, ed, n, &size);
2481               if (data)
2482                 {
2483                    eet_data_stream_write(ds, data, size);
2484                    free(data);
2485                 }
2486            }
2487          break;
2488
2489       case EET_G_ARRAY:
2490       case EET_G_VAR_ARRAY:
2491          for (child_type = EET_T_NULL, n = node->values; n; n = n->next)
2492            {
2493               if (n->type != EET_T_NULL)
2494                 {
2495                    child_type = n->type;
2496                    break;
2497                 }
2498            }
2499
2500          data = eet_data_put_type(ed,
2501                                   EET_T_INT,
2502                                   &node->count,
2503                                   &size);
2504                        eet_data_encode(ed,
2505                          ds,
2506                          data,
2507                          node->name,
2508                          size,
2509                          child_type,
2510                          node->type);
2511
2512          count = node->count;
2513
2514          for (n = node->values; n; n = n->next)
2515            {
2516               int pos = ds->pos;
2517
2518               switch (n->type)
2519                 {
2520                  case EET_T_STRING:
2521                  case EET_T_INLINED_STRING:
2522                     data = eet_data_put_type(ed,
2523                                              n->type,
2524                                              &(n->data.value.str),
2525                                              &size);
2526                     if (data)
2527                        eet_data_encode(ed,
2528                                        ds,
2529                                        data,
2530                                        node->name,
2531                                        size,
2532                                        n->type,
2533                                        node->type);
2534
2535                     break;
2536
2537                  case EET_T_NULL:
2538                     continue;
2539
2540                  default:
2541                     data = _eet_data_dump_encode(n->type, ed, n, &size);
2542                        eet_data_encode(ed,
2543                                     ds,
2544                                     data,
2545                                     node->name,
2546                                     size,
2547                                     n->type,
2548                                     node->type);
2549                     break;
2550                 }
2551               if (ds->pos != pos)
2552                  count--;
2553            }
2554
2555          for (; count; count--)
2556            {
2557                        eet_data_encode(ed,
2558                               ds,
2559                               NULL,
2560                               node->name,
2561                               0,
2562                               EET_T_NULL,
2563                               node->type);
2564            }
2565
2566          /* Array is somekind of special case, so we should embed it inside another chunk. */
2567          *size_ret = ds->pos;
2568          cdata = ds->data;
2569
2570          ds->data = NULL;
2571          ds->size = 0;
2572          eet_data_stream_free(ds);
2573
2574          return cdata;
2575          break;
2576
2577       case EET_G_LIST:
2578          for (n = node->values; n; n = n->next)
2579            {
2580               switch (n->type)
2581                 {
2582                  case EET_T_STRING:
2583                  case EET_T_INLINED_STRING:
2584                     data = eet_data_put_type(ed,
2585                                              n->type,
2586                                              &(n->data.value.str),
2587                                              &size);
2588                     if (data)
2589                        eet_data_encode(ed,
2590                                        ds,
2591                                        data,
2592                                        node->name,
2593                                        size,
2594                                        n->type,
2595                                        node->type);
2596
2597                     break;
2598
2599                  case EET_T_NULL:
2600                     continue;
2601
2602                  default:
2603                     data = _eet_data_dump_encode(node->type, ed, n, &size);
2604                        eet_data_encode(ed,
2605                                     ds,
2606                                     data,
2607                                     node->name,
2608                                     size,
2609                                     n->type,
2610                                     node->type);
2611                 }
2612            }
2613
2614          /* List is another somekind of special case, every chunk is embed inside a list chunk. */
2615          *size_ret = ds->pos;
2616          cdata = ds->data;
2617
2618          ds->data = NULL;
2619          ds->size = 0;
2620          eet_data_stream_free(ds);
2621
2622          return cdata;
2623          break;
2624
2625       case EET_G_HASH:
2626          if (node->key)
2627            {
2628               data = eet_data_put_type(ed,
2629                                        EET_T_STRING,
2630                                        &node->key,
2631                                        &size);
2632                        eet_data_encode(ed,
2633                               ds,
2634                               data,
2635                               node->name,
2636                               size,
2637                               node->type,
2638                               node->type);
2639            }
2640          else
2641             /* A Hash without key will not decode correctly. */
2642             return NULL;
2643
2644          for (n = node->values; n; n = n->next)
2645            {
2646               switch (n->type)
2647                 {
2648                  case EET_T_STRING:
2649                  case EET_T_INLINED_STRING:
2650                     data = eet_data_put_type(ed,
2651                                              n->type,
2652                                              &(n->data.value.str),
2653                                              &size);
2654                     if (data)
2655                        eet_data_encode(ed,
2656                                        ds,
2657                                        data,
2658                                        node->name,
2659                                        size,
2660                                        n->type,
2661                                        node->type);
2662
2663                     break;
2664
2665                  case EET_T_NULL:
2666                     continue;
2667
2668                  default:
2669                     data = _eet_data_dump_encode(node->type, ed, n, &size);
2670                        eet_data_encode(ed,
2671                                     ds,
2672                                     data,
2673                                     node->name,
2674                                     size,
2675                                     n->type,
2676                                     node->type);
2677                 }
2678            }
2679
2680          /* Hash is somekind of special case, so we should embed it inside another chunk. */
2681          *size_ret = ds->pos;
2682          cdata = ds->data;
2683
2684          eet_data_stream_flush(ds);
2685
2686          return cdata;
2687
2688       case EET_T_NULL:
2689          break;
2690
2691 #define EET_DATA_NODE_ENCODE(Eet_Type, Type)                            \
2692  case Eet_Type:                                                    \
2693     data = eet_data_put_type(ed, node->type, &(node->data.value.Type), &size); \
2694     if (data)                                                               \
2695       {                                                             \
2696          eet_data_encode(ed, \
2697                          ds, \
2698                          data, \
2699                          node->name, \
2700                          size, \
2701                          node->type, \
2702                          parent_type); \
2703          cdata = ds->data;                                          \
2704          *size_ret = ds->pos;                                       \
2705          eet_data_stream_flush(ds);                                 \
2706          return cdata;                                              \
2707       }                                                             \
2708     break;
2709
2710          EET_DATA_NODE_ENCODE(EET_T_CHAR,           c);
2711          EET_DATA_NODE_ENCODE(EET_T_SHORT,          s);
2712          EET_DATA_NODE_ENCODE(EET_T_INT,            i);
2713          EET_DATA_NODE_ENCODE(EET_T_LONG_LONG,      l);
2714          EET_DATA_NODE_ENCODE(EET_T_FLOAT,          f);
2715          EET_DATA_NODE_ENCODE(EET_T_DOUBLE,         d);
2716          EET_DATA_NODE_ENCODE(EET_T_UCHAR,          uc);
2717          EET_DATA_NODE_ENCODE(EET_T_USHORT,         us);
2718          EET_DATA_NODE_ENCODE(EET_T_UINT,           ui);
2719          EET_DATA_NODE_ENCODE(EET_T_ULONG_LONG,     ul);
2720          EET_DATA_NODE_ENCODE(EET_T_INLINED_STRING, str);
2721          EET_DATA_NODE_ENCODE(EET_T_STRING,         str);
2722
2723       default:
2724          break;
2725      }
2726
2727    if ((node->type >= EET_G_UNKNOWN) && (node->type < EET_G_LAST))
2728       chnk = eet_data_chunk_new(ds->data,
2729                                 ds->pos,
2730                                 node->name,
2731                                 EET_T_UNKNOW,
2732                                 node->type);
2733    else
2734       chnk = eet_data_chunk_new(ds->data,
2735                                 ds->pos,
2736                                 node->name,
2737                                 node->type,
2738                                 EET_G_UNKNOWN);
2739
2740    eet_data_stream_flush(ds);
2741
2742    ds = eet_data_stream_new();
2743    eet_data_chunk_put(ed, chnk, ds);
2744    cdata = ds->data;
2745    csize = ds->pos;
2746
2747    eet_data_stream_flush(ds);
2748    *size_ret = csize;
2749
2750    free(chnk->data);
2751    eet_data_chunk_free(chnk);
2752
2753    return cdata;
2754 }
2755
2756 static void *
2757 _eet_data_dump_parse(Eet_Dictionary *ed,
2758                      int *size_ret,
2759                      const char *src,
2760                      int size)
2761 {
2762    void *cdata = NULL;
2763    const char *p = NULL;
2764 #define M_NONE 0
2765 #define M_STRUCT 1
2766 #define M_ 2
2767    int left, jump;
2768    Eet_Node *node_base = NULL;
2769    Eet_Node *node = NULL;
2770    Eet_Node *n = NULL, *nn = NULL;
2771
2772    /* FIXME; handle parse errors */
2773 #define TOK_GET(t) \
2774    jump = left; t = _eet_data_dump_token_get(p, &left); p += jump - left;
2775    left = size;
2776    for (p = src; p < (src + size); )
2777      {
2778         char *tok1, *tok2, *tok3, *tok4;
2779
2780                             TOK_GET(tok1);
2781         if (tok1)
2782           {
2783              if (!strcmp(tok1, "group"))
2784                {
2785                             TOK_GET(tok2);
2786                   if (tok2)
2787                     {
2788                             TOK_GET(tok3);
2789                        if (tok3)
2790                          {
2791                             TOK_GET(tok4);
2792                             if (tok4)
2793                               {
2794                                  if (!strcmp(tok4, "{"))
2795                                    {
2796 /* we have 'group NAM TYP {' */
2797                                       n = eet_node_new();
2798                                       if (n)
2799                                         {
2800                                            n->parent = node;
2801                                            if (!node_base)
2802                                               node_base = n;
2803
2804                                            if (node)
2805                                              {
2806 /* append node */
2807                                                 if (!node->values)
2808                                                    node->values = n;
2809                                                 else
2810                                                    for (nn = node->values; nn;
2811                                                         nn = nn->next)
2812                                                      {
2813                                                         if (!nn->next)
2814                                                           {
2815                                                              nn->next = n;
2816                                                              break;
2817                                                           }
2818                                                      }
2819                                              }
2820
2821                                            n->name = eina_stringshare_add(tok2);
2822                                            if      (!strcmp(tok3, "struct"))
2823                                               n->type = EET_G_UNKNOWN;
2824                                            else if (!strcmp(tok3, "array"))
2825                                               n->type = EET_G_ARRAY;
2826                                            else if (!strcmp(tok3, "var_array"))
2827                                               n->type = EET_G_VAR_ARRAY;
2828                                            else if (!strcmp(tok3, "list"))
2829                                               n->type = EET_G_LIST;
2830                                            else if (!strcmp(tok3, "hash"))
2831                                               n->type = EET_G_HASH;
2832                                            else
2833                                               ERR(
2834                                                  "ERROR: group type '%s' invalid.",
2835                                                  tok3);
2836
2837                                            node = n;
2838                                         }
2839                                    }
2840
2841                                  free(tok4);
2842                               }
2843
2844                                  free(tok3);
2845                          }
2846
2847                                  free(tok2);
2848                     }
2849                }
2850              else if (!strcmp(tok1, "value"))
2851                {
2852                             TOK_GET(tok2);
2853                   if (tok2)
2854                     {
2855                             TOK_GET(tok3);
2856                        if (tok3)
2857                          {
2858                             TOK_GET(tok4);
2859                             if (tok4)
2860                               {
2861 /* we have 'value NAME TYP XXX' */
2862                                  if (node_base)
2863                                    {
2864                                       n = eet_node_new();
2865                                       if (n)
2866                                         {
2867                                            n->parent = node;
2868 /* append node */
2869                                            if (!node->values)
2870                                               node->values = n;
2871                                            else
2872                                               for (nn = node->values; nn;
2873                                                    nn = nn->next)
2874                                                 {
2875                                                    if (!nn->next)
2876                                                      {
2877                                                         nn->next = n;
2878                                                         break;
2879                                                      }
2880                                                 }
2881
2882                                            n->name = eina_stringshare_add(tok2);
2883                                            if      (!strcmp(tok3, "char:"))
2884                                              {
2885                                                 n->type = EET_T_CHAR;
2886                                                 sscanf(tok4, "%hhi",
2887                                                        &(n->data.value.c));
2888                                              }
2889                                            else if (!strcmp(tok3, "short:"))
2890                                              {
2891                                                 n->type = EET_T_SHORT;
2892                                                 sscanf(tok4, "%hi",
2893                                                        &(n->data.value.s));
2894                                              }
2895                                            else if (!strcmp(tok3, "int:"))
2896                                              {
2897                                                 n->type = EET_T_INT;
2898                                                 sscanf(tok4, "%i",
2899                                                        &(n->data.value.i));
2900                                              }
2901                                            else if (!strcmp(tok3, "long_long:"))
2902                                              {
2903                                                 n->type = EET_T_LONG_LONG;
2904                                                 sscanf(tok4, "%lli",
2905                                                        &(n->data.value.l));
2906                                              }
2907                                            else if (!strcmp(tok3, "float:"))
2908                                              {
2909                                                 n->type = EET_T_FLOAT;
2910                                                 sscanf(tok4, "%f",
2911                                                        &(n->data.value.f));
2912                                              }
2913                                            else if (!strcmp(tok3, "double:"))
2914                                              {
2915                                                 n->type = EET_T_DOUBLE;
2916                                                 sscanf(tok4, "%lf",
2917                                                        &(n->data.value.d));
2918                                              }
2919                                            else if (!strcmp(tok3, "uchar:"))
2920                                              {
2921                                                 n->type = EET_T_UCHAR;
2922                                                 sscanf(tok4, "%hhu",
2923                                                        &(n->data.value.uc));
2924                                              }
2925                                            else if (!strcmp(tok3, "ushort:"))
2926                                              {
2927                                                 n->type = EET_T_USHORT;
2928                                                 sscanf(tok4, "%hu",
2929                                                        &(n->data.value.us));
2930                                              }
2931                                            else if (!strcmp(tok3, "uint:"))
2932                                              {
2933                                                 n->type = EET_T_UINT;
2934                                                 sscanf(tok4, "%u",
2935                                                        &(n->data.value.ui));
2936                                              }
2937                                            else if (!strcmp(tok3, "ulong_long:"))
2938                                              {
2939                                                 n->type = EET_T_ULONG_LONG;
2940                                                 sscanf(tok4, "%llu",
2941                                                        &(n->data.value.ul));
2942                                              }
2943                                            else if (!strcmp(tok3, "string:"))
2944                                              {
2945                                                 n->type = EET_T_STRING;
2946                                                 n->data.value.str =
2947                                                    eina_stringshare_add(tok4);
2948                                              }
2949                                            else if (!strcmp(tok3, "inlined:"))
2950                                              {
2951                                                 n->type = EET_T_INLINED_STRING;
2952                                                 n->data.value.str =
2953                                                    eina_stringshare_add(tok4);
2954                                              }
2955                                            else if (!strcmp(tok3, "null"))
2956                                              {
2957                                                 n->type = EET_T_NULL;
2958                                                 n->data.value.str = NULL;
2959                                              }
2960                                            else
2961                                               ERR(
2962                                                  "ERROR: value type '%s' invalid.",
2963                                                  tok4);
2964                                         }
2965                                    }
2966
2967                                  free(tok4);
2968                               }
2969
2970                                  free(tok3);
2971                          }
2972
2973                                  free(tok2);
2974                     }
2975                }
2976              else if (!strcmp(tok1, "key"))
2977                {
2978                   TOK_GET(tok2);
2979                   if (tok2)
2980                     {
2981 /* we have 'key NAME' */
2982                        if (node)
2983                           node->key = eina_stringshare_add(tok2);
2984
2985                        free(tok2);
2986                     }
2987                }
2988              else if (!strcmp(tok1, "count"))
2989                {
2990                   TOK_GET(tok2);
2991                   if (tok2)
2992                     {
2993 /* we have a 'count COUNT' */
2994                        if (node)
2995                           sscanf(tok2, "%i", &(node->count));
2996
2997                        free(tok2);
2998                     }
2999                }
3000              else if (!strcmp(tok1, "}"))
3001                 /* we have an end of the group */
3002                 if (node)
3003                    node = node->parent;
3004
3005                        free(tok1);
3006           }
3007      }
3008
3009    if (node_base)
3010      {
3011         cdata = _eet_data_dump_encode(EET_G_UNKNOWN, ed, node_base, size_ret);
3012         eet_node_del(node_base);
3013      }
3014
3015    return cdata;
3016 }
3017
3018 #define NEXT_CHUNK(P, Size, Echnk, Ed)                  \
3019    {                                                     \
3020       int tmp;                                    \
3021       tmp = Ed ? (int)(sizeof(int) * 2) : Echnk.len + 4; \
3022       P += (4 + Echnk.size + tmp);                       \
3023       Size -= (4 + Echnk.size + tmp);                    \
3024    }
3025
3026 static void *
3027 _eet_data_descriptor_decode(Eet_Free_Context *context,
3028                             const Eet_Dictionary *ed,
3029                             Eet_Data_Descriptor *edd,
3030                             const void *data_in,
3031                             int size_in)
3032 {
3033    Eet_Node *result = NULL;
3034    void *data = NULL;
3035    char *p;
3036    int size, i;
3037    Eet_Data_Chunk chnk;
3038
3039    if (_eet_data_words_bigendian == -1)
3040      {
3041         unsigned long int v;
3042
3043         v = htonl(0x12345678);
3044         if (v == 0x12345678)
3045            _eet_data_words_bigendian = 1;
3046         else
3047            _eet_data_words_bigendian = 0;
3048      }
3049
3050    if (edd)
3051      {
3052         data = edd->func.mem_alloc(edd->size);
3053         if (!data)
3054            return NULL;
3055
3056         if (edd->ed != ed)
3057           {
3058              for (i = 0; i < edd->elements.num; i++)
3059                 edd->elements.set[i].directory_name_ptr = NULL;
3060              edd->ed = ed;
3061           }
3062      }
3063
3064    _eet_freelist_all_ref(context);
3065    if (data)
3066       _eet_freelist_add(context, data);
3067
3068    memset(&chnk, 0, sizeof(Eet_Data_Chunk));
3069    eet_data_chunk_get(ed, &chnk, data_in, size_in);
3070    if (!chnk.name)
3071       goto error;
3072
3073    if (edd)
3074       if (strcmp(chnk.name, edd->name))
3075          goto error;
3076
3077    p = chnk.data;
3078    if (ed)
3079       size = size_in - (4 + sizeof(int) * 2);
3080    else
3081       size = size_in - (4 + 4 + chnk.len);
3082
3083    if (edd)
3084      {
3085         if (!edd->elements.hash.buckets)
3086            _eet_descriptor_hash_new(edd);
3087      }
3088    else
3089      {
3090         switch (chnk.group_type)
3091           {
3092            case EET_G_UNKNOWN:
3093               switch (chnk.type)
3094                 {
3095                  case EET_T_STRING:
3096                     return eet_node_string_new(chnk.name, chnk.data);
3097
3098                  case EET_T_INLINED_STRING:
3099                     return eet_node_inlined_string_new(chnk.name, chnk.data);
3100
3101                  case EET_T_NULL:
3102                     return eet_node_null_new(chnk.name);
3103
3104                  default:
3105                     result = eet_node_struct_new(chnk.name, NULL);
3106                 }
3107               break;
3108
3109            case EET_G_VAR_ARRAY:
3110               return eet_node_var_array_new(chnk.name, NULL);
3111
3112            case EET_G_LIST:
3113            case EET_G_HASH:
3114            case EET_G_ARRAY:
3115            case EET_G_UNION:
3116            case EET_G_VARIANT:
3117            default:
3118               goto error;
3119           }
3120      }
3121
3122    while (size > 0)
3123      {
3124         Eet_Data_Chunk echnk;
3125         Eet_Data_Element *ede = NULL;
3126         Eet_Node *child = NULL;
3127         int group_type = EET_G_UNKNOWN, type = EET_T_UNKNOW;
3128         int ret = 0;
3129
3130         /* get next data chunk */
3131         memset(&echnk, 0, sizeof(Eet_Data_Chunk));
3132         eet_data_chunk_get(ed, &echnk, p, size);
3133         if (!echnk.name)
3134            goto error;  /* FIXME: don't REPLY on edd - work without */
3135
3136         if (edd)
3137           {
3138              ede = _eet_descriptor_hash_find(edd, echnk.name, echnk.hash);
3139              if (ede)
3140                {
3141                   group_type = ede->group_type;
3142                   type = ede->type;
3143                   if ((echnk.type == 0) && (echnk.group_type == 0))
3144                     {
3145                        type = ede->type;
3146                        group_type = ede->group_type;
3147                     }
3148                   else
3149                     {
3150                        if (IS_SIMPLE_TYPE(echnk.type) &&
3151                            eet_data_type_match(echnk.type, ede->type))
3152 /* Needed when converting on the fly from FP to Float */
3153                           type = ede->type;
3154                        else if ((echnk.group_type > EET_G_UNKNOWN) &&
3155                                 (echnk.group_type <
3156                                  EET_G_LAST) &&
3157                                 (echnk.group_type ==
3158                                  ede->group_type))
3159                           group_type = echnk.group_type;
3160                     }
3161                }
3162           }
3163         /*...... dump to node */
3164         else
3165           {
3166              type = echnk.type;
3167              group_type = echnk.group_type;
3168           }
3169
3170         if (!edd && group_type == EET_G_UNKNOWN && IS_SIMPLE_TYPE(type))
3171           {
3172              unsigned char dd[128];
3173
3174              ret = eet_data_get_type(ed,
3175                                      type,
3176                                      echnk.data,
3177                                      ((char *)echnk.data) + echnk.size,
3178                                      dd);
3179              if (ret <= 0)
3180                 goto error;
3181
3182              child = eet_data_node_simple_type(type, echnk.name, dd);
3183
3184              eet_node_struct_append(result, echnk.name, child);
3185           }
3186         else
3187           {
3188              ret = eet_group_codec[group_type - 100].get(
3189                    context,
3190                    ed,
3191                    edd,
3192                    ede,
3193                    &echnk,
3194                    type,
3195                    group_type,
3196                    ede ? (void *)(((char
3197                                     *)
3198                                    data)
3199                                   + ede->
3200                                   offset)
3201                    : (void **)&result,
3202                    &p,
3203                    &size);
3204
3205              if (ret <= 0)
3206                 goto error;
3207           }
3208
3209         /* advance to next chunk */
3210         NEXT_CHUNK(p, size, echnk, ed);
3211      }
3212
3213    _eet_freelist_all_unref(context);
3214    if (!edd)
3215      {
3216         _eet_freelist_str_free(context, edd);
3217         _eet_freelist_direct_str_free(context, edd);
3218         _eet_freelist_list_free(context, edd);
3219         _eet_freelist_hash_free(context, edd);
3220         _eet_freelist_free(context, edd);
3221      }
3222    else
3223      {
3224         _eet_freelist_reset(context);
3225         _eet_freelist_str_reset(context);
3226         _eet_freelist_list_reset(context);
3227         _eet_freelist_hash_reset(context);
3228         _eet_freelist_direct_str_reset(context);
3229      }
3230
3231    if (!edd)
3232       return result;
3233
3234    return data;
3235
3236 error:
3237    eet_node_del(result);
3238
3239    _eet_freelist_all_unref(context);
3240    _eet_freelist_str_free(context, edd);
3241    _eet_freelist_direct_str_free(context, edd);
3242    _eet_freelist_list_free(context, edd);
3243    _eet_freelist_hash_free(context, edd);
3244    _eet_freelist_free(context, edd);
3245
3246    /* FIXME: Warn that something goes wrong here. */
3247    return NULL;
3248 }
3249
3250 static int
3251 eet_data_get_list(Eet_Free_Context *context,
3252                   const Eet_Dictionary *ed,
3253                   Eet_Data_Descriptor *edd,
3254                   Eet_Data_Element *ede,
3255                   Eet_Data_Chunk *echnk,
3256                   int type,
3257                   int group_type __UNUSED__,
3258                   void *data,
3259                   char **p,
3260                   int *size)
3261 {
3262    Eet_Data_Descriptor *subtype = NULL;
3263    void *list = NULL;
3264    void **ptr;
3265    void *data_ret;
3266
3267    EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0);
3268
3269    if (edd)
3270      {
3271         subtype = ede->subtype;
3272
3273         if (type != ede->type)
3274            return 0;
3275      }
3276
3277    ptr = (void **)data;
3278    list = *ptr;
3279    data_ret = NULL;
3280
3281    if (IS_POINTER_TYPE(type))
3282       POINTER_TYPE_DECODE(context,
3283                           ed,
3284                           edd,
3285                           ede,
3286                           echnk,
3287                           type,
3288                           &data_ret,
3289                           p,
3290                           size,
3291                           on_error);
3292    else
3293       STRUCT_TYPE_DECODE(data_ret,
3294                          context,
3295                          ed,
3296                          subtype,
3297                          echnk->data,
3298                          echnk->size,
3299                          on_error);
3300
3301    if (edd)
3302      {
3303         list = edd->func.list_append(list, data_ret);
3304         *ptr = list;
3305         _eet_freelist_list_add(context, ptr);
3306      }
3307    else
3308       eet_node_list_append(*((Eet_Node **)data), echnk->name, data_ret);
3309
3310    return 1;
3311
3312 on_error:
3313    return 0;
3314 }
3315
3316 static int
3317 eet_data_get_hash(Eet_Free_Context *context,
3318                   const Eet_Dictionary *ed,
3319                   Eet_Data_Descriptor *edd,
3320                   Eet_Data_Element *ede,
3321                   Eet_Data_Chunk *echnk,
3322                   int type,
3323                   int group_type __UNUSED__,
3324                   void *data,
3325                   char **p,
3326                   int *size)
3327 {
3328    void **ptr;
3329    void *hash = NULL;
3330    char *key = NULL;
3331    void *data_ret = NULL;
3332    int ret = 0;
3333
3334    EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0);
3335
3336    ptr = (void **)data;
3337    hash = *ptr;
3338
3339    /* Read key */
3340    ret = eet_data_get_type(ed,
3341                            EET_T_STRING,
3342                            echnk->data,
3343                            ((char *)echnk->data) + echnk->size,
3344                            &key);
3345    if (ret <= 0)
3346       goto on_error;
3347
3348    /* Advance to next chunk */
3349    NEXT_CHUNK((*p), (*size), (*echnk), ed);
3350    memset(echnk, 0, sizeof(Eet_Data_Chunk));
3351
3352    /* Read value */
3353    eet_data_chunk_get(ed, echnk, *p, *size);
3354    if (!echnk->name)
3355       goto on_error;
3356
3357    if (IS_POINTER_TYPE(echnk->type))
3358       POINTER_TYPE_DECODE(context,
3359                           ed,
3360                           edd,
3361                           ede,
3362                           echnk,
3363                           echnk->type,
3364                           &data_ret,
3365                           p,
3366                           size,
3367                           on_error);
3368    else
3369       STRUCT_TYPE_DECODE(data_ret,
3370                          context,
3371                          ed,
3372                          ede ? ede->subtype : NULL,
3373                          echnk->data,
3374                          echnk->size,
3375                          on_error);
3376
3377    if (edd)
3378      {
3379         hash = edd->func.hash_add(hash, key, data_ret);
3380         *ptr = hash;
3381         _eet_freelist_hash_add(context, hash);
3382      }
3383    else
3384       eet_node_hash_add(*((Eet_Node **)data), echnk->name, key, data_ret);
3385
3386    return 1;
3387
3388 on_error:
3389    return ret;
3390 }
3391
3392 /* var arrays and fixed arrays have to
3393  * get all chunks at once. for fixed arrays
3394  * we can get each chunk and increment a
3395  * counter stored on the element itself but
3396  * it wont be thread safe. for var arrays
3397  * we still need a way to get the number of
3398  * elements from the data, so storing the
3399  * number of elements and the element data on
3400  * each chunk is pointless.
3401  */
3402 static int
3403 eet_data_get_array(Eet_Free_Context *context,
3404                    const Eet_Dictionary *ed,
3405                    Eet_Data_Descriptor *edd,
3406                    Eet_Data_Element *ede,
3407                    Eet_Data_Chunk *echnk,
3408                    int type,
3409                    int group_type,
3410                    void *data,
3411                    char **p,
3412                    int *size)
3413 {
3414    Eina_List *childs = NULL;
3415    const char *name;
3416    Eet_Node *tmp;
3417    void *ptr;
3418    int count;
3419    int ret;
3420    int subsize = 0;
3421    int i;
3422
3423    EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0);
3424
3425    ptr = data;
3426    /* read the number of elements */
3427    ret = eet_data_get_type(ed,
3428                            EET_T_INT,
3429                            echnk->data,
3430                            ((char *)echnk->data) + echnk->size,
3431                            &count);
3432    if (ret <= 0)
3433       return ret;
3434
3435    name = echnk->name;
3436
3437    if (ede)
3438      {
3439         if (IS_POINTER_TYPE(type))
3440            subsize = eet_basic_codec[ede->type].size;
3441         else
3442            subsize = ede->subtype->size;
3443
3444         if (group_type == EET_G_VAR_ARRAY)
3445           {
3446              /* store the number of elements
3447               * on the counter offset */
3448              *(int *)(((char *)data) + ede->count - ede->offset) = count;
3449              /* allocate space for the array of elements */
3450              *(void **)ptr = edd->func.mem_alloc(count * subsize);
3451
3452              if (!*(void **)ptr)
3453                 return 0;
3454
3455              memset(*(void **)ptr, 0, count * subsize);
3456
3457              _eet_freelist_add(context, *(void **)ptr);
3458           }
3459      }
3460
3461    /* get all array elements */
3462    for (i = 0; i < count; i++)
3463      {
3464         void *dst = NULL;
3465         void *data_ret = NULL;
3466
3467         /* Advance to next chunk */
3468         NEXT_CHUNK((*p), (*size), (*echnk), ed);
3469         memset(echnk, 0, sizeof(Eet_Data_Chunk));
3470
3471         eet_data_chunk_get(ed, echnk, *p, *size);
3472         if (!echnk->name || strcmp(echnk->name, name) != 0)
3473            goto on_error;  /* get the data */
3474
3475         if (echnk->group_type != group_type
3476             || (echnk->type != type && echnk->type != EET_T_NULL))
3477            goto on_error;
3478
3479         if (ede)
3480            if (ede->group_type != echnk->group_type
3481                || (echnk->type != ede->type && echnk->type != EET_T_NULL))
3482               goto on_error;
3483
3484         /* get the destination pointer */
3485         if (ede)
3486           {
3487              if (group_type == EET_G_ARRAY)
3488                 dst = (char *)ptr + (subsize * i);
3489              else
3490                 dst = *(char **)ptr + (subsize * i);
3491           }
3492
3493         if (IS_POINTER_TYPE(echnk->type))
3494           {
3495              POINTER_TYPE_DECODE(context,
3496                                  ed,
3497                                  edd,
3498                                  ede,
3499                                  echnk,
3500                                  echnk->type,
3501                                  &data_ret,
3502                                  p,
3503                                  size,
3504                                  on_error);
3505              if (dst)
3506                 memcpy(dst, &data_ret, subsize);
3507
3508              if (!edd)
3509                 childs = eina_list_append(childs, data_ret);
3510           }
3511         else
3512           {
3513              STRUCT_TYPE_DECODE(data_ret,
3514                                 context,
3515                                 ed,
3516                                 ede ? ede->subtype : NULL,
3517                                 echnk->data,
3518                                 echnk->size,
3519                                 on_error);
3520              if (dst)
3521                {
3522                   memcpy(dst, data_ret, subsize);
3523                   _eet_freelist_add(context, data_ret);
3524                }
3525
3526              if (!edd)
3527                 childs = eina_list_append(childs, data_ret);
3528           }
3529      }
3530
3531    if (!edd)
3532      {
3533         Eet_Node *parent = *((Eet_Node **)data);
3534         Eet_Node *array;
3535
3536         if (group_type == EET_G_ARRAY)
3537            array = eet_node_array_new(name, count, childs);
3538         else
3539            array = eet_node_var_array_new(name, childs);
3540
3541         if (!array)
3542            goto on_error;
3543
3544         eet_node_struct_append(parent, name, array);
3545      }
3546
3547    return 1;
3548
3549 on_error:
3550    EINA_LIST_FREE(childs, tmp)
3551    eet_node_del(tmp);
3552
3553    return 0;
3554 }
3555
3556 static void
3557 eet_data_put_union(Eet_Dictionary *ed,
3558                    Eet_Data_Descriptor *edd __UNUSED__,
3559                    Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in)
3560 {
3561    const char *union_type;
3562    int i;
3563
3564    EET_ASSERT(!((ede->type != EET_T_UNKNOW) || (!ede->subtype)), return );
3565
3566    union_type = ede->subtype->func.type_get(
3567          ((char *)data_in) + ede->count - ede->offset,
3568          NULL);
3569
3570    if (!union_type)
3571       return;
3572
3573    /* Search the structure of the union to encode. */
3574    for (i = 0; i < ede->subtype->elements.num; ++i)
3575       if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0)
3576         {
3577            Eet_Data_Element *sede;
3578            void *data;
3579            int size;
3580
3581            /* Yeah we found it ! */
3582            data = eet_data_put_type(ed, EET_T_STRING, &union_type, &size);
3583            if (data)
3584               eet_data_encode(ed,
3585                               ds,
3586                               data,
3587                               ede->name,
3588                               size,
3589                               ede->type,
3590                               ede->group_type);
3591
3592            sede = &(ede->subtype->elements.set[i]);
3593            data = _eet_data_descriptor_encode(ed,
3594                                               sede->subtype,
3595                                               data_in,
3596                                               &size);
3597            if (data)
3598               eet_data_encode(ed,
3599                               ds,
3600                               data,
3601                               ede->name,
3602                               size,
3603                               ede->type,
3604                               ede->group_type);
3605
3606            break;
3607         }
3608
3609 }
3610
3611 static int
3612 eet_data_get_union(Eet_Free_Context *context, const Eet_Dictionary *ed,
3613                    Eet_Data_Descriptor *edd __UNUSED__,
3614                    Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
3615                    int type, int group_type, void *data,
3616                    char **p, int *size)
3617 {
3618    const char *union_type;
3619    void *data_ret = NULL;
3620    int ret = 0;
3621    int i;
3622
3623    /* Read type */
3624    ret = eet_data_get_type(ed,
3625                            EET_T_STRING,
3626                            echnk->data,
3627                            ((char *)echnk->data) + echnk->size,
3628                            &union_type);
3629    if (ret <= 0)
3630       goto on_error;
3631
3632    /* Advance to next chunk */
3633    NEXT_CHUNK((*p), (*size), (*echnk), ed);
3634    memset(echnk, 0, sizeof(Eet_Data_Chunk));
3635
3636    /* Read value */
3637    eet_data_chunk_get(ed, echnk, *p, *size);
3638    if (!echnk->name)
3639       goto on_error;
3640
3641    if (ede)
3642      {
3643                 EET_ASSERT(!(ede->group_type != group_type || ede->type != type),
3644                    goto on_error);
3645
3646         /* Search the structure of the union to decode */
3647         for (i = 0; i < ede->subtype->elements.num; ++i)
3648            if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0)
3649              {
3650                 Eet_Data_Element *sede;
3651                 char *ut;
3652
3653                 /* Yeah we found it ! */
3654                 sede = &(ede->subtype->elements.set[i]);
3655                 EET_ASSERT(sede->subtype, goto on_error);
3656
3657                 data_ret = _eet_data_descriptor_decode(context,
3658                                                        ed,
3659                                                        sede->subtype,
3660                                                        echnk->data,
3661                                                        echnk->size);
3662                 if (!data_ret)
3663                    goto on_error;
3664
3665                 /* Memcopy the structure content to remove pointer indirection. */
3666                 memcpy(data, data_ret, sede->subtype->size);
3667
3668                 /* data_ret is now useless. */
3669                 sede->subtype->func.mem_free(data_ret);
3670
3671                 /* Set union type. */
3672                 if ((!ed) || (!ede->subtype->func.str_direct_alloc))
3673                   {
3674                      ut = ede->subtype->func.str_alloc(union_type);
3675                      _eet_freelist_str_add(context, ut);
3676                   }
3677                 else
3678                   {
3679                      ut = ede->subtype->func.str_direct_alloc(union_type);
3680                      _eet_freelist_direct_str_add(context, ut);
3681                   }
3682
3683                 ede->subtype->func.type_set(
3684                    ut,
3685                    ((char *)data) + ede->count -
3686                    ede->offset,
3687                    EINA_FALSE);
3688
3689                 break;
3690              }
3691
3692      }
3693    else
3694      {
3695         /* FIXME: generate node structure. */
3696         data_ret = _eet_data_descriptor_decode(context,
3697                                                ed, NULL,
3698                                                echnk->data, echnk->size);
3699         goto on_error;
3700      }
3701
3702    return 1;
3703
3704 on_error:
3705    return 0;
3706 }
3707
3708 static void
3709 eet_data_put_variant(Eet_Dictionary *ed,
3710                      Eet_Data_Descriptor *edd __UNUSED__,
3711                      Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in)
3712 {
3713    const char *union_type;
3714    void *data;
3715    Eina_Bool unknow = EINA_FALSE;
3716    int size;
3717    int i;
3718
3719    EET_ASSERT(!((ede->type != EET_T_UNKNOW) || (!ede->subtype)), return );
3720
3721    union_type = ede->subtype->func.type_get(
3722          ((char *)data_in) + ede->count - ede->offset,
3723          &unknow);
3724
3725    if (!union_type && unknow == EINA_FALSE)
3726       return;
3727
3728    if (unknow)
3729      {
3730         /* Handle opaque internal representation */
3731         Eet_Variant_Unknow *evu;
3732
3733         data = eet_data_put_type(ed, EET_T_STRING, &union_type, &size);
3734         if (data)
3735                         eet_data_encode(ed,
3736                            ds,
3737                            data,
3738                            ede->name,
3739                            size,
3740                            ede->type,
3741                            ede->group_type);
3742
3743         evu = (Eet_Variant_Unknow *)data_in;
3744         if (evu && EINA_MAGIC_CHECK(evu, EET_MAGIC_VARIANT))
3745                         eet_data_encode(ed,
3746                            ds,
3747                            evu->data,
3748                            ede->name,
3749                            evu->size,
3750                            ede->type,
3751                            ede->group_type);
3752      }
3753    else
3754       /* Search the structure of the union to encode. */
3755       for (i = 0; i < ede->subtype->elements.num; ++i)
3756          if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0)
3757            {
3758               Eet_Data_Element *sede;
3759
3760               /* Yeah we found it ! */
3761               data = eet_data_put_type(ed, EET_T_STRING, &union_type, &size);
3762               if (data)
3763                         eet_data_encode(ed,
3764                                  ds,
3765                                  data,
3766                                  ede->name,
3767                                  size,
3768                                  ede->type,
3769                                  ede->group_type);
3770
3771               sede = &(ede->subtype->elements.set[i]);
3772
3773               if (sede->group_type != EET_G_UNKNOWN)
3774                 {
3775                    Eet_Data_Stream *lds;
3776
3777                    lds = eet_data_stream_new();
3778                    eet_group_codec[sede->group_type - 100].put(ed,
3779                                                                sede->subtype,
3780                                                                sede,
3781                                                                lds,
3782                                                                data_in);
3783                    if (lds->size != 0)
3784                      {
3785                         eet_data_encode(ed, ds, lds->data, ede->name, lds->pos,
3786                                         ede->type, ede->group_type);
3787
3788                         lds->data = NULL;
3789                         lds->size = 0;
3790                      }
3791                    else
3792                         eet_data_encode(ed, ds, NULL, ede->name, 0,
3793                                       EET_T_NULL, ede->group_type);
3794
3795                         eet_data_stream_free(lds);
3796                 }
3797               else
3798                 {
3799                    data = _eet_data_descriptor_encode(ed,
3800                                                       sede->subtype,
3801                                                       *(void **)data_in,
3802                                                       &size);
3803                    if (data)
3804                       eet_data_encode(ed,
3805                                       ds,
3806                                       data,
3807                                       ede->name,
3808                                       size,
3809                                       ede->type,
3810                                       ede->group_type);
3811                 }
3812
3813               break;
3814            }
3815
3816 }
3817
3818 static int
3819 eet_data_get_variant(Eet_Free_Context *context, const Eet_Dictionary *ed,
3820                      Eet_Data_Descriptor *edd __UNUSED__,
3821                      Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
3822                      int type __UNUSED__, int group_type __UNUSED__, void *data,
3823                      char **p, int *size)
3824 {
3825    const char *union_type;
3826    void *data_ret = NULL;
3827    int ret = 0;
3828    int i;
3829
3830    /* Read type */
3831    ret = eet_data_get_type(ed,
3832                            EET_T_STRING,
3833                            echnk->data,
3834                            ((char *)echnk->data) + echnk->size,
3835                            &union_type);
3836    if (ret <= 0)
3837       goto on_error;
3838
3839    /* Advance to next chunk */
3840    NEXT_CHUNK((*p), (*size), (*echnk), ed);
3841    memset(echnk, 0, sizeof(Eet_Data_Chunk));
3842
3843    /* Read value */
3844    eet_data_chunk_get(ed, echnk, *p, *size);
3845    if (!echnk->name)
3846       goto on_error;
3847
3848    if (ede)
3849      {
3850         char *ut;
3851
3852         EET_ASSERT(ede->subtype, goto on_error);
3853
3854         if ((!ed) || (!ede->subtype->func.str_direct_alloc))
3855           {
3856              ut = ede->subtype->func.str_alloc(union_type);
3857              _eet_freelist_str_add(context, ut);
3858           }
3859         else
3860           {
3861              ut = ede->subtype->func.str_direct_alloc(union_type);
3862              _eet_freelist_direct_str_add(context, ut);
3863           }
3864
3865         /* Search the structure of the union to decode */
3866         for (i = 0; i < ede->subtype->elements.num; ++i)
3867            if (strcmp(ede->subtype->elements.set[i].name, union_type) == 0)
3868              {
3869                 Eet_Data_Element *sede;
3870
3871                 /* Yeah we found it ! */
3872                 sede = &(ede->subtype->elements.set[i]);
3873
3874                 if (sede->group_type != EET_G_UNKNOWN)
3875                   {
3876                      Eet_Data_Chunk chnk;
3877                      char *p2;
3878                      int size2;
3879                      int ret;
3880
3881                      p2 = echnk->data;
3882                      size2 = echnk->size;
3883
3884                      /* Didn't find a proper way to provide this
3885                         without duplicating code */
3886                      while (size2 > 0)
3887                        {
3888                           memset(&chnk, 0, sizeof(Eet_Data_Chunk));
3889                           eet_data_chunk_get(ed, &chnk, p2, size2);
3890
3891                           if (!chnk.name)
3892                              goto on_error;
3893
3894                           ret = eet_group_codec[sede->group_type - 100].get(
3895                                 context,
3896                                 ed,
3897                                 sede->subtype,
3898                                 sede,
3899                                 &chnk,
3900                                 sede
3901                                 ->type,
3902                                 sede->group_type,
3903                                 data,
3904                                 &p2,
3905                                 &size2);
3906
3907                           if (ret <= 0)
3908                              goto on_error;
3909
3910 /* advance to next chunk */
3911                           NEXT_CHUNK(p2, size2, chnk, ed);
3912                        }
3913
3914                      /* Put garbage so that we will not put eet_variant_unknow in it */
3915                      data_ret = (void *)data;
3916
3917                      /* Set variant type. */
3918                      ede->subtype->func.type_set(
3919                         ut,
3920                         ((char *)data) + ede->count -
3921                         ede->offset,
3922                         EINA_FALSE);
3923                      break;
3924                   }
3925
3926                 data_ret = _eet_data_descriptor_decode(context,
3927                                                        ed,
3928                                                        sede->subtype,
3929                                                        echnk->data,
3930                                                        echnk->size);
3931                 if (!data_ret)
3932                    break;
3933
3934                 /* And point to the variant data. */
3935                 *(void **)data = data_ret;
3936
3937                 /* Set variant type. */
3938                 ede->subtype->func.type_set(
3939                    ut,
3940                    ((char *)data) + ede->count -
3941                    ede->offset,
3942                    EINA_FALSE);
3943                 break;
3944              }
3945
3946         if (!data_ret)
3947           {
3948              Eet_Variant_Unknow *evu;
3949
3950              evu = calloc(1, sizeof (Eet_Variant_Unknow) + echnk->size - 1);
3951              if (!evu)
3952                 goto on_error;
3953
3954              evu->size = echnk->size;
3955              memcpy(evu->data, echnk->data, evu->size);
3956              EINA_MAGIC_SET(evu, EET_MAGIC_VARIANT);
3957
3958              /* And point to the opaque internal data scructure */
3959              *(void **)data = evu;
3960
3961              /* Set variant type. */
3962              ede->subtype->func.type_set(
3963                 ut,
3964                 ((char *)data) + ede->count -
3965                 ede->offset,
3966                 EINA_TRUE);
3967           }
3968      }
3969    else
3970      {
3971         /* FIXME: dump node structure. */
3972         data_ret = _eet_data_descriptor_decode(context,
3973                                                ed, NULL,
3974                                                echnk->data, echnk->size);
3975         goto on_error;
3976      }
3977
3978    return 1;
3979
3980 on_error:
3981    return 0;
3982 }
3983
3984 static Eet_Node *
3985 eet_data_node_simple_type(int type, const char *name, void *dd)
3986 {
3987 #ifdef EET_T_TYPE
3988 # undef EET_T_TYPE
3989 #endif
3990
3991 #define EET_T_TYPE(Eet_Type, Eet_Node_Type, Type)                       \
3992  case Eet_Type:                                                       \
3993     return eet_node_ ## Eet_Node_Type ## _new(name, *((Type *)dd));       \
3994
3995    switch (type)
3996      {
3997         EET_T_TYPE(EET_T_CHAR,           char,               char);
3998         EET_T_TYPE(EET_T_SHORT,          short,              short);
3999         EET_T_TYPE(EET_T_INT,            int,                int);
4000         EET_T_TYPE(EET_T_LONG_LONG,      long_long,          long long);
4001         EET_T_TYPE(EET_T_FLOAT,          float,              float);
4002         EET_T_TYPE(EET_T_DOUBLE,         double,             double);
4003         EET_T_TYPE(EET_T_UCHAR,          unsigned_char,      unsigned char);
4004         EET_T_TYPE(EET_T_USHORT,         unsigned_short,     unsigned short);
4005         EET_T_TYPE(EET_T_UINT,           unsigned_int,       unsigned int);
4006         EET_T_TYPE(EET_T_ULONG_LONG,     unsigned_long_long, unsigned long long);
4007         EET_T_TYPE(EET_T_STRING,         string,             char *);
4008         EET_T_TYPE(EET_T_INLINED_STRING, inlined_string,     char *);
4009
4010       case EET_T_NULL:
4011          return eet_node_null_new(name);
4012
4013       default:
4014          ERR("Unknow type passed to eet_data_node_simple_type");
4015          return NULL;
4016      }
4017 }
4018
4019 static int
4020 eet_data_get_unknown(Eet_Free_Context *context,
4021                      const Eet_Dictionary *ed,
4022                      Eet_Data_Descriptor *edd,
4023                      Eet_Data_Element *ede,
4024                      Eet_Data_Chunk *echnk,
4025                      int type,
4026                      int group_type __UNUSED__,
4027                      void *data,
4028                      char **p __UNUSED__,
4029                      int *size __UNUSED__)
4030 {
4031    int ret;
4032    void *data_ret;
4033
4034    if (IS_SIMPLE_TYPE(type))
4035      {
4036         unsigned char dd[128];
4037
4038         ret = eet_data_get_type(ed,
4039                                 type,
4040                                 echnk->data,
4041                                 ((char *)echnk->data) + echnk->size,
4042                                 edd ? (char *)data : (char *)dd);
4043         if (ret <= 0)
4044            return ret;
4045
4046         if (!edd)
4047           {
4048              Eet_Node **parent = data;
4049              Eet_Node *node;
4050
4051              node = eet_data_node_simple_type(type, echnk->name, dd);
4052
4053              if (*parent)
4054                 eet_node_struct_append(*parent, echnk->name, node);
4055              else
4056                 *parent = node;
4057           }
4058         else
4059           {
4060              if (type == EET_T_STRING)
4061                {
4062                   char **str;
4063
4064                   str = (char **)(((char *)data));
4065                   if (*str)
4066                     {
4067                        if ((ed == NULL) || (edd->func.str_direct_alloc == NULL))
4068                          {
4069                             *str = edd->func.str_alloc(*str);
4070                             _eet_freelist_str_add(context, *str);
4071                          }
4072                        else
4073                          {
4074                             *str = edd->func.str_direct_alloc(*str);
4075                             _eet_freelist_direct_str_add(context, *str);
4076                          }
4077                     }
4078                }
4079              else if (edd && type == EET_T_INLINED_STRING)
4080                {
4081                   char **str;
4082
4083                   str = (char **)(((char *)data));
4084                   if (*str)
4085                     {
4086                        *str = edd->func.str_alloc(*str);
4087                        _eet_freelist_str_add(context, *str);
4088                     }
4089                }
4090           }
4091      }
4092    else
4093      {
4094         Eet_Data_Descriptor *subtype;
4095
4096         subtype = ede ? ede->subtype : NULL;
4097
4098         if (subtype || !edd)
4099           {
4100              Eet_Node **parent = data;
4101              void **ptr;
4102
4103              data_ret = _eet_data_descriptor_decode(context,
4104                                                     ed,
4105                                                     subtype,
4106                                                     echnk->data,
4107                                                     echnk->size);
4108              if (!data_ret)
4109                 return 0;
4110
4111              if (edd)
4112                {
4113                   ptr = (void **)(((char *)data));
4114                   *ptr = (void *)data_ret;
4115                }
4116              else
4117                {
4118                   Eet_Node *node = data_ret;
4119
4120                   if (*parent)
4121                     {
4122                        node = eet_node_struct_child_new(echnk->name, node);
4123                        eet_node_struct_append(*parent, echnk->name, node);
4124                     }
4125                   else
4126                      *parent = node;
4127                }
4128           }
4129      }
4130
4131    return 1;
4132 }
4133
4134 static void
4135 eet_data_put_array(Eet_Dictionary *ed,
4136                    Eet_Data_Descriptor *edd __UNUSED__,
4137                    Eet_Data_Element *ede,
4138                    Eet_Data_Stream *ds,
4139                    void *data_in)
4140 {
4141    void *data;
4142    int offset = 0;
4143    int subsize;
4144    int count;
4145    int size;
4146    int j;
4147
4148    EET_ASSERT(!((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING)),
4149               return );
4150
4151    if (ede->group_type == EET_G_ARRAY)
4152       count = ede->counter_offset;
4153    else
4154       count = *(int *)(((char *)data_in) + ede->count - ede->offset);
4155
4156    if (count <= 0)
4157       return;  /* Store number of elements */
4158
4159    data = eet_data_put_type(ed, EET_T_INT, &count, &size);
4160    if (data)
4161       eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
4162
4163    if (IS_POINTER_TYPE(ede->type))
4164       subsize = eet_basic_codec[ede->type].size;
4165    else
4166       subsize = ede->subtype->size;
4167
4168    for (j = 0; j < count; j++)
4169      {
4170         void *d;
4171         int pos = ds->pos;
4172
4173         if (ede->group_type == EET_G_ARRAY)
4174            d = (void *)(((char *)data_in) + offset);
4175         else
4176            d = *(((char **)data_in)) + offset;
4177
4178         if (IS_POINTER_TYPE(ede->type))
4179           {
4180              if (*(char **)d)
4181                 eet_data_put_unknown(ed, NULL, ede, ds, d);
4182           }
4183         else
4184           {
4185              data = _eet_data_descriptor_encode(ed, ede->subtype, d, &size);
4186              if (data)
4187                 eet_data_encode(ed,
4188                                 ds,
4189                                 data,
4190                                 ede->name,
4191                                 size,
4192                                 ede->type,
4193                                 ede->group_type);
4194           }
4195
4196         if (pos == ds->pos)
4197            /* Add a NULL element just to have the correct array layout. */
4198                 eet_data_encode(ed,
4199                            ds,
4200                            NULL,
4201                            ede->name,
4202                            0,
4203                            EET_T_NULL,
4204                            ede->group_type);
4205
4206         offset += subsize;
4207      }
4208 }
4209
4210 static void
4211 eet_data_put_unknown(Eet_Dictionary *ed,
4212                      Eet_Data_Descriptor *edd __UNUSED__,
4213                      Eet_Data_Element *ede,
4214                      Eet_Data_Stream *ds,
4215                      void *data_in)
4216 {
4217    void *data = NULL;
4218    int size;
4219
4220    if (IS_SIMPLE_TYPE(ede->type))
4221       data = eet_data_put_type(ed, ede->type, data_in, &size);
4222    else if (ede->subtype)
4223       if (*((char **)data_in))
4224          data = _eet_data_descriptor_encode(ed,
4225                                             ede->subtype,
4226                                             *((char **)((char *)(data_in))),
4227                                             &size);
4228
4229    if (data)
4230                 eet_data_encode(ed,
4231                       ds,
4232                       data,
4233                       ede->name,
4234                       size,
4235                       ede->type,
4236                       ede->group_type);
4237 }
4238
4239 static void
4240 eet_data_put_list(Eet_Dictionary *ed,
4241                   Eet_Data_Descriptor *edd,
4242                   Eet_Data_Element *ede,
4243                   Eet_Data_Stream *ds,
4244                   void *data_in)
4245 {
4246    void *data;
4247    void *l;
4248    int size;
4249
4250    EET_ASSERT(!(((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING))
4251                 || ((ede->type > EET_T_NULL) && (ede->type < EET_T_LAST))),
4252               return );
4253
4254    l = *((void **)(((char *)data_in)));
4255    for (; l; l = edd->func.list_next(l))
4256      {
4257         if (IS_POINTER_TYPE(ede->type))
4258           {
4259              const void *str = edd->func.list_data(l);
4260              eet_data_put_unknown(ed, NULL, ede, ds, &str);
4261           }
4262         else
4263           {
4264              data = _eet_data_descriptor_encode(ed,
4265                                                 ede->subtype,
4266                                                 edd->func.list_data(l),
4267                                                 &size);
4268              if (data)
4269                 eet_data_encode(ed,
4270                                 ds,
4271                                 data,
4272                                 ede->name,
4273                                 size,
4274                                 ede->type,
4275                                 ede->group_type);
4276           }
4277      }
4278 }
4279
4280 static void
4281 eet_data_put_hash(Eet_Dictionary *ed,
4282                   Eet_Data_Descriptor *edd,
4283                   Eet_Data_Element *ede,
4284                   Eet_Data_Stream *ds,
4285                   void *data_in)
4286 {
4287    Eet_Data_Encode_Hash_Info fdata;
4288    void *l;
4289
4290    l = *((void **)(((char *)data_in)));
4291    fdata.ds = ds;
4292    fdata.ede = ede;
4293    fdata.ed = ed;
4294    edd->func.hash_foreach(l, eet_data_descriptor_encode_hash_cb, &fdata);
4295 }
4296
4297 EAPI int
4298 eet_data_dump_cipher(Eet_File *ef,
4299                      const char *name, const char *cipher_key,
4300                      void (*dumpfunc)(void *data, const char *str),
4301                      void *dumpdata)
4302 {
4303    const Eet_Dictionary *ed = NULL;
4304    const void *data = NULL;
4305    Eet_Node *result;
4306    Eet_Free_Context context;
4307    int required_free = 0;
4308    int size;
4309
4310    ed = eet_dictionary_get(ef);
4311
4312    if (!cipher_key)
4313       data = eet_read_direct(ef, name, &size);
4314
4315    if (!data)
4316      {
4317         required_free = 1;
4318         data = eet_read_cipher(ef, name, &size, cipher_key);
4319         if (!data)
4320            return 0;
4321      }
4322
4323    memset(&context, 0, sizeof (context));
4324    result = _eet_data_descriptor_decode(&context, ed, NULL, data, size);
4325
4326    eet_node_dump(result, 0, dumpfunc, dumpdata);
4327
4328    eet_node_del(result);
4329
4330    if (required_free)
4331       free((void *)data);
4332
4333    return result ? 1 : 0;
4334 }
4335
4336 EAPI int
4337 eet_data_dump(Eet_File *ef,
4338               const char *name,
4339               void (*dumpfunc)(void *data, const char *str),
4340               void *dumpdata)
4341 {
4342    return eet_data_dump_cipher(ef, name, NULL, dumpfunc, dumpdata);
4343 }
4344
4345
4346 EAPI int
4347 eet_data_text_dump_cipher(const void *data_in,
4348                           const char *cipher_key, int size_in,
4349                           void (*dumpfunc)(void *data, const char *str),
4350                           void *dumpdata)
4351 {
4352    void *ret = NULL;
4353    Eet_Node *result;
4354    Eet_Free_Context context;
4355    unsigned int ret_len = 0;
4356
4357    if (!data_in)
4358       return 0;
4359
4360    if (cipher_key)
4361      {
4362         if (eet_decipher(data_in, size_in, cipher_key,
4363                          strlen(cipher_key), &ret, &ret_len))
4364           {
4365              if (ret)
4366                 free(ret);
4367
4368              return 0;
4369           }
4370      }
4371    else
4372      {
4373         ret = (void *)data_in;
4374         ret_len = size_in;
4375      }
4376
4377    memset(&context, 0, sizeof (context));
4378    result = _eet_data_descriptor_decode(&context, NULL, NULL, ret, ret_len);
4379
4380    eet_node_dump(result, 0, dumpfunc, dumpdata);
4381
4382    eet_node_del(result);
4383    if (cipher_key)
4384       free(ret);
4385
4386    return result ? 1 : 0;
4387 }
4388
4389 EAPI int
4390 eet_data_text_dump(const void *data_in,
4391                    int size_in,
4392                    void (*dumpfunc)(void *data, const char *str),
4393                    void *dumpdata)
4394 {
4395    return eet_data_text_dump_cipher(data_in, NULL, size_in, dumpfunc, dumpdata);
4396 }
4397
4398 EAPI void *
4399 eet_data_text_undump_cipher(const char *text,
4400                             const char *cipher_key,
4401                             int textlen,
4402                             int *size_ret)
4403 {
4404    void *ret = NULL;
4405
4406    ret = _eet_data_dump_parse(NULL, size_ret, text, textlen);
4407    if (ret && cipher_key)
4408      {
4409         void *ciphered = NULL;
4410         unsigned int ciphered_len;
4411
4412         if (eet_cipher(ret, *size_ret, cipher_key,
4413                        strlen(cipher_key), &ciphered, &ciphered_len))
4414           {
4415              if (ciphered)
4416                 free(ciphered);
4417
4418              size_ret = 0;
4419                 free(ret);
4420              return NULL;
4421           }
4422
4423                 free(ret);
4424         *size_ret = ciphered_len;
4425         ret = ciphered;
4426      }
4427
4428    return ret;
4429 }
4430
4431 EAPI void *
4432 eet_data_text_undump(const char *text,
4433                      int textlen,
4434                      int *size_ret)
4435 {
4436    return eet_data_text_undump_cipher(text, NULL, textlen, size_ret);
4437 }
4438
4439 EAPI int
4440 eet_data_undump_cipher(Eet_File *ef,
4441                        const char *name,
4442                        const char *cipher_key,
4443                        const char *text,
4444                        int textlen,
4445                        int compress)
4446 {
4447    Eet_Dictionary *ed;
4448    void *data_enc;
4449    int size;
4450    int val;
4451
4452    ed = eet_dictionary_get(ef);
4453
4454    data_enc = _eet_data_dump_parse(ed, &size, text, textlen);
4455    if (!data_enc)
4456       return 0;
4457
4458    val = eet_write_cipher(ef, name, data_enc, size, compress, cipher_key);
4459                 free(data_enc);
4460    return val;
4461 }
4462
4463 EAPI int
4464 eet_data_undump(Eet_File *ef,
4465                 const char *name,
4466                 const char *text,
4467                 int textlen,
4468                 int compress)
4469 {
4470    return eet_data_undump_cipher(ef, name, NULL, text, textlen, compress);
4471 }
4472
4473 EAPI void *
4474 eet_data_descriptor_decode_cipher(Eet_Data_Descriptor *edd,
4475                                   const void *data_in,
4476                                   const char *cipher_key,
4477                                   int size_in)
4478 {
4479    void *deciphered = (void *)data_in;
4480    void *ret;
4481    Eet_Free_Context context;
4482    unsigned int deciphered_len = size_in;
4483
4484    if (cipher_key && data_in)
4485       if (eet_decipher(data_in, size_in, cipher_key,
4486                        strlen(cipher_key), &deciphered, &deciphered_len))
4487         {
4488            if (deciphered)
4489               free(deciphered);
4490
4491            return NULL;
4492         }
4493
4494    memset(&context, 0, sizeof (context));
4495    ret = _eet_data_descriptor_decode(&context,
4496                                      NULL,
4497                                      edd,
4498                                      deciphered,
4499                                      deciphered_len);
4500
4501    if (data_in != deciphered)
4502       free(deciphered);
4503
4504    return ret;
4505 }
4506
4507 EAPI void *
4508 eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
4509                            const void *data_in,
4510                            int size_in)
4511 {
4512    return eet_data_descriptor_decode_cipher(edd, data_in, NULL, size_in);
4513 }
4514
4515 EAPI Eet_Node *
4516 eet_data_node_decode_cipher(const void *data_in,
4517                             const char *cipher_key,
4518                             int size_in)
4519 {
4520    void *deciphered = (void *)data_in;
4521    Eet_Node *ret;
4522    Eet_Free_Context context;
4523    unsigned int deciphered_len = size_in;
4524
4525    if (cipher_key && data_in)
4526       if (eet_decipher(data_in, size_in, cipher_key,
4527                        strlen(cipher_key), &deciphered, &deciphered_len))
4528         {
4529            if (deciphered)
4530               free(deciphered);
4531
4532            return NULL;
4533         }
4534
4535    memset(&context, 0, sizeof (context));
4536    ret = _eet_data_descriptor_decode(&context,
4537                                      NULL,
4538                                      NULL,
4539                                      deciphered,
4540                                      deciphered_len);
4541
4542    if (data_in != deciphered)
4543       free(deciphered);
4544
4545    return ret;
4546 }
4547
4548 static void *
4549 _eet_data_descriptor_encode(Eet_Dictionary *ed,
4550                             Eet_Data_Descriptor *edd,
4551                             const void *data_in,
4552                             int *size_ret)
4553 {
4554    Eet_Data_Stream *ds;
4555    Eet_Data_Chunk *chnk;
4556    void *cdata;
4557    int csize;
4558    int i;
4559
4560    if (_eet_data_words_bigendian == -1)
4561      {
4562         unsigned long int v;
4563
4564         v = htonl(0x12345678);
4565         if (v == 0x12345678)
4566            _eet_data_words_bigendian = 1;
4567         else
4568            _eet_data_words_bigendian = 0;
4569      }
4570
4571    ds = eet_data_stream_new();
4572    for (i = 0; i < edd->elements.num; i++)
4573      {
4574         Eet_Data_Element *ede;
4575
4576         ede = &(edd->elements.set[i]);
4577         eet_group_codec[ede->group_type - 100].put(
4578            ed,
4579            edd,
4580            ede,
4581            ds,
4582            ((char *)data_in) +
4583            ede->offset);
4584      }
4585    chnk = eet_data_chunk_new(ds->data,
4586                              ds->pos,
4587                              edd->name,
4588                              EET_T_UNKNOW,
4589                              EET_G_UNKNOWN);
4590    ds->data = NULL;
4591    ds->size = 0;
4592    eet_data_stream_free(ds);
4593
4594    ds = eet_data_stream_new();
4595    eet_data_chunk_put(ed, chnk, ds);
4596    cdata = ds->data;
4597    csize = ds->pos;
4598
4599    ds->data = NULL;
4600    ds->size = 0;
4601    eet_data_stream_free(ds);
4602    *size_ret = csize;
4603
4604    free(chnk->data);
4605    eet_data_chunk_free(chnk);
4606
4607    return cdata;
4608 }
4609
4610 EAPI int
4611 eet_data_node_write_cipher(Eet_File *ef,
4612                            const char *name,
4613                            const char *cipher_key,
4614                            Eet_Node *node,
4615                            int compress)
4616 {
4617    Eet_Dictionary *ed;
4618    void *data_enc;
4619    int size;
4620    int val;
4621
4622    ed = eet_dictionary_get(ef);
4623
4624    data_enc = _eet_data_dump_encode(EET_G_UNKNOWN, ed, node, &size);
4625    if (!data_enc)
4626       return 0;
4627
4628    val = eet_write_cipher(ef, name, data_enc, size, compress, cipher_key);
4629    free(data_enc);
4630    return val;
4631 }
4632
4633 EAPI void *
4634 eet_data_node_encode_cipher(Eet_Node *node,
4635                             const char *cipher_key,
4636                             int *size_ret)
4637 {
4638    void *ret = NULL;
4639    void *ciphered = NULL;
4640    unsigned int ciphered_len = 0;
4641    int size;
4642
4643    ret = _eet_data_dump_encode(EET_G_UNKNOWN, NULL, node, &size);
4644    if (cipher_key && ret)
4645      {
4646         if (eet_cipher(ret, size, cipher_key,
4647                        strlen(cipher_key), &ciphered, &ciphered_len))
4648           {
4649              if (ciphered)
4650                 free(ciphered);
4651
4652              if (size_ret)
4653                 *size_ret = 0;
4654
4655                 free(ret);
4656              return NULL;
4657           }
4658
4659                 free(ret);
4660         size = (int)ciphered_len;
4661         ret = ciphered;
4662      }
4663
4664    if (size_ret)
4665       *size_ret = size;
4666
4667    return ret;
4668 }
4669
4670 EAPI void *
4671 eet_data_descriptor_encode_cipher(Eet_Data_Descriptor *edd,
4672                                   const void *data_in,
4673                                   const char *cipher_key,
4674                                   int *size_ret)
4675 {
4676    void *ret = NULL;
4677    void *ciphered = NULL;
4678    unsigned int ciphered_len = 0;
4679    int size;
4680
4681    ret = _eet_data_descriptor_encode(NULL, edd, data_in, &size);
4682    if (cipher_key && ret)
4683      {
4684         if (eet_cipher(ret, size, cipher_key,
4685                        strlen(cipher_key), &ciphered, &ciphered_len))
4686           {
4687              if (ciphered)
4688                 free(ciphered);
4689
4690              if (size_ret)
4691                 *size_ret = 0;
4692
4693                 free(ret);
4694              return NULL;
4695           }
4696
4697                 free(ret);
4698         size = ciphered_len;
4699         ret = ciphered;
4700      }
4701
4702    if (size_ret)
4703       *size_ret = size;
4704
4705    return ret;
4706 }
4707
4708 EAPI void *
4709 eet_data_descriptor_encode(Eet_Data_Descriptor *edd,
4710                            const void *data_in,
4711                            int *size_ret)
4712 {
4713    return eet_data_descriptor_encode_cipher(edd, data_in, NULL, size_ret);
4714 }