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