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