fix typo: cypher -> cipher
[framework/uifw/eet.git] / src / lib / eet_data.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #ifdef HAVE_CONFIG_H
6 # include <config.h>
7 #endif
8
9 #if HAVE___ATTRIBUTE__
10 #define __UNUSED__ __attribute__((unused))
11 #else
12 #define __UNUSED__
13 #endif
14
15 #include <stdio.h>
16 #include <string.h>
17 #include <math.h>
18 #include <ctype.h>
19 #include <limits.h>
20
21 #ifdef HAVE_NETINET_IN_H
22 # include <netinet/in.h>
23 #endif
24
25 #if defined(_WIN32) && ! defined(__CEGCC__)
26 # include <winsock2.h>
27 #endif
28
29 #include <Eina.h>
30
31 #include "Eet.h"
32 #include "Eet_private.h"
33
34 /*
35  * routines for doing data -> struct and struct -> data conversion
36  *
37  * types:
38  *
39  * basic types:
40  *   a sequence of...
41  *
42  *   char
43  *   short
44  *   int
45  *   long long
46  *   float
47  *   double
48  *   unsigned char
49  *   unsigned short
50  *   unsigned int
51  *   unsgined long long
52  *   string
53  *
54  * groupings:
55  *   multiple entries ordered as...
56  *
57  *   fixed size array    [ of basic types ]
58  *   variable size array [ of basic types ]
59  *   linked list         [ of basic types ]
60  *   hash table          [ of basic types ]
61  *
62  * need to provide builder/accessor funcs for:
63  *
64  *   list_next
65  *   list_append
66  *
67  *   hash_foreach
68  *   hash_add
69  *
70  */
71
72 /*---*/
73
74 typedef struct _Eet_Data_Element            Eet_Data_Element;
75 typedef struct _Eet_Data_Basic_Type_Codec   Eet_Data_Basic_Type_Codec;
76 typedef struct _Eet_Data_Group_Type_Codec   Eet_Data_Group_Type_Codec;
77 typedef struct _Eet_Data_Chunk              Eet_Data_Chunk;
78 typedef struct _Eet_Data_Stream             Eet_Data_Stream;
79 typedef struct _Eet_Data_Descriptor_Hash    Eet_Data_Descriptor_Hash;
80 typedef struct _Eet_Data_Encode_Hash_Info   Eet_Data_Encode_Hash_Info;
81
82 /*---*/
83
84 /* TODO:
85  * Eet_Data_Basic_Type_Codec (Coder, Decoder)
86  * Eet_Data_Group_Type_Codec (Coder, Decoder)
87  */
88 struct _Eet_Data_Basic_Type_Codec
89 {
90    int         size;
91    const char *name;
92    int       (*get) (const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
93    void     *(*put) (Eet_Dictionary *ed, const void *src, int *size_ret);
94 };
95
96 struct _Eet_Data_Group_Type_Codec
97 {
98    int  (*get) (const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, int type, int group_type, void *data_in, int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata, char **p, int *size);
99    void (*put) (Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
100 };
101
102 struct _Eet_Data_Chunk
103 {
104    char          *name;
105    int            len;
106    int            size;
107    int            hash;
108    void          *data;
109    unsigned char  type;
110    unsigned char  group_type;
111 };
112
113 struct _Eet_Data_Stream
114 {
115    void *data;
116    int   size;
117    int   pos;
118 };
119
120 struct _Eet_Data_Descriptor_Hash
121 {
122    Eet_Data_Element         *element;
123    Eet_Data_Descriptor_Hash *next;
124 };
125
126 struct _Eet_Data_Descriptor
127 {
128    const char           *name;
129    const Eet_Dictionary *ed;
130    int                   size;
131    struct {
132       void *(*mem_alloc) (size_t size);
133       void  (*mem_free) (void *mem);
134       char *(*str_alloc) (const char *str);
135       char *(*str_direct_alloc) (const char *str);
136       void  (*str_free) (const char *str);
137       void  (*str_direct_free) (const char *str);
138       void *(*list_next) (void *l);
139       void *(*list_append) (void *l, void *d);
140       void *(*list_data) (void *l);
141       void *(*list_free) (void *l);
142       void  (*hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt);
143       void *(*hash_add) (void *h, const char *k, void *d);
144       void  (*hash_free) (void *h);
145    } func;
146    struct {
147       int                num;
148       Eet_Data_Element  *set;
149       struct {
150          int                             size;
151          Eet_Data_Descriptor_Hash       *buckets;
152       } hash;
153    } elements;
154 //   char *strings;
155 //   int   strings_len;
156 };
157
158 struct _Eet_Data_Element
159 {
160    const char          *name;
161    const char          *counter_name;
162    const char          *directory_name_ptr;
163    Eet_Data_Descriptor *subtype;
164    int                  offset;         /* offset in bytes from the base element */
165    int                  count;          /* number of elements for a fixed array */
166    int                  counter_offset; /* for a variable array we need the offset of the count variable */
167    unsigned char        type;           /* EET_T_XXX */
168    unsigned char        group_type;     /* EET_G_XXX */
169 };
170
171 struct _Eet_Data_Encode_Hash_Info
172 {
173   Eet_Data_Stream       *ds;
174   Eet_Data_Element      *ede;
175   Eet_Dictionary        *ed;
176 };
177
178 /*---*/
179
180 static int   eet_data_get_char(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
181 static void *eet_data_put_char(Eet_Dictionary *ed, const void *src, int *size_ret);
182 static int   eet_data_get_short(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
183 static void *eet_data_put_short(Eet_Dictionary *ed, const void *src, int *size_ret);
184 static inline int   eet_data_get_int(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
185 static void *eet_data_put_int(Eet_Dictionary *ed, const void *src, int *size_ret);
186 static int   eet_data_get_long_long(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
187 static void *eet_data_put_long_long(Eet_Dictionary *ed, const void *src, int *size_ret);
188 static int   eet_data_get_float(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
189 static void *eet_data_put_float(Eet_Dictionary *ed, const void *src, int *size_ret);
190 static int   eet_data_get_double(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
191 static void *eet_data_put_double(Eet_Dictionary *ed, const void *src, int *size_ret);
192 static inline int   eet_data_get_string(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
193 static void *eet_data_put_string(Eet_Dictionary *ed, const void *src, int *size_ret);
194 static int   eet_data_get_istring(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
195 static void *eet_data_put_istring(Eet_Dictionary *ed, const void *src, int *size_ret);
196 static int   eet_data_get_null(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
197 static void *eet_data_put_null(Eet_Dictionary *ed, const void *src, int *size_ret);
198
199 static int   eet_data_get_type(const Eet_Dictionary *ed, int type, const void *src, const void *src_end, void *dest);
200 static void *eet_data_put_type(Eet_Dictionary *ed, int type, const void *src, int *size_ret);
201
202 static int  eet_data_get_unknown(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, int type, int group_type, void *data_in, int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata, char **p, int *size);
203 static void eet_data_put_unknown(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
204 static void eet_data_put_array(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
205 static int  eet_data_get_array(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, int type, int group_type, void *data, int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata, char **p, int *size);
206 static int  eet_data_get_list(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, int type, int group_type, void *data_in, int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata, char **p, int *size);
207 static void eet_data_put_list(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
208 static void eet_data_put_hash(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
209 static int  eet_data_get_hash(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, int type, int group_type, void *data, int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata, char **p, int *size);
210
211 static void            eet_data_chunk_get(const Eet_Dictionary *ed, Eet_Data_Chunk *chnk, const void *src, int size);
212 static Eet_Data_Chunk *eet_data_chunk_new(void *data, int size, const char *name, int type, int group_type);
213 static void            eet_data_chunk_free(Eet_Data_Chunk *chnk);
214
215 static Eet_Data_Stream *eet_data_stream_new(void);
216 static void             eet_data_stream_write(Eet_Data_Stream *ds, const void *data, int size);
217 static void             eet_data_stream_free(Eet_Data_Stream *ds);
218
219 static void             eet_data_chunk_put(Eet_Dictionary *ed, Eet_Data_Chunk *chnk, Eet_Data_Stream *ds);
220
221 static int       eet_data_descriptor_encode_hash_cb(void *hash, const char *key, void *hdata, void *fdata);
222 static void     *_eet_data_descriptor_encode(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, const void *data_in, int *size_ret);
223 static void     *_eet_data_descriptor_decode(const Eet_Dictionary *ed,
224                                              Eet_Data_Descriptor *edd,
225                                              const void *data_in,
226                                              int size_in,
227                                              int level,
228                                              void (*dumpfunc) (void *data, const char *str),
229                                              void *dumpdata);
230
231 /*---*/
232
233 static const Eet_Data_Basic_Type_Codec eet_basic_codec[] =
234 {
235      {sizeof(char),      "char",       eet_data_get_char,      eet_data_put_char     },
236      {sizeof(short),     "short",      eet_data_get_short,     eet_data_put_short    },
237      {sizeof(int),       "int",        eet_data_get_int,       eet_data_put_int      },
238      {sizeof(long long), "long_long",  eet_data_get_long_long, eet_data_put_long_long},
239      {sizeof(float),     "float",      eet_data_get_float,     eet_data_put_float    },
240      {sizeof(double),    "double",     eet_data_get_double,    eet_data_put_double   },
241      {sizeof(char),      "uchar",      eet_data_get_char,      eet_data_put_char     },
242      {sizeof(short),     "ushort",     eet_data_get_short,     eet_data_put_short    },
243      {sizeof(int),       "uint",       eet_data_get_int,       eet_data_put_int      },
244      {sizeof(long long), "ulong_long", eet_data_get_long_long, eet_data_put_long_long},
245      {sizeof(char *),    "string",     eet_data_get_string,    eet_data_put_string   },
246      {sizeof(char *),    "inlined",    eet_data_get_istring,   eet_data_put_istring  },
247      {sizeof(void *),    "NULL",       eet_data_get_null,      eet_data_put_null     }
248 };
249
250 static const Eet_Data_Group_Type_Codec eet_group_codec[] =
251 {
252      { eet_data_get_unknown,  eet_data_put_unknown },
253      { eet_data_get_array,    eet_data_put_array },
254      { eet_data_get_array,    eet_data_put_array },
255      { eet_data_get_list,     eet_data_put_list },
256      { eet_data_get_hash,     eet_data_put_hash }
257 };
258
259 static int words_bigendian = -1;
260
261 /*---*/
262
263 #define SWAP64(x) (x) = \
264    ((((unsigned long long)(x) & 0x00000000000000ffULL ) << 56) |\
265        (((unsigned long long)(x) & 0x000000000000ff00ULL ) << 40) |\
266        (((unsigned long long)(x) & 0x0000000000ff0000ULL ) << 24) |\
267        (((unsigned long long)(x) & 0x00000000ff000000ULL ) << 8) |\
268        (((unsigned long long)(x) & 0x000000ff00000000ULL ) >> 8) |\
269        (((unsigned long long)(x) & 0x0000ff0000000000ULL ) >> 24) |\
270        (((unsigned long long)(x) & 0x00ff000000000000ULL ) >> 40) |\
271        (((unsigned long long)(x) & 0xff00000000000000ULL ) >> 56))
272 #define SWAP32(x) (x) = \
273    ((((int)(x) & 0x000000ff ) << 24) |\
274        (((int)(x) & 0x0000ff00 ) << 8) |\
275        (((int)(x) & 0x00ff0000 ) >> 8) |\
276        (((int)(x) & 0xff000000 ) >> 24))
277 #define SWAP16(x) (x) = \
278    ((((short)(x) & 0x00ff ) << 8) |\
279        (((short)(x) & 0xff00 ) >> 8))
280
281 #define CONV8(x)
282 #define CONV16(x) {if (words_bigendian) SWAP16(x);}
283 #define CONV32(x) {if (words_bigendian) SWAP32(x);}
284 #define CONV64(x) {if (words_bigendian) SWAP64(x);}
285
286 #define IS_SIMPLE_TYPE(Type)    (Type > EET_T_UNKNOW && Type < EET_T_LAST)
287
288 /*---*/
289
290 /* CHAR TYPE */
291 static int
292 eet_data_get_char(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst)
293 {
294    char *s, *d;
295
296    if (((char *)src + sizeof(char)) > (char *)src_end) return -1;
297    s = (char *)src;
298    d = (char *)dst;
299    *d = *s;
300    CONV8(*d);
301    return sizeof(char);
302 }
303
304 static void *
305 eet_data_put_char(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret)
306 {
307    char *s, *d;
308
309    d = (char *)malloc(sizeof(char));
310    if (!d) return NULL;
311    s = (char *)src;
312    *d = *s;
313    CONV8(*d);
314    *size_ret = sizeof(char);
315    return d;
316 }
317
318 /* SHORT TYPE */
319 static int
320 eet_data_get_short(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst)
321 {
322    short *d;
323
324    if (((char *)src + sizeof(short)) > (char *)src_end) return -1;
325    memcpy(dst, src, sizeof(short));
326    d = (short *)dst;
327    CONV16(*d);
328    return sizeof(short);
329 }
330
331 static void *
332 eet_data_put_short(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret)
333 {
334    short *s, *d;
335
336    d = (short *)malloc(sizeof(short));
337    if (!d) return NULL;
338    s = (short *)src;
339    *d = *s;
340    CONV16(*d);
341    *size_ret = sizeof(short);
342    return d;
343 }
344
345 /* INT TYPE */
346 static inline int
347 eet_data_get_int(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst)
348 {
349    int *d;
350
351    if (((char *)src + sizeof(int)) > (char *)src_end) return -1;
352    memcpy(dst, src, sizeof(int));
353    d = (int *)dst;
354    CONV32(*d);
355    return sizeof(int);
356 }
357
358 static void *
359 eet_data_put_int(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret)
360 {
361    int *s, *d;
362
363    d = (int *)malloc(sizeof(int));
364    if (!d) return NULL;
365    s = (int *)src;
366    *d = *s;
367    CONV32(*d);
368    *size_ret = sizeof(int);
369    return d;
370 }
371
372 /* LONG LONG TYPE */
373 static int
374 eet_data_get_long_long(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst)
375 {
376    unsigned long long *d;
377
378    if (((char *)src + sizeof(unsigned long long)) > (char *)src_end) return -1;
379    memcpy(dst, src, sizeof(unsigned long long));
380    d = (unsigned long long *)dst;
381    CONV64(*d);
382    return sizeof(unsigned long long);
383 }
384
385 static void *
386 eet_data_put_long_long(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret)
387 {
388    unsigned long long *s, *d;
389
390    d = (unsigned long long *)malloc(sizeof(unsigned long long));
391    if (!d) return NULL;
392    s = (unsigned long long *)src;
393    *d = *s;
394    CONV64(*d);
395    *size_ret = sizeof(unsigned long long);
396    return d;
397 }
398
399 /* STRING TYPE */
400 static inline int
401 eet_data_get_string_hash(const Eet_Dictionary *ed, const void *src, const void *src_end)
402 {
403    if (ed)
404      {
405         int               index;
406
407         if (eet_data_get_int(ed, src, src_end, &index) < 0) return -1;
408
409         return eet_dictionary_string_get_hash(ed, index);
410      }
411
412    return -1;
413 }
414
415 static inline int
416 eet_data_get_string(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
417 {
418    char *s, **d;
419
420    d = (char **)dst;
421
422    if (ed)
423      {
424         const char       *str;
425         int               index;
426
427         if (eet_data_get_int(ed, src, src_end, &index) < 0) return -1;
428
429         str = eet_dictionary_string_get_char(ed, index);
430         if (str == NULL)
431           return -1;
432
433         *d = (char *) str;
434         return eet_dictionary_string_get_size(ed, index);
435      }
436
437    s = (char *)src;
438    if (s == NULL)
439      {
440         *d = NULL;
441         return 0;
442      }
443
444    *d = s;
445    return strlen(s) + 1;
446 }
447
448 static void *
449 eet_data_put_string(Eet_Dictionary *ed, const void *src, int *size_ret)
450 {
451    char *s, *d;
452    int len;
453
454    if (ed)
455      {
456         const char      *str;
457         int              index;
458
459         str = *((const char **) src);
460         if (!str) return NULL;
461
462         index = eet_dictionary_string_add(ed, str);
463         if (index == -1) return NULL;
464
465         return eet_data_put_int(ed, &index, size_ret);
466      }
467
468    s = (char *)(*((char **)src));
469    if (!s) return NULL;
470    len = strlen(s);
471    d = malloc(len + 1);
472    if (!d) return NULL;
473    memcpy(d, s, len + 1);
474    *size_ret = len + 1;
475    return d;
476 }
477
478 /* ALWAYS INLINED STRING TYPE */
479 static int
480 eet_data_get_istring(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst)
481 {
482    return eet_data_get_string(NULL, src, src_end, dst);
483 }
484
485 static void *
486 eet_data_put_istring(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret)
487 {
488    return eet_data_put_string(NULL, src, size_ret);
489 }
490
491 /* ALWAYS NULL TYPE */
492 static int
493 eet_data_get_null(const Eet_Dictionary *ed __UNUSED__, const void *src __UNUSED__, const void *src_end __UNUSED__, void *dst)
494 {
495    char **d;
496
497    d = (char**) dst;
498
499    *d = NULL;
500    return 0;
501 }
502
503 static void *
504 eet_data_put_null(Eet_Dictionary *ed __UNUSED__, const void *src __UNUSED__, int *size_ret)
505 {
506    *size_ret = 0;
507    return NULL;
508 }
509
510 /**
511  * Fast lookups of simple doubles/floats.
512  *
513  * These aren't properly a cache because they don't store pre-calculated
514  * values, but have a so simple math that is almost as fast.
515  */
516 static inline int
517 _eet_data_float_cache_get(const char *s, int len, float *d)
518 {
519    /* fast handle of simple case 0xMp+E*/
520    if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p'))
521      {
522         int mantisse = (s[2] >= 'a') ? (s[2] - 'a' + 10) : (s[2] - '0');
523         int exponent = (s[5] - '0');
524
525         if (s[4] == '+') *d = (float)(mantisse << exponent);
526         else             *d = (float)mantisse / (float)(1 << exponent);
527
528         return 1;
529      }
530    return 0;
531 }
532
533 static inline int
534 _eet_data_double_cache_get(const char *s, int len, double *d)
535 {
536    /* fast handle of simple case 0xMp+E*/
537    if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p'))
538      {
539         int mantisse = (s[2] >= 'a') ? (s[2] - 'a' + 10) : (s[2] - '0');
540         int exponent = (s[5] - '0');
541
542         if (s[4] == '+') *d = (double)(mantisse << exponent);
543         else             *d = (double)mantisse / (double)(1 << exponent);
544
545         return 1;
546      }
547    return 0;
548 }
549
550 /* FLOAT TYPE */
551 static int
552 eet_data_get_float(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
553 {
554    float        *d;
555    int           index;
556
557    d = (float *) dst;
558    if (!ed)
559      {
560         const char   *s, *p;
561         long long     mantisse;
562         long          exponent;
563         int           len;
564
565         s = (const char *)src;
566         p = s;
567         len = 0;
568         while ((p < (const char *)src_end) && (*p != 0)) {len++; p++;}
569
570         if (_eet_data_float_cache_get(s, len, d) != 0) return len + 1;
571
572         if (eina_convert_atod(s, len, &mantisse, &exponent) == EINA_FALSE) return -1;
573         *d = (float)ldexp((double)mantisse, exponent);
574
575         return len + 1;
576      }
577
578    if (eet_data_get_int(ed, src, src_end, &index) < 0) return -1;
579
580    if (!eet_dictionary_string_get_float(ed, index, d))
581      return -1;
582    return 1;
583 }
584
585 static void *
586 eet_data_put_float(Eet_Dictionary *ed, const void *src, int *size_ret)
587 {
588    char  buf[128];
589    int   index;
590
591    eina_convert_dtoa((double)(*(float *)src), buf);
592
593    if (!ed)
594      {
595         char    *d;
596         int      len;
597
598         len = strlen(buf);
599         d = malloc(len + 1);
600         if (!d) return NULL;
601         memcpy(d, buf, len + 1);
602         *size_ret = len + 1;
603         return d;
604      }
605
606    index = eet_dictionary_string_add(ed, buf);
607    if (index == -1) return NULL;
608
609    return eet_data_put_int(ed, &index, size_ret);
610 }
611
612 /* DOUBLE TYPE */
613 static int
614 eet_data_get_double(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
615 {
616    double       *d;
617    int           index;
618
619    d = (double *) dst;
620
621    if (!ed)
622      {
623         const char     *s, *p;
624         long long       mantisse = 0;
625         long            exponent = 0;
626         int             len;
627
628         s = (const char *) src;
629         p = s;
630         len = 0;
631         while ((p < (const char *)src_end) && (*p != 0)) {len++; p++;}
632
633         if (_eet_data_double_cache_get(s, len, d) != 0) return len + 1;
634
635         if (eina_convert_atod(s, len, &mantisse, &exponent) == EINA_FALSE) return -1;
636         *d = ldexp((double) mantisse, exponent);
637
638         return len + 1;
639      }
640
641    if (eet_data_get_int(ed, src, src_end, &index) < 0) return -1;
642
643    if (!eet_dictionary_string_get_double(ed, index, d))
644      return -1;
645    return 1;
646 }
647
648 static void *
649 eet_data_put_double(Eet_Dictionary *ed, const void *src, int *size_ret)
650 {
651    char  buf[128];
652    int   index;
653
654    eina_convert_dtoa((double)(*(double *)src), buf);
655
656    if (!ed)
657      {
658         char   *d;
659         int     len;
660
661         len = strlen(buf);
662         d = malloc(len + 1);
663         if (!d) return NULL;
664         memcpy(d, buf, len + 1);
665         *size_ret = len + 1;
666
667         return d;
668      }
669
670    index = eet_dictionary_string_add(ed, buf);
671    if (index == -1) return NULL;
672
673    return eet_data_put_int(ed, &index, size_ret);
674 }
675
676 static inline int
677 eet_data_get_type(const Eet_Dictionary *ed, int type, const void *src, const void *src_end, void *dest)
678 {
679    int ret;
680
681    ret = eet_basic_codec[type - 1].get(ed, src, src_end, dest);
682    return ret;
683 }
684
685 static inline void *
686 eet_data_put_type(Eet_Dictionary *ed, int type, const void *src, int *size_ret)
687 {
688    void *ret;
689
690    ret = eet_basic_codec[type - 1].put(ed, src, size_ret);
691    return ret;
692 }
693
694 /* chunk format...
695  *
696  * char[4] = "CHnK"; // untyped data ... or
697  * char[4] = "CHKx"; // typed data - x == type
698  *
699  * int     = chunk size (including magic string);
700  * char[]  = chunk magic/name string (0 byte terminated);
701  * ... sub-chunks (a chunk can contain chuncks recusrively) ...
702  * or
703  * ... payload data ...
704  *
705  */
706
707 static inline void
708 eet_data_chunk_get(const Eet_Dictionary *ed, Eet_Data_Chunk *chnk,
709                    const void *src, int size)
710 {
711    const char *s;
712    int ret1, ret2;
713
714    if (!src)
715      {
716         fprintf(stderr, "stiouf -3\n");
717         return;
718      }
719    if (size <= 8)
720      {
721         fprintf(stderr, "stiouf -2 %i\n", size);
722         return;
723      }
724
725    if (!chnk)
726      {
727         fprintf(stderr, "stiouf -1\n");
728         return;
729      }
730
731    s = src;
732    if (s[2] == 'K')
733      {
734         if ((s[0] != 'C') || (s[1] != 'H') || (s[2] != 'K'))
735           {
736              fprintf(stderr, "stiouf 0\n");
737              return;
738           }
739         chnk->type = (unsigned char)(s[3]);
740         if (chnk->type > EET_T_LAST)
741           {
742              chnk->group_type = chnk->type;
743              chnk->type = EET_T_UNKNOW;
744           }
745         else
746           chnk->group_type = EET_G_UNKNOWN;
747         if ((chnk->type >= EET_T_LAST) ||
748             (chnk->group_type >= EET_G_LAST))
749           {
750              chnk->type = 0;
751              chnk->group_type = 0;
752           }
753      }
754    else
755      {
756         if ((s[0] != 'C') || (s[1] != 'H') || (s[2] != 'n') || (s[3] != 'K'))
757           {
758              fprintf(stderr, "stiouf 1\n");
759              return;
760           }
761      }
762    ret1 = eet_data_get_type(ed, EET_T_INT, (s + 4), (s + size), &(chnk->size));
763    if (ret1 <= 0)
764      {
765         fprintf(stderr, "stiouf 2\n");
766         return;
767      }
768    if ((chnk->size < 0) || ((chnk->size + 8) > size))
769      {
770         fprintf(stderr, "stiouf 3\n");
771         return;
772      }
773    ret2 = eet_data_get_type(ed, EET_T_STRING, (s + 8), (s + size), &(chnk->name));
774    if (ret2 <= 0)
775      {
776         fprintf(stderr, "stiouf 4\n");
777         return;
778      }
779
780    chnk->len = ret2;
781
782    /* Precalc hash */
783    chnk->hash = eet_data_get_string_hash(ed, (s + 8), (s + size));
784
785    if (ed)
786      {
787         chnk->data = (char *)src + 4 + ret1 + sizeof(int);
788         chnk->size -= sizeof(int);
789      }
790    else
791      {
792         chnk->data = (char *)src + 4 + ret1 + chnk->len;
793         chnk->size -= chnk->len;
794      }
795
796    return;
797 }
798
799 static inline Eet_Data_Chunk *
800 eet_data_chunk_new(void *data, int size, const char *name, int type, int group_type)
801 {
802    Eet_Data_Chunk *chnk;
803
804    if (!name) return NULL;
805    chnk = calloc(1, sizeof(Eet_Data_Chunk));
806    if (!chnk) return NULL;
807
808    chnk->name = strdup(name);
809    chnk->len = strlen(name) + 1;
810    chnk->size = size;
811    chnk->data = data;
812    chnk->type = type;
813    chnk->group_type = group_type;
814    return chnk;
815 }
816
817 static inline void
818 eet_data_chunk_free(Eet_Data_Chunk *chnk)
819 {
820    if (chnk->name) free(chnk->name);
821    free(chnk);
822 }
823
824 static inline Eet_Data_Stream *
825 eet_data_stream_new(void)
826 {
827    Eet_Data_Stream *ds;
828
829    ds = calloc(1, sizeof(Eet_Data_Stream));
830    if (!ds) return NULL;
831    return ds;
832 }
833
834 static inline void
835 eet_data_stream_free(Eet_Data_Stream *ds)
836 {
837    if (ds->data) free(ds->data);
838    free(ds);
839 }
840
841 static inline void
842 eet_data_stream_write(Eet_Data_Stream *ds, const void *data, int size)
843 {
844    char *p;
845
846    if ((ds->pos + size) > ds->size)
847      {
848         ds->data = realloc(ds->data, ds->size + size + 512);
849         if (!ds->data)
850           {
851              ds->pos = 0;
852              ds->size = 0;
853              return;
854           }
855         ds->size = ds->size + size + 512;
856      }
857    p = ds->data;
858    memcpy(p + ds->pos, data, size);
859    ds->pos += size;
860 }
861
862 static void
863 eet_data_chunk_put(Eet_Dictionary *ed, Eet_Data_Chunk *chnk, Eet_Data_Stream *ds)
864 {
865    int  *size;
866    void *string;
867    int   s;
868    int   size_ret = 0;
869    int   string_ret = 0;
870    unsigned char buf[4] = "CHK";
871
872    if (!chnk->data && chnk->type != EET_T_NULL) return;
873    /* chunk head */
874
875 /*   eet_data_stream_write(ds, "CHnK", 4);*/
876    if (chnk->type != EET_T_UNKNOW) buf[3] = chnk->type;
877    else buf[3] = chnk->group_type;
878
879    string = eet_data_put_string(ed, &chnk->name, &string_ret);
880    if (!string)
881      return ;
882
883    /* size of chunk payload data + name */
884    s = chnk->size + string_ret;
885    size = eet_data_put_int(ed, &s, &size_ret);
886
887    /* FIXME: If something goes wrong the resulting file will be corrupted. */
888    if (!size)
889      goto on_error;
890
891    eet_data_stream_write(ds, buf, 4);
892
893    /* write chunk length */
894    eet_data_stream_write(ds, size, size_ret);
895
896    /* write chunk name */
897    eet_data_stream_write(ds, string, string_ret);
898
899    /* write payload */
900    eet_data_stream_write(ds, chnk->data, chnk->size);
901
902    free(string);
903  on_error:
904    free(size);
905 }
906
907 /*---*/
908
909 static void
910 _eet_descriptor_hash_new(Eet_Data_Descriptor *edd)
911 {
912    int i;
913
914    edd->elements.hash.size = 1 << 6;
915    edd->elements.hash.buckets = calloc(1, sizeof(Eet_Data_Descriptor_Hash) * edd->elements.hash.size);
916    for (i = 0; i < edd->elements.num; i++)
917      {
918         Eet_Data_Element *ede;
919         int hash;
920
921         ede = &(edd->elements.set[i]);
922         hash = _eet_hash_gen((char *) ede->name, 6);
923         if (!edd->elements.hash.buckets[hash].element)
924           edd->elements.hash.buckets[hash].element = ede;
925         else
926           {
927              Eet_Data_Descriptor_Hash *bucket;
928
929              bucket = calloc(1, sizeof(Eet_Data_Descriptor_Hash));
930              bucket->element = ede;
931              bucket->next = edd->elements.hash.buckets[hash].next;
932              edd->elements.hash.buckets[hash].next = bucket;
933           }
934      }
935 }
936
937 static void
938 _eet_descriptor_hash_free(Eet_Data_Descriptor *edd)
939 {
940    int i;
941
942    for (i = 0; i < edd->elements.hash.size; i++)
943      {
944         Eet_Data_Descriptor_Hash *bucket, *pbucket;
945
946         bucket = edd->elements.hash.buckets[i].next;
947         while (bucket)
948           {
949              pbucket = bucket;
950              bucket = bucket->next;
951              free(pbucket);
952           }
953      }
954    if (edd->elements.hash.buckets) free(edd->elements.hash.buckets);
955 }
956
957 static Eet_Data_Element *
958 _eet_descriptor_hash_find(Eet_Data_Descriptor *edd, char *name, int hash)
959 {
960    Eet_Data_Descriptor_Hash *bucket;
961
962    if (hash < 0) hash = _eet_hash_gen(name, 6);
963    else hash &= 0x3f;
964    if (!edd->elements.hash.buckets[hash].element) return NULL;
965    /*
966      When we use the dictionnary as a source for chunk name, we will always
967      have the same pointer in name. It's a good idea to just compare pointer
968      instead of running strcmp on both string.
969    */
970    if (edd->elements.hash.buckets[hash].element->directory_name_ptr == name)
971      return edd->elements.hash.buckets[hash].element;
972    if (!strcmp(edd->elements.hash.buckets[hash].element->name, name))
973      {
974         edd->elements.hash.buckets[hash].element->directory_name_ptr = name;
975         return edd->elements.hash.buckets[hash].element;
976      }
977    bucket = edd->elements.hash.buckets[hash].next;
978    while (bucket)
979      {
980         if (bucket->element->directory_name_ptr == name) return bucket->element;
981         if (!strcmp(bucket->element->name, name))
982           {
983              bucket->element->directory_name_ptr = name;
984              return bucket->element;
985           }
986         bucket = bucket->next;
987      }
988    return NULL;
989 }
990
991 static void *
992 _eet_mem_alloc(size_t size)
993 {
994    return calloc(1, size);
995 }
996
997 static void
998 _eet_mem_free(void *mem)
999 {
1000    free(mem);
1001 }
1002
1003 static char *
1004 _eet_str_alloc(const char *str)
1005 {
1006    return strdup(str);
1007 }
1008
1009 static void
1010 _eet_str_free(const char *str)
1011 {
1012    free((char *)str);
1013 }
1014
1015 /*---*/
1016
1017 EAPI Eet_Data_Descriptor *
1018 eet_data_descriptor_new(const char *name,
1019                         int size,
1020                         void *(*func_list_next) (void *l),
1021                         void *(*func_list_append) (void *l, void *d),
1022                         void *(*func_list_data) (void *l),
1023                         void *(*func_list_free) (void *l),
1024                         void  (*func_hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt),
1025                         void *(*func_hash_add) (void *h, const char *k, void *d),
1026                         void  (*func_hash_free) (void *h))
1027 {
1028    Eet_Data_Descriptor *edd;
1029
1030    if (!name) return NULL;
1031    edd = calloc(1, sizeof(Eet_Data_Descriptor));
1032    if (!edd) return NULL;
1033
1034    edd->name = name;
1035    edd->ed = NULL;
1036    edd->size = size;
1037    edd->func.mem_alloc = _eet_mem_alloc;
1038    edd->func.mem_free = _eet_mem_free;
1039    edd->func.str_alloc = _eet_str_alloc;
1040    edd->func.str_direct_alloc = NULL;
1041    edd->func.str_direct_free = NULL;
1042    edd->func.str_free = _eet_str_free;
1043    edd->func.list_next = func_list_next;
1044    edd->func.list_append = func_list_append;
1045    edd->func.list_data = func_list_data;
1046    edd->func.list_free = func_list_free;
1047    edd->func.hash_foreach = func_hash_foreach;
1048    edd->func.hash_add = func_hash_add;
1049    edd->func.hash_free = func_hash_free;
1050    return edd;
1051 }
1052
1053 /* new replcement */
1054 EAPI Eet_Data_Descriptor *
1055 eet_data_descriptor2_new(Eet_Data_Descriptor_Class *eddc)
1056 {
1057    Eet_Data_Descriptor *edd;
1058
1059    if (!eddc) return NULL;
1060    if (eddc->version < 1) return NULL;
1061    edd = calloc(1, sizeof(Eet_Data_Descriptor));
1062    if (!edd) return NULL;
1063
1064    edd->name = eddc->name;
1065    edd->ed = NULL;
1066    edd->size = eddc->size;
1067    edd->func.mem_alloc = _eet_mem_alloc;
1068    edd->func.mem_free = _eet_mem_free;
1069    edd->func.str_alloc = _eet_str_alloc;
1070    edd->func.str_free = _eet_str_free;
1071    if (eddc->func.mem_alloc)
1072      edd->func.mem_alloc = eddc->func.mem_alloc;
1073    if (eddc->func.mem_free)
1074      edd->func.mem_free = eddc->func.mem_free;
1075    if (eddc->func.str_alloc)
1076      edd->func.str_alloc = eddc->func.str_alloc;
1077    if (eddc->func.str_free)
1078      edd->func.str_free = eddc->func.str_free;
1079    edd->func.list_next = eddc->func.list_next;
1080    edd->func.list_append = eddc->func.list_append;
1081    edd->func.list_data = eddc->func.list_data;
1082    edd->func.list_free = eddc->func.list_free;
1083    edd->func.hash_foreach = eddc->func.hash_foreach;
1084    edd->func.hash_add = eddc->func.hash_add;
1085    edd->func.hash_free = eddc->func.hash_free;
1086
1087    return edd;
1088 }
1089
1090 EAPI Eet_Data_Descriptor *
1091 eet_data_descriptor3_new(Eet_Data_Descriptor_Class *eddc)
1092 {
1093    Eet_Data_Descriptor *edd;
1094
1095    if (!eddc) return NULL;
1096    if (eddc->version < 2) return NULL;
1097    edd = calloc(1, sizeof(Eet_Data_Descriptor));
1098    if (!edd) return NULL;
1099
1100    edd->name = eddc->name;
1101    edd->ed = NULL;
1102    edd->size = eddc->size;
1103    edd->func.mem_alloc = _eet_mem_alloc;
1104    edd->func.mem_free = _eet_mem_free;
1105    edd->func.str_alloc = _eet_str_alloc;
1106    edd->func.str_free = _eet_str_free;
1107    if (eddc->func.mem_alloc)
1108      edd->func.mem_alloc = eddc->func.mem_alloc;
1109    if (eddc->func.mem_free)
1110      edd->func.mem_free = eddc->func.mem_free;
1111    if (eddc->func.str_alloc)
1112      edd->func.str_alloc = eddc->func.str_alloc;
1113    if (eddc->func.str_free)
1114      edd->func.str_free = eddc->func.str_free;
1115    edd->func.list_next = eddc->func.list_next;
1116    edd->func.list_append = eddc->func.list_append;
1117    edd->func.list_data = eddc->func.list_data;
1118    edd->func.list_free = eddc->func.list_free;
1119    edd->func.hash_foreach = eddc->func.hash_foreach;
1120    edd->func.hash_add = eddc->func.hash_add;
1121    edd->func.hash_free = eddc->func.hash_free;
1122    edd->func.str_direct_alloc = eddc->func.str_direct_alloc;
1123    edd->func.str_direct_free = eddc->func.str_direct_free;
1124
1125    return edd;
1126 }
1127
1128 EAPI void
1129 eet_data_descriptor_free(Eet_Data_Descriptor *edd)
1130 {
1131    _eet_descriptor_hash_free(edd);
1132    if (edd->elements.set) free(edd->elements.set);
1133    free(edd);
1134 }
1135
1136 EAPI void
1137 eet_data_descriptor_element_add(Eet_Data_Descriptor *edd,
1138                                 const char *name,
1139                                 int type,
1140                                 int group_type,
1141                                 int offset,
1142                                 int count,
1143 /*                              int counter_offset, */
1144                                 const char *counter_name /* Useless should go on a major release */,
1145                                 Eet_Data_Descriptor *subtype)
1146 {
1147    Eet_Data_Element *ede;
1148    /* int l1, l2, p1, p2, i;
1149    char *ps;*/
1150
1151    /* FIXME: Fail safely when realloc fail. */
1152    edd->elements.num++;
1153    edd->elements.set = realloc(edd->elements.set, edd->elements.num * sizeof(Eet_Data_Element));
1154    if (!edd->elements.set) return;
1155    ede = &(edd->elements.set[edd->elements.num - 1]);
1156    ede->name = name;
1157    ede->directory_name_ptr = NULL;
1158
1159    /*
1160     * We do a special case when we do list,hash or whatever group of simple type.
1161     * Instead of handling it in encode/decode/dump/undump, we create an
1162     * implicit structure with only the simple type.
1163     */
1164    if (group_type > EET_G_UNKNOWN
1165        && group_type < EET_G_LAST
1166        && type > EET_T_UNKNOW && type < EET_T_STRING
1167        && subtype == NULL)
1168      {
1169         subtype = calloc(1, sizeof (Eet_Data_Descriptor));
1170         if (!subtype) return ;
1171         subtype->name = "implicit";
1172         subtype->size = eet_basic_codec[type - 1].size;
1173         memcpy(&subtype->func, &edd->func, sizeof(subtype->func));
1174
1175         eet_data_descriptor_element_add(subtype, eet_basic_codec[type - 1].name, type,
1176                                         EET_G_UNKNOWN, 0, 0, /* 0,  */NULL, NULL);
1177         type = EET_T_UNKNOW;
1178      }
1179
1180    ede->type = type;
1181    ede->group_type = group_type;
1182    ede->offset = offset;
1183    ede->count = count;
1184    /* FIXME: For the time being, EET_G_VAR_ARRAY will put the counter_offset in count. */
1185    ede->counter_offset = count;
1186 /*    ede->counter_offset = counter_offset; */
1187    ede->counter_name = counter_name;
1188
1189    ede->subtype = subtype;
1190 }
1191
1192 EAPI void *
1193 eet_data_read_cipher(Eet_File *ef, Eet_Data_Descriptor *edd, const char *name, const char *key)
1194 {
1195    const Eet_Dictionary *ed = NULL;
1196    const void           *data = NULL;
1197    void                 *data_dec;
1198    int                   required_free = 0;
1199    int                   size;
1200
1201    ed = eet_dictionary_get(ef);
1202
1203    if (!key)
1204      data = eet_read_direct(ef, name, &size);
1205    if (!data)
1206      {
1207         required_free = 1;
1208         data = eet_read_cipher(ef, name, &size, key);
1209         if (!data) return NULL;
1210      }
1211
1212    data_dec = _eet_data_descriptor_decode(ed, edd, data, size, 0, NULL, NULL);
1213    if (required_free)
1214      free((void*)data);
1215
1216    return data_dec;
1217 }
1218
1219 EAPI void *
1220 eet_data_read(Eet_File *ef, Eet_Data_Descriptor *edd, const char *name)
1221 {
1222    return eet_data_read_cipher(ef, edd, name, NULL);
1223 }
1224
1225 EAPI int
1226 eet_data_write_cipher(Eet_File *ef, Eet_Data_Descriptor *edd, const char *name, const char *key, const void *data, int compress)
1227 {
1228    Eet_Dictionary       *ed;
1229    void                 *data_enc;
1230    int                   size;
1231    int                   val;
1232
1233    ed = eet_dictionary_get(ef);
1234
1235    data_enc = _eet_data_descriptor_encode(ed, edd, data, &size);
1236    if (!data_enc) return 0;
1237    val = eet_write_cipher(ef, name, data_enc, size, compress, key);
1238    free(data_enc);
1239    return val;
1240 }
1241
1242 EAPI int
1243 eet_data_write(Eet_File *ef, Eet_Data_Descriptor *edd, const char *name, const void *data, int compress)
1244 {
1245    return eet_data_write_cipher(ef, edd, name, NULL, data, compress);
1246 }
1247
1248 typedef struct _Eet_Free        Eet_Free;
1249 struct _Eet_Free
1250 {
1251   int     ref;
1252   int     len[256];
1253   int     num[256];
1254   void  **list[256];
1255 };
1256
1257 static int
1258 _eet_free_hash(void *data)
1259 {
1260    unsigned long ptr = (unsigned long)(data);
1261    int hash;
1262
1263    hash = ptr;
1264    hash ^= ptr >> 8;
1265    hash ^= ptr >> 16;
1266    hash ^= ptr >> 24;
1267
1268 #if LONG_BIT != 32
1269    hash ^= ptr >> 32;
1270    hash ^= ptr >> 40;
1271    hash ^= ptr >> 48;
1272    hash ^= ptr >> 56;
1273 #endif
1274
1275    return hash & 0xFF;
1276 }
1277
1278 static void
1279 _eet_free_add(Eet_Free *ef, void *data)
1280 {
1281    int hash;
1282    int i;
1283
1284    hash = _eet_free_hash(data);
1285
1286    for (i = 0; i < ef->num[hash]; ++i)
1287      if (ef->list[hash][i] == data) return;
1288
1289    ef->num[hash]++;
1290    if (ef->num[hash] > ef->len[hash])
1291      {
1292         void    **tmp;
1293
1294         tmp = realloc(ef->list[hash], (ef->len[hash] + 16) * sizeof(void*));
1295         if (!tmp) return ;
1296
1297         ef->len[hash] += 16;
1298         ef->list[hash] = tmp;
1299      }
1300    ef->list[hash][ef->num[hash] - 1] = data;
1301 }
1302 static void
1303 _eet_free_reset(Eet_Free *ef)
1304 {
1305    int i;
1306
1307    if (ef->ref > 0) return ;
1308    for (i = 0; i < 256; ++i)
1309      {
1310         ef->len[i] = 0;
1311         ef->num[i] = 0;
1312         if (ef->list[i]) free(ef->list[i]);
1313         ef->list[i] = NULL;
1314      }
1315 }
1316 static void
1317 _eet_free_ref(Eet_Free *ef)
1318 {
1319    ef->ref++;
1320 }
1321 static void
1322 _eet_free_unref(Eet_Free *ef)
1323 {
1324    ef->ref--;
1325 }
1326
1327 static Eet_Free freelist = { 0, { 0 }, { 0 }, { NULL } };
1328
1329 #define _eet_freelist_add(Data)         _eet_free_add(&freelist, Data);
1330 #define _eet_freelist_reset()           _eet_free_reset(&freelist);
1331 #define _eet_freelist_ref()             _eet_free_ref(&freelist);
1332 #define _eet_freelist_unref()           _eet_free_unref(&freelist);
1333
1334 static void
1335 _eet_freelist_free(Eet_Data_Descriptor *edd)
1336 {
1337    int j;
1338    int i;
1339
1340    if (freelist.ref > 0) return;
1341    for (j = 0; j < 256; ++j)
1342      for (i = 0; i < freelist.num[j]; ++i)
1343        {
1344           if (edd)
1345             edd->func.mem_free(freelist.list[j][i]);
1346           else
1347             free(freelist.list[j][i]);
1348        }
1349    _eet_free_reset(&freelist);
1350 }
1351
1352 static Eet_Free freeleak = { 0, { 0 }, { 0 }, { NULL } };
1353
1354 #define _eet_freeleak_add(Data)         _eet_free_add(&freeleak, Data);
1355 #define _eet_freeleak_reset()           _eet_free_reset(&freeleak);
1356 #define _eet_freeleak_ref()             _eet_free_ref(&freeleak);
1357 #define _eet_freeleak_unref()           _eet_free_unref(&freeleak);
1358
1359 static void
1360 _eet_freeleak_free(Eet_Data_Descriptor *edd)
1361 {
1362    int j;
1363    int i;
1364
1365    if (freeleak.ref > 0) return;
1366    for (j = 0; j < 256; ++j)
1367      for (i = 0; i < freeleak.num[j]; ++i)
1368        {
1369           if (edd)
1370             edd->func.mem_free(freeleak.list[j][i]);
1371           else
1372             free(freeleak.list[j][i]);
1373        }
1374    _eet_free_reset(&freeleak);
1375 }
1376
1377 static Eet_Free freelist_list = { 0, { 0 }, { 0 }, { NULL } };
1378
1379 #define _eet_freelist_list_add(Data)    _eet_free_add(&freelist_list, Data);
1380 #define _eet_freelist_list_reset()      _eet_free_reset(&freelist_list);
1381 #define _eet_freelist_list_ref()        _eet_free_ref(&freelist_list);
1382 #define _eet_freelist_list_unref()      _eet_free_unref(&freelist_list);
1383
1384 static void
1385 _eet_freelist_list_free(Eet_Data_Descriptor *edd)
1386 {
1387    int j;
1388    int i;
1389
1390    if (freelist_list.ref > 0) return;
1391    for (j = 0; j < 256; ++j)
1392      for (i = 0; i < freelist_list.num[j]; ++i)
1393        {
1394           if (edd)
1395             edd->func.list_free(*((void**)(freelist_list.list[j][i])));
1396        }
1397    _eet_free_reset(&freelist_list);
1398 }
1399
1400 static Eet_Free freelist_str = { 0, { 0 }, { 0 }, { NULL } };
1401
1402 #define _eet_freelist_str_add(Data)     _eet_free_add(&freelist_str, Data);
1403 #define _eet_freelist_str_reset()       _eet_free_reset(&freelist_str);
1404 #define _eet_freelist_str_ref()         _eet_free_ref(&freelist_str);
1405 #define _eet_freelist_str_unref()       _eet_free_unref(&freelist_str);
1406
1407 static void
1408 _eet_freelist_str_free(Eet_Data_Descriptor *edd)
1409 {
1410    int j;
1411    int i;
1412
1413    if (freelist_str.ref > 0) return;
1414    for (j = 0; j < 256; ++j)
1415      for (i = 0; i < freelist_str.num[j]; ++i)
1416        {
1417           if (edd)
1418             edd->func.str_free(freelist_str.list[j][i]);
1419           else
1420             free(freelist_str.list[j][i]);
1421        }
1422    _eet_free_reset(&freelist_str);
1423 }
1424
1425 static Eet_Free freelist_direct_str = { 0, { 0 }, { 0 }, { NULL } };
1426
1427 #define _eet_freelist_direct_str_add(Data)      _eet_free_add(&freelist_direct_str, Data);
1428 #define _eet_freelist_direct_str_reset()        _eet_free_reset(&freelist_direct_str);
1429 #define _eet_freelist_direct_str_ref()          _eet_free_ref(&freelist_direct_str);
1430 #define _eet_freelist_direct_str_unref()        _eet_free_unref(&freelist_direct_str);
1431
1432 static void
1433 _eet_freelist_direct_str_free(Eet_Data_Descriptor *edd)
1434 {
1435    int j;
1436    int i;
1437
1438    if (freelist_str.ref > 0) return;
1439    for (j = 0; j < 256; ++j)
1440      for (i = 0; i < freelist_str.num[j]; ++i)
1441        {
1442           if (edd)
1443             edd->func.str_direct_free(freelist_str.list[j][i]);
1444           else
1445             free(freelist_str.list[j][i]);
1446        }
1447    _eet_free_reset(&freelist_str);
1448 }
1449
1450 static int
1451 eet_data_descriptor_encode_hash_cb(void *hash __UNUSED__, const char *key, void *hdata, void *fdata)
1452 {
1453    Eet_Dictionary               *ed;
1454    Eet_Data_Encode_Hash_Info    *edehi;
1455    Eet_Data_Stream              *ds;
1456    Eet_Data_Element             *ede;
1457    Eet_Data_Chunk               *echnk;
1458    void                         *data = NULL;
1459    int                           size;
1460
1461    edehi = fdata;
1462    ede = edehi->ede;
1463    ds = edehi->ds;
1464    ed = edehi->ed;
1465
1466    /* Store key */
1467    data = eet_data_put_type(ed,
1468                             EET_T_STRING,
1469                             &key,
1470                             &size);
1471    if (data)
1472      {
1473         echnk = eet_data_chunk_new(data, size, ede->name, ede->type, ede->group_type);
1474         eet_data_chunk_put(ed, echnk, ds);
1475         eet_data_chunk_free(echnk);
1476         free(data);
1477         data = NULL;
1478      }
1479
1480    EET_ASSERT(!((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING)), return );
1481
1482    /* Store data */
1483    if (ede->type >= EET_T_STRING)
1484      eet_data_put_unknown(ed, NULL, ede, ds, &hdata);
1485    else
1486      {
1487         if (ede->subtype)
1488           data = _eet_data_descriptor_encode(ed,
1489                                              ede->subtype,
1490                                              hdata,
1491                                              &size);
1492         if (data)
1493           {
1494              echnk = eet_data_chunk_new(data, size, ede->name, ede->type, ede->group_type);
1495              eet_data_chunk_put(ed, echnk, ds);
1496              eet_data_chunk_free(echnk);
1497              free(data);
1498              data = NULL;
1499           }
1500      }
1501
1502    return 1;
1503 }
1504
1505 static char *
1506 _eet_data_string_escape(const char *str)
1507 {
1508    char *s, *sp;
1509    const char *strp;
1510    int sz = 0;
1511
1512    for (strp = str; *strp; strp++)
1513      {
1514         if (*strp == '\"') sz += 2;
1515         else if (*strp == '\\') sz += 2;
1516         else sz += 1;
1517      }
1518    s = malloc(sz + 1);
1519    if (!s) return NULL;
1520    for (strp = str, sp = s; *strp; strp++, sp++)
1521      {
1522         if (*strp == '\"')
1523           {
1524              *sp = '\\';
1525              sp++;
1526           }
1527         else if (*strp == '\\')
1528           {
1529              *sp = '\\';
1530              sp++;
1531           }
1532         *sp = *strp;
1533      }
1534    *sp = 0;
1535    return s;
1536 }
1537
1538 static void
1539 _eet_data_dump_string_escape(void *dumpdata, void dumpfunc(void *data, const char *str), const char *str)
1540 {
1541    char *s;
1542
1543    s = _eet_data_string_escape(str);
1544    if (s)
1545      {
1546         dumpfunc(dumpdata, s);
1547         free(s);
1548      }
1549 }
1550
1551 static char *
1552 _eet_data_dump_token_get(const char *src, int *len)
1553 {
1554    const char *p;
1555    char *tok = NULL;
1556    int in_token = 0;
1557    int in_quote = 0;
1558    int tlen = 0, tsize = 0;
1559
1560 #define TOK_ADD(x) \
1561    { \
1562       tlen++; \
1563       if (tlen >= tsize) \
1564         { \
1565            tsize += 32; \
1566            tok = realloc(tok, tsize); \
1567         } \
1568       tok[tlen - 1] = x; \
1569    }
1570
1571    for (p = src; *len > 0; p++, (*len)--)
1572      {
1573         if (in_token)
1574           {
1575              if (in_quote)
1576                {
1577                   if ((p[0] == '\"') && (p > src) && (p[-1] != '\\'))
1578                     {
1579                        in_quote = 0;
1580                     }
1581                   else if ((p[0] == '\\') && (*len > 1) && (p[1] == '\"'))
1582                     {
1583                        /* skip */
1584                     }
1585                   else if ((p[0] == '\\') && (p > src) && (p[-1] == '\\'))
1586                     {
1587                        /* skip */
1588                     }
1589                   else
1590                     TOK_ADD(p[0]);
1591                }
1592              else
1593                {
1594                   if (p[0] == '\"') in_quote = 1;
1595                   else
1596                     {
1597                        if ((isspace(p[0])) || (p[0] == ';')) /* token ends here */
1598                          {
1599                             TOK_ADD(0);
1600                             (*len)--;
1601                             return tok;
1602                          }
1603                        else
1604                          TOK_ADD(p[0]);
1605                     }
1606                }
1607           }
1608         else
1609           {
1610              if (!((isspace(p[0])) || (p[0] == ';')))
1611                {
1612                   in_token = 1;
1613                   (*len)++;
1614                   p--;
1615                }
1616           }
1617      }
1618    if (in_token)
1619      {
1620         TOK_ADD(0);
1621         return tok;
1622      }
1623    if (tok) free(tok);
1624    return NULL;
1625 }
1626
1627 typedef struct _Node Node;
1628
1629 struct _Node
1630 {
1631    int    type;
1632    int    count;
1633    char  *name;
1634    char  *key;
1635    Node  *values;
1636    Node  *prev;
1637    Node  *next;
1638    Node  *parent;
1639    union {
1640       char                c;
1641       short               s;
1642       int                 i;
1643       long long           l;
1644       float               f;
1645       double              d;
1646       unsigned char       uc;
1647       unsigned short      us;
1648       unsigned int        ui;
1649       unsigned long long  ul;
1650       char               *str;
1651    } data;
1652 };
1653
1654 static void
1655 _eet_data_dump_free(Node *node)
1656 {
1657    Node *n, *n2;
1658
1659    switch (node->type)
1660      {
1661       case EET_G_UNKNOWN:
1662       case EET_G_ARRAY:
1663       case EET_G_VAR_ARRAY:
1664       case EET_G_LIST:
1665       case EET_G_HASH:
1666         if (node->key) free(node->key);
1667         for (n = node->values; n;)
1668           {
1669              n2 = n;
1670              n = n->next;
1671              _eet_data_dump_free(n2);
1672           }
1673         break;
1674       case EET_T_CHAR:
1675       case EET_T_SHORT:
1676       case EET_T_INT:
1677       case EET_T_LONG_LONG:
1678       case EET_T_FLOAT:
1679       case EET_T_DOUBLE:
1680       case EET_T_UCHAR:
1681       case EET_T_USHORT:
1682       case EET_T_UINT:
1683       case EET_T_ULONG_LONG:
1684       case EET_T_NULL:
1685         break;
1686       case EET_T_INLINED_STRING:
1687       case EET_T_STRING:
1688         if (node->data.str) free(node->data.str);
1689         break;
1690       default:
1691         break;
1692      }
1693    free(node);
1694 }
1695
1696 static void *
1697 _eet_data_dump_encode(Eet_Dictionary *ed,
1698                       Node *node,
1699                       int *size_ret)
1700 {
1701    Eet_Data_Chunk *chnk = NULL, *echnk = NULL;
1702    Eet_Data_Stream *ds;
1703    void *cdata, *data;
1704    int csize, size;
1705    Node *n;
1706
1707    if (words_bigendian == -1)
1708      {
1709         unsigned long int v;
1710
1711         v = htonl(0x12345678);
1712         if (v == 0x12345678) words_bigendian = 1;
1713         else words_bigendian = 0;
1714      }
1715
1716    ds = eet_data_stream_new();
1717    if (!ds) return NULL;
1718
1719    switch (node->type)
1720      {
1721       case EET_G_UNKNOWN:
1722         for (n = node->values; n; n = n->next)
1723           {
1724              data = _eet_data_dump_encode(ed, n, &size);
1725              if (data)
1726                {
1727                   eet_data_stream_write(ds, data, size);
1728                   free(data);
1729                }
1730           }
1731         break;
1732       case EET_G_ARRAY:
1733       case EET_G_VAR_ARRAY:
1734         data = eet_data_put_type(ed,
1735                                  EET_T_INT,
1736                                  &node->count,
1737                                  &size);
1738         if (data)
1739           {
1740              echnk = eet_data_chunk_new(data, size, node->name, node->type, node->type);
1741              eet_data_chunk_put(ed, echnk, ds);
1742              eet_data_chunk_free(echnk);
1743              free(data);
1744           }
1745         for (n = node->values; n; n = n->next)
1746           {
1747              data = _eet_data_dump_encode(ed, n, &size);
1748              if (data)
1749                {
1750                   echnk = eet_data_chunk_new(data, size, node->name, node->type, node->type);
1751                   eet_data_chunk_put(ed, echnk, ds);
1752                   eet_data_chunk_free(echnk);
1753                   free(data);
1754                }
1755           }
1756
1757         /* Array is somekind of special case, so we should embed it inside another chunk. */
1758         *size_ret = ds->pos;
1759         cdata = ds->data;
1760
1761         ds->data = NULL;
1762         ds->size = 0;
1763         eet_data_stream_free(ds);
1764
1765         return cdata;
1766       case EET_G_LIST:
1767         for (n = node->values; n; n = n->next)
1768           {
1769              data = _eet_data_dump_encode(ed, n, &size);
1770              if (data)
1771                {
1772                   eet_data_stream_write(ds, data, size);
1773                   free(data);
1774                }
1775           }
1776         break;
1777       case EET_G_HASH:
1778         if (node->key)
1779           {
1780              data = eet_data_put_type(ed,
1781                                       EET_T_STRING,
1782                                       &node->key,
1783                                       &size);
1784              if (data)
1785                {
1786                   echnk = eet_data_chunk_new(data, size, node->name, node->type, node->type);
1787                   eet_data_chunk_put(ed, echnk, ds);
1788                   eet_data_chunk_free(echnk);
1789                   free(data);
1790                }
1791           }
1792         for (n = node->values; n; n = n->next)
1793           {
1794              data = _eet_data_dump_encode(ed, n, &size);
1795              if (data)
1796                {
1797                   echnk = eet_data_chunk_new(data, size, node->name, node->type, node->type);
1798                   eet_data_chunk_put(ed, echnk, ds);
1799                   eet_data_chunk_free(echnk);
1800                   free(data);
1801                }
1802           }
1803
1804         /* Hash is somekind of special case, so we should embed it inside another chunk. */
1805         *size_ret = ds->pos;
1806         cdata = ds->data;
1807
1808         ds->data = NULL;
1809         ds->size = 0;
1810         eet_data_stream_free(ds);
1811
1812         return cdata;
1813       case EET_T_NULL:
1814          break;
1815       case EET_T_CHAR:
1816         data = eet_data_put_type(ed, node->type, &(node->data.c), &size);
1817         if (data)
1818           {
1819              eet_data_stream_write(ds, data, size);
1820              free(data);
1821           }
1822         break;
1823       case EET_T_SHORT:
1824         data = eet_data_put_type(ed, node->type, &(node->data.s), &size);
1825         if (data)
1826           {
1827              eet_data_stream_write(ds, data, size);
1828              free(data);
1829           }
1830         break;
1831       case EET_T_INT:
1832         data = eet_data_put_type(ed, node->type, &(node->data.i), &size);
1833         if (data)
1834           {
1835              eet_data_stream_write(ds, data, size);
1836              free(data);
1837           }
1838         break;
1839       case EET_T_LONG_LONG:
1840         data = eet_data_put_type(ed, node->type, &(node->data.l), &size);
1841         if (data)
1842           {
1843              eet_data_stream_write(ds, data, size);
1844              free(data);
1845           }
1846         break;
1847       case EET_T_FLOAT:
1848         data = eet_data_put_type(ed, node->type, &(node->data.f), &size);
1849         if (data)
1850           {
1851              eet_data_stream_write(ds, data, size);
1852              free(data);
1853           }
1854         break;
1855       case EET_T_DOUBLE:
1856         data = eet_data_put_type(ed, node->type, &(node->data.d), &size);
1857         if (data)
1858           {
1859              eet_data_stream_write(ds, data, size);
1860              free(data);
1861           }
1862         break;
1863       case EET_T_UCHAR:
1864         data = eet_data_put_type(ed, node->type, &(node->data.uc), &size);
1865         if (data)
1866           {
1867              eet_data_stream_write(ds, data, size);
1868              free(data);
1869           }
1870         break;
1871       case EET_T_USHORT:
1872         data = eet_data_put_type(ed, node->type, &(node->data.us), &size);
1873         if (data)
1874           {
1875              eet_data_stream_write(ds, data, size);
1876              free(data);
1877           }
1878         break;
1879       case EET_T_UINT:
1880         data = eet_data_put_type(ed, node->type, &(node->data.ui), &size);
1881         if (data)
1882           {
1883              eet_data_stream_write(ds, data, size);
1884              free(data);
1885           }
1886         break;
1887       case EET_T_ULONG_LONG:
1888         data = eet_data_put_type(ed, node->type, &(node->data.ul), &size);
1889         if (data)
1890           {
1891              eet_data_stream_write(ds, data, size);
1892              free(data);
1893           }
1894         break;
1895       case EET_T_INLINED_STRING:
1896         data = eet_data_put_type(ed, node->type, &(node->data.str), &size);
1897         if (data)
1898           {
1899              eet_data_stream_write(ds, data, size);
1900              free(data);
1901           }
1902         break;
1903       case EET_T_STRING:
1904         data = eet_data_put_type(ed, node->type, &(node->data.str), &size);
1905         if (data)
1906           {
1907              eet_data_stream_write(ds, data, size);
1908              free(data);
1909           }
1910         break;
1911       default:
1912         break;
1913      }
1914
1915    if ((node->type >= EET_G_UNKNOWN) && (node->type < EET_G_LAST))
1916      chnk = eet_data_chunk_new(ds->data, ds->pos, node->name, EET_T_UNKNOW, node->type);
1917    else
1918      chnk = eet_data_chunk_new(ds->data, ds->pos, node->name, node->type, EET_G_UNKNOWN);
1919    ds->data = NULL;
1920    ds->size = 0;
1921    eet_data_stream_free(ds);
1922
1923    ds = eet_data_stream_new();
1924    eet_data_chunk_put(ed, chnk, ds);
1925    cdata = ds->data;
1926    csize = ds->pos;
1927
1928    ds->data = NULL;
1929    ds->size = 0;
1930    eet_data_stream_free(ds);
1931    *size_ret = csize;
1932
1933    free(chnk->data);
1934    eet_data_chunk_free(chnk);
1935
1936    return cdata;
1937 }
1938
1939 static void *
1940 _eet_data_dump_parse(Eet_Dictionary *ed,
1941                      int *size_ret,
1942                      const char *src,
1943                      int size)
1944 {
1945    void *cdata = NULL;
1946    const char *p;
1947 #define M_NONE 0
1948 #define M_STRUCT 1
1949 #define M_ 2
1950    int left, jump;
1951    Node *node_base = NULL;
1952    Node *node = NULL;
1953    Node *n, *nn;
1954
1955    /* FIXME; handle parse errors */
1956 #define TOK_GET(t) \
1957    jump = left; t = _eet_data_dump_token_get(p, &left); p += jump - left;
1958    left = size;
1959    for (p = src; p < (src + size);)
1960      {
1961         char *tok1, *tok2, *tok3, *tok4;
1962
1963         TOK_GET(tok1);
1964         if (tok1)
1965           {
1966              if (!strcmp(tok1, "group"))
1967                {
1968                   TOK_GET(tok2);
1969                   if (tok2)
1970                     {
1971                        TOK_GET(tok3);
1972                        if (tok3)
1973                          {
1974                             TOK_GET(tok4);
1975                             if (tok4)
1976                               {
1977                                  if (!strcmp(tok4, "{"))
1978                                    {
1979                                       /* we have 'group NAM TYP {' */
1980                                       n = calloc(1, sizeof(Node));
1981                                       if (n)
1982                                         {
1983                                            n->parent = node;
1984                                            if (!node_base)
1985                                              {
1986                                                 node_base = n;
1987                                              }
1988                                            if (!node)
1989                                              {
1990                                                 node = n;
1991                                              }
1992                                            else
1993                                              {
1994                                                 /* append node */
1995                                                 if (!node->values)
1996                                                   node->values = n;
1997                                                 else
1998                                                   {
1999                                                      for (nn = node->values; nn; nn = nn->next)
2000                                                        {
2001                                                           if (!nn->next)
2002                                                             {
2003                                                                nn->next = n;
2004                                                                n->prev = nn;
2005                                                                break;
2006                                                             }
2007                                                        }
2008                                                   }
2009                                              }
2010                                            n->name = strdup(tok2);
2011                                            if      (!strcmp(tok3, "struct"))    n->type = EET_G_UNKNOWN;
2012                                            else if (!strcmp(tok3, "array"))     n->type = EET_G_ARRAY;
2013                                            else if (!strcmp(tok3, "var_array")) n->type = EET_G_VAR_ARRAY;
2014                                            else if (!strcmp(tok3, "list"))      n->type = EET_G_LIST;
2015                                            else if (!strcmp(tok3, "hash"))      n->type = EET_G_HASH;
2016                                            else
2017                                              {
2018                                                 printf("ERROR: group type '%s' invalid.\n", tok3);
2019                                              }
2020                                            node = n;
2021                                         }
2022                                    }
2023                                  free(tok4);
2024                               }
2025                             free(tok3);
2026                          }
2027                        free(tok2);
2028                     }
2029                }
2030              else if (!strcmp(tok1, "value"))
2031                {
2032                   TOK_GET(tok2);
2033                   if (tok2)
2034                     {
2035                        TOK_GET(tok3);
2036                        if (tok3)
2037                          {
2038                             TOK_GET(tok4);
2039                             if (tok4)
2040                               {
2041                                  /* we have 'value NAME TYP XXX' */
2042                                  if (node_base)
2043                                    {
2044                                       n = calloc(1, sizeof(Node));
2045                                       if (n)
2046                                         {
2047                                            n->parent = node;
2048                                            /* append node */
2049                                            if (!node->values)
2050                                              node->values = n;
2051                                            else
2052                                              {
2053                                                 for (nn = node->values; nn; nn = nn->next)
2054                                                   {
2055                                                      if (!nn->next)
2056                                                        {
2057                                                           nn->next = n;
2058                                                           n->prev = nn;
2059                                                           break;
2060                                                        }
2061                                                   }
2062                                              }
2063                                            n->name = strdup(tok2);
2064                                            if      (!strcmp(tok3, "char:"))
2065                                              {
2066                                                 n->type = EET_T_CHAR;
2067                                                 sscanf(tok4, "%hhi", &(n->data.c));
2068                                              }
2069                                            else if (!strcmp(tok3, "short:"))
2070                                              {
2071                                                 n->type = EET_T_SHORT;
2072                                                 sscanf(tok4, "%hi", &(n->data.s));
2073                                              }
2074                                            else if (!strcmp(tok3, "int:"))
2075                                              {
2076                                                 n->type = EET_T_INT;
2077                                                 sscanf(tok4, "%i", &(n->data.i));
2078                                              }
2079                                            else if (!strcmp(tok3, "long_long:"))
2080                                              {
2081                                                 n->type = EET_T_LONG_LONG;
2082                                                 sscanf(tok4, "%lli", &(n->data.l));
2083                                              }
2084                                            else if (!strcmp(tok3, "float:"))
2085                                              {
2086                                                 n->type = EET_T_FLOAT;
2087                                                 sscanf(tok4, "%f", &(n->data.f));
2088                                              }
2089                                            else if (!strcmp(tok3, "double:"))
2090                                              {
2091                                                 n->type = EET_T_DOUBLE;
2092                                                 sscanf(tok4, "%lf", &(n->data.d));
2093                                              }
2094                                            else if (!strcmp(tok3, "uchar:"))
2095                                              {
2096                                                 n->type = EET_T_UCHAR;
2097                                                 sscanf(tok4, "%hhu", &(n->data.uc));
2098                                              }
2099                                            else if (!strcmp(tok3, "ushort:"))
2100                                              {
2101                                                 n->type = EET_T_USHORT;
2102                                                 sscanf(tok4, "%hu", &(n->data.us));
2103                                              }
2104                                            else if (!strcmp(tok3, "uint:"))
2105                                              {
2106                                                 n->type = EET_T_UINT;
2107                                                 sscanf(tok4, "%u", &(n->data.ui));
2108                                              }
2109                                            else if (!strcmp(tok3, "ulong_long:"))
2110                                              {
2111                                                 n->type = EET_T_ULONG_LONG;
2112                                                 sscanf(tok4, "%llu", &(n->data.ul));
2113                                              }
2114                                            else if (!strcmp(tok3, "string:"))
2115                                              {
2116                                                 n->type = EET_T_STRING;
2117                                                 n->data.str = strdup(tok4);
2118                                              }
2119                                            else if (!strcmp(tok3, "inlined:"))
2120                                              {
2121                                                 n->type = EET_T_INLINED_STRING;
2122                                                 n->data.str = strdup(tok4);
2123                                              }
2124                                            else if (!strcmp(tok3, "null"))
2125                                              {
2126                                                 n->type = EET_T_NULL;
2127                                                 n->data.str = NULL;
2128                                              }
2129                                            else
2130                                              {
2131                                                 printf("ERROR: value type '%s' invalid.\n", tok4);
2132                                              }
2133                                         }
2134                                    }
2135                                  free(tok4);
2136                               }
2137                             free(tok3);
2138                          }
2139                        free(tok2);
2140                     }
2141                }
2142              else if (!strcmp(tok1, "key"))
2143                {
2144                   TOK_GET(tok2);
2145                   if (tok2)
2146                     {
2147                        /* we have 'key NAME' */
2148                        if (node)
2149                          {
2150                             node->key = strdup(tok2);
2151                          }
2152                        free(tok2);
2153                     }
2154                }
2155              else if (!strcmp(tok1, "count"))
2156                {
2157                   TOK_GET(tok2);
2158                   if (tok2)
2159                     {
2160                        /* we have a 'count COUNT' */
2161                        if (node)
2162                          {
2163                             sscanf(tok2, "%i", &(node->count));
2164                          }
2165                        free(tok2);
2166                     }
2167                }
2168              else if (!strcmp(tok1, "}"))
2169                {
2170                   /* we have an end of the group */
2171                   if (node) node = node->parent;
2172                }
2173              free(tok1);
2174           }
2175      }
2176
2177    if (node_base)
2178      {
2179         cdata = _eet_data_dump_encode(ed, node_base, size_ret);
2180         _eet_data_dump_free(node_base);
2181      }
2182    return cdata;
2183 }
2184
2185 #define NEXT_CHUNK(P, Size, Echnk, Ed)                  \
2186   {                                                     \
2187      int        tmp;                                    \
2188      tmp = Ed ? (int) (sizeof(int) * 2) : Echnk.len + 4;\
2189      P += (4 + Echnk.size + tmp);                       \
2190      Size -= (4 + Echnk.size + tmp);                    \
2191   }
2192
2193 static void *
2194 _eet_data_descriptor_decode(const Eet_Dictionary *ed,
2195                             Eet_Data_Descriptor *edd,
2196                             const void *data_in,
2197                             int size_in,
2198                             int level,
2199                             void (*dumpfunc) (void *data, const char *str),
2200                             void *dumpdata)
2201 {
2202    void *data = NULL;
2203    char *p, *buf, tbuf[256];
2204    int size, i, dump;
2205    Eet_Data_Chunk chnk;
2206
2207    if (words_bigendian == -1)
2208      {
2209         unsigned long int v;
2210
2211         v = htonl(0x12345678);
2212         if (v == 0x12345678) words_bigendian = 1;
2213         else words_bigendian = 0;
2214      }
2215
2216    if (edd)
2217      {
2218         data = edd->func.mem_alloc(edd->size);
2219         if (!data) return NULL;
2220         if (edd->ed != ed)
2221           {
2222              for (i = 0; i < edd->elements.num; i++)
2223                edd->elements.set[i].directory_name_ptr = NULL;
2224              edd->ed = ed;
2225           }
2226      }
2227    _eet_freelist_ref();
2228    _eet_freeleak_ref();
2229    _eet_freelist_str_ref();
2230    _eet_freelist_list_ref();
2231    if (data) _eet_freelist_add(data);
2232    dump = 0;
2233    memset(&chnk, 0, sizeof(Eet_Data_Chunk));
2234    eet_data_chunk_get(ed, &chnk, data_in, size_in);
2235    if (!chnk.name) goto error;
2236    if (edd)
2237      {
2238         if (strcmp(chnk.name, edd->name)) goto error;
2239      }
2240    p = chnk.data;
2241    if (ed)
2242      size = size_in - (4 + sizeof(int) * 2);
2243    else
2244      size = size_in - (4 + 4 + chnk.len);
2245    if (edd)
2246      {
2247         if (!edd->elements.hash.buckets) _eet_descriptor_hash_new(edd);
2248      }
2249    if (dumpfunc)
2250      {
2251         dump = 1;
2252         if (chnk.type == EET_T_UNKNOW)
2253           {
2254              buf = tbuf;
2255
2256              for (i = 0; i < level; i++) dumpfunc(dumpdata, "  ");
2257              dumpfunc(dumpdata, "group \"");
2258              _eet_data_dump_string_escape(dumpdata, dumpfunc, chnk.name);
2259              dumpfunc(dumpdata, "\" ");
2260              switch (chnk.group_type)
2261                {
2262                 case EET_G_UNKNOWN:
2263                   dumpfunc(dumpdata, "struct");
2264                   break;
2265                 case EET_G_ARRAY:
2266                   dumpfunc(dumpdata, "array");
2267                   break;
2268                 case EET_G_VAR_ARRAY:
2269                   dumpfunc(dumpdata, "var_array");
2270                   break;
2271                 case EET_G_LIST:
2272                   dumpfunc(dumpdata, "list");
2273                   break;
2274                 case EET_G_HASH:
2275                   dumpfunc(dumpdata, "hash");
2276                   break;
2277                 default:
2278                   dumpfunc(dumpdata, "???");
2279                   break;
2280                }
2281              dumpfunc(dumpdata, " {\n");
2282           }
2283      }
2284    while (size > 0)
2285      {
2286         Eet_Data_Chunk echnk;
2287         Eet_Data_Element *ede;
2288
2289         /* get next data chunk */
2290         memset(&echnk, 0, sizeof(Eet_Data_Chunk));
2291         eet_data_chunk_get(ed, &echnk, p, size);
2292         if (!echnk.name) goto error;
2293         /* FIXME: don't REPLY on edd - work without */
2294         if ((edd) && (!dumpfunc))
2295           {
2296              ede = _eet_descriptor_hash_find(edd, echnk.name, echnk.hash);
2297              if (ede)
2298                {
2299                   int group_type = EET_G_UNKNOWN, type = EET_T_UNKNOW;
2300                   int ret = 0;
2301
2302                   group_type = ede->group_type;
2303                   type = ede->type;
2304                   if ((echnk.type == 0) && (echnk.group_type == 0))
2305                     {
2306                        type = ede->type;
2307                        group_type = ede->group_type;
2308                     }
2309                   else
2310                     {
2311                        if (IS_SIMPLE_TYPE(echnk.type) &&
2312                            (echnk.type == ede->type))
2313                          type = echnk.type;
2314                        else if ((echnk.group_type > EET_G_UNKNOWN) &&
2315                                 (echnk.group_type < EET_G_LAST) &&
2316                                 (echnk.group_type == ede->group_type))
2317                          group_type = echnk.group_type;
2318                     }
2319                   /* hashes doesnt fit well with the table */
2320                   ret = eet_group_codec[group_type - 100].get(ed, edd, ede, &echnk, type, group_type, ((char *)data) + ede->offset, level, dumpfunc, dumpdata, &p, &size);
2321                   if (ret <= 0) goto error;
2322                }
2323           }
2324         /*...... dump func */
2325         else if (dumpfunc)
2326           {
2327              unsigned char dd[128];
2328              int group_type = EET_G_UNKNOWN, type = EET_T_UNKNOW;
2329
2330              if ((echnk.type > EET_T_UNKNOW) &&
2331                  (echnk.type < EET_T_LAST))
2332                type = echnk.type;
2333              else if ((echnk.group_type > EET_G_UNKNOWN) &&
2334                       (echnk.group_type < EET_G_LAST))
2335                group_type = echnk.group_type;
2336              if (group_type == EET_G_UNKNOWN)
2337                {
2338                   int ret;
2339                   void *data_ret;
2340
2341                   if (IS_SIMPLE_TYPE(type))
2342                     {
2343                        ret = eet_data_get_type(ed,
2344                                                type,
2345                                                echnk.data,
2346                                                ((char *)echnk.data) + echnk.size,
2347                                                dd);
2348                        for (i = 0; i < level; i++) dumpfunc(dumpdata, "  ");
2349                        dumpfunc(dumpdata, "  value \"");
2350                        _eet_data_dump_string_escape(dumpdata, dumpfunc, echnk.name);
2351                        dumpfunc(dumpdata, "\" ");
2352                        switch (type)
2353                          {
2354                           case EET_T_CHAR:
2355                             dumpfunc(dumpdata, "char: ");
2356                             snprintf(tbuf, sizeof(tbuf), "%hhi", *((char *)dd));
2357                             dumpfunc(dumpdata, tbuf); break;
2358                           case EET_T_SHORT:
2359                             dumpfunc(dumpdata, "short: ");
2360                             snprintf(tbuf, sizeof(tbuf), "%hi", *((short *)dd));
2361                             dumpfunc(dumpdata, tbuf); break;
2362                           case EET_T_INT:
2363                             dumpfunc(dumpdata, "int: ");
2364                             snprintf(tbuf, sizeof(tbuf), "%i", *((int *)dd));
2365                             dumpfunc(dumpdata, tbuf); break;
2366                           case EET_T_LONG_LONG:
2367                             dumpfunc(dumpdata, "long_long: ");
2368                             snprintf(tbuf, sizeof(tbuf), "%lli", *((long long *)dd));
2369                             dumpfunc(dumpdata, tbuf); break;
2370                           case EET_T_FLOAT:
2371                             dumpfunc(dumpdata, "float: ");
2372                             snprintf(tbuf, sizeof(tbuf), "%1.25f", *((float *)dd));
2373                             dumpfunc(dumpdata, tbuf); break;
2374                           case EET_T_DOUBLE:
2375                             dumpfunc(dumpdata, "double: ");
2376                             snprintf(tbuf, sizeof(tbuf), "%1.25f", *((double *)dd));
2377                             dumpfunc(dumpdata, tbuf); break;
2378                           case EET_T_UCHAR:
2379                             dumpfunc(dumpdata, "uchar: ");
2380                             snprintf(tbuf, sizeof(tbuf), "%hhu", *((unsigned char *)dd));
2381                             dumpfunc(dumpdata, tbuf); break;
2382                           case EET_T_USHORT:
2383                             dumpfunc(dumpdata, "ushort: ");
2384                             snprintf(tbuf, sizeof(tbuf), "%i", *((unsigned short *)dd));
2385                             dumpfunc(dumpdata, tbuf); break;
2386                           case EET_T_UINT:
2387                             dumpfunc(dumpdata, "uint: ");
2388                             snprintf(tbuf, sizeof(tbuf), "%u", *((unsigned int *)dd));
2389                             dumpfunc(dumpdata, tbuf); break;
2390                           case EET_T_ULONG_LONG:
2391                             dumpfunc(dumpdata, "ulong_long: ");
2392                             snprintf(tbuf, sizeof(tbuf), "%llu", *((unsigned long long *)dd));
2393                             dumpfunc(dumpdata, tbuf); break;
2394                           case EET_T_INLINED_STRING:
2395                               {
2396                                  char *s;
2397
2398                                  s = *((char **)dd);
2399                                  if (s)
2400                                    {
2401                                       dumpfunc(dumpdata, "inlined: \"");
2402                                       _eet_data_dump_string_escape(dumpdata, dumpfunc, s);
2403                                       dumpfunc(dumpdata, "\"");
2404                                    }
2405                               }
2406                             break;
2407                           case EET_T_STRING:
2408                               {
2409                                  char *s;
2410
2411                                  s = *((char **)dd);
2412                                  if (s)
2413                                    {
2414                                       dumpfunc(dumpdata, "string: \"");
2415                                       _eet_data_dump_string_escape(dumpdata, dumpfunc, s);
2416                                       dumpfunc(dumpdata, "\"");
2417                                    }
2418                               }
2419                             break;
2420                           case EET_T_NULL:
2421                             dumpfunc(dumpdata, "null");
2422                             break;
2423                           default:
2424                             dumpfunc(dumpdata, "???: ???"); break;
2425                             break;
2426                          }
2427                        dumpfunc(dumpdata, ";\n");
2428                     }
2429                   else
2430                     {
2431                        data_ret = _eet_data_descriptor_decode(ed,
2432                                                               NULL,
2433                                                               echnk.data,
2434                                                               echnk.size,
2435                                                               level + 1,
2436                                                               dumpfunc,
2437                                                               dumpdata);
2438                        if (!data_ret) goto error;
2439                     }
2440                }
2441              else
2442                {
2443                   for (i = 0; i < level; i++) dumpfunc(dumpdata, "  ");
2444                   dumpfunc(dumpdata, "  group \"");
2445                   _eet_data_dump_string_escape(dumpdata, dumpfunc, echnk.name);
2446                   dumpfunc(dumpdata, "\" ");
2447                   switch (echnk.group_type)
2448                     {
2449                      case EET_G_UNKNOWN:
2450                        dumpfunc(dumpdata, "struct");break;
2451                      case EET_G_ARRAY:
2452                        dumpfunc(dumpdata, "array");break;
2453                      case EET_G_VAR_ARRAY:
2454                        dumpfunc(dumpdata, "var_array");break;
2455                      case EET_G_LIST:
2456                        dumpfunc(dumpdata, "list");break;
2457                      case EET_G_HASH:
2458                        dumpfunc(dumpdata, "hash");break;
2459                      default:
2460                        dumpfunc(dumpdata, "???");break;
2461                        break;
2462                     }
2463                   dumpfunc(dumpdata, " {\n");
2464                   switch (group_type)
2465                     {
2466                      case EET_G_ARRAY:
2467                      case EET_G_VAR_ARRAY:
2468                          {
2469                             int count;
2470                             int ret;
2471                             int i;
2472
2473                             EET_ASSERT(!IS_SIMPLE_TYPE(type), goto error);
2474
2475                             ret = eet_data_get_type(ed,
2476                                                     EET_T_INT,
2477                                                     echnk.data,
2478                                                     ((char *)echnk.data) + echnk.size,
2479                                                     &count);
2480                             if (ret <= 0) goto error;
2481
2482                             for (i = 0; i < level; i++) dumpfunc(dumpdata, "  ");
2483                             dumpfunc(dumpdata, "    count ");
2484                             snprintf(tbuf, sizeof(tbuf), "%i", count);
2485                             dumpfunc(dumpdata, tbuf);
2486                             dumpfunc(dumpdata, ";\n");
2487
2488                             /* get all array elements */
2489                             for (i = 0; i < count; i++)
2490                               {
2491                                  void *data_ret = NULL;
2492
2493                                  /* Advance to next chunk */
2494                                  NEXT_CHUNK(p, size, echnk, ed);
2495                                  memset(&echnk, 0, sizeof(Eet_Data_Chunk));
2496
2497                                  eet_data_chunk_get(ed, &echnk, p, size);
2498                                  if (!echnk.name) goto error;
2499                                  /* get the data */
2500                                  data_ret = _eet_data_descriptor_decode(ed,
2501                                                                         NULL,
2502                                                                         echnk.data,
2503                                                                         echnk.size,
2504                                                                         level + 2,
2505                                                                         dumpfunc,
2506                                                                         dumpdata);
2507                                  if (!data_ret) goto error;
2508                               }
2509                          }
2510                        break;
2511                      case EET_G_LIST:
2512                          {
2513                             void *data_ret = NULL;
2514
2515                             EET_ASSERT(!IS_SIMPLE_TYPE(type), goto error);
2516
2517                             data_ret = _eet_data_descriptor_decode(ed,
2518                                                                    NULL,
2519                                                                    echnk.data,
2520                                                                    echnk.size,
2521                                                                    level + 2,
2522                                                                    dumpfunc,
2523                                                                    dumpdata);
2524                             if (!data_ret) goto error;
2525                          }
2526                        break;
2527                      case EET_G_HASH:
2528                          {
2529                             int ret;
2530                             char *key = NULL;
2531                             void *data_ret = NULL;
2532
2533                             /* Read key */
2534                             ret = eet_data_get_type(ed,
2535                                                     EET_T_STRING,
2536                                                     echnk.data,
2537                                                     ((char *)echnk.data) + echnk.size,
2538                                                     &key);
2539                             if (ret <= 0) goto error;
2540
2541                             /* Advance to next chunk */
2542                             NEXT_CHUNK(p, size, echnk, ed);
2543                             memset(&echnk, 0, sizeof(Eet_Data_Chunk));
2544
2545                             /* Read value */
2546                             eet_data_chunk_get(ed, &echnk, p, size);
2547                             if (!echnk.name) goto error;
2548
2549                             EET_ASSERT(!IS_SIMPLE_TYPE(type), goto error);
2550
2551                             {
2552                                char *s;
2553
2554                                s = key;
2555                                if (s)
2556                                  {
2557                                     for (i = 0; i < level; i++) dumpfunc(dumpdata, "  ");
2558                                     dumpfunc(dumpdata, "    key \"");
2559                                     _eet_data_dump_string_escape(dumpdata, dumpfunc, s);
2560                                     dumpfunc(dumpdata, "\";\n");
2561                                  }
2562                                data_ret = _eet_data_descriptor_decode(ed,
2563                                                                       NULL,
2564                                                                       echnk.data,
2565                                                                       echnk.size,
2566                                                                       level + 2,
2567                                                                       dumpfunc,
2568                                                                       dumpdata);
2569                             }
2570                             if (!data_ret)
2571                               {
2572                                  goto error;
2573                               }
2574                          }
2575                        break;
2576                      default:
2577                        break;
2578                     }
2579                   if (dumpfunc)
2580                     {
2581                        for (i = 0; i < level; i++) dumpfunc(dumpdata, "  ");
2582                        dumpfunc(dumpdata, "  }\n");
2583                     }
2584                }
2585           }
2586         /* advance to next chunk */
2587         NEXT_CHUNK(p, size, echnk, ed);
2588      }
2589
2590    _eet_freelist_unref();
2591    _eet_freeleak_unref();
2592    _eet_freelist_str_unref();
2593    _eet_freelist_list_unref();
2594    if (dumpfunc)
2595      {
2596         _eet_freelist_str_free(edd);
2597         _eet_freelist_direct_str_free(edd);
2598         _eet_freelist_list_free(edd);
2599         _eet_freelist_free(edd);
2600         _eet_freeleak_reset();
2601      }
2602    else
2603      {
2604         _eet_freelist_reset();
2605         _eet_freeleak_free(edd);
2606         _eet_freelist_str_reset();
2607         _eet_freelist_list_reset();
2608         _eet_freelist_direct_str_reset();
2609      }
2610    if (dumpfunc)
2611      {
2612         if (dump)
2613           {
2614              if (chnk.type == EET_T_UNKNOW)
2615                {
2616                   for (i = 0; i < level; i++) dumpfunc(dumpdata, "  ");
2617                   dumpfunc(dumpdata, "}\n");
2618                }
2619           }
2620         return (void *)1;
2621      }
2622    return data;
2623
2624 error:
2625    _eet_freelist_unref();
2626    _eet_freeleak_unref();
2627    _eet_freelist_str_unref();
2628    _eet_freelist_list_unref();
2629    _eet_freelist_str_free(edd);
2630    _eet_freelist_direct_str_free(edd);
2631    _eet_freelist_list_free(edd);
2632    _eet_freelist_free(edd);
2633    _eet_freeleak_reset();
2634    if (dumpfunc)
2635      {
2636         if (dump)
2637           {
2638              if (chnk.type == EET_T_UNKNOW)
2639                {
2640                   for (i = 0; i < level; i++) dumpfunc(dumpdata, "  ");
2641                   dumpfunc(dumpdata, "}\n");
2642                }
2643           }
2644      }
2645    return NULL;
2646 }
2647
2648 static int
2649 eet_data_get_list(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
2650                   int type __UNUSED__, int group_type __UNUSED__, void *data,
2651                   int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata,
2652                   char **p __UNUSED__, int *size __UNUSED__)
2653 {
2654    void *list = NULL;
2655    void **ptr;
2656    void *data_ret;
2657
2658    EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0);
2659
2660    ptr = (void **)data;
2661    list = *ptr;
2662    data_ret = NULL;
2663
2664    if (ede->type >= EET_T_STRING)
2665      {
2666         int ret;
2667
2668         ret = eet_data_get_unknown(ed, edd, ede, echnk, ede->type, EET_G_UNKNOWN,
2669                                    &data_ret, level, dumpfunc, dumpdata, p, size);
2670         if (!ret) return 0;
2671      }
2672    else
2673      {
2674         data_ret = _eet_data_descriptor_decode(ed, ede->subtype, echnk->data, echnk->size, level + 2, dumpfunc, dumpdata);
2675         if (!data_ret) return 0;
2676      }
2677
2678    list = edd->func.list_append(list, data_ret);
2679    *ptr = list;
2680    _eet_freelist_list_add(ptr);
2681
2682    return 1;
2683 }
2684
2685 static int
2686 eet_data_get_hash(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
2687                   int type, int group_type __UNUSED__, void *data,
2688                   int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata,
2689                   char **p, int *size)
2690 {
2691    void **ptr;
2692    void *hash = NULL;
2693    char *key = NULL;
2694    void *data_ret = NULL;
2695    int ret = 0;
2696
2697    EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0);
2698
2699    ptr = (void **)data;
2700    hash = *ptr;
2701
2702    /* Read key */
2703    ret = eet_data_get_type(ed,
2704                            EET_T_STRING,
2705                            echnk->data,
2706                            ((char *)echnk->data) + echnk->size,
2707                            &key);
2708    if (ret <= 0) goto on_error;
2709
2710    /* Advance to next chunk */
2711    NEXT_CHUNK((*p), (*size), (*echnk), ed);
2712    memset(echnk, 0, sizeof(Eet_Data_Chunk));
2713
2714    /* Read value */
2715    eet_data_chunk_get(ed, echnk, *p, *size);
2716    if (!echnk->name) goto on_error;
2717
2718    if (type >= EET_T_STRING)
2719      {
2720         int ret;
2721
2722         ret = eet_data_get_unknown(ed, edd, ede, echnk, ede->type, EET_G_UNKNOWN,
2723                                    &data_ret, level, dumpfunc, dumpdata, p, size);
2724         if (!ret) return 0;
2725      }
2726    else
2727      {
2728         data_ret = _eet_data_descriptor_decode(ed,
2729                                                ede->subtype,
2730                                                echnk->data,
2731                                                echnk->size,
2732                                                level + 2,
2733                                                dumpfunc,
2734                                                dumpdata);
2735         if (!data_ret) goto on_error;
2736      }
2737
2738    hash = edd->func.hash_add(hash, key, data_ret);
2739    *ptr = hash;
2740    _eet_freelist_list_add(ptr);
2741    return 1;
2742
2743  on_error:
2744    return ret;
2745 }
2746
2747 /* var arrays and fixed arrays have to
2748  * get all chunks at once. for fixed arrays
2749  * we can get each chunk and increment a
2750  * counter stored on the element itself but
2751  * it wont be thread safe. for var arrays
2752  * we still need a way to get the number of
2753  * elements from the data, so storing the
2754  * number of elements and the element data on
2755  * each chunk is pointless.
2756  */
2757 static int
2758 eet_data_get_array(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd __UNUSED__, 
2759                    Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
2760                    int type, int group_type, void *data,
2761                    int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata,
2762                    char **p, int *size)
2763 {
2764    const char *name;
2765    void *ptr;
2766    int count;
2767    int ret;
2768    int subsize;
2769    int i;
2770
2771    EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0);
2772
2773    ptr = data;
2774    /* read the number of elements */
2775    ret = eet_data_get_type(ed,
2776                            EET_T_INT,
2777                            echnk->data,
2778                            ((char *)echnk->data) + echnk->size,
2779                            &count);
2780    if (ret <= 0) return ret;
2781
2782    if (type >= EET_T_STRING)
2783      subsize = eet_basic_codec[ede->type].size;
2784    else
2785      subsize = ede->subtype->size;
2786
2787    name = echnk->name;
2788
2789    if (group_type == EET_G_VAR_ARRAY)
2790      {
2791         /* store the number of elements
2792          * on the counter offset */
2793         *(int *)(((char *)data) + ede->count - ede->offset) = count;
2794         /* allocate space for the array of elements */
2795         *(void **)ptr = calloc(count, subsize);
2796
2797         if (!*(void **)ptr) return 0;
2798
2799         _eet_freelist_add(*(void **)ptr);
2800      }
2801
2802    /* get all array elements */
2803    for (i = 0; i < count; i++)
2804      {
2805         void *dst;
2806         void *data_ret = NULL;
2807
2808         /* Advance to next chunk */
2809         NEXT_CHUNK((*p), (*size), (*echnk), ed);
2810         memset(echnk, 0, sizeof(Eet_Data_Chunk));
2811
2812         eet_data_chunk_get(ed, echnk, *p, *size);
2813         if (!echnk->name || strcmp(echnk->name, name) != 0) return 0;
2814         /* get the data */
2815
2816         /* get the destination pointer */
2817         if (group_type == EET_G_ARRAY)
2818           dst = (char *)ptr + (subsize * i);
2819         else
2820           dst = *(char **)ptr + (subsize * i);
2821
2822         if (type >= EET_T_STRING)
2823           {
2824              int ret;
2825
2826              ret = eet_data_get_unknown(ed,
2827                                         edd,
2828                                         ede,
2829                                         echnk,
2830                                         ede->type,
2831                                         EET_G_UNKNOWN,
2832                                         &data_ret,
2833                                         level,
2834                                         dumpfunc,
2835                                         dumpdata,
2836                                         p,
2837                                         size);
2838              if (!ret) return 0;
2839              memcpy(dst, &data_ret, subsize);
2840           }
2841         else
2842           {
2843              data_ret = _eet_data_descriptor_decode(ed,
2844                                                     ede->subtype,
2845                                                     echnk->data,
2846                                                     echnk->size,
2847                                                     level + 2,
2848                                                     dumpfunc,
2849                                                     dumpdata);
2850              if (!data_ret) return 0;
2851              memcpy(dst, data_ret, subsize);
2852              _eet_freeleak_add(data_ret);
2853           }
2854      }
2855    return 1;
2856 }
2857
2858 static int
2859 eet_data_get_unknown(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
2860                      int type, int group_type __UNUSED__, void *data,
2861                      int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata,
2862                      char **p __UNUSED__, int *size __UNUSED__)
2863 {
2864    int ret;
2865    void *data_ret;
2866
2867    if (IS_SIMPLE_TYPE(type))
2868      {
2869         ret = eet_data_get_type(ed, type, echnk->data, ((char *)echnk->data) + echnk->size, ((char *)data));
2870         if (ret <= 0) return ret;
2871
2872         if (type == EET_T_STRING)
2873           {
2874              char **str;
2875
2876              str = (char **)(((char *)data));
2877              if (*str)
2878                {
2879                   if ((ed == NULL) || (edd->func.str_direct_alloc == NULL))
2880                     {
2881                        *str = edd->func.str_alloc(*str);
2882                        _eet_freelist_str_add(*str);
2883                     }
2884                   else
2885                     {
2886                        *str = edd->func.str_direct_alloc(*str);
2887                        _eet_freelist_direct_str_add(*str);
2888                     }
2889                }
2890           }
2891         else if (type == EET_T_INLINED_STRING)
2892           {
2893              char **str;
2894
2895              str = (char **)(((char *)data));
2896              if (*str)
2897                {
2898                   *str = edd->func.str_alloc(*str);
2899                   _eet_freelist_str_add(*str);
2900                }
2901           }
2902      }
2903    else if (ede->subtype)
2904      {
2905         void **ptr;
2906
2907         data_ret = _eet_data_descriptor_decode(ed, ede->subtype, echnk->data, echnk->size, level + 1, dumpfunc, dumpdata);
2908         if (!data_ret) return 0;
2909
2910         ptr = (void **)(((char *)data));
2911         *ptr = (void *)data_ret;
2912      }
2913
2914    return 1;
2915 }
2916
2917 static void
2918 eet_data_encode(Eet_Dictionary *ed, Eet_Data_Stream *ds, void *data, const char *name, int size, int type, int group_type)
2919 {
2920    Eet_Data_Chunk *echnk;
2921
2922    echnk = eet_data_chunk_new(data, size, name, type, group_type);
2923    eet_data_chunk_put(ed, echnk, ds);
2924    eet_data_chunk_free(echnk);
2925    if (data) free(data);
2926 }
2927
2928 static void
2929 eet_data_put_array(Eet_Dictionary *ed, Eet_Data_Descriptor *edd __UNUSED__, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in)
2930 {
2931    void *data;
2932    int offset = 0;
2933    int subsize;
2934    int count;
2935    int size;
2936    int j;
2937
2938    EET_ASSERT(!((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING)), return );
2939
2940    if (ede->group_type == EET_G_ARRAY)
2941      count = ede->counter_offset;
2942    else
2943      count = *(int *)(((char *)data_in) + ede->count - ede->offset);
2944
2945    if (count <= 0) return;
2946    /* Store number of elements */
2947    data = eet_data_put_type(ed, EET_T_INT, &count, &size);
2948    if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
2949
2950    if (ede->type >= EET_T_STRING)
2951      subsize = eet_basic_codec[ede->type].size;
2952    else
2953      subsize = ede->subtype->size;
2954
2955    for (j = 0; j < count; j++)
2956      {
2957         void *d;
2958         int pos = ds->pos;
2959
2960         if (ede->group_type == EET_G_ARRAY)
2961           d = (void *)(((char *)data_in) + offset);
2962         else
2963           d = *(((char **)data_in)) + offset;
2964
2965         if (ede->type >= EET_T_STRING)
2966           eet_data_put_unknown(ed, NULL, ede, ds, d);
2967         else
2968           {
2969              data = _eet_data_descriptor_encode(ed, ede->subtype, d, &size);
2970              if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
2971           }
2972
2973         if (pos == ds->pos)
2974           {
2975              /* Add a NULL element just to have the correct array layout. */
2976              eet_data_encode(ed, ds, NULL, ede->name, 0, EET_T_NULL, ede->group_type);
2977           }
2978
2979         offset += subsize;
2980      }
2981 }
2982
2983 static void
2984 eet_data_put_unknown(Eet_Dictionary *ed, Eet_Data_Descriptor *edd __UNUSED__, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in)
2985 {
2986    void *data = NULL;
2987    int size;
2988
2989    if (IS_SIMPLE_TYPE(ede->type))
2990      data = eet_data_put_type(ed, ede->type, data_in, &size);
2991    else if (ede->subtype)
2992      {
2993         if (*((char **)data_in))
2994           data = _eet_data_descriptor_encode(ed,
2995                                              ede->subtype,
2996                                              *((char **)((char *)(data_in))),
2997                                              &size);
2998      }
2999    if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
3000 }
3001
3002 static void
3003 eet_data_put_list(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in)
3004 {
3005    void *data;
3006    void *l;
3007    int size;
3008
3009    EET_ASSERT(!((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING)), return );
3010
3011    l = *((void **)(((char *)data_in)));
3012    for (; l; l = edd->func.list_next(l))
3013      {
3014         if (ede->type >= EET_T_STRING)
3015           {
3016              const char *str = edd->func.list_data(l);
3017              eet_data_put_unknown(ed, NULL, ede, ds, &str);
3018           }
3019         else
3020           {
3021              data = _eet_data_descriptor_encode(ed,
3022                                                 ede->subtype,
3023                                                 edd->func.list_data(l),
3024                                                 &size);
3025              if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
3026           }
3027      }
3028 }
3029
3030 static void
3031 eet_data_put_hash(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in)
3032 {
3033    Eet_Data_Encode_Hash_Info fdata;
3034    void *l;
3035
3036    l = *((void **)(((char *)data_in)));
3037    fdata.ds = ds;
3038    fdata.ede = ede;
3039    fdata.ed = ed;
3040    edd->func.hash_foreach(l, eet_data_descriptor_encode_hash_cb, &fdata);
3041 }
3042
3043 EAPI int
3044 eet_data_dump_cipher(Eet_File *ef,
3045                      const char *name, const char *key,
3046                      void (*dumpfunc) (void *data, const char *str),
3047                      void *dumpdata)
3048 {
3049    const Eet_Dictionary *ed = NULL;
3050    const void           *data = NULL;
3051    int                   ret = 0;
3052    int                   required_free = 0;
3053    int                   size;
3054
3055    ed = eet_dictionary_get(ef);
3056
3057    if (!key)
3058      data = eet_read_direct(ef, name, &size);
3059    if (!data)
3060      {
3061         required_free = 1;
3062         data = eet_read_cipher(ef, name, &size, key);
3063         if (!data) return 0;
3064      }
3065
3066    if (_eet_data_descriptor_decode(ed, NULL, data, size, 0,
3067                                    dumpfunc, dumpdata))
3068      ret = 1;
3069
3070    if (required_free)
3071      free((void*)data);
3072
3073    return ret;
3074 }
3075
3076 EAPI int
3077 eet_data_dump(Eet_File *ef,
3078               const char *name,
3079               void (*dumpfunc) (void *data, const char *str),
3080               void *dumpdata)
3081 {
3082    return eet_data_dump_cipher(ef, name, NULL, dumpfunc, dumpdata);
3083 }
3084
3085
3086 EAPI int
3087 eet_data_text_dump_cipher(const void *data_in,
3088                           const char *key, int size_in,
3089                           void (*dumpfunc) (void *data, const char *str),
3090                           void *dumpdata)
3091 {
3092    void *ret = NULL;
3093    unsigned int ret_len = 0;
3094
3095    if (data_in && key)
3096      {
3097        if (eet_decipher(data_in, size_in, key, strlen(key), &ret, &ret_len))
3098          {
3099            if (ret) free(ret);
3100            return 1;
3101          }
3102        if (_eet_data_descriptor_decode(NULL, NULL, ret, ret_len, 0,
3103                                        dumpfunc, dumpdata))
3104          {
3105            free(ret);
3106            return 1;
3107          }
3108        free(ret);
3109        return 0;
3110      }
3111    if (_eet_data_descriptor_decode(NULL, NULL, data_in, size_in, 0,
3112                                    dumpfunc, dumpdata))
3113      return 1;
3114    return 0;
3115 }
3116
3117 EAPI int
3118 eet_data_text_dump(const void *data_in,
3119                    int size_in,
3120                    void (*dumpfunc) (void *data, const char *str),
3121                    void *dumpdata)
3122 {
3123    return eet_data_text_dump_cipher(data_in, NULL, size_in, dumpfunc, dumpdata);
3124 }
3125
3126 EAPI void *
3127 eet_data_text_undump_cipher(const char *text,
3128                             const char *key,
3129                             int textlen,
3130                             int *size_ret)
3131 {
3132    void *ret = NULL;
3133
3134    ret = _eet_data_dump_parse(NULL, size_ret, text, textlen);
3135    if (ret && key)
3136      {
3137         void *ciphered = NULL;
3138         unsigned int ciphered_len;
3139
3140        if (eet_cipher(ret, *size_ret, key, strlen(key), &ciphered, &ciphered_len))
3141          {
3142            if (ciphered) free(ciphered);
3143            size_ret = 0;
3144            free(ret);
3145            return NULL;
3146          }
3147        free(ret);
3148        *size_ret = ciphered_len;
3149        ret = ciphered;
3150      }
3151    return ret;
3152 }
3153
3154 EAPI void *
3155 eet_data_text_undump(const char *text,
3156                      int textlen,
3157                      int *size_ret)
3158 {
3159    return eet_data_text_undump_cipher(text, NULL, textlen, size_ret);
3160 }
3161
3162 EAPI int
3163 eet_data_undump_cipher(Eet_File *ef,
3164                        const char *name,
3165                        const char *key,
3166                        const char *text,
3167                        int textlen,
3168                        int compress)
3169 {
3170    Eet_Dictionary       *ed;
3171    void                 *data_enc;
3172    int                   size;
3173    int                   val;
3174
3175    ed = eet_dictionary_get(ef);
3176
3177    data_enc = _eet_data_dump_parse(ed, &size, text, textlen);
3178    if (!data_enc) return 0;
3179    val = eet_write_cipher(ef, name, data_enc, size, compress, key);
3180    free(data_enc);
3181    return val;
3182 }
3183
3184 EAPI int
3185 eet_data_undump(Eet_File *ef,
3186                 const char *name,
3187                 const char *text,
3188                 int textlen,
3189                 int compress)
3190 {
3191    return eet_data_undump_cipher(ef, name, NULL, text, textlen, compress);
3192 }
3193
3194 EAPI void *
3195 eet_data_descriptor_decode_cipher(Eet_Data_Descriptor *edd,
3196                                   const void *data_in,
3197                                   const char *key,
3198                                   int size_in)
3199 {
3200    void *deciphered = NULL;
3201    unsigned int deciphered_len = 0;
3202    void *ret;
3203
3204    if (key && data_in)
3205      {
3206        if (eet_decipher(data_in, size_in, key, strlen(key), &deciphered, &deciphered_len))
3207          {
3208            if (deciphered) free(deciphered);
3209            return NULL;
3210          }
3211        ret = _eet_data_descriptor_decode(NULL, edd, deciphered, deciphered_len, 0,
3212                                          NULL, NULL);
3213        free(deciphered);
3214        return ret;
3215      }
3216    return _eet_data_descriptor_decode(NULL, edd, data_in, size_in, 0,
3217                                       NULL, NULL);
3218 }
3219
3220 EAPI void *
3221 eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
3222                            const void *data_in,
3223                            int size_in)
3224 {
3225    return eet_data_descriptor_decode_cipher(edd, data_in, NULL, size_in);
3226 }
3227
3228 static void *
3229 _eet_data_descriptor_encode(Eet_Dictionary *ed,
3230                             Eet_Data_Descriptor *edd,
3231                             const void *data_in,
3232                             int *size_ret)
3233 {
3234    Eet_Data_Stream      *ds;
3235    Eet_Data_Chunk       *chnk;
3236    void                 *cdata;
3237    int                   csize;
3238    int                   i;
3239
3240    if (words_bigendian == -1)
3241      {
3242         unsigned long int v;
3243
3244         v = htonl(0x12345678);
3245         if (v == 0x12345678) words_bigendian = 1;
3246         else words_bigendian = 0;
3247      }
3248
3249    ds = eet_data_stream_new();
3250    for (i = 0; i < edd->elements.num; i++)
3251      {
3252         Eet_Data_Element *ede;
3253
3254         ede = &(edd->elements.set[i]);
3255         eet_group_codec[ede->group_type - 100].put(ed, edd, ede, ds, ((char *)data_in) + ede->offset);
3256      }
3257    chnk = eet_data_chunk_new(ds->data, ds->pos, edd->name, EET_T_UNKNOW, EET_G_UNKNOWN);
3258    ds->data = NULL;
3259    ds->size = 0;
3260    eet_data_stream_free(ds);
3261
3262    ds = eet_data_stream_new();
3263    eet_data_chunk_put(ed, chnk, ds);
3264    cdata = ds->data;
3265    csize = ds->pos;
3266
3267    ds->data = NULL;
3268    ds->size = 0;
3269    eet_data_stream_free(ds);
3270    *size_ret = csize;
3271
3272    free(chnk->data);
3273    eet_data_chunk_free(chnk);
3274
3275    return cdata;
3276 }
3277
3278 EAPI void *
3279 eet_data_descriptor_encode_cipher(Eet_Data_Descriptor *edd,
3280                                   const void *data_in,
3281                                   const char *key,
3282                                   int *size_ret)
3283 {
3284    void *ret = NULL;
3285    void *ciphered = NULL;
3286    unsigned int ciphered_len = 0;
3287
3288    ret = _eet_data_descriptor_encode(NULL, edd, data_in, size_ret);
3289    if (key && ret)
3290      {
3291        if (eet_cipher(ret, *size_ret, key, strlen(key), &ciphered, &ciphered_len))
3292          {
3293            if (ciphered) free(ciphered);
3294            size_ret = 0;
3295            free(ret);
3296            return NULL;
3297          }
3298        free(ret);
3299        *size_ret = ciphered_len;
3300        ret = ciphered;
3301      }
3302    return ret;
3303 }
3304
3305 EAPI void *
3306 eet_data_descriptor_encode(Eet_Data_Descriptor *edd,
3307                            const void *data_in,
3308                            int *size_ret)
3309 {
3310    return eet_data_descriptor_encode_cipher(edd, data_in, NULL, size_ret);
3311 }