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