2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
10 #define __UNUSED__ __attribute__((unused))
21 #ifdef HAVE_NETINET_IN_H
22 # include <netinet/in.h>
25 #if defined(_WIN32) && ! defined(__CEGCC__)
26 # include <winsock2.h>
32 #include "Eet_private.h"
35 * routines for doing data -> struct and struct -> data conversion
55 * multiple entries ordered as...
57 * fixed size array [ of basic types ]
58 * variable size array [ of basic types ]
59 * linked list [ of basic types ]
60 * hash table [ of basic types ]
62 * need to provide builder/accessor funcs for:
74 typedef struct _Eet_Data_Element Eet_Data_Element;
75 typedef struct _Eet_Data_Basic_Type_Codec Eet_Data_Basic_Type_Codec;
76 typedef struct _Eet_Data_Group_Type_Codec Eet_Data_Group_Type_Codec;
77 typedef struct _Eet_Data_Chunk Eet_Data_Chunk;
78 typedef struct _Eet_Data_Stream Eet_Data_Stream;
79 typedef struct _Eet_Data_Descriptor_Hash Eet_Data_Descriptor_Hash;
80 typedef struct _Eet_Data_Encode_Hash_Info Eet_Data_Encode_Hash_Info;
85 * Eet_Data_Basic_Type_Codec (Coder, Decoder)
86 * Eet_Data_Group_Type_Codec (Coder, Decoder)
88 struct _Eet_Data_Basic_Type_Codec
92 int (*get) (const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
93 void *(*put) (Eet_Dictionary *ed, const void *src, int *size_ret);
96 struct _Eet_Data_Group_Type_Codec
98 int (*get) (const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, int type, int group_type, void *data_in, int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata, char **p, int *size);
99 void (*put) (Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
102 struct _Eet_Data_Chunk
110 unsigned char group_type;
113 struct _Eet_Data_Stream
120 struct _Eet_Data_Descriptor_Hash
122 Eet_Data_Element *element;
123 Eet_Data_Descriptor_Hash *next;
126 struct _Eet_Data_Descriptor
129 const Eet_Dictionary *ed;
132 void *(*mem_alloc) (size_t size);
133 void (*mem_free) (void *mem);
134 char *(*str_alloc) (const char *str);
135 char *(*str_direct_alloc) (const char *str);
136 void (*str_free) (const char *str);
137 void (*str_direct_free) (const char *str);
138 void *(*list_next) (void *l);
139 void *(*list_append) (void *l, void *d);
140 void *(*list_data) (void *l);
141 void *(*list_free) (void *l);
142 void (*hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt);
143 void *(*hash_add) (void *h, const char *k, void *d);
144 void (*hash_free) (void *h);
148 Eet_Data_Element *set;
151 Eet_Data_Descriptor_Hash *buckets;
158 struct _Eet_Data_Element
161 const char *counter_name;
162 const char *directory_name_ptr;
163 Eet_Data_Descriptor *subtype;
164 int offset; /* offset in bytes from the base element */
165 int count; /* number of elements for a fixed array */
166 int counter_offset; /* for a variable array we need the offset of the count variable */
167 unsigned char type; /* EET_T_XXX */
168 unsigned char group_type; /* EET_G_XXX */
171 struct _Eet_Data_Encode_Hash_Info
174 Eet_Data_Element *ede;
180 static int eet_data_get_char(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
181 static void *eet_data_put_char(Eet_Dictionary *ed, const void *src, int *size_ret);
182 static int eet_data_get_short(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
183 static void *eet_data_put_short(Eet_Dictionary *ed, const void *src, int *size_ret);
184 static inline int eet_data_get_int(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
185 static void *eet_data_put_int(Eet_Dictionary *ed, const void *src, int *size_ret);
186 static int eet_data_get_long_long(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
187 static void *eet_data_put_long_long(Eet_Dictionary *ed, const void *src, int *size_ret);
188 static int eet_data_get_float(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
189 static void *eet_data_put_float(Eet_Dictionary *ed, const void *src, int *size_ret);
190 static int eet_data_get_double(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
191 static void *eet_data_put_double(Eet_Dictionary *ed, const void *src, int *size_ret);
192 static inline int eet_data_get_string(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
193 static void *eet_data_put_string(Eet_Dictionary *ed, const void *src, int *size_ret);
194 static int eet_data_get_istring(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
195 static void *eet_data_put_istring(Eet_Dictionary *ed, const void *src, int *size_ret);
197 static int eet_data_get_type(const Eet_Dictionary *ed, int type, const void *src, const void *src_end, void *dest);
198 static void *eet_data_put_type(Eet_Dictionary *ed, int type, const void *src, int *size_ret);
200 static int eet_data_get_unknown(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, int type, int group_type, void *data_in, int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata, char **p, int *size);
201 static void eet_data_put_unknown(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
202 static void eet_data_put_array(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
203 static int eet_data_get_array(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, int type, int group_type, void *data, int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata, char **p, int *size);
204 static int eet_data_get_list(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, int type, int group_type, void *data_in, int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata, char **p, int *size);
205 static void eet_data_put_list(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
206 static void eet_data_put_hash(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in);
207 static int eet_data_get_hash(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk, int type, int group_type, void *data, int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata, char **p, int *size);
209 static void eet_data_chunk_get(const Eet_Dictionary *ed, Eet_Data_Chunk *chnk, const void *src, int size);
210 static Eet_Data_Chunk *eet_data_chunk_new(void *data, int size, const char *name, int type, int group_type);
211 static void eet_data_chunk_free(Eet_Data_Chunk *chnk);
213 static Eet_Data_Stream *eet_data_stream_new(void);
214 static void eet_data_stream_write(Eet_Data_Stream *ds, const void *data, int size);
215 static void eet_data_stream_free(Eet_Data_Stream *ds);
217 static void eet_data_chunk_put(Eet_Dictionary *ed, Eet_Data_Chunk *chnk, Eet_Data_Stream *ds);
219 static int eet_data_descriptor_encode_hash_cb(void *hash, const char *key, void *hdata, void *fdata);
220 static void *_eet_data_descriptor_encode(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, const void *data_in, int *size_ret);
221 static void *_eet_data_descriptor_decode(const Eet_Dictionary *ed,
222 Eet_Data_Descriptor *edd,
226 void (*dumpfunc) (void *data, const char *str),
231 static const Eet_Data_Basic_Type_Codec eet_basic_codec[] =
233 {sizeof(char), "char", eet_data_get_char, eet_data_put_char },
234 {sizeof(short), "short", eet_data_get_short, eet_data_put_short },
235 {sizeof(int), "int", eet_data_get_int, eet_data_put_int },
236 {sizeof(long long), "long_long", eet_data_get_long_long, eet_data_put_long_long},
237 {sizeof(float), "float", eet_data_get_float, eet_data_put_float },
238 {sizeof(double), "double", eet_data_get_double, eet_data_put_double },
239 {sizeof(char), "uchar", eet_data_get_char, eet_data_put_char },
240 {sizeof(short), "ushort", eet_data_get_short, eet_data_put_short },
241 {sizeof(int), "uint", eet_data_get_int, eet_data_put_int },
242 {sizeof(long long), "ulong_long", eet_data_get_long_long, eet_data_put_long_long},
243 {sizeof(char *), "string", eet_data_get_string, eet_data_put_string },
244 {sizeof(char *), "inlined", eet_data_get_istring, eet_data_put_istring }
247 static const Eet_Data_Group_Type_Codec eet_group_codec[] =
249 { eet_data_get_unknown, eet_data_put_unknown },
250 { eet_data_get_array, eet_data_put_array },
251 { eet_data_get_array, eet_data_put_array },
252 { eet_data_get_list, eet_data_put_list },
253 { eet_data_get_hash, eet_data_put_hash }
256 static int words_bigendian = -1;
260 #define SWAP64(x) (x) = \
261 ((((unsigned long long)(x) & 0x00000000000000ffULL ) << 56) |\
262 (((unsigned long long)(x) & 0x000000000000ff00ULL ) << 40) |\
263 (((unsigned long long)(x) & 0x0000000000ff0000ULL ) << 24) |\
264 (((unsigned long long)(x) & 0x00000000ff000000ULL ) << 8) |\
265 (((unsigned long long)(x) & 0x000000ff00000000ULL ) >> 8) |\
266 (((unsigned long long)(x) & 0x0000ff0000000000ULL ) >> 24) |\
267 (((unsigned long long)(x) & 0x00ff000000000000ULL ) >> 40) |\
268 (((unsigned long long)(x) & 0xff00000000000000ULL ) >> 56))
269 #define SWAP32(x) (x) = \
270 ((((int)(x) & 0x000000ff ) << 24) |\
271 (((int)(x) & 0x0000ff00 ) << 8) |\
272 (((int)(x) & 0x00ff0000 ) >> 8) |\
273 (((int)(x) & 0xff000000 ) >> 24))
274 #define SWAP16(x) (x) = \
275 ((((short)(x) & 0x00ff ) << 8) |\
276 (((short)(x) & 0xff00 ) >> 8))
279 #define CONV16(x) {if (words_bigendian) SWAP16(x);}
280 #define CONV32(x) {if (words_bigendian) SWAP32(x);}
281 #define CONV64(x) {if (words_bigendian) SWAP64(x);}
283 #define IS_SIMPLE_TYPE(Type) (Type > EET_T_UNKNOW && Type < EET_T_LAST)
289 eet_data_get_char(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst)
293 if (((char *)src + sizeof(char)) > (char *)src_end) return -1;
302 eet_data_put_char(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret)
306 d = (char *)malloc(sizeof(char));
311 *size_ret = sizeof(char);
317 eet_data_get_short(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst)
321 if (((char *)src + sizeof(short)) > (char *)src_end) return -1;
322 memcpy(dst, src, sizeof(short));
325 return sizeof(short);
329 eet_data_put_short(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret)
333 d = (short *)malloc(sizeof(short));
338 *size_ret = sizeof(short);
344 eet_data_get_int(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst)
348 if (((char *)src + sizeof(int)) > (char *)src_end) return -1;
349 memcpy(dst, src, sizeof(int));
356 eet_data_put_int(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret)
360 d = (int *)malloc(sizeof(int));
365 *size_ret = sizeof(int);
371 eet_data_get_long_long(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst)
373 unsigned long long *d;
375 if (((char *)src + sizeof(unsigned long long)) > (char *)src_end) return -1;
376 memcpy(dst, src, sizeof(unsigned long long));
377 d = (unsigned long long *)dst;
379 return sizeof(unsigned long long);
383 eet_data_put_long_long(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret)
385 unsigned long long *s, *d;
387 d = (unsigned long long *)malloc(sizeof(unsigned long long));
389 s = (unsigned long long *)src;
392 *size_ret = sizeof(unsigned long long);
398 eet_data_get_string_hash(const Eet_Dictionary *ed, const void *src, const void *src_end)
404 if (eet_data_get_int(ed, src, src_end, &index) < 0) return -1;
406 return eet_dictionary_string_get_hash(ed, index);
413 eet_data_get_string(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
424 if (eet_data_get_int(ed, src, src_end, &index) < 0) return -1;
426 str = eet_dictionary_string_get_char(ed, index);
431 return eet_dictionary_string_get_size(ed, index);
442 return strlen(s) + 1;
446 eet_data_put_string(Eet_Dictionary *ed, const void *src, int *size_ret)
456 str = *((const char **) src);
457 if (!str) return NULL;
459 index = eet_dictionary_string_add(ed, str);
460 if (index == -1) return NULL;
462 return eet_data_put_int(ed, &index, size_ret);
465 s = (char *)(*((char **)src));
470 memcpy(d, s, len + 1);
475 /* ALWAYS INLINED STRING TYPE */
477 eet_data_get_istring(const Eet_Dictionary *ed __UNUSED__, const void *src, const void *src_end, void *dst)
479 return eet_data_get_string(NULL, src, src_end, dst);
483 eet_data_put_istring(Eet_Dictionary *ed __UNUSED__, const void *src, int *size_ret)
485 return eet_data_put_string(NULL, src, size_ret);
489 * Fast lookups of simple doubles/floats.
491 * These aren't properly a cache because they don't store pre-calculated
492 * values, but have a so simple math that is almost as fast.
495 _eet_data_float_cache_get(const char *s, int len, float *d)
497 /* fast handle of simple case 0xMp+E*/
498 if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p'))
500 int mantisse = (s[2] >= 'a') ? (s[2] - 'a' + 10) : (s[2] - '0');
501 int exponent = (s[5] - '0');
503 if (s[4] == '+') *d = (float)(mantisse << exponent);
504 else *d = (float)mantisse / (float)(1 << exponent);
512 _eet_data_double_cache_get(const char *s, int len, double *d)
514 /* fast handle of simple case 0xMp+E*/
515 if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p'))
517 int mantisse = (s[2] >= 'a') ? (s[2] - 'a' + 10) : (s[2] - '0');
518 int exponent = (s[5] - '0');
520 if (s[4] == '+') *d = (double)(mantisse << exponent);
521 else *d = (double)mantisse / (double)(1 << exponent);
530 eet_data_get_float(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
543 s = (const char *)src;
546 while ((p < (const char *)src_end) && (*p != 0)) {len++; p++;}
548 if (_eet_data_float_cache_get(s, len, d) != 0) return len + 1;
550 if (eina_convert_atod(s, len, &mantisse, &exponent) == EINA_FALSE) return -1;
551 *d = (float)ldexp((double)mantisse, exponent);
556 if (eet_data_get_int(ed, src, src_end, &index) < 0) return -1;
558 if (!eet_dictionary_string_get_float(ed, index, d))
564 eet_data_put_float(Eet_Dictionary *ed, const void *src, int *size_ret)
569 eina_convert_dtoa((double)(*(float *)src), buf);
579 memcpy(d, buf, len + 1);
584 index = eet_dictionary_string_add(ed, buf);
585 if (index == -1) return NULL;
587 return eet_data_put_int(ed, &index, size_ret);
592 eet_data_get_double(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
602 long long mantisse = 0;
606 s = (const char *) src;
609 while ((p < (const char *)src_end) && (*p != 0)) {len++; p++;}
611 if (_eet_data_double_cache_get(s, len, d) != 0) return len + 1;
613 if (eina_convert_atod(s, len, &mantisse, &exponent) == EINA_FALSE) return -1;
614 *d = ldexp((double) mantisse, exponent);
619 if (eet_data_get_int(ed, src, src_end, &index) < 0) return -1;
621 if (!eet_dictionary_string_get_double(ed, index, d))
627 eet_data_put_double(Eet_Dictionary *ed, const void *src, int *size_ret)
632 eina_convert_dtoa((double)(*(double *)src), buf);
642 memcpy(d, buf, len + 1);
648 index = eet_dictionary_string_add(ed, buf);
649 if (index == -1) return NULL;
651 return eet_data_put_int(ed, &index, size_ret);
655 eet_data_get_type(const Eet_Dictionary *ed, int type, const void *src, const void *src_end, void *dest)
659 ret = eet_basic_codec[type - 1].get(ed, src, src_end, dest);
664 eet_data_put_type(Eet_Dictionary *ed, int type, const void *src, int *size_ret)
668 ret = eet_basic_codec[type - 1].put(ed, src, size_ret);
674 * char[4] = "CHnK"; // untyped data ... or
675 * char[4] = "CHKx"; // typed data - x == type
677 * int = chunk size (including magic string);
678 * char[] = chunk magic/name string (0 byte terminated);
679 * ... sub-chunks (a chunk can contain chuncks recusrively) ...
681 * ... payload data ...
686 eet_data_chunk_get(const Eet_Dictionary *ed, Eet_Data_Chunk *chnk,
687 const void *src, int size)
693 if (size <= 8) return;
700 if ((s[0] != 'C') || (s[1] != 'H') || (s[2] != 'K'))
704 chnk->type = (unsigned char)(s[3]);
705 if (chnk->type > EET_T_LAST)
707 chnk->group_type = chnk->type;
708 chnk->type = EET_T_UNKNOW;
711 chnk->group_type = EET_G_UNKNOWN;
712 if ((chnk->type >= EET_T_LAST) ||
713 (chnk->group_type >= EET_G_LAST))
716 chnk->group_type = 0;
721 if ((s[0] != 'C') || (s[1] != 'H') || (s[2] != 'n') || (s[3] != 'K'))
726 ret1 = eet_data_get_type(ed, EET_T_INT, (s + 4), (s + size), &(chnk->size));
731 if ((chnk->size < 0) || ((chnk->size + 8) > size))
735 ret2 = eet_data_get_type(ed, EET_T_STRING, (s + 8), (s + size), &(chnk->name));
744 chnk->hash = eet_data_get_string_hash(ed, (s + 8), (s + size));
748 chnk->data = (char *)src + 4 + ret1 + sizeof(int);
749 chnk->size -= sizeof(int);
753 chnk->data = (char *)src + 4 + ret1 + chnk->len;
754 chnk->size -= chnk->len;
760 static inline Eet_Data_Chunk *
761 eet_data_chunk_new(void *data, int size, const char *name, int type, int group_type)
763 Eet_Data_Chunk *chnk;
765 if (!name) return NULL;
766 chnk = calloc(1, sizeof(Eet_Data_Chunk));
767 if (!chnk) return NULL;
769 chnk->name = strdup(name);
770 chnk->len = strlen(name) + 1;
774 chnk->group_type = group_type;
779 eet_data_chunk_free(Eet_Data_Chunk *chnk)
781 if (chnk->name) free(chnk->name);
785 static inline Eet_Data_Stream *
786 eet_data_stream_new(void)
790 ds = calloc(1, sizeof(Eet_Data_Stream));
791 if (!ds) return NULL;
796 eet_data_stream_free(Eet_Data_Stream *ds)
798 if (ds->data) free(ds->data);
803 eet_data_stream_write(Eet_Data_Stream *ds, const void *data, int size)
807 if ((ds->pos + size) > ds->size)
809 ds->data = realloc(ds->data, ds->size + size + 512);
816 ds->size = ds->size + size + 512;
819 memcpy(p + ds->pos, data, size);
824 eet_data_chunk_put(Eet_Dictionary *ed, Eet_Data_Chunk *chnk, Eet_Data_Stream *ds)
831 unsigned char buf[4] = "CHK";
833 if (!chnk->data) return;
836 /* eet_data_stream_write(ds, "CHnK", 4);*/
837 if (chnk->type != EET_T_UNKNOW) buf[3] = chnk->type;
838 else buf[3] = chnk->group_type;
840 string = eet_data_put_string(ed, &chnk->name, &string_ret);
844 /* size of chunk payload data + name */
845 s = chnk->size + string_ret;
846 size = eet_data_put_int(ed, &s, &size_ret);
848 /* FIXME: If something goes wrong the resulting file will be corrupted. */
852 eet_data_stream_write(ds, buf, 4);
854 /* write chunk length */
855 eet_data_stream_write(ds, size, size_ret);
857 /* write chunk name */
858 eet_data_stream_write(ds, string, string_ret);
861 eet_data_stream_write(ds, chnk->data, chnk->size);
871 _eet_descriptor_hash_new(Eet_Data_Descriptor *edd)
875 edd->elements.hash.size = 1 << 6;
876 edd->elements.hash.buckets = calloc(1, sizeof(Eet_Data_Descriptor_Hash) * edd->elements.hash.size);
877 for (i = 0; i < edd->elements.num; i++)
879 Eet_Data_Element *ede;
882 ede = &(edd->elements.set[i]);
883 hash = _eet_hash_gen((char *) ede->name, 6);
884 if (!edd->elements.hash.buckets[hash].element)
885 edd->elements.hash.buckets[hash].element = ede;
888 Eet_Data_Descriptor_Hash *bucket;
890 bucket = calloc(1, sizeof(Eet_Data_Descriptor_Hash));
891 bucket->element = ede;
892 bucket->next = edd->elements.hash.buckets[hash].next;
893 edd->elements.hash.buckets[hash].next = bucket;
899 _eet_descriptor_hash_free(Eet_Data_Descriptor *edd)
903 for (i = 0; i < edd->elements.hash.size; i++)
905 Eet_Data_Descriptor_Hash *bucket, *pbucket;
907 bucket = edd->elements.hash.buckets[i].next;
911 bucket = bucket->next;
915 if (edd->elements.hash.buckets) free(edd->elements.hash.buckets);
918 static Eet_Data_Element *
919 _eet_descriptor_hash_find(Eet_Data_Descriptor *edd, char *name, int hash)
921 Eet_Data_Descriptor_Hash *bucket;
923 if (hash < 0) hash = _eet_hash_gen(name, 6);
925 if (!edd->elements.hash.buckets[hash].element) return NULL;
927 When we use the dictionnary as a source for chunk name, we will always
928 have the same pointer in name. It's a good idea to just compare pointer
929 instead of running strcmp on both string.
931 if (edd->elements.hash.buckets[hash].element->directory_name_ptr == name)
932 return edd->elements.hash.buckets[hash].element;
933 if (!strcmp(edd->elements.hash.buckets[hash].element->name, name))
935 edd->elements.hash.buckets[hash].element->directory_name_ptr = name;
936 return edd->elements.hash.buckets[hash].element;
938 bucket = edd->elements.hash.buckets[hash].next;
941 if (bucket->element->directory_name_ptr == name) return bucket->element;
942 if (!strcmp(bucket->element->name, name))
944 bucket->element->directory_name_ptr = name;
945 return bucket->element;
947 bucket = bucket->next;
953 _eet_mem_alloc(size_t size)
955 return calloc(1, size);
959 _eet_mem_free(void *mem)
965 _eet_str_alloc(const char *str)
971 _eet_str_free(const char *str)
978 EAPI Eet_Data_Descriptor *
979 eet_data_descriptor_new(const char *name,
981 void *(*func_list_next) (void *l),
982 void *(*func_list_append) (void *l, void *d),
983 void *(*func_list_data) (void *l),
984 void *(*func_list_free) (void *l),
985 void (*func_hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt),
986 void *(*func_hash_add) (void *h, const char *k, void *d),
987 void (*func_hash_free) (void *h))
989 Eet_Data_Descriptor *edd;
991 if (!name) return NULL;
992 edd = calloc(1, sizeof(Eet_Data_Descriptor));
993 if (!edd) return NULL;
998 edd->func.mem_alloc = _eet_mem_alloc;
999 edd->func.mem_free = _eet_mem_free;
1000 edd->func.str_alloc = _eet_str_alloc;
1001 edd->func.str_direct_alloc = NULL;
1002 edd->func.str_direct_free = NULL;
1003 edd->func.str_free = _eet_str_free;
1004 edd->func.list_next = func_list_next;
1005 edd->func.list_append = func_list_append;
1006 edd->func.list_data = func_list_data;
1007 edd->func.list_free = func_list_free;
1008 edd->func.hash_foreach = func_hash_foreach;
1009 edd->func.hash_add = func_hash_add;
1010 edd->func.hash_free = func_hash_free;
1014 /* new replcement */
1015 EAPI Eet_Data_Descriptor *
1016 eet_data_descriptor2_new(Eet_Data_Descriptor_Class *eddc)
1018 Eet_Data_Descriptor *edd;
1020 if (!eddc) return NULL;
1021 if (eddc->version < 1) return NULL;
1022 edd = calloc(1, sizeof(Eet_Data_Descriptor));
1023 if (!edd) return NULL;
1025 edd->name = eddc->name;
1027 edd->size = eddc->size;
1028 edd->func.mem_alloc = _eet_mem_alloc;
1029 edd->func.mem_free = _eet_mem_free;
1030 edd->func.str_alloc = _eet_str_alloc;
1031 edd->func.str_free = _eet_str_free;
1032 if (eddc->func.mem_alloc)
1033 edd->func.mem_alloc = eddc->func.mem_alloc;
1034 if (eddc->func.mem_free)
1035 edd->func.mem_free = eddc->func.mem_free;
1036 if (eddc->func.str_alloc)
1037 edd->func.str_alloc = eddc->func.str_alloc;
1038 if (eddc->func.str_free)
1039 edd->func.str_free = eddc->func.str_free;
1040 edd->func.list_next = eddc->func.list_next;
1041 edd->func.list_append = eddc->func.list_append;
1042 edd->func.list_data = eddc->func.list_data;
1043 edd->func.list_free = eddc->func.list_free;
1044 edd->func.hash_foreach = eddc->func.hash_foreach;
1045 edd->func.hash_add = eddc->func.hash_add;
1046 edd->func.hash_free = eddc->func.hash_free;
1051 EAPI Eet_Data_Descriptor *
1052 eet_data_descriptor3_new(Eet_Data_Descriptor_Class *eddc)
1054 Eet_Data_Descriptor *edd;
1056 if (!eddc) return NULL;
1057 if (eddc->version < 2) return NULL;
1058 edd = calloc(1, sizeof(Eet_Data_Descriptor));
1059 if (!edd) return NULL;
1061 edd->name = eddc->name;
1063 edd->size = eddc->size;
1064 edd->func.mem_alloc = _eet_mem_alloc;
1065 edd->func.mem_free = _eet_mem_free;
1066 edd->func.str_alloc = _eet_str_alloc;
1067 edd->func.str_free = _eet_str_free;
1068 if (eddc->func.mem_alloc)
1069 edd->func.mem_alloc = eddc->func.mem_alloc;
1070 if (eddc->func.mem_free)
1071 edd->func.mem_free = eddc->func.mem_free;
1072 if (eddc->func.str_alloc)
1073 edd->func.str_alloc = eddc->func.str_alloc;
1074 if (eddc->func.str_free)
1075 edd->func.str_free = eddc->func.str_free;
1076 edd->func.list_next = eddc->func.list_next;
1077 edd->func.list_append = eddc->func.list_append;
1078 edd->func.list_data = eddc->func.list_data;
1079 edd->func.list_free = eddc->func.list_free;
1080 edd->func.hash_foreach = eddc->func.hash_foreach;
1081 edd->func.hash_add = eddc->func.hash_add;
1082 edd->func.hash_free = eddc->func.hash_free;
1083 edd->func.str_direct_alloc = eddc->func.str_direct_alloc;
1084 edd->func.str_direct_free = eddc->func.str_direct_free;
1090 eet_data_descriptor_free(Eet_Data_Descriptor *edd)
1092 _eet_descriptor_hash_free(edd);
1093 if (edd->elements.set) free(edd->elements.set);
1098 eet_data_descriptor_element_add(Eet_Data_Descriptor *edd,
1104 /* int counter_offset, */
1105 const char *counter_name /* Useless should go on a major release */,
1106 Eet_Data_Descriptor *subtype)
1108 Eet_Data_Element *ede;
1109 /* int l1, l2, p1, p2, i;
1112 /* FIXME: Fail safely when realloc fail. */
1113 edd->elements.num++;
1114 edd->elements.set = realloc(edd->elements.set, edd->elements.num * sizeof(Eet_Data_Element));
1115 if (!edd->elements.set) return;
1116 ede = &(edd->elements.set[edd->elements.num - 1]);
1118 ede->directory_name_ptr = NULL;
1121 * We do a special case when we do list,hash or whatever group of simple type.
1122 * Instead of handling it in encode/decode/dump/undump, we create an
1123 * implicit structure with only the simple type.
1125 if (group_type > EET_G_UNKNOWN
1126 && group_type < EET_G_LAST
1127 && type > EET_T_UNKNOW && type < EET_T_STRING
1130 subtype = calloc(1, sizeof (Eet_Data_Descriptor));
1131 if (!subtype) return ;
1132 subtype->name = "implicit";
1133 subtype->size = eet_basic_codec[type - 1].size;
1134 memcpy(&subtype->func, &edd->func, sizeof(subtype->func));
1136 eet_data_descriptor_element_add(subtype, eet_basic_codec[type - 1].name, type,
1137 EET_G_UNKNOWN, 0, 0, /* 0, */NULL, NULL);
1138 type = EET_T_UNKNOW;
1142 ede->group_type = group_type;
1143 ede->offset = offset;
1145 /* FIXME: For the time being, EET_G_VAR_ARRAY will put the counter_offset in count. */
1146 ede->counter_offset = count;
1147 /* ede->counter_offset = counter_offset; */
1148 ede->counter_name = counter_name;
1150 ede->subtype = subtype;
1154 eet_data_read(Eet_File *ef, Eet_Data_Descriptor *edd, const char *name)
1156 const Eet_Dictionary *ed = NULL;
1160 int required_free = 0;
1162 ed = eet_dictionary_get(ef);
1164 data = eet_read_direct(ef, name, &size);
1168 data = eet_read(ef, name, &size);
1169 if (!data) return NULL;
1172 data_dec = _eet_data_descriptor_decode(ed, edd, data, size, 0, NULL, NULL);
1180 eet_data_write(Eet_File *ef, Eet_Data_Descriptor *edd, const char *name, const void *data, int compress)
1187 ed = eet_dictionary_get(ef);
1189 data_enc = _eet_data_descriptor_encode(ed, edd, data, &size);
1190 if (!data_enc) return 0;
1191 val = eet_write(ef, name, data_enc, size, compress);
1196 typedef struct _Eet_Free Eet_Free;
1206 _eet_free_hash(void *data)
1208 unsigned long ptr = (unsigned long)(data);
1227 _eet_free_add(Eet_Free *ef, void *data)
1232 hash = _eet_free_hash(data);
1234 for (i = 0; i < ef->num[hash]; ++i)
1235 if (ef->list[hash][i] == data) return;
1238 if (ef->num[hash] > ef->len[hash])
1242 tmp = realloc(ef->list[hash], (ef->len[hash] + 16) * sizeof(void*));
1245 ef->len[hash] += 16;
1246 ef->list[hash] = tmp;
1248 ef->list[hash][ef->num[hash] - 1] = data;
1251 _eet_free_reset(Eet_Free *ef)
1255 if (ef->ref > 0) return ;
1256 for (i = 0; i < 256; ++i)
1260 if (ef->list[i]) free(ef->list[i]);
1265 _eet_free_ref(Eet_Free *ef)
1270 _eet_free_unref(Eet_Free *ef)
1275 static Eet_Free freelist = { 0, { 0 }, { 0 }, { NULL } };
1277 #define _eet_freelist_add(Data) _eet_free_add(&freelist, Data);
1278 #define _eet_freelist_reset() _eet_free_reset(&freelist);
1279 #define _eet_freelist_ref() _eet_free_ref(&freelist);
1280 #define _eet_freelist_unref() _eet_free_unref(&freelist);
1283 _eet_freelist_free(Eet_Data_Descriptor *edd)
1288 if (freelist.ref > 0) return;
1289 for (j = 0; j < 256; ++j)
1290 for (i = 0; i < freelist.num[j]; ++i)
1293 edd->func.mem_free(freelist.list[j][i]);
1295 free(freelist.list[j][i]);
1297 _eet_free_reset(&freelist);
1300 static Eet_Free freelist_list = { 0, { 0 }, { 0 }, { NULL } };
1302 #define _eet_freelist_list_add(Data) _eet_free_add(&freelist_list, Data);
1303 #define _eet_freelist_list_reset() _eet_free_reset(&freelist_list);
1304 #define _eet_freelist_list_ref() _eet_free_ref(&freelist_list);
1305 #define _eet_freelist_list_unref() _eet_free_unref(&freelist_list);
1308 _eet_freelist_list_free(Eet_Data_Descriptor *edd)
1313 if (freelist_list.ref > 0) return;
1314 for (j = 0; j < 256; ++j)
1315 for (i = 0; i < freelist_list.num[j]; ++i)
1318 edd->func.list_free(*((void**)(freelist_list.list[j][i])));
1320 _eet_free_reset(&freelist_list);
1323 static Eet_Free freelist_str = { 0, { 0 }, { 0 }, { NULL } };
1325 #define _eet_freelist_str_add(Data) _eet_free_add(&freelist_str, Data);
1326 #define _eet_freelist_str_reset() _eet_free_reset(&freelist_str);
1327 #define _eet_freelist_str_ref() _eet_free_ref(&freelist_str);
1328 #define _eet_freelist_str_unref() _eet_free_unref(&freelist_str);
1331 _eet_freelist_str_free(Eet_Data_Descriptor *edd)
1336 if (freelist_str.ref > 0) return;
1337 for (j = 0; j < 256; ++j)
1338 for (i = 0; i < freelist_str.num[j]; ++i)
1341 edd->func.str_free(freelist_str.list[j][i]);
1343 free(freelist_str.list[j][i]);
1345 _eet_free_reset(&freelist_str);
1348 static Eet_Free freelist_direct_str = { 0, { 0 }, { 0 }, { NULL } };
1350 #define _eet_freelist_direct_str_add(Data) _eet_free_add(&freelist_direct_str, Data);
1351 #define _eet_freelist_direct_str_reset() _eet_free_reset(&freelist_direct_str);
1352 #define _eet_freelist_direct_str_ref() _eet_free_ref(&freelist_direct_str);
1353 #define _eet_freelist_direct_str_unref() _eet_free_unref(&freelist_direct_str);
1356 _eet_freelist_direct_str_free(Eet_Data_Descriptor *edd)
1361 if (freelist_str.ref > 0) return;
1362 for (j = 0; j < 256; ++j)
1363 for (i = 0; i < freelist_str.num[j]; ++i)
1366 edd->func.str_direct_free(freelist_str.list[j][i]);
1368 free(freelist_str.list[j][i]);
1370 _eet_free_reset(&freelist_str);
1374 eet_data_descriptor_encode_hash_cb(void *hash __UNUSED__, const char *key, void *hdata, void *fdata)
1377 Eet_Data_Encode_Hash_Info *edehi;
1378 Eet_Data_Stream *ds;
1379 Eet_Data_Element *ede;
1380 Eet_Data_Chunk *echnk;
1390 data = eet_data_put_type(ed,
1396 echnk = eet_data_chunk_new(data, size, ede->name, ede->type, ede->group_type);
1397 eet_data_chunk_put(ed, echnk, ds);
1398 eet_data_chunk_free(echnk);
1403 EET_ASSERT(!((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING)), return );
1406 if (ede->type >= EET_T_STRING)
1407 eet_data_put_unknown(ed, NULL, ede, ds, &hdata);
1411 data = _eet_data_descriptor_encode(ed,
1417 echnk = eet_data_chunk_new(data, size, ede->name, ede->type, ede->group_type);
1418 eet_data_chunk_put(ed, echnk, ds);
1419 eet_data_chunk_free(echnk);
1429 _eet_data_string_escape(const char *str)
1435 for (strp = str; *strp; strp++)
1437 if (*strp == '\"') sz += 2;
1438 else if (*strp == '\\') sz += 2;
1442 if (!s) return NULL;
1443 for (strp = str, sp = s; *strp; strp++, sp++)
1450 else if (*strp == '\\')
1462 _eet_data_dump_string_escape(void *dumpdata, void dumpfunc(void *data, const char *str), const char *str)
1466 s = _eet_data_string_escape(str);
1469 dumpfunc(dumpdata, s);
1475 _eet_data_dump_token_get(const char *src, int *len)
1481 int tlen = 0, tsize = 0;
1483 #define TOK_ADD(x) \
1486 if (tlen >= tsize) \
1489 tok = realloc(tok, tsize); \
1491 tok[tlen - 1] = x; \
1494 for (p = src; *len > 0; p++, (*len)--)
1500 if ((p[0] == '\"') && (p > src) && (p[-1] != '\\'))
1504 else if ((p[0] == '\\') && (*len > 1) && (p[1] == '\"'))
1508 else if ((p[0] == '\\') && (p > src) && (p[-1] == '\\'))
1517 if (p[0] == '\"') in_quote = 1;
1520 if ((isspace(p[0])) || (p[0] == ';')) /* token ends here */
1533 if (!((isspace(p[0])) || (p[0] == ';')))
1550 typedef struct _Node Node;
1572 unsigned long long ul;
1578 _eet_data_dump_free(Node *node)
1586 case EET_G_VAR_ARRAY:
1589 if (node->key) free(node->key);
1590 for (n = node->values; n;)
1594 _eet_data_dump_free(n2);
1600 case EET_T_LONG_LONG:
1606 case EET_T_ULONG_LONG:
1608 case EET_T_INLINED_STRING:
1610 if (node->data.str) free(node->data.str);
1619 _eet_data_dump_encode(Eet_Dictionary *ed,
1623 Eet_Data_Chunk *chnk = NULL, *echnk = NULL;
1624 Eet_Data_Stream *ds;
1629 if (words_bigendian == -1)
1631 unsigned long int v;
1633 v = htonl(0x12345678);
1634 if (v == 0x12345678) words_bigendian = 1;
1635 else words_bigendian = 0;
1638 ds = eet_data_stream_new();
1639 if (!ds) return NULL;
1644 for (n = node->values; n; n = n->next)
1646 data = _eet_data_dump_encode(ed, n, &size);
1649 eet_data_stream_write(ds, data, size);
1655 case EET_G_VAR_ARRAY:
1656 data = eet_data_put_type(ed,
1662 echnk = eet_data_chunk_new(data, size, node->name, node->type, node->type);
1663 eet_data_chunk_put(ed, echnk, ds);
1664 eet_data_chunk_free(echnk);
1667 for (n = node->values; n; n = n->next)
1669 data = _eet_data_dump_encode(ed, n, &size);
1672 echnk = eet_data_chunk_new(data, size, node->name, node->type, node->type);
1673 eet_data_chunk_put(ed, echnk, ds);
1674 eet_data_chunk_free(echnk);
1679 /* Array is somekind of special case, so we should embed it inside another chunk. */
1680 *size_ret = ds->pos;
1685 eet_data_stream_free(ds);
1689 for (n = node->values; n; n = n->next)
1691 data = _eet_data_dump_encode(ed, n, &size);
1694 eet_data_stream_write(ds, data, size);
1702 data = eet_data_put_type(ed,
1708 echnk = eet_data_chunk_new(data, size, node->name, node->type, node->type);
1709 eet_data_chunk_put(ed, echnk, ds);
1710 eet_data_chunk_free(echnk);
1714 for (n = node->values; n; n = n->next)
1716 data = _eet_data_dump_encode(ed, n, &size);
1719 echnk = eet_data_chunk_new(data, size, node->name, node->type, node->type);
1720 eet_data_chunk_put(ed, echnk, ds);
1721 eet_data_chunk_free(echnk);
1726 /* Hash is somekind of special case, so we should embed it inside another chunk. */
1727 *size_ret = ds->pos;
1732 eet_data_stream_free(ds);
1736 data = eet_data_put_type(ed, node->type, &(node->data.c), &size);
1739 eet_data_stream_write(ds, data, size);
1744 data = eet_data_put_type(ed, node->type, &(node->data.s), &size);
1747 eet_data_stream_write(ds, data, size);
1752 data = eet_data_put_type(ed, node->type, &(node->data.i), &size);
1755 eet_data_stream_write(ds, data, size);
1759 case EET_T_LONG_LONG:
1760 data = eet_data_put_type(ed, node->type, &(node->data.l), &size);
1763 eet_data_stream_write(ds, data, size);
1768 data = eet_data_put_type(ed, node->type, &(node->data.f), &size);
1771 eet_data_stream_write(ds, data, size);
1776 data = eet_data_put_type(ed, node->type, &(node->data.d), &size);
1779 eet_data_stream_write(ds, data, size);
1784 data = eet_data_put_type(ed, node->type, &(node->data.uc), &size);
1787 eet_data_stream_write(ds, data, size);
1792 data = eet_data_put_type(ed, node->type, &(node->data.us), &size);
1795 eet_data_stream_write(ds, data, size);
1800 data = eet_data_put_type(ed, node->type, &(node->data.ui), &size);
1803 eet_data_stream_write(ds, data, size);
1807 case EET_T_ULONG_LONG:
1808 data = eet_data_put_type(ed, node->type, &(node->data.ul), &size);
1811 eet_data_stream_write(ds, data, size);
1815 case EET_T_INLINED_STRING:
1816 data = eet_data_put_type(ed, node->type, &(node->data.str), &size);
1819 eet_data_stream_write(ds, data, size);
1824 data = eet_data_put_type(ed, node->type, &(node->data.str), &size);
1827 eet_data_stream_write(ds, data, size);
1835 if ((node->type >= EET_G_UNKNOWN) && (node->type < EET_G_LAST))
1836 chnk = eet_data_chunk_new(ds->data, ds->pos, node->name, EET_T_UNKNOW, node->type);
1838 chnk = eet_data_chunk_new(ds->data, ds->pos, node->name, node->type, EET_G_UNKNOWN);
1841 eet_data_stream_free(ds);
1843 ds = eet_data_stream_new();
1844 eet_data_chunk_put(ed, chnk, ds);
1850 eet_data_stream_free(ds);
1854 eet_data_chunk_free(chnk);
1860 _eet_data_dump_parse(Eet_Dictionary *ed,
1871 Node *node_base = NULL;
1875 /* FIXME; handle parse errors */
1876 #define TOK_GET(t) \
1877 jump = left; t = _eet_data_dump_token_get(p, &left); p += jump - left;
1879 for (p = src; p < (src + size);)
1881 char *tok1, *tok2, *tok3, *tok4;
1886 if (!strcmp(tok1, "group"))
1897 if (!strcmp(tok4, "{"))
1899 /* we have 'group NAM TYP {' */
1900 n = calloc(1, sizeof(Node));
1919 for (nn = node->values; nn; nn = nn->next)
1930 n->name = strdup(tok2);
1931 if (!strcmp(tok3, "struct")) n->type = EET_G_UNKNOWN;
1932 else if (!strcmp(tok3, "array")) n->type = EET_G_ARRAY;
1933 else if (!strcmp(tok3, "var_array")) n->type = EET_G_VAR_ARRAY;
1934 else if (!strcmp(tok3, "list")) n->type = EET_G_LIST;
1935 else if (!strcmp(tok3, "hash")) n->type = EET_G_HASH;
1938 printf("ERROR: group type '%s' invalid.\n", tok3);
1950 else if (!strcmp(tok1, "value"))
1961 /* we have 'value NAME TYP XXX' */
1964 n = calloc(1, sizeof(Node));
1973 for (nn = node->values; nn; nn = nn->next)
1983 n->name = strdup(tok2);
1984 if (!strcmp(tok3, "char:"))
1986 n->type = EET_T_CHAR;
1987 sscanf(tok4, "%hhi", &(n->data.c));
1989 else if (!strcmp(tok3, "short:"))
1991 n->type = EET_T_SHORT;
1992 sscanf(tok4, "%hi", &(n->data.s));
1994 else if (!strcmp(tok3, "int:"))
1996 n->type = EET_T_INT;
1997 sscanf(tok4, "%i", &(n->data.i));
1999 else if (!strcmp(tok3, "long_long:"))
2001 n->type = EET_T_LONG_LONG;
2002 sscanf(tok4, "%lli", &(n->data.l));
2004 else if (!strcmp(tok3, "float:"))
2006 n->type = EET_T_FLOAT;
2007 sscanf(tok4, "%f", &(n->data.f));
2009 else if (!strcmp(tok3, "double:"))
2011 n->type = EET_T_DOUBLE;
2012 sscanf(tok4, "%lf", &(n->data.d));
2014 else if (!strcmp(tok3, "uchar:"))
2016 n->type = EET_T_UCHAR;
2017 sscanf(tok4, "%hhu", &(n->data.uc));
2019 else if (!strcmp(tok3, "ushort:"))
2021 n->type = EET_T_USHORT;
2022 sscanf(tok4, "%hu", &(n->data.us));
2024 else if (!strcmp(tok3, "uint:"))
2026 n->type = EET_T_UINT;
2027 sscanf(tok4, "%u", &(n->data.ui));
2029 else if (!strcmp(tok3, "ulong_long:"))
2031 n->type = EET_T_ULONG_LONG;
2032 sscanf(tok4, "%llu", &(n->data.ul));
2034 else if (!strcmp(tok3, "string:"))
2036 n->type = EET_T_STRING;
2037 n->data.str = strdup(tok4);
2039 else if (!strcmp(tok3, "inlined:"))
2041 n->type = EET_T_INLINED_STRING;
2042 n->data.str = strdup(tok4);
2046 printf("ERROR: value type '%s' invalid.\n", tok4);
2057 else if (!strcmp(tok1, "key"))
2062 /* we have 'key NAME' */
2065 node->key = strdup(tok2);
2070 else if (!strcmp(tok1, "count"))
2075 /* we have a 'count COUNT' */
2078 sscanf(tok2, "%i", &(node->count));
2083 else if (!strcmp(tok1, "}"))
2085 /* we have an end of the group */
2086 if (node) node = node->parent;
2094 cdata = _eet_data_dump_encode(ed, node_base, size_ret);
2095 _eet_data_dump_free(node_base);
2100 #define NEXT_CHUNK(P, Size, Echnk, Ed) \
2103 tmp = Ed ? (int) (sizeof(int) * 2) : Echnk.len + 4;\
2104 P += (4 + Echnk.size + tmp); \
2105 Size -= (4 + Echnk.size + tmp); \
2109 _eet_data_descriptor_decode(const Eet_Dictionary *ed,
2110 Eet_Data_Descriptor *edd,
2111 const void *data_in,
2114 void (*dumpfunc) (void *data, const char *str),
2118 char *p, *buf, tbuf[256];
2120 Eet_Data_Chunk chnk;
2122 if (words_bigendian == -1)
2124 unsigned long int v;
2126 v = htonl(0x12345678);
2127 if (v == 0x12345678) words_bigendian = 1;
2128 else words_bigendian = 0;
2133 data = edd->func.mem_alloc(edd->size);
2134 if (!data) return NULL;
2137 for (i = 0; i < edd->elements.num; i++)
2138 edd->elements.set[i].directory_name_ptr = NULL;
2142 _eet_freelist_ref();
2143 _eet_freelist_str_ref();
2144 _eet_freelist_list_ref();
2145 if (data) _eet_freelist_add(data);
2147 memset(&chnk, 0, sizeof(Eet_Data_Chunk));
2148 eet_data_chunk_get(ed, &chnk, data_in, size_in);
2149 if (!chnk.name) goto error;
2152 if (strcmp(chnk.name, edd->name)) goto error;
2156 size = size_in - (4 + sizeof(int) * 2);
2158 size = size_in - (4 + 4 + chnk.len);
2161 if (!edd->elements.hash.buckets) _eet_descriptor_hash_new(edd);
2166 if (chnk.type == EET_T_UNKNOW)
2170 for (i = 0; i < level; i++) dumpfunc(dumpdata, " ");
2171 dumpfunc(dumpdata, "group \"");
2172 _eet_data_dump_string_escape(dumpdata, dumpfunc, chnk.name);
2173 dumpfunc(dumpdata, "\" ");
2174 switch (chnk.group_type)
2177 dumpfunc(dumpdata, "struct");
2180 dumpfunc(dumpdata, "array");
2182 case EET_G_VAR_ARRAY:
2183 dumpfunc(dumpdata, "var_array");
2186 dumpfunc(dumpdata, "list");
2189 dumpfunc(dumpdata, "hash");
2192 dumpfunc(dumpdata, "???");
2195 dumpfunc(dumpdata, " {\n");
2200 Eet_Data_Chunk echnk;
2201 Eet_Data_Element *ede;
2203 /* get next data chunk */
2204 memset(&echnk, 0, sizeof(Eet_Data_Chunk));
2205 eet_data_chunk_get(ed, &echnk, p, size);
2206 if (!echnk.name) goto error;
2207 /* FIXME: don't REPLY on edd - work without */
2208 if ((edd) && (!dumpfunc))
2210 ede = _eet_descriptor_hash_find(edd, echnk.name, echnk.hash);
2213 int group_type = EET_G_UNKNOWN, type = EET_T_UNKNOW;
2216 group_type = ede->group_type;
2218 if ((echnk.type == 0) && (echnk.group_type == 0))
2221 group_type = ede->group_type;
2225 if (IS_SIMPLE_TYPE(echnk.type) &&
2226 (echnk.type == ede->type))
2228 else if ((echnk.group_type > EET_G_UNKNOWN) &&
2229 (echnk.group_type < EET_G_LAST) &&
2230 (echnk.group_type == ede->group_type))
2231 group_type = echnk.group_type;
2233 /* hashes doesnt fit well with the table */
2234 ret = eet_group_codec[group_type - 100].get(ed, edd, ede, &echnk, type, group_type, ((char *)data) + ede->offset, level, dumpfunc, dumpdata, &p, &size);
2235 if (ret <= 0) goto error;
2238 /*...... dump func */
2241 unsigned char dd[128];
2242 int group_type = EET_G_UNKNOWN, type = EET_T_UNKNOW;
2244 if ((echnk.type > EET_T_UNKNOW) &&
2245 (echnk.type < EET_T_LAST))
2247 else if ((echnk.group_type > EET_G_UNKNOWN) &&
2248 (echnk.group_type < EET_G_LAST))
2249 group_type = echnk.group_type;
2250 if (group_type == EET_G_UNKNOWN)
2255 if (IS_SIMPLE_TYPE(type))
2257 ret = eet_data_get_type(ed,
2260 ((char *)echnk.data) + echnk.size,
2262 for (i = 0; i < level; i++) dumpfunc(dumpdata, " ");
2263 dumpfunc(dumpdata, " value \"");
2264 _eet_data_dump_string_escape(dumpdata, dumpfunc, echnk.name);
2265 dumpfunc(dumpdata, "\" ");
2269 dumpfunc(dumpdata, "char: ");
2270 snprintf(tbuf, sizeof(tbuf), "%hhi", *((char *)dd));
2271 dumpfunc(dumpdata, tbuf); break;
2273 dumpfunc(dumpdata, "short: ");
2274 snprintf(tbuf, sizeof(tbuf), "%hi", *((short *)dd));
2275 dumpfunc(dumpdata, tbuf); break;
2277 dumpfunc(dumpdata, "int: ");
2278 snprintf(tbuf, sizeof(tbuf), "%i", *((int *)dd));
2279 dumpfunc(dumpdata, tbuf); break;
2280 case EET_T_LONG_LONG:
2281 dumpfunc(dumpdata, "long_long: ");
2282 snprintf(tbuf, sizeof(tbuf), "%lli", *((long long *)dd));
2283 dumpfunc(dumpdata, tbuf); break;
2285 dumpfunc(dumpdata, "float: ");
2286 snprintf(tbuf, sizeof(tbuf), "%1.25f", *((float *)dd));
2287 dumpfunc(dumpdata, tbuf); break;
2289 dumpfunc(dumpdata, "double: ");
2290 snprintf(tbuf, sizeof(tbuf), "%1.25f", *((double *)dd));
2291 dumpfunc(dumpdata, tbuf); break;
2293 dumpfunc(dumpdata, "uchar: ");
2294 snprintf(tbuf, sizeof(tbuf), "%hhu", *((unsigned char *)dd));
2295 dumpfunc(dumpdata, tbuf); break;
2297 dumpfunc(dumpdata, "ushort: ");
2298 snprintf(tbuf, sizeof(tbuf), "%i", *((unsigned short *)dd));
2299 dumpfunc(dumpdata, tbuf); break;
2301 dumpfunc(dumpdata, "uint: ");
2302 snprintf(tbuf, sizeof(tbuf), "%u", *((unsigned int *)dd));
2303 dumpfunc(dumpdata, tbuf); break;
2304 case EET_T_ULONG_LONG:
2305 dumpfunc(dumpdata, "ulong_long: ");
2306 snprintf(tbuf, sizeof(tbuf), "%llu", *((unsigned long long *)dd));
2307 dumpfunc(dumpdata, tbuf); break;
2308 case EET_T_INLINED_STRING:
2315 dumpfunc(dumpdata, "inlined: \"");
2316 _eet_data_dump_string_escape(dumpdata, dumpfunc, s);
2317 dumpfunc(dumpdata, "\"");
2328 dumpfunc(dumpdata, "string: \"");
2329 _eet_data_dump_string_escape(dumpdata, dumpfunc, s);
2330 dumpfunc(dumpdata, "\"");
2335 dumpfunc(dumpdata, "???: ???"); break;
2338 dumpfunc(dumpdata, ";\n");
2342 data_ret = _eet_data_descriptor_decode(ed,
2349 if (!data_ret) goto error;
2354 for (i = 0; i < level; i++) dumpfunc(dumpdata, " ");
2355 dumpfunc(dumpdata, " group \"");
2356 _eet_data_dump_string_escape(dumpdata, dumpfunc, echnk.name);
2357 dumpfunc(dumpdata, "\" ");
2358 switch (echnk.group_type)
2361 dumpfunc(dumpdata, "struct");break;
2363 dumpfunc(dumpdata, "array");break;
2364 case EET_G_VAR_ARRAY:
2365 dumpfunc(dumpdata, "var_array");break;
2367 dumpfunc(dumpdata, "list");break;
2369 dumpfunc(dumpdata, "hash");break;
2371 dumpfunc(dumpdata, "???");break;
2374 dumpfunc(dumpdata, " {\n");
2378 case EET_G_VAR_ARRAY:
2384 EET_ASSERT(!IS_SIMPLE_TYPE(type), goto error);
2386 ret = eet_data_get_type(ed,
2389 ((char *)echnk.data) + echnk.size,
2391 if (ret <= 0) goto error;
2393 for (i = 0; i < level; i++) dumpfunc(dumpdata, " ");
2394 dumpfunc(dumpdata, " count ");
2395 snprintf(tbuf, sizeof(tbuf), "%i", count);
2396 dumpfunc(dumpdata, tbuf);
2397 dumpfunc(dumpdata, ";\n");
2399 /* get all array elements */
2400 for (i = 0; i < count; i++)
2402 void *data_ret = NULL;
2404 /* Advance to next chunk */
2405 NEXT_CHUNK(p, size, echnk, ed);
2406 memset(&echnk, 0, sizeof(Eet_Data_Chunk));
2408 eet_data_chunk_get(ed, &echnk, p, size);
2409 if (!echnk.name) goto error;
2411 data_ret = _eet_data_descriptor_decode(ed,
2418 if (!data_ret) goto error;
2424 void *data_ret = NULL;
2426 EET_ASSERT(!IS_SIMPLE_TYPE(type), goto error);
2428 data_ret = _eet_data_descriptor_decode(ed,
2435 if (!data_ret) goto error;
2442 void *data_ret = NULL;
2445 ret = eet_data_get_type(ed,
2448 ((char *)echnk.data) + echnk.size,
2450 if (ret <= 0) goto error;
2452 /* Advance to next chunk */
2453 NEXT_CHUNK(p, size, echnk, ed);
2454 memset(&echnk, 0, sizeof(Eet_Data_Chunk));
2457 eet_data_chunk_get(ed, &echnk, p, size);
2458 if (!echnk.name) goto error;
2460 EET_ASSERT(!IS_SIMPLE_TYPE(type), goto error);
2468 for (i = 0; i < level; i++) dumpfunc(dumpdata, " ");
2469 dumpfunc(dumpdata, " key \"");
2470 _eet_data_dump_string_escape(dumpdata, dumpfunc, s);
2471 dumpfunc(dumpdata, "\";\n");
2473 data_ret = _eet_data_descriptor_decode(ed,
2492 for (i = 0; i < level; i++) dumpfunc(dumpdata, " ");
2493 dumpfunc(dumpdata, " }\n");
2497 /* advance to next chunk */
2498 NEXT_CHUNK(p, size, echnk, ed);
2501 _eet_freelist_unref();
2502 _eet_freelist_str_unref();
2503 _eet_freelist_list_unref();
2506 _eet_freelist_str_free(edd);
2507 _eet_freelist_direct_str_free(edd);
2508 _eet_freelist_list_free(edd);
2509 _eet_freelist_free(edd);
2513 _eet_freelist_reset();
2514 _eet_freelist_str_reset();
2515 _eet_freelist_list_reset();
2516 _eet_freelist_direct_str_reset();
2522 if (chnk.type == EET_T_UNKNOW)
2524 for (i = 0; i < level; i++) dumpfunc(dumpdata, " ");
2525 dumpfunc(dumpdata, "}\n");
2533 _eet_freelist_unref();
2534 _eet_freelist_str_unref();
2535 _eet_freelist_list_unref();
2536 _eet_freelist_str_free(edd);
2537 _eet_freelist_direct_str_free(edd);
2538 _eet_freelist_list_free(edd);
2539 _eet_freelist_free(edd);
2544 if (chnk.type == EET_T_UNKNOW)
2546 for (i = 0; i < level; i++) dumpfunc(dumpdata, " ");
2547 dumpfunc(dumpdata, "}\n");
2555 eet_data_get_list(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
2556 int type __UNUSED__, int group_type __UNUSED__, void *data,
2557 int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata,
2558 char **p __UNUSED__, int *size __UNUSED__)
2564 EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0);
2566 ptr = (void **)data;
2570 if (ede->type >= EET_T_STRING)
2574 ret = eet_data_get_unknown(ed, edd, ede, echnk, ede->type, EET_G_UNKNOWN,
2575 &data_ret, level, dumpfunc, dumpdata, p, size);
2580 data_ret = _eet_data_descriptor_decode(ed, ede->subtype, echnk->data, echnk->size, level + 2, dumpfunc, dumpdata);
2581 if (!data_ret) return 0;
2584 list = edd->func.list_append(list, data_ret);
2586 _eet_freelist_list_add(ptr);
2592 eet_data_get_hash(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
2593 int type, int group_type __UNUSED__, void *data,
2594 int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata,
2595 char **p, int *size)
2600 void *data_ret = NULL;
2603 EET_ASSERT(!((type > EET_T_UNKNOW) && (type < EET_T_STRING)), return 0);
2605 ptr = (void **)data;
2609 ret = eet_data_get_type(ed,
2612 ((char *)echnk->data) + echnk->size,
2614 if (ret <= 0) goto on_error;
2616 /* Advance to next chunk */
2617 NEXT_CHUNK((*p), (*size), (*echnk), ed);
2618 memset(echnk, 0, sizeof(Eet_Data_Chunk));
2621 eet_data_chunk_get(ed, echnk, *p, *size);
2622 if (!echnk->name) goto on_error;
2624 if (type >= EET_T_STRING)
2628 ret = eet_data_get_unknown(ed, edd, ede, echnk, ede->type, EET_G_UNKNOWN,
2629 &data_ret, level, dumpfunc, dumpdata, p, size);
2634 data_ret = _eet_data_descriptor_decode(ed,
2641 if (!data_ret) goto on_error;
2644 hash = edd->func.hash_add(hash, key, data_ret);
2646 _eet_freelist_list_add(ptr);
2653 /* var arrays and fixed arrays have to
2654 * get all chunks at once. for fixed arrays
2655 * we can get each chunk and increment a
2656 * counter stored on the element itself but
2657 * it wont be thread safe. for var arrays
2658 * we still need a way to get the number of
2659 * elements from the data, so storing the
2660 * number of elements and the element data on
2661 * each chunk is pointless.
2664 eet_data_get_array(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd __UNUSED__,
2665 Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
2666 int type, int group_type, void *data,
2667 int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata,
2668 char **p, int *size)
2675 EET_ASSERT(!IS_SIMPLE_TYPE(type), return 0);
2678 /* read the number of elements */
2679 ret = eet_data_get_type(ed,
2682 ((char *)echnk->data) + echnk->size,
2684 if (ret <= 0) return ret;
2685 if (group_type == EET_G_VAR_ARRAY)
2687 /* store the number of elements
2688 * on the counter offset */
2689 *(int *)(((char *)data) + ede->count - ede->offset) = count;
2690 /* allocate space for the array of elements */
2691 *(void **)ptr = calloc(count, ede->subtype->size);
2693 if (!*(void **)ptr) return 0;
2695 _eet_freelist_add(*(void **)ptr);
2698 /* get all array elements */
2699 for (i = 0; i < count; i++)
2702 void *data_ret = NULL;
2704 /* Advance to next chunk */
2705 NEXT_CHUNK((*p), (*size), (*echnk), ed);
2706 memset(echnk, 0, sizeof(Eet_Data_Chunk));
2708 eet_data_chunk_get(ed, echnk, *p, *size);
2709 if (!echnk->name) return 0;
2712 /* get the destination pointer */
2713 if (group_type == EET_G_ARRAY)
2714 dst = (char *)ptr + (ede->subtype->size * i);
2716 dst = *(char **)ptr + (ede->subtype->size * i);
2717 data_ret = _eet_data_descriptor_decode(ed,
2724 if (!data_ret) return 0;
2725 memcpy(dst, data_ret, ede->subtype->size);
2732 eet_data_get_unknown(const Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Chunk *echnk,
2733 int type, int group_type __UNUSED__, void *data,
2734 int level, void (*dumpfunc) (void *data, const char *str), void *dumpdata,
2735 char **p __UNUSED__, int *size __UNUSED__)
2740 if (IS_SIMPLE_TYPE(type))
2742 ret = eet_data_get_type(ed, type, echnk->data, ((char *)echnk->data) + echnk->size, ((char *)data));
2743 if (ret <= 0) return ret;
2745 if (type == EET_T_STRING)
2749 str = (char **)(((char *)data));
2752 if ((ed == NULL) || (edd->func.str_direct_alloc == NULL))
2754 *str = edd->func.str_alloc(*str);
2755 _eet_freelist_str_add(*str);
2759 *str = edd->func.str_direct_alloc(*str);
2760 _eet_freelist_direct_str_add(*str);
2764 else if (type == EET_T_INLINED_STRING)
2768 str = (char **)(((char *)data));
2771 *str = edd->func.str_alloc(*str);
2772 _eet_freelist_str_add(*str);
2776 else if (ede->subtype)
2780 data_ret = _eet_data_descriptor_decode(ed, ede->subtype, echnk->data, echnk->size, level + 1, dumpfunc, dumpdata);
2781 if (!data_ret) return 0;
2783 ptr = (void **)(((char *)data));
2784 *ptr = (void *)data_ret;
2791 eet_data_encode(Eet_Dictionary *ed, Eet_Data_Stream *ds, void *data, const char *name, int size, int type, int group_type)
2793 Eet_Data_Chunk *echnk;
2795 echnk = eet_data_chunk_new(data, size, name, type, group_type);
2796 eet_data_chunk_put(ed, echnk, ds);
2797 eet_data_chunk_free(echnk);
2802 eet_data_put_array(Eet_Dictionary *ed, Eet_Data_Descriptor *edd __UNUSED__, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in)
2810 EET_ASSERT(!IS_SIMPLE_TYPE(ede->type), return );
2812 if (ede->group_type == EET_G_ARRAY)
2813 count = ede->counter_offset;
2815 count = *(int *)(((char *)data_in) + ede->count - ede->offset);
2817 if (count <= 0) return;
2818 /* Store number of elements */
2819 data = eet_data_put_type(ed, EET_T_INT, &count, &size);
2820 if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
2822 for (j = 0; j < count; j++)
2826 if (ede->group_type == EET_G_ARRAY)
2827 d = (void *)(((char *)data_in) + offset);
2829 d = *(((char **)data_in)) + offset;
2831 data = _eet_data_descriptor_encode(ed, ede->subtype, d, &size);
2832 offset += ede->subtype->size;
2833 if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
2838 eet_data_put_unknown(Eet_Dictionary *ed, Eet_Data_Descriptor *edd __UNUSED__, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in)
2843 if (IS_SIMPLE_TYPE(ede->type))
2844 data = eet_data_put_type(ed, ede->type, data_in, &size);
2845 else if (ede->subtype)
2847 if (*((char **)data_in))
2848 data = _eet_data_descriptor_encode(ed,
2850 *((char **)((char *)(data_in))),
2853 if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
2857 eet_data_put_list(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in)
2863 EET_ASSERT(!((ede->type > EET_T_UNKNOW) && (ede->type < EET_T_STRING)), return );
2865 l = *((void **)(((char *)data_in)));
2866 for (; l; l = edd->func.list_next(l))
2868 if (ede->type >= EET_T_STRING)
2870 const char *str = edd->func.list_data(l);
2871 eet_data_put_unknown(ed, NULL, ede, ds, &str);
2875 data = _eet_data_descriptor_encode(ed,
2877 edd->func.list_data(l),
2879 if (data) eet_data_encode(ed, ds, data, ede->name, size, ede->type, ede->group_type);
2885 eet_data_put_hash(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, Eet_Data_Element *ede, Eet_Data_Stream *ds, void *data_in)
2887 Eet_Data_Encode_Hash_Info fdata;
2890 l = *((void **)(((char *)data_in)));
2894 edd->func.hash_foreach(l, eet_data_descriptor_encode_hash_cb, &fdata);
2898 eet_data_dump(Eet_File *ef,
2900 void (*dumpfunc) (void *data, const char *str),
2903 const Eet_Dictionary *ed = NULL;
2906 int required_free = 0;
2909 ed = eet_dictionary_get(ef);
2911 data = eet_read_direct(ef, name, &size);
2915 data = eet_read(ef, name, &size);
2916 if (!data) return 0;
2919 if (_eet_data_descriptor_decode(ed, NULL, data, size, 0,
2920 dumpfunc, dumpdata))
2931 eet_data_text_dump(const void *data_in,
2933 void (*dumpfunc) (void *data, const char *str),
2936 if (_eet_data_descriptor_decode(NULL, NULL, data_in, size_in, 0,
2937 dumpfunc, dumpdata))
2943 eet_data_text_undump(const char *text,
2947 return _eet_data_dump_parse(NULL, size_ret, text, textlen);
2951 eet_data_undump(Eet_File *ef,
2962 ed = eet_dictionary_get(ef);
2964 data_enc = _eet_data_dump_parse(ed, &size, text, textlen);
2965 if (!data_enc) return 0;
2966 val = eet_write(ef, name, data_enc, size, compress);
2972 eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
2973 const void *data_in,
2976 return _eet_data_descriptor_decode(NULL, edd, data_in, size_in, 0,
2981 _eet_data_descriptor_encode(Eet_Dictionary *ed,
2982 Eet_Data_Descriptor *edd,
2983 const void *data_in,
2986 Eet_Data_Stream *ds;
2987 Eet_Data_Chunk *chnk;
2992 if (words_bigendian == -1)
2994 unsigned long int v;
2996 v = htonl(0x12345678);
2997 if (v == 0x12345678) words_bigendian = 1;
2998 else words_bigendian = 0;
3001 ds = eet_data_stream_new();
3002 for (i = 0; i < edd->elements.num; i++)
3004 Eet_Data_Element *ede;
3006 ede = &(edd->elements.set[i]);
3007 eet_group_codec[ede->group_type - 100].put(ed, edd, ede, ds, ((char *)data_in) + ede->offset);
3009 chnk = eet_data_chunk_new(ds->data, ds->pos, edd->name, EET_T_UNKNOW, EET_G_UNKNOWN);
3012 eet_data_stream_free(ds);
3014 ds = eet_data_stream_new();
3015 eet_data_chunk_put(ed, chnk, ds);
3021 eet_data_stream_free(ds);
3025 eet_data_chunk_free(chnk);
3031 eet_data_descriptor_encode(Eet_Data_Descriptor *edd,
3032 const void *data_in,
3035 return _eet_data_descriptor_encode(NULL, edd, data_in, size_ret);