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