move eet to HEAD
[profile/ivi/eet.git] / src / lib / eet_data.c
1 #include "Eet.h"
2 #define _GNU_SOURCE /* need this for fmemopen & open_memstream */
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <limits.h>
6 #include <stdlib.h>
7 #include <time.h>
8 #include <sys/types.h>
9 #include <fcntl.h>
10 #include <netinet/in.h>
11 #include <zlib.h>
12 #include <string.h>
13 #include <fnmatch.h>
14 #include <jpeglib.h>
15 #include <setjmp.h>
16 #include <zlib.h>
17 #include <locale.h>
18
19
20 /*
21  * rotuines for doing data -> struct and struct -> data conversion
22  * 
23  * types:
24  * 
25  * basic types:
26  *   a sequence of...
27  * 
28  *   char
29  *   short
30  *   int
31  *   long long
32  *   float
33  *   double
34  *   unsigned char
35  *   unsigned short
36  *   unsigned int
37  *   unsgined long long
38  *   string
39  * 
40  * groupings:
41  *   multiple entries ordered as...
42  * 
43  *   fixed size array    [ of basic types ]
44  *   variable size array [ of basic types ]
45  *   linked list         [ of basic types ]
46  *   hash table          [ of basic types ]
47  * 
48  * need to provide builder/accessor funcs for:
49  * 
50  *   list_next
51  *   list_append
52  * 
53  *   hash_foreach
54  *   hash_add
55  * 
56  */
57
58 /*---*/
59
60 typedef struct _Eet_Data_Element            Eet_Data_Element;
61 typedef struct _Eet_Data_Basic_Type_Decoder Eet_Data_Basic_Type_Decoder;
62 typedef struct _Eet_Data_Chunk              Eet_Data_Chunk;
63 typedef struct _Eet_Data_Stream             Eet_Data_Stream;
64 typedef struct _JPEG_error_mgr             *emptr;
65
66 /*---*/
67
68 struct _Eet_Data_Basic_Type_Decoder
69 {
70    int     size;
71    int   (*get) (void *src, void *src_end, void *dest);
72    void *(*put) (void *src, int *size_ret);
73 };
74
75 struct _Eet_Data_Chunk
76 {
77    char *name;
78    int   size;
79    void *data;
80 };
81
82 struct _Eet_Data_Stream
83 {
84    void *data;
85    int   size;
86    int   pos;
87 };
88
89 struct _Eet_Data_Descriptor
90 {
91    char *name;
92    int   size;
93    struct {
94       void *(*list_next) (void *l);
95       void *(*list_append) (void *l, void *d);
96       void *(*list_data) (void *l);
97       void  (*hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt);
98       void *(*hash_add) (void *h, const char *k, void *d);
99    } func;
100    struct {
101       int               num;
102       Eet_Data_Element *set;
103    } elements;
104 };
105
106 struct _Eet_Data_Element
107 {
108    char                *name;
109    int                  type;
110    int                  group_type;
111    int                  offset;
112    int                  count;
113    char                *counter_name;
114    Eet_Data_Descriptor *subtype;
115 };
116
117 struct _JPEG_error_mgr
118 {
119    struct     jpeg_error_mgr pub;
120    jmp_buf    setjmp_buffer;
121 };
122
123 /*---*/
124
125 static void _JPEGFatalErrorHandler(j_common_ptr cinfo);
126 static void _JPEGErrorHandler(j_common_ptr cinfo);
127 static void _JPEGErrorHandler2(j_common_ptr cinfo, int msg_level);
128
129 static void *eet_data_image_jpeg_rgb_decode(void *data, int size, int *w, int *h);
130 static void *eet_data_image_jpeg_alpha_decode(void *data, int size, unsigned int *d, int *w, int *h);
131 static void *eet_data_image_lossless_convert(int *size, void *data, int w, int h, int alpha);
132 static void *eet_data_image_lossless_compressed_convert(int *size, void *data, int w, int h, int alpha, int compression);
133 static void *eet_data_image_jpeg_convert(int *size, void *data, int w, int h, int alpha, int quality);
134 static void *eet_data_image_jpeg_alpha_convert(int *size, void *data, int w, int h, int alpha, int quality);
135
136 static int   eet_data_get_char(void *src, void *src_end, void *dest);
137 static void *eet_data_put_char(void *src, int *size_ret);
138 static int   eet_data_get_short(void *src, void *src_end, void *dest);
139 static void *eet_data_put_short(void *src, int *size_ret);
140 static int   eet_data_get_int(void *src, void *src_end, void *dest);
141 static void *eet_data_put_int(void *src, int *size_ret);
142 static int   eet_data_get_long_long(void *src, void *src_end, void *dest);
143 static void *eet_data_put_long_long(void *src, int *size_ret);
144 static int   eet_data_get_float(void *src, void *src_end, void *dest);
145 static void *eet_data_put_float(void *src, int *size_ret);
146 static int   eet_data_get_double(void *src, void *src_end, void *dest);
147 static void *eet_data_put_double(void *src, int *size_ret);
148 static int   eet_data_get_string(void *src, void *src_end, void *dest);
149 static void *eet_data_put_string(void *src, int *size_ret);
150
151 static int   eet_data_get_type(int type, void *src, void *src_end, void *dest);
152 static void *eet_data_put_type(int type, void *src, int *size_ret);
153
154 static Eet_Data_Chunk *eet_data_chunk_get(void *src, int size);
155 static Eet_Data_Chunk *eet_data_chunk_new(void *data, int size, char *name);
156 static void            eet_data_chunk_free(Eet_Data_Chunk *chnk);
157
158 static Eet_Data_Stream *eet_data_stream_new(void);
159 static void             eet_data_stream_write(Eet_Data_Stream *ds, void *data, int size);
160 static void             eet_data_stream_free(Eet_Data_Stream *ds);
161
162 static void             eet_data_chunk_put(Eet_Data_Chunk *chnk, Eet_Data_Stream *ds);
163
164 /*---*/
165
166 const Eet_Data_Basic_Type_Decoder eet_coder[] = 
167 {
168      {sizeof(char),      eet_data_get_char,      eet_data_put_char     },
169      {sizeof(short),     eet_data_get_short,     eet_data_put_short    },
170      {sizeof(int),       eet_data_get_int,       eet_data_put_int      },
171      {sizeof(long long), eet_data_get_long_long, eet_data_put_long_long},
172      {sizeof(float),     eet_data_get_float,     eet_data_put_float    },
173      {sizeof(double),    eet_data_get_double,    eet_data_put_double   },
174      {sizeof(char),      eet_data_get_char,      eet_data_put_char     },
175      {sizeof(short),     eet_data_get_short,     eet_data_put_short    },
176      {sizeof(int),       eet_data_get_int,       eet_data_put_int      },
177      {sizeof(long long), eet_data_get_long_long, eet_data_put_long_long},
178      {sizeof(char *),    eet_data_get_string,    eet_data_put_string   }
179 };
180
181 static int words_bigendian = -1;
182
183 /*---*/
184
185 #define SWAP64(x) (x) = \
186    ((((x) & 0x00000000000000ff ) << 56) |\
187        (((x) & 0x000000000000ff00 ) << 40) |\
188        (((x) & 0x0000000000ff0000 ) << 24) |\
189        (((x) & 0x00000000ff000000 ) << 8) |\
190        (((x) & 0x000000ff00000000 ) >> 8) |\
191        (((x) & 0x0000ff0000000000 ) >> 24) |\
192        (((x) & 0x00ff000000000000 ) >> 40) |\
193        (((x) & 0xff00000000000000 ) >> 56))
194 #define SWAP32(x) (x) = \
195    ((((x) & 0x000000ff ) << 24) |\
196        (((x) & 0x0000ff00 ) << 8) |\
197        (((x) & 0x00ff0000 ) >> 8) |\
198        (((x) & 0xff000000 ) >> 24))
199 #define SWAP16(x) (x) = \
200    ((((x) & 0x00ff ) << 8) |\
201        (((x) & 0xff00 ) >> 8))
202
203 #define CONV8(x)
204 #define CONV16(x) {if (words_bigendian) SWAP16(x);}
205 #define CONV32(x) {if (words_bigendian) SWAP32(x);}
206 #define CONV64(x) {if (words_bigendian) SWAP64(x);}
207
208 /*---*/
209
210 static void
211 _JPEGFatalErrorHandler(j_common_ptr cinfo)
212 {
213    emptr errmgr;
214    
215    errmgr = (emptr) cinfo->err;
216    /*   cinfo->err->output_message(cinfo);*/
217    longjmp(errmgr->setjmp_buffer, 1);
218    return;
219 }
220    
221 static void
222 _JPEGErrorHandler(j_common_ptr cinfo)
223 {
224    emptr errmgr;
225    
226    errmgr = (emptr) cinfo->err;
227    /*   cinfo->err->output_message(cinfo);*/
228    /*   longjmp(errmgr->setjmp_buffer, 1);*/
229    return;
230 }
231      
232 static void
233 _JPEGErrorHandler2(j_common_ptr cinfo, int msg_level)
234 {
235    emptr errmgr;
236    
237    errmgr = (emptr) cinfo->err;
238    /*   cinfo->err->output_message(cinfo);*/
239    /*   longjmp(errmgr->setjmp_buffer, 1);*/
240    return;
241    msg_level = 0;
242 }
243
244 static void *
245 eet_data_image_jpeg_rgb_decode(void *data, int size, int *w, int *h)
246 {
247    unsigned int *d;
248    struct jpeg_decompress_struct cinfo;
249    struct _JPEG_error_mgr jerr;
250    unsigned char *ptr, *line[16], *tdata;
251    unsigned int *ptr2;
252    int x, y, l, i, scans, count, prevy;
253    FILE *f;
254    
255    f = fmemopen(data, (size_t)size, "r");   
256    if (!f) return NULL;
257    cinfo.err = jpeg_std_error(&(jerr.pub));
258    jerr.pub.error_exit = _JPEGFatalErrorHandler;
259    jerr.pub.emit_message = _JPEGErrorHandler2;
260    jerr.pub.output_message = _JPEGErrorHandler;
261    if (setjmp(jerr.setjmp_buffer))
262      {
263         jpeg_destroy_decompress(&cinfo);
264         fclose(f);
265         return NULL;
266      }
267    jpeg_create_decompress(&cinfo);
268    jpeg_stdio_src(&cinfo, f);
269    jpeg_read_header(&cinfo, TRUE);
270    cinfo.do_fancy_upsampling = FALSE;
271    cinfo.do_block_smoothing = FALSE;
272    jpeg_start_decompress(&cinfo);
273    
274    /* head decoding */
275    *w = cinfo.output_width;
276    *h = cinfo.output_height;
277    /* end head decoding */
278    /* data decoding */
279    if (cinfo.rec_outbuf_height > 16)
280      {
281         jpeg_destroy_decompress(&cinfo);
282         fclose(f);
283         return NULL;
284      }
285    tdata = malloc((*w) * 16 * 3);
286    if (!tdata)
287      {
288         jpeg_destroy_decompress(&cinfo);
289         fclose(f);
290         return NULL;
291      }
292    d = malloc((*w) * (*h) * 4);
293    if (!d)
294      {
295         free(tdata);
296         jpeg_destroy_decompress(&cinfo);
297         fclose(f);
298         return NULL;
299      }
300    ptr2 = d;
301    count = 0;
302    prevy = 0;
303    if (cinfo.output_components == 3)
304      {
305         for (i = 0; i < cinfo.rec_outbuf_height; i++)
306           line[i] = tdata + (i * (*w) * 3);
307         for (l = 0; l < (*h); l += cinfo.rec_outbuf_height)
308           {
309              jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
310                           scans = cinfo.rec_outbuf_height;
311              if (((*h) - l) < scans) scans = (*h) - l;
312              ptr = tdata;
313              for (y = 0; y < scans; y++)
314                {
315                   for (x = 0; x < (*w); x++)
316                     {
317                        *ptr2 =
318                          (0xff000000) | ((ptr[0]) << 16) | ((ptr[1]) << 8) | (ptr[2]);
319                        ptr += 3;
320                        ptr2++;
321                     }
322                }
323           }
324      }
325    else if (cinfo.output_components == 1)
326      {
327         for (i = 0; i < cinfo.rec_outbuf_height; i++)
328           line[i] = tdata + (i * (*w));
329         for (l = 0; l < (*h); l += cinfo.rec_outbuf_height)
330           {
331              jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
332              scans = cinfo.rec_outbuf_height;
333              if (((*h) - l) < scans) scans = (*h) - l;
334              ptr = tdata;
335              for (y = 0; y < scans; y++)
336                {
337                   for (x = 0; x < (*w); x++)
338                     {
339                        *ptr2 =
340                          (0xff000000) | ((ptr[0]) << 16) | ((ptr[0]) << 8) | (ptr[0]);
341                        ptr++;
342                        ptr2++;
343                     }
344                }
345           }
346      }
347    free(tdata);
348    fclose(f);
349    /* end data decoding */
350    jpeg_finish_decompress(&cinfo);
351    jpeg_destroy_decompress(&cinfo);
352    return d;
353 }
354
355 static void *
356 eet_data_image_jpeg_alpha_decode(void *data, int size, unsigned int *d, int *w, int *h)
357 {
358    struct jpeg_decompress_struct cinfo;
359    struct _JPEG_error_mgr jerr;
360    unsigned char *ptr, *line[16], *tdata;
361    unsigned int *ptr2;
362    int x, y, l, i, scans, count, prevy;
363    FILE *f;
364    
365    f = fmemopen(data, (size_t)size, "r");   
366    if (!f) return NULL;
367    cinfo.err = jpeg_std_error(&(jerr.pub));
368    jerr.pub.error_exit = _JPEGFatalErrorHandler;
369    jerr.pub.emit_message = _JPEGErrorHandler2;
370    jerr.pub.output_message = _JPEGErrorHandler;
371    if (setjmp(jerr.setjmp_buffer))
372      {
373         jpeg_destroy_decompress(&cinfo);
374         fclose(f);
375         return NULL;
376      }
377    jpeg_create_decompress(&cinfo);
378    jpeg_stdio_src(&cinfo, f);
379    jpeg_read_header(&cinfo, TRUE);
380    cinfo.do_fancy_upsampling = FALSE;
381    cinfo.do_block_smoothing = FALSE;
382    jpeg_start_decompress(&cinfo);
383    
384    /* head decoding */
385    if ((*w) != cinfo.output_width)
386      {
387         jpeg_destroy_decompress(&cinfo);
388         fclose(f);
389         return NULL;    
390      }
391    if ((*h) != cinfo.output_height)
392      {
393         jpeg_destroy_decompress(&cinfo);
394         fclose(f);
395         return NULL;    
396      }
397    *w = cinfo.output_width;
398    *h = cinfo.output_height;
399    /* end head decoding */
400    /* data decoding */
401    if (cinfo.rec_outbuf_height > 16)
402      {
403         jpeg_destroy_decompress(&cinfo);
404         fclose(f);
405         return NULL;
406      }
407    tdata = malloc((*w) * 16 * 3);
408    if (!tdata)
409      {
410         jpeg_destroy_decompress(&cinfo);
411         fclose(f);
412         return NULL;
413      }
414    ptr2 = d;
415    count = 0;
416    prevy = 0;
417    if (cinfo.output_components == 3)
418      {
419         for (i = 0; i < cinfo.rec_outbuf_height; i++)
420           line[i] = tdata + (i * (*w) * 3);
421         for (l = 0; l < (*h); l += cinfo.rec_outbuf_height)
422           {
423              jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
424                           scans = cinfo.rec_outbuf_height;
425              if (((*h) - l) < scans) scans = (*h) - l;
426              ptr = tdata;
427              for (y = 0; y < scans; y++)
428                {
429                   for (x = 0; x < (*w); x++)
430                     {
431                        *ptr2 =
432                          ((*ptr2) & 0x00ffffff) |
433                          (((ptr[0] + ptr[1] + ptr[2]) / 3) << 24);
434                        ptr += 3;
435                        ptr2++;
436                     }
437                }
438           }
439      }
440    else if (cinfo.output_components == 1)
441      {
442         for (i = 0; i < cinfo.rec_outbuf_height; i++)
443           line[i] = tdata + (i * (*w));
444         for (l = 0; l < (*h); l += cinfo.rec_outbuf_height)
445           {
446              jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
447              scans = cinfo.rec_outbuf_height;
448              if (((*h) - l) < scans) scans = (*h) - l;
449              ptr = tdata;
450              for (y = 0; y < scans; y++)
451                {
452                   for (x = 0; x < (*w); x++)
453                     {
454                        *ptr2 =
455                          ((*ptr2) & 0x00ffffff) |
456                          ((ptr[0]) << 24);
457                        ptr++;
458                        ptr2++;
459                     }
460                }
461           }
462      }
463    free(tdata);
464    fclose(f);
465    /* end data decoding */
466    jpeg_finish_decompress(&cinfo);
467    jpeg_destroy_decompress(&cinfo);
468    return d;
469 }
470
471 static void *
472 eet_data_image_lossless_convert(int *size, void *data, int w, int h, int alpha)
473 {
474    if (words_bigendian == -1)
475      {
476         unsigned long int v;
477
478         v = htonl(0x12345678);
479         if (v == 0x12345678) words_bigendian = 1;
480         else words_bigendian = 0;
481      }
482      {
483         unsigned char *d;
484         int           *header;
485         
486         d = malloc((w * h * 4) + (8 * 4));
487         if (!d) return NULL;
488         header = (int *)d;
489         header[0] = 0xac1dfeed;
490         header[1] = w;
491         header[2] = h;
492         header[3] = alpha;
493         header[4] = 0;
494         memcpy(d + 32, data, w * h * 4);
495         
496         if (words_bigendian)
497           {
498              int i;
499              
500              for (i = 0; i < ((w * h) + 8); i++) SWAP32(header[i]);
501           }
502         *size = ((w * h * 4) + (8 * 4));
503         return d;
504      }
505 }
506
507 static void *
508 eet_data_image_lossless_compressed_convert(int *size, void *data, int w, int h, int alpha, int compression)
509 {
510    if (words_bigendian == -1)
511      {
512         unsigned long int v;
513
514         v = htonl(0x12345678);
515         if (v == 0x12345678) words_bigendian = 1;
516         else words_bigendian = 0;
517      }
518
519      {
520         unsigned char *d;
521         unsigned char *comp;
522         int           *header;
523         int            ret;
524         uLongf         buflen;
525         
526         d = malloc((w * h * 4) + (8 * 4));
527         if (!d) return NULL;
528         buflen = (((w * h * 101) / 100) + 3) * 4;
529         comp = malloc(buflen);
530         if (!comp)
531           {
532              free(d);
533              return NULL;
534           }
535         header = (int *)d;
536         header[0] = 0xac1dfeed;
537         header[1] = w;
538         header[2] = h;
539         header[3] = alpha;
540         header[4] = compression;
541         memcpy(d + 32, data, w * h * 4);
542         
543         if (words_bigendian)
544           {
545              int i;
546              
547              for (i = 0; i < ((w * h) + 8); i++) SWAP32(header[i]);
548           }
549         ret = compress2((Bytef *)comp, &buflen,
550                         (Bytef *)(d + 32),
551                         (uLong)(w * h * 4),
552                         compression);
553         if (buflen > (w * h * 4))
554           {
555              free(comp);
556              *size = ((w * h * 4) + (8 * 4));
557              return d;
558           }
559         memcpy(d + 32, comp, buflen);
560         *size = (8 * 4) + buflen;
561         free(comp);
562         return d;
563      }
564 }
565
566 static void *
567 eet_data_image_jpeg_convert(int *size, void *data, int w, int h, int alpha, int quality)
568 {
569    int *ptr;
570    char *d = NULL;
571    size_t sz = 0;
572    struct _JPEG_error_mgr jerr;
573    JSAMPROW *jbuf;
574    struct jpeg_compress_struct cinfo;
575    FILE *f;
576    unsigned char *buf;
577       
578    f = open_memstream(&d, &sz);
579    if (!f) return NULL;
580    
581    buf = malloc(3 * w);
582    if (!buf) 
583      {
584         fclose(f);
585         if (d) free(d);
586         return NULL;
587      }
588    
589    cinfo.err = jpeg_std_error(&(jerr.pub));
590    jerr.pub.error_exit = _JPEGFatalErrorHandler;
591    jerr.pub.emit_message = _JPEGErrorHandler2;
592    jerr.pub.output_message = _JPEGErrorHandler;
593    if (setjmp(jerr.setjmp_buffer))
594      {
595         jpeg_destroy_compress(&cinfo);
596         if (buf) free(buf);
597         fclose(f);
598         if (d) free(d);
599         return NULL;
600      }
601    jpeg_create_compress(&cinfo);
602    jpeg_stdio_dest(&cinfo, f);
603    cinfo.image_width = w;
604    cinfo.image_height = h;
605    cinfo.input_components = 3;
606    cinfo.in_color_space = JCS_RGB;
607    jpeg_set_defaults(&cinfo);
608    jpeg_set_quality(&cinfo, quality, TRUE);
609    jpeg_start_compress(&cinfo, TRUE);
610
611    ptr = data;
612    while (cinfo.next_scanline < cinfo.image_height)
613      {
614         int i, j;
615         
616         /* convert scaline from ARGB to RGB packed */
617         for (j = 0, i = 0; i < w; i++)
618           {
619              buf[j++] = ((*ptr) >> 16) & 0xff;
620              buf[j++] = ((*ptr) >> 8) & 0xff;
621              buf[j++] = ((*ptr)) & 0xff;
622              ptr++;
623           }
624         jbuf = (JSAMPROW *) (&buf);
625         jpeg_write_scanlines(&cinfo, jbuf, 1);       
626      }
627    
628    jpeg_finish_compress(&cinfo);
629    jpeg_destroy_compress(&cinfo);
630    
631    *size = sz;
632    if (buf) free(buf);   
633    fclose(f);
634    return d;
635 }
636
637 static void *
638 eet_data_image_jpeg_alpha_convert(int *size, void *data, int w, int h, int alpha, int quality)
639 {
640    unsigned char *d1, *d2;
641    unsigned char *d;
642    int *header;
643    int sz1, sz2;
644    
645    if (words_bigendian == -1)
646      {
647         unsigned long int v;
648
649         v = htonl(0x12345678);
650         if (v == 0x12345678) words_bigendian = 1;
651         else words_bigendian = 0;
652      }
653    
654      {
655         int *ptr;
656         char *d = NULL;
657         size_t sz = 0;
658         struct _JPEG_error_mgr jerr;
659         JSAMPROW *jbuf;
660         struct jpeg_compress_struct cinfo;
661         FILE *f;
662         unsigned char *buf;
663         
664         f = open_memstream(&d, &sz);
665         if (!f) return NULL;
666         
667         buf = malloc(3 * w);
668         if (!buf) 
669           {
670              fclose(f);
671              if (d) free(d);
672              return NULL;
673           }
674         
675         cinfo.err = jpeg_std_error(&(jerr.pub));
676         jerr.pub.error_exit = _JPEGFatalErrorHandler;
677         jerr.pub.emit_message = _JPEGErrorHandler2;
678         jerr.pub.output_message = _JPEGErrorHandler;
679         if (setjmp(jerr.setjmp_buffer))
680           {
681              jpeg_destroy_compress(&cinfo);
682              if (buf) free(buf);
683              fclose(f);
684              if (d) free(d);
685              return NULL;
686           }
687         jpeg_create_compress(&cinfo);
688         jpeg_stdio_dest(&cinfo, f);
689         cinfo.image_width = w;
690         cinfo.image_height = h;
691         cinfo.input_components = 3;
692         cinfo.in_color_space = JCS_RGB;
693         jpeg_set_defaults(&cinfo);
694         jpeg_set_quality(&cinfo, quality, TRUE);
695         jpeg_start_compress(&cinfo, TRUE);
696         
697         ptr = data;
698         while (cinfo.next_scanline < cinfo.image_height)
699           {
700              int i, j;
701              
702              /* convert scaline from ARGB to RGB packed */
703              for (j = 0, i = 0; i < w; i++)
704                {
705                   buf[j++] = ((*ptr) >> 16) & 0xff;
706                   buf[j++] = ((*ptr) >> 8) & 0xff;
707                   buf[j++] = ((*ptr)) & 0xff;
708                   ptr++;
709                }
710              jbuf = (JSAMPROW *) (&buf);
711              jpeg_write_scanlines(&cinfo, jbuf, 1);          
712           }
713         
714         jpeg_finish_compress(&cinfo);
715         jpeg_destroy_compress(&cinfo);
716         
717         if (buf) free(buf);   
718         fclose(f);
719         d1 = d;
720         sz1 = sz;
721      }
722      {
723         int *ptr;
724         char *d = NULL;
725         size_t sz = 0;
726         struct _JPEG_error_mgr jerr;
727         JSAMPROW *jbuf;
728         struct jpeg_compress_struct cinfo;
729         FILE *f;
730         unsigned char *buf;
731         
732         f = open_memstream(&d, &sz);
733         if (!f) 
734           {
735              free(d1);
736              return NULL;
737           }
738         
739         buf = malloc(3 * w);
740         if (!buf) 
741           {
742              fclose(f);
743              if (d) free(d);
744              free(d1);
745              return NULL;
746           }
747         
748         cinfo.err = jpeg_std_error(&(jerr.pub));
749         jerr.pub.error_exit = _JPEGFatalErrorHandler;
750         jerr.pub.emit_message = _JPEGErrorHandler2;
751         jerr.pub.output_message = _JPEGErrorHandler;
752         if (setjmp(jerr.setjmp_buffer))
753           {
754              jpeg_destroy_compress(&cinfo);
755              if (buf) free(buf);
756              fclose(f);
757              if (d) free(d);
758              free(d1);
759              return NULL;
760           }
761         jpeg_create_compress(&cinfo);
762         jpeg_stdio_dest(&cinfo, f);
763         cinfo.image_width = w;
764         cinfo.image_height = h;
765         cinfo.input_components = 1;
766         cinfo.in_color_space = JCS_GRAYSCALE;
767         jpeg_set_defaults(&cinfo);
768         jpeg_set_quality(&cinfo, quality, TRUE);
769         jpeg_start_compress(&cinfo, TRUE);
770         
771         ptr = data;
772         while (cinfo.next_scanline < cinfo.image_height)
773           {
774              int i, j;
775              
776              /* convert scaline from ARGB to RGB packed */
777              for (j = 0, i = 0; i < w; i++)
778                {
779                   buf[j++] = ((*ptr) >> 24) & 0xff;
780                   ptr++;
781                }
782              jbuf = (JSAMPROW *) (&buf);
783              jpeg_write_scanlines(&cinfo, jbuf, 1);          
784           }
785         
786         jpeg_finish_compress(&cinfo);
787         jpeg_destroy_compress(&cinfo);
788         
789         if (buf) free(buf);   
790         fclose(f);
791         d2 = d;
792         sz2 = sz;
793      }
794    d = malloc(12 + sz1 + sz2);
795    if (!d)
796      {
797         free(d1);
798         free(d2);
799         return NULL;
800      }
801    header = (int *)d;
802    header[0] = 0xbeeff00d;
803    header[1] = sz1;
804    header[2] = sz2;
805    if (words_bigendian)
806      {
807         int i;
808         
809         for (i = 0; i < ((w * h) + 3); i++) SWAP32(header[i]);
810      }
811    memcpy(d + 12, d1, sz1);
812    memcpy(d + 12 + sz1, d2, sz2);
813    
814    free(d1);
815    free(d2);
816    *size = 12 + sz1 + sz2;
817    return d;   
818 }
819
820
821 /* CHAR TYPE */
822 static int
823 eet_data_get_char(void *src, void *src_end, void *dst)
824 {
825    char *s, *d;
826    
827    if ((src + sizeof(char)) > src_end) return -1;
828    s = (char *)src;
829    d = (char *)dst;
830    *s = *d;
831    CONV8(*s);
832    return sizeof(char);
833 }
834
835 static void *
836 eet_data_put_char(void *src, int *size_ret)
837 {
838    char *s, *d;
839    
840    d = (char *)malloc(sizeof(char));
841    if (!d) return NULL;
842    s = (char *)src;
843    *d = *s;
844    CONV8(*d);
845    *size_ret = sizeof(char);
846    return d;
847 }
848
849 /* SHORT TYPE */
850 static int
851 eet_data_get_short(void *src, void *src_end, void *dst)
852 {
853    short *s, *d;
854    short tmp;
855    
856    if ((src + sizeof(short)) > src_end) return -1;
857    s = (short *)src;
858    d = (short *)dst;
859    /* alignment fixup */
860    if ((int)s & (sizeof(short) - 1))
861      {
862         memcpy(&tmp, s, sizeof(short));
863         s = &tmp;
864      }
865    *d = *s;
866    CONV16(*d);
867    return sizeof(short);
868 }
869
870 static void *
871 eet_data_put_short(void *src, int *size_ret)
872 {
873    short *s, *d;
874    
875    d = (short *)malloc(sizeof(short));
876    if (!d) return NULL;
877    s = (short *)src;
878    *d = *s;
879    CONV16(*d);
880    *size_ret = sizeof(short);
881    return d;
882 }
883
884 /* INT TYPE */
885 static int
886 eet_data_get_int(void *src, void *src_end, void *dst)
887 {
888    int *s, *d;
889    int tmp;
890    
891    if ((src + sizeof(int)) > src_end) return -1;
892    s = (int *)src;
893    d = (int *)dst;
894    /* alignment fixup */
895    if ((int)s & (sizeof(int) - 1))
896      {
897         memcpy(&tmp, s, sizeof(int));
898         s = &tmp;
899      }
900    *d = *s;
901    CONV32(*d);
902    return sizeof(int);
903 }
904
905 static void *
906 eet_data_put_int(void *src, int *size_ret)
907 {
908    int *s, *d;
909    
910    d = (int *)malloc(sizeof(int));
911    if (!d) return NULL;
912    s = (int *)src;
913    *d = *s;
914    CONV32(*d);
915    *size_ret = sizeof(int);
916    return d;
917 }
918
919 /* LONG LONG TYPE */
920 static int
921 eet_data_get_long_long(void *src, void *src_end, void *dst)
922 {
923    long long *s, *d;
924    long long tmp;
925    
926    if ((src + sizeof(long long)) > src_end) return -1;
927    s = (long long *)src;
928    d = (long long *)dst;
929    /* alignment fixup */
930    if ((int)s & (sizeof(long long) - 1))
931      {
932         memcpy(&tmp, s, sizeof(long long));
933         s = &tmp;
934      }
935    *d = *s;
936    CONV64(*d);
937    return sizeof(long long);
938 }
939
940 static void *
941 eet_data_put_long_long(void *src, int *size_ret)
942 {
943    long long *s, *d;
944    
945    d = (long long *)malloc(sizeof(long long));
946    if (!d) return NULL;
947    s = (long long *)src;
948    *d = *s;
949    CONV64(*d);
950    *size_ret = sizeof(long long);
951    return d;
952 }
953
954 /* STRING TYPE */
955 static int
956 eet_data_get_string(void *src, void *src_end, void *dst)
957 {
958    char *s, **d, *p;
959    int len;
960    
961    s = (char *)src;
962    d = (char **)dst;
963    p = s;
964    len = 0;
965    while ((p < (char *)src_end) && (*p != 0)) {len++; p++;}
966    *d = malloc(len + 1);
967    if (!(*d)) return -1;
968    memcpy(*d, s, len);
969    (*d)[len] = 0;
970    return len + 1;
971 }
972
973 static void *
974 eet_data_put_string(void *src, int *size_ret)
975 {
976    char *s, *d;
977    int len;
978    
979    if (!src) src = "";
980    s = (char *)(*((char **)src));
981    len = strlen(s);
982    d = malloc(len + 1);
983    if (!d) return NULL;
984    strcpy(d, s);
985    *size_ret = len + 1;
986    return d;
987 }
988
989 /* FLOAT TYPE */
990 static int
991 eet_data_get_float(void *src, void *src_end, void *dst)
992 {
993    float *d;
994    char *s, *str, *p, *prev_locale;
995    int len;
996    
997    s = (char *)src;
998    d = (float *)dst;
999    p = s;
1000    len = 0;
1001    while ((p < (char *)src_end) && (*p != 0)) {len++; p++;}
1002    str = malloc(len + 1);
1003    if (!str) return -1;
1004    memcpy(str, s, len);
1005    str[len] = 0;
1006    
1007    prev_locale = setlocale(LC_NUMERIC, "C");
1008    *d = (float)atof(str);
1009    if (prev_locale) setlocale(LC_NUMERIC, prev_locale);
1010    
1011    free(str);
1012    return len + 1;
1013 }
1014
1015 static void *
1016 eet_data_put_float(void *src, int *size_ret)
1017 {
1018    float *s;
1019    char *d, buf[64], *prev_locale;
1020    int len;
1021    
1022    s = (float *)src;
1023    prev_locale = setlocale(LC_NUMERIC, "C");
1024    snprintf(buf, sizeof(buf), "%16.16f", (double)(*s));
1025    if (prev_locale) setlocale(LC_NUMERIC, prev_locale);
1026    len = strlen(buf);
1027    d = malloc(len + 1);
1028    if (!d) return NULL;
1029    strcpy(d, buf);
1030    *size_ret = len + 1;
1031    return d;
1032 }
1033
1034 /* DOUBLE TYPE */
1035 static int
1036 eet_data_get_double(void *src, void *src_end, void *dst)
1037 {
1038    double *d;
1039    char *s, *str, *p, *prev_locale;
1040    int len;
1041    
1042    s = (char *)src;
1043    d = (double *)dst;
1044    p = s;
1045    len = 0;
1046    while ((p < (char *)src_end) && (*p != 0)) {len++; p++;}
1047    str = malloc(len + 1);
1048    if (!str) return -1;
1049    memcpy(str, s, len);
1050    str[len] = 0;
1051    
1052    prev_locale = setlocale(LC_NUMERIC, "C");
1053    *d = (double)atof(str);
1054    if (prev_locale) setlocale(LC_NUMERIC, prev_locale);
1055    
1056    free(str);
1057    return len + 1;
1058 }
1059
1060 static void *
1061 eet_data_put_double(void *src, int *size_ret)
1062 {
1063    double *s;
1064    char *d, buf[128], *prev_locale;
1065    int len;
1066    
1067    s = (double *)src;
1068    prev_locale = setlocale(LC_NUMERIC, "C");
1069    snprintf(buf, sizeof(buf), "%32.32f", (double)(*s));
1070    if (prev_locale) setlocale(LC_NUMERIC, prev_locale);
1071    len = strlen(buf);
1072    d = malloc(len + 1);
1073    if (!d) return NULL;
1074    strcpy(d, buf);
1075    *size_ret = len + 1;
1076    return d;
1077 }
1078
1079 static int
1080 eet_data_get_type(int type, void *src, void *src_end, void *dest)
1081 {
1082    int ret;
1083    
1084    ret = eet_coder[type - 1].get(src, src_end, dest);
1085    return ret;
1086 }
1087
1088 static void *
1089 eet_data_put_type(int type, void *src, int *size_ret)
1090 {
1091    void *ret;
1092    
1093    ret = eet_coder[type - 1].put(src, size_ret);
1094    return ret;
1095 }
1096
1097 /* chunk format...
1098  * 
1099  * char[4] = "CHnK";
1100  * int     = chunk size (including magic string);
1101  * char[]  = chuck magic/name string (0 byte terminated);
1102  * ... sub-chunks (a chunk can contain chuncks recusrively) ...
1103  * or
1104  * ... payload data ...
1105  * 
1106  */
1107
1108 static Eet_Data_Chunk *
1109 eet_data_chunk_get(void *src, int size)
1110 {
1111    Eet_Data_Chunk *chnk;
1112    char *s;
1113    int ret1, ret2;
1114    
1115    if (!src) return NULL;
1116    if (size <= 8) return NULL;
1117    
1118    chnk = calloc(1, sizeof(Eet_Data_Chunk));
1119    if (!chnk) return NULL;
1120    
1121    s = src;
1122    if ((s[0] != 'C') || (s[1] != 'H') || (s[2] != 'n') || (s[3] != 'K'))
1123      {
1124         free(chnk);
1125         return NULL;
1126      }
1127    ret1 = eet_data_get_type(EET_T_INT, (void *)(s + 4), (void *)(s + size), &(chnk->size));
1128    if (ret1 <= 0)
1129      {
1130         free(chnk);
1131         return NULL;    
1132      }
1133    if ((chnk->size < 0) || ((chnk->size + 8) > size))
1134      {
1135         free(chnk);
1136         return NULL;    
1137      }
1138    ret2 = eet_data_get_type(EET_T_STRING, (void *)(s + 8), (void *)(s + size), &(chnk->name));
1139    if (ret2 <= 0)
1140      {
1141         free(chnk);
1142         return NULL;    
1143      }
1144    chnk->data = src + 4 + ret1 + ret2;
1145    chnk->size -= ret2;
1146    return chnk;
1147 }
1148
1149 static Eet_Data_Chunk *
1150 eet_data_chunk_new(void *data, int size, char *name)
1151 {
1152    Eet_Data_Chunk *chnk;
1153    
1154    if (!name) return NULL;
1155    chnk = calloc(1, sizeof(Eet_Data_Chunk));
1156    if (!chnk) return NULL;
1157    
1158    chnk->name = strdup(name);
1159    chnk->size = size;
1160    chnk->data = data;
1161    
1162    return chnk;
1163 }
1164
1165 static void
1166 eet_data_chunk_free(Eet_Data_Chunk *chnk)
1167 {
1168    if (chnk->name) free(chnk->name);
1169    free(chnk);
1170 }
1171
1172 static Eet_Data_Stream *
1173 eet_data_stream_new(void)
1174 {
1175    Eet_Data_Stream *ds;
1176    
1177    ds = calloc(1, sizeof(Eet_Data_Stream));
1178    if (!ds) return NULL;
1179    return ds;
1180 }
1181
1182 static void
1183 eet_data_stream_free(Eet_Data_Stream *ds)
1184 {
1185    if (ds->data) free(ds->data);
1186    free(ds);
1187 }
1188
1189 static void
1190 eet_data_stream_write(Eet_Data_Stream *ds, void *data, int size)
1191 {
1192    char *p;
1193         
1194    if ((ds->pos + size) > ds->size)
1195      {
1196         ds->data = realloc(ds->data, ds->size + size + 256);
1197         if (!ds->data)
1198           {
1199              ds->pos = 0;
1200              ds->size = 0;
1201              return;
1202           }
1203         ds->size = ds->size + size + 256;
1204      }
1205    p = ds->data;
1206    memcpy(p + ds->pos, data, size);
1207    ds->pos += size;
1208 }
1209
1210 static void
1211 eet_data_chunk_put(Eet_Data_Chunk *chnk, Eet_Data_Stream *ds)
1212 {
1213    int *size;
1214    int s;
1215    int size_ret;
1216
1217    if (!chnk->data) return;
1218    /* chunk head */
1219    eet_data_stream_write(ds, "CHnK", 4);
1220    /* size of chunk payload data + name */
1221    s = strlen(chnk->name) + 1 + chnk->size;
1222    size = eet_data_put_int(&s, &size_ret);
1223    if (size)
1224      {
1225         eet_data_stream_write(ds, size, size_ret);
1226         free(size);
1227      }
1228    /* write chunk name */
1229    eet_data_stream_write(ds, chnk->name, strlen(chnk->name) + 1);
1230    /* write payload */
1231    eet_data_stream_write(ds, chnk->data, chnk->size);
1232 }
1233
1234 /*---*/
1235
1236 int
1237 eet_data_image_write(Eet_File *ef, char *name,
1238                      void *data, int w, int h, int alpha, 
1239                      int compress, int quality, int lossy)
1240 {
1241    void *d = NULL;
1242    int size = 0;
1243
1244    d = eet_data_image_encode(data, &size, w, h, alpha, compress, quality, lossy);
1245    if (d)
1246      {
1247         int v;
1248         
1249         v = eet_write(ef, name, d, size, 0);
1250         free(d);
1251         return v;
1252      }
1253    return 0;
1254 }
1255
1256 void *
1257 eet_data_image_read(Eet_File *ef, char *name,
1258                     int *w, int *h, int *alpha,
1259                     int *compress, int *quality, int *lossy)
1260 {
1261    void *data;
1262    int size;
1263    unsigned int *d = NULL;
1264    int header[8];
1265    
1266    data = eet_read(ef, name, &size);
1267    if (!data) return NULL;
1268    d = eet_data_image_decode(data, size, w, h, alpha, compress, quality, lossy);
1269    free(data);
1270    return d;
1271 }
1272
1273 void *
1274 eet_data_image_encode(void *data, int *size_ret, int w, int h, int alpha, int compress, int quality, int lossy)
1275 {
1276    void *d = NULL;
1277    int size = 0;
1278    
1279    if (lossy == 0)
1280      {
1281         if (compress <= 0)
1282           d = eet_data_image_lossless_convert(&size, data, w, h, alpha);
1283         else
1284           d = eet_data_image_lossless_compressed_convert(&size, data, w, h, alpha, compress);
1285      }
1286    else
1287      {
1288         if (!alpha)
1289           d = eet_data_image_jpeg_convert(&size, data, w, h, alpha, quality);
1290         else
1291           d = eet_data_image_jpeg_alpha_convert(&size, data, w, h, alpha, quality);
1292      }
1293    if (size_ret) *size_ret = size;
1294    return d;
1295 }
1296
1297 void *
1298 eet_data_image_decode(void *data, int size, int *w, int *h, int *alpha, int *compress, int *quality, int *lossy)
1299 {
1300    unsigned int *d = NULL;
1301    int header[8];
1302    
1303    if (words_bigendian == -1)
1304      {
1305         unsigned long int v;
1306
1307         v = htonl(0x12345678);
1308         if (v == 0x12345678) words_bigendian = 1;
1309         else words_bigendian = 0;
1310      }
1311    
1312    if (size < 32) return NULL;
1313
1314    memcpy(header, data, 32);
1315    if (words_bigendian)
1316      {
1317         int i;
1318         
1319         for (i = 0; i < 8; i++) SWAP32(header[i]);           
1320      }
1321    if (header[0] == 0xac1dfeed)
1322      {
1323         int iw, ih, al, cp;
1324         unsigned int *body;
1325         
1326         iw = header[1];
1327         ih = header[2];
1328         al = header[3];
1329         cp = header[4];
1330         if ((iw > 8192) || (ih > 8192)) return NULL;
1331         if ((cp == 0) && (size < ((iw * ih * 4) + 32))) return NULL;
1332         body = ((unsigned int *)data) + 8;
1333         d = malloc(iw * ih * 4);
1334         if (!d) return NULL;         
1335         if (!cp)
1336           {
1337              memcpy(d, body, iw * ih * 4);
1338              if (words_bigendian)
1339                {
1340                   int x;
1341                   
1342                   for (x = 0; x < (iw * ih); x++) SWAP32(d[x]);
1343                }
1344           }
1345         else
1346           {
1347              uLongf dlen;
1348              
1349              dlen = iw * ih * 4;
1350              uncompress((Bytef *)d, &dlen, (Bytef *)body,
1351                         (uLongf)(size - 32));
1352              if (words_bigendian)
1353                {
1354                   int x;
1355                   
1356                   for (x = 0; x < (iw * ih); x++) SWAP32(d[x]);
1357                }
1358           }
1359         if (d)
1360           {
1361              if (w) *w = iw;
1362              if (h) *h = ih;
1363              if (alpha) *alpha = al;
1364              if (compress) *compress = cp;
1365              if (lossy) *lossy = 0;
1366              if (quality) *quality = 100;
1367           }     
1368      }
1369    else if (header[0] == 0xbeeff00d)
1370      {
1371         int iw = 0, ih = 0;
1372         int sz1, sz2;
1373         unsigned char *dt;
1374         
1375         sz1 = header[1];
1376         sz2 = header[2];
1377         dt = data;
1378         dt += 12;
1379         d = eet_data_image_jpeg_rgb_decode(dt, sz1, &iw, &ih);
1380         if (d)
1381           {
1382              dt += sz1;
1383              eet_data_image_jpeg_alpha_decode(dt, sz2, d, &iw, &ih);
1384           }
1385         if (d)
1386           {
1387              if (w) *w = iw;
1388              if (h) *h = ih;
1389              if (alpha) *alpha = 1;
1390              if (compress) *compress = 0;
1391              if (lossy) *lossy = 1;
1392              if (quality) *quality = 75;
1393           }
1394      }
1395    else
1396      {
1397         int iw = 0, ih = 0;
1398         
1399         d = eet_data_image_jpeg_rgb_decode(data, size, &iw, &ih);
1400         if (d)
1401           {
1402              if (w) *w = iw;
1403              if (h) *h = ih;
1404              if (alpha) *alpha = 0;
1405              if (compress) *compress = 0;
1406              if (lossy) *lossy = 1;
1407              if (quality) *quality = 75;
1408           }
1409      }
1410    return d;
1411 }
1412
1413 Eet_Data_Descriptor *
1414 eet_data_descriptor_new(char *name,
1415                         int size,
1416                         void *(*func_list_next) (void *l),
1417                         void *(*func_list_append) (void *l, void *d),
1418                         void *(*func_list_data) (void *l),
1419                         void  (*func_hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt),
1420                         void *(*func_hash_add) (void *h, const char *k, void *d))
1421 {
1422    Eet_Data_Descriptor *edd;
1423    
1424    edd = calloc(1, sizeof(Eet_Data_Descriptor));
1425    edd->name = strdup(name);
1426    edd->size = size;
1427    edd->func.list_next = func_list_next;
1428    edd->func.list_append = func_list_append;
1429    edd->func.list_data = func_list_data;
1430    edd->func.hash_foreach = func_hash_foreach;
1431    edd->func.hash_add = func_hash_add;
1432    return edd;
1433 }
1434
1435 void
1436 eet_data_descriptor_free(Eet_Data_Descriptor *edd)
1437 {
1438    int i;
1439    
1440    if (edd->name) free(edd->name);
1441    for (i = 0; i < edd->elements.num; i++)
1442      {
1443         if (edd->elements.set[i].name) free(edd->elements.set[i].name);
1444         if (edd->elements.set[i].counter_name) free(edd->elements.set[i].counter_name);
1445      }
1446    if (edd->elements.set) free(edd->elements.set);
1447    free(edd);
1448 }
1449
1450 void
1451 eet_data_descriptor_element_add(Eet_Data_Descriptor *edd, char *name, int type, 
1452                                 int group_type, 
1453                                 int offset, 
1454                                 int count, char *counter_name, 
1455                                 Eet_Data_Descriptor *subtype)
1456 {
1457    Eet_Data_Element *ede;
1458    
1459    edd->elements.num++;
1460    edd->elements.set = realloc(edd->elements.set, edd->elements.num * sizeof(Eet_Data_Element));
1461    if (!edd->elements.set) return;
1462    ede = &(edd->elements.set[edd->elements.num - 1]);
1463    ede->name = strdup(name);
1464    ede->type = type;
1465    ede->group_type = group_type;
1466    ede->offset = offset;
1467    ede->count = count;
1468    if (counter_name)
1469      ede->counter_name = strdup(counter_name);
1470    else ede->counter_name = NULL;
1471    ede->subtype = subtype;
1472 }
1473
1474 void *
1475 eet_data_read(Eet_File *ef, Eet_Data_Descriptor *edd, char *name)
1476 {
1477    void *data_dec;
1478    void *data;
1479    int size;
1480    
1481    data = eet_read(ef, name, &size);
1482    if (!data) return NULL;
1483    data_dec = eet_data_descriptor_decode(edd, data, size);
1484    free(data);
1485    return data_dec;
1486 }
1487
1488 int
1489 eet_data_write(Eet_File *ef, Eet_Data_Descriptor *edd, char *name, void *data, int compress)
1490 {
1491    void *data_enc;
1492    int size;
1493    int val;
1494    
1495    data_enc = eet_data_descriptor_encode(edd, data, &size);
1496    if (!data_enc) return 0;
1497    val = eet_write(ef, name, data_enc, size, compress);
1498    free(data_enc);
1499    return val;
1500 }
1501
1502 void *
1503 eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
1504                            void *data_in,
1505                            int size_in)
1506 {
1507    void *data;
1508    char *p;
1509    int size;
1510    Eet_Data_Chunk *chnk;
1511    
1512    if (words_bigendian == -1)
1513      {
1514         unsigned long int v;
1515
1516         v = htonl(0x12345678);
1517         if (v == 0x12345678) words_bigendian = 1;
1518         else words_bigendian = 0;
1519      }
1520    
1521    data = calloc(1, edd->size);
1522    if (!data) return NULL;
1523    chnk = eet_data_chunk_get(data_in, size_in);
1524    if (!chnk)
1525      {
1526         free(data);
1527         return NULL;
1528      }
1529    if (strcmp(chnk->name, edd->name))
1530      {
1531         eet_data_chunk_free(chnk);
1532         free(data);
1533         return NULL;
1534      }
1535    p = chnk->data;
1536    size = size_in - (4 + 4 + strlen(chnk->name) + 1);
1537    while (size > 0)
1538      {
1539         Eet_Data_Chunk *echnk;
1540         int i;
1541         
1542         /* get next data chunk */
1543         echnk = eet_data_chunk_get(p, size);
1544         if (!echnk)
1545           {
1546              /* FIXME: partially built data struct - leak!!!! */
1547              free(data);
1548              eet_data_chunk_free(chnk);
1549              return NULL;
1550           }
1551         for (i = 0; i < edd->elements.num; i++)
1552           {
1553              Eet_Data_Element *ede;
1554              
1555              ede = &(edd->elements.set[i]);
1556              if (!strcmp(echnk->name, ede->name))
1557                {
1558                   if (ede->group_type == EET_G_UNKNOWN)
1559                     {
1560                        int ret;
1561                        void *data_ret;
1562                        
1563                        if ((ede->type >= EET_T_CHAR) && 
1564                            (ede->type <= EET_T_STRING))
1565                          {
1566                             ret = eet_data_get_type(ede->type,
1567                                                     echnk->data,
1568                                                     ((char *)echnk->data) + echnk->size,
1569                                                     ((char *)data) + ede->offset);
1570                          }
1571                        else if (ede->subtype)
1572                          {
1573                             void **ptr;
1574                             
1575                             data_ret = eet_data_descriptor_decode(ede->subtype,
1576                                                                   echnk->data,
1577                                                                   echnk->size);
1578                             ptr = (void **)(((char *)data) + ede->offset);
1579                             *ptr = (void *)data_ret;
1580                          }
1581                     }
1582                   else
1583                     {
1584                        switch (ede->group_type)
1585                          {
1586                           case EET_G_ARRAY:
1587                           case EET_G_VAR_ARRAY:
1588                               {
1589                                  printf("ARRAY TYPE NOT IMPLIMENTED YET!!!\n");
1590                               }
1591                             break;
1592                           case EET_G_LIST:
1593                               {
1594                                  int ret;
1595                                  void *list = NULL;
1596                                  void **ptr;
1597                                  void *data_ret;
1598                                    
1599                                  ptr = (void **)(((char *)data) + ede->offset);
1600                                  list = *ptr;
1601                                  data_ret = NULL;
1602                                  if ((ede->type >= EET_T_CHAR) &&
1603                                      (ede->type <= EET_T_STRING))
1604                                    {
1605                                       data_ret = calloc(1, eet_coder[ede->type].size);
1606                                       if (data_ret)
1607                                         {
1608                                            ret = eet_data_get_type(ede->type,
1609                                                                    echnk->data,
1610                                                                    ((char *)echnk->data) + echnk->size,
1611                                                                    data_ret);
1612                                            if (ret <= 0)
1613                                              {
1614                                                 free(data_ret);
1615                                                 data_ret = NULL;
1616                                              }
1617                                         }
1618                                    }
1619                                  else if (ede->subtype)
1620                                    {
1621                                       data_ret = eet_data_descriptor_decode(ede->subtype,
1622                                                                             echnk->data,
1623                                                                             echnk->size);
1624                                    }
1625                                  if (data_ret)
1626                                    {
1627                                       list = edd->func.list_append(list, data_ret);
1628                                       *ptr = list;
1629                                    }
1630                               }
1631                             break;
1632                           case EET_G_HASH:
1633                             printf("HASH TYPE NOT IMPLIMENTED YET!!!\n");
1634                             break;
1635                           default:
1636                             break;
1637                          }
1638                     }
1639                   break;
1640                }
1641           }
1642         /* advance to next chunk */
1643         p += (4 + 4 + strlen(echnk->name) + 1 + echnk->size);
1644         size -= (4 + 4 + strlen(echnk->name) + 1 + echnk->size);
1645         eet_data_chunk_free(echnk);
1646      }
1647    eet_data_chunk_free(chnk);
1648    return data;
1649 }
1650
1651 void *
1652 eet_data_descriptor_encode(Eet_Data_Descriptor *edd,
1653                            void *data_in,
1654                            int *size_ret)
1655 {
1656    Eet_Data_Chunk *chnk;
1657    Eet_Data_Stream *ds;
1658    int i;
1659    void *cdata;
1660    int csize;
1661    
1662    if (words_bigendian == -1)
1663      {
1664         unsigned long int v;
1665
1666         v = htonl(0x12345678);
1667         if (v == 0x12345678) words_bigendian = 1;
1668         else words_bigendian = 0;
1669      }
1670    
1671    ds = eet_data_stream_new();
1672    for (i = 0; i < edd->elements.num; i++)
1673      {
1674         Eet_Data_Element *ede;
1675         Eet_Data_Chunk *echnk;
1676         void *data;
1677         int size;
1678         
1679         ede = &(edd->elements.set[i]);
1680         data = NULL;
1681         if (ede->group_type == EET_G_UNKNOWN)
1682           {
1683              if ((ede->type >= EET_T_CHAR) && 
1684                  (ede->type <= EET_T_STRING))
1685                data = eet_data_put_type(ede->type, 
1686                                         ((char *)data_in) + ede->offset, 
1687                                         &size);
1688              else if (ede->subtype)
1689                data = eet_data_descriptor_encode(ede->subtype, 
1690                                                  *((char **)(((char *)data_in) + ede->offset)),
1691                                                  &size);
1692              if (data) 
1693                {
1694                   echnk = eet_data_chunk_new(data, size, ede->name);
1695                   eet_data_chunk_put(echnk, ds);
1696                   eet_data_chunk_free(echnk);
1697                   free(data);
1698                   data = NULL;
1699                }
1700           }
1701         else
1702           {
1703              switch (ede->group_type)
1704                {
1705                 case EET_G_ARRAY:
1706                 case EET_G_VAR_ARRAY:
1707                     {
1708                        printf("ARRAY TYPE NOT IMPLIMENTED YET!!!\n");
1709                     }
1710                   break;
1711                 case EET_G_LIST:
1712                     {
1713                        void *l;
1714                        
1715                        l = *((void **)(((char *)data_in) + ede->offset));
1716                        for (; l; l = edd->func.list_next(l))
1717                          {
1718                             if ((ede->type >= EET_T_CHAR) &&
1719                                 (ede->type <= EET_T_STRING))
1720                               data = eet_data_put_type(ede->type,
1721                                                        edd->func.list_data(l),
1722                                                        &size);
1723                             else if (ede->subtype)
1724                               data = eet_data_descriptor_encode(ede->subtype,
1725                                                                 edd->func.list_data(l),
1726                                                                 &size);
1727                             if (data)
1728                               {
1729                                  echnk = eet_data_chunk_new(data, size, ede->name); 
1730                                  eet_data_chunk_put(echnk, ds);
1731                                  eet_data_chunk_free(echnk);
1732                                  free(data);
1733                                  data = NULL;
1734                               }
1735                          }
1736                     }
1737                   break;
1738                 case EET_G_HASH:
1739                     {
1740                        printf("HASH TYPE NOT IMPLIMENTED YET!!!\n");
1741                     }
1742                   break;
1743                 default:
1744                   break;
1745                }
1746           }
1747      }
1748    chnk = eet_data_chunk_new(ds->data, ds->pos, edd->name);
1749    ds->data = NULL;
1750    ds->size = 0;
1751    eet_data_stream_free(ds);
1752    
1753    ds = eet_data_stream_new();
1754    eet_data_chunk_put(chnk, ds);
1755    cdata = ds->data;
1756    csize = ds->pos;
1757
1758    ds->data = NULL;
1759    ds->size = 0;
1760    eet_data_stream_free(ds);
1761    *size_ret = csize;
1762    eet_data_chunk_free(chnk);
1763    
1764    return cdata;
1765 }