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